From 12405c9e6747a07aef969d5db7e652b2fbb08f21 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 22 Mar 2026 15:31:33 +0900 Subject: [PATCH 01/91] update: 3.0.0 --- .github/workflows/package.yml | 4 +- .github/workflows/pr-test.yml | 4 +- .github/workflows/publish.yml | 4 +- AGENTS.md | 2 +- BANNER.md | 4 +- README.md | 4 +- .../model/api/bone/BoneEventDispatcher.java | 6 +-- .../kr/toxicity/model/api/bone/BoneName.java | 2 +- .../toxicity/model/api/bone/RenderedBone.java | 6 +-- .../kr/toxicity/model/api/data/Float3.java | 2 +- .../kr/toxicity/model/api/data/Float4.java | 2 +- .../data/blueprint/AnimationGenerator.java | 2 +- .../model/api/data/raw/ModelMeta.java | 2 +- .../model/api/data/raw/ModelOutliner.java | 2 +- .../model/api/data/raw/ModelPlaceholder.java | 2 +- .../api/data/renderer/ModelRenderer.java | 12 ++--- .../api/data/renderer/RenderPipeline.java | 10 ++-- .../toxicity/model/api/event/ModelEvent.java | 2 - .../model/api/manager/ModelManager.java | 2 +- .../model/api/nms/HitBoxListener.java | 2 +- .../java/kr/toxicity/model/api/nms/NMS.java | 2 +- .../kr/toxicity/model/api/pack/PackMeta.java | 8 +-- .../model/api/pack/PackObfuscator.java | 2 +- .../toxicity/model/api/pack/PackResult.java | 2 +- .../toxicity/model/api/player/PlayerLimb.java | 4 +- .../model/api/script/AnimationScript.java | 4 +- .../model/api/tracker/EntityTracker.java | 6 +-- .../api/tracker/EntityTrackerRegistry.java | 6 +-- .../model/api/tracker/ModelRotator.java | 14 ++--- .../model/api/tracker/ModelScaler.java | 8 +-- .../toxicity/model/api/tracker/Tracker.java | 14 ++--- .../model/api/tracker/TrackerAnimation.java | 10 ++-- .../api/tracker/TrackerBuiltInAnimation.java | 4 +- .../model/api/tracker/TrackerData.java | 16 +++--- .../api/tracker/TrackerExtraAnimation.java | 6 +-- .../kr/toxicity/model/api/util/HttpUtil.java | 4 +- .../api/util/function/BonePredicate.java | 4 +- .../api/util/function/FloatFunction.java | 2 +- buildSrc/src/main/kotlin/Extensions.kt | 5 +- changelog/{2.2.1.md => 3.0.0.md} | 0 gradle.properties | 6 +-- gradle/libs.versions.toml | 6 +-- platform/fabric/build.gradle.kts | 24 ++++----- .../kr/toxicity/model/mixin/EntityMixin.java | 2 - .../impl/fabric/BetterModelFabricImpl.kt | 2 +- .../kr/toxicity/model/impl/fabric/Entities.kt | 4 +- .../impl/fabric/entity/HitBoxEntityImpl.kt | 52 ++++--------------- .../fabric/entity/InteractionEntityImpl.kt | 6 +-- .../impl/fabric/manager/EntityManager.kt | 6 +-- .../scheduler/FabricModelSchedulerImpl.kt | 2 +- .../model/impl/fabric/world/Chunks.kt | 4 +- renovate.json | 2 +- settings.gradle.kts | 37 +++++++------ 53 files changed, 160 insertions(+), 190 deletions(-) rename changelog/{2.2.1.md => 3.0.0.md} (100%) diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 7aacf3abc..42c1ab6ac 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -20,10 +20,10 @@ jobs: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} steps: - uses: actions/checkout@v6 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'temurin' - name: Grant execute permission for gradlew run: chmod +x gradlew diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index e216a79e2..e3f578994 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -13,10 +13,10 @@ jobs: steps: - uses: actions/checkout@v6 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'temurin' - name: Grant execute permission for gradlew diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index a5fae5947..b26705be3 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -18,10 +18,10 @@ jobs: COMMIT_MESSAGE: ${{ github.event.head_commit.message }} steps: - uses: actions/checkout@v6 - - name: Set up JDK 21 + - name: Set up JDK 25 uses: actions/setup-java@v5 with: - java-version: '21' + java-version: '25' distribution: 'temurin' - name: Grant execute permission for gradlew run: chmod +x gradlew diff --git a/AGENTS.md b/AGENTS.md index 6fac9f5b8..1fb739a35 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -33,7 +33,7 @@ Scope: entire repository unless a deeper AGENTS.md overrides this file. ## 2) Language and File Placement Rules ### MUST -- Use Modern Java (language level 21) and Kotlin. +- Use Modern Java (language level 25) and Kotlin. - `api` module is Java-only for production code (Kotlin DSL build scripts are allowed). - Non-`api` modules should be Kotlin-first unless existing local code is explicitly Java-bound (e.g., mixin/accessor interop). - Follow existing package root `kr.toxicity.model...` and module-specific suffixes. diff --git a/BANNER.md b/BANNER.md index 1792eb8ef..c4f661412 100644 --- a/BANNER.md +++ b/BANNER.md @@ -69,8 +69,8 @@ BetterModel supports **player model with using user's custom skin without textur ## 🏗️ Supported environment -[![](https://img.shields.io/badge/minecraft-1.21%7E1.21.11-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) -[![](https://img.shields.io/badge/java-21%7E-ED8B00?style=for-the-badge)](https://adoptium.net/) +[![](https://img.shields.io/badge/minecraft-1.21%7E26.1-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/java-25%7E-ED8B00?style=for-the-badge)](https://adoptium.net/) ### Bukkit [![](https://img.shields.io/badge/folia-supported-blue?style=for-the-badge)](https://papermc.io/downloads/folia) diff --git a/README.md b/README.md index 7a421faa5..c3c07fdde 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim ## 🛠️ Build info -[![](https://img.shields.io/badge/minecraft-1.21%7E1.21.11-8FCA5C)](https://www.minecraft.net/en-us/download/server) -[![](https://img.shields.io/badge/java-21%7E-ED8B00)](https://adoptium.net/) +[![](https://img.shields.io/badge/minecraft-1.21%7E26.1-8FCA5C)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/java-25%7E-ED8B00)](https://adoptium.net/) #### Build [![](https://cdn.jsdelivr.net/npm/@intergrav/devins-badges@3/assets/cozy/built-with/gradle_vector.svg)](https://gradle.org/) diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java index 6644ea7d2..856e66735 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java @@ -93,9 +93,9 @@ private static class EventFunction { EventFunction() { this( - (b, l) -> l, - (b, u) -> {}, - (b, u) -> {} + (_, l) -> l, + (_, _) -> {}, + (_, _) -> {} ); } diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java index f5a5b366c..365fe215d 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java @@ -26,7 +26,7 @@ public record BoneName(@NotNull @Unmodifiable Set tags, @NotNull String * A JSON deserializer for parsing BoneName from a string. * @since 2.0.1 */ - public static final JsonDeserializer PARSER = (json, typeOfT, context) -> BoneName.of(json.getAsString()); + public static final JsonDeserializer PARSER = (json, _, _) -> BoneName.of(json.getAsString()); /** * Internal constructor for BoneName. diff --git a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java index ec17be3bc..91fc2a5ec 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java @@ -141,7 +141,7 @@ public RenderedBone( applyItem(d); }); } else display = null; - globalState = new BoneStateHandler(null, uuid -> {}); + globalState = new BoneStateHandler(null, _ -> {}); } public void locator(@NotNull BoneIKSolver solver) { @@ -188,7 +188,7 @@ public boolean updateItem(@NotNull BoneRenderContext context) { synchronized (this) { renderContext = context; } - return updateItem(bone -> true); + return updateItem(_ -> true); } /** @@ -554,7 +554,7 @@ private BoneStateHandler(@Nullable UUID uuid, @NotNull Consumer consumer) this.consumer = consumer; state = new AnimationStateHandler<>( AnimationProgress.EMPTY, - (b, a) -> skipInterpolation = (a != null && a.skipInterpolation()) || (parent != null && parent.state(uuid).skipInterpolation) + (_, a) -> skipInterpolation = (a != null && a.skipInterpolation()) || (parent != null && parent.state(uuid).skipInterpolation) ); } diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float3.java b/api/src/main/java/kr/toxicity/model/api/data/Float3.java index 3a68e38f4..c6b977216 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float3.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float3.java @@ -46,7 +46,7 @@ public Float3(float value) { /** * Parser */ - public static final JsonDeserializer PARSER = (json, typeOfT, context) -> { + public static final JsonDeserializer PARSER = (json, _, _) -> { var array = json.getAsJsonArray(); return new Float3( array.get(0).getAsFloat(), diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float4.java b/api/src/main/java/kr/toxicity/model/api/data/Float4.java index e569a0d0a..a7b0efe7a 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float4.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float4.java @@ -31,7 +31,7 @@ public record Float4( /** * Parser */ - public static final JsonDeserializer PARSER = (json, typeOfT, context) -> { + public static final JsonDeserializer PARSER = (json, _, _) -> { var array = json.getAsJsonArray(); return new Float4( array.get(0).getAsFloat(), diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index 12272996d..6bcadb36f 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -197,7 +197,7 @@ private float tree(float first, float second, @NotNull Function target) { - return valueCache.computeIfAbsent(time, f -> { + return valueCache.computeIfAbsent(time, _ -> { if (target.size() <= 1) return EMPTY; var i = searchCache; for (; i < target.size(); i++) { diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java index 4e7d4bf95..8219b4623 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java @@ -31,7 +31,7 @@ public record ModelMeta( * A JSON deserializer for parsing {@link ModelMeta} from the "meta" object in a .bbmodel file. * @since 1.15.2 */ - public static final JsonDeserializer PARSER = (json, type, context) -> new ModelMeta( + public static final JsonDeserializer PARSER = (json, _, _) -> new ModelMeta( FormatVersion.find(new Semver(json.getAsJsonObject().getAsJsonPrimitive("format_version").getAsString(), Semver.SemverType.LOOSE).getMajor()) ); diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java index 48d2551c7..aff165a2f 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java @@ -40,7 +40,7 @@ public sealed interface ModelOutliner { *

* @since 1.15.2 */ - JsonDeserializer PARSER = (json, typeOfT, context) -> { + JsonDeserializer PARSER = (json, _, context) -> { if (json.isJsonPrimitive()) return new Reference(json.getAsString()); else if (json.isJsonObject()) { var children = json.getAsJsonObject().getAsJsonArray("children"); diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java index 8e145fb2f..c64268d39 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java @@ -38,7 +38,7 @@ public record ModelPlaceholder( * A JSON deserializer for parsing placeholders from a multi-line string. * @since 1.15.2 */ - public static final JsonDeserializer PARSER = (json, typeOfT, context) -> new ModelPlaceholder(associate( + public static final JsonDeserializer PARSER = (json, _, _) -> new ModelPlaceholder(associate( Arrays.stream(json.getAsString().split("\n")) .map(line -> line.split("=", 2)) .filter(array -> array.length == 2), diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java index 650aaa23e..9406a6307 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java @@ -103,7 +103,7 @@ public record ModelRenderer( * @return empty tracker */ public @NotNull DummyTracker create(@NotNull PlatformLocation location, @NotNull TrackerModifier modifier) { - return create(location, modifier, t -> { + return create(location, modifier, _ -> { }); } @@ -180,7 +180,7 @@ public record ModelRenderer( * @return empty tracker */ public @NotNull DummyTracker create(@NotNull PlatformLocation location, ModelProfile.Uncompleted profile, @NotNull TrackerModifier modifier) { - return create(location, profile, modifier, t -> { + return create(location, profile, modifier, _ -> { }); } @@ -395,7 +395,7 @@ public record ModelRenderer( * @return entity tracker */ public @NotNull EntityTracker create(@NotNull BaseEntity entity, @NotNull TrackerModifier modifier) { - return create(entity, modifier, t -> { + return create(entity, modifier, _ -> { }); } @@ -472,7 +472,7 @@ public record ModelRenderer( * @return entity tracker */ public @NotNull EntityTracker create(@NotNull BaseEntity entity, @NotNull ModelProfile.Uncompleted profile, @NotNull TrackerModifier modifier) { - return create(entity, profile, modifier, t -> { + return create(entity, profile, modifier, _ -> { }); } @@ -512,7 +512,7 @@ public record ModelRenderer( * @return entity tracker */ public @NotNull EntityTracker getOrCreate(@NotNull BaseEntity entity, @NotNull TrackerModifier modifier) { - return getOrCreate(entity, modifier, t -> { + return getOrCreate(entity, modifier, _ -> { }); } @@ -592,7 +592,7 @@ public record ModelRenderer( * @return entity tracker */ public @NotNull EntityTracker getOrCreate(@NotNull BaseEntity entity, ModelProfile.Uncompleted profile, @NotNull TrackerModifier modifier) { - return getOrCreate(entity, profile, modifier, t -> { + return getOrCreate(entity, profile, modifier, _ -> { }); } diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java index 7429321ae..be36c6cb6 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java @@ -62,13 +62,13 @@ public final class RenderPipeline implements BoneEventHandler, Iterable viewFilter = p -> true; + private Predicate viewFilter = _ -> true; private Predicate hideFilter = p -> hidePlayerSet.contains(p.uuid()); - private Consumer spawnPacketHandler = b -> {}; - private Consumer despawnPacketHandler = b -> {}; - private Consumer hidePacketHandler = b -> {}; - private Consumer showPacketHandler = b -> {}; + private Consumer spawnPacketHandler = _ -> {}; + private Consumer despawnPacketHandler = _ -> {}; + private Consumer hidePacketHandler = _ -> {}; + private Consumer showPacketHandler = _ -> {}; @Getter private ModelRotation rotation = ModelRotation.INVALID; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java index a01837178..227c195c4 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java @@ -7,8 +7,6 @@ package kr.toxicity.model.api.event; import kr.toxicity.model.api.BetterModel; -import kr.toxicity.model.api.BetterModelEventBus; -import org.jetbrains.annotations.NotNull; /** * Represents a base event in the BetterModel system. diff --git a/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java b/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java index 664fe191a..acc4bb4bf 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java @@ -122,7 +122,7 @@ default boolean animate(@NotNull PlatformPlayer player, @NotNull String model, @ * @since 1.15.2 */ default boolean animate(@NotNull PlatformPlayer player, @NotNull String model, @NotNull String animation, @NotNull AnimationModifier modifier) { - return animate(player, model, animation, modifier, t -> {}); + return animate(player, model, animation, modifier, _ -> {}); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java index 2524e50cb..bcc020f87 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java @@ -78,7 +78,7 @@ private Builder( */ @SuppressWarnings("unchecked") public @NotNull Builder listen(@NotNull Class eventClass, @NotNull Consumer consumer) { - listeners.compute(eventClass, (k, old) -> old == null ? consumer : ((Consumer) old).andThen(consumer)); + listeners.compute(eventClass, (_, old) -> old == null ? consumer : ((Consumer) old).andThen(consumer)); return this; } diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java index e77bad183..8ba215276 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java @@ -45,7 +45,7 @@ public interface NMS { * @since 1.15.2 */ default @NotNull ModelDisplay create(@NotNull PlatformLocation location) { - return create(location, 0, d -> {}); + return create(location, 0, _ -> {}); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java b/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java index 61881e101..4dcb72eef 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java @@ -42,15 +42,15 @@ public record PackMeta( */ public static final PackPath PATH = new PackPath("pack.mcmeta"); private static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(PackVersion.class, (JsonDeserializer) (json, typeOfT, context) -> { + .registerTypeAdapter(PackVersion.class, (JsonDeserializer) (json, _, _) -> { if (json.isJsonPrimitive()) return new PackVersion(json.getAsInt()); else if (json.isJsonArray()) { var array = json.getAsJsonArray(); return new PackVersion(array.get(0).getAsInt(), array.size() < 2 ? 0 : array.get(1).getAsInt()); } else return null; }) - .registerTypeAdapter(PackVersion.class, (JsonSerializer) (src, typeOfSrc, context) -> src.toJson()) - .registerTypeAdapter(VersionRange.class, (JsonDeserializer) (json, typeOfT, context) -> { + .registerTypeAdapter(PackVersion.class, (JsonSerializer) (src, _, _) -> src.toJson()) + .registerTypeAdapter(VersionRange.class, (JsonDeserializer) (json, _, context) -> { if (json.isJsonPrimitive()) return new VersionRange(json.getAsInt()); else if (json.isJsonArray()) { var array = json.getAsJsonArray(); @@ -62,7 +62,7 @@ else if (json.isJsonArray()) { return context.deserialize(json, VersionRange.class); } else return null; }) - .registerTypeAdapter(VersionRange.class, (JsonSerializer) (src, typeOfSrc, context) -> src.toJson()) + .registerTypeAdapter(VersionRange.class, (JsonSerializer) (src, _, _) -> src.toJson()) .create(); /** diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java b/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java index c4e38f755..2e9babd89 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java @@ -96,7 +96,7 @@ private Order() { } public @NotNull String obfuscate(@NotNull String rawName) { - return nameMap.computeIfAbsent(rawName, n -> { + return nameMap.computeIfAbsent(rawName, _ -> { var size = nameMap.size(); builder.setLength(0); while (size >= NAME_LENGTH) { diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java b/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java index e9297e7d8..b1c90f89e 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java @@ -57,7 +57,7 @@ public void set(@Nullable PackOverlay overlay, @NotNull PackByte packByte) { return; } synchronized (overlays) { - overlays.computeIfAbsent(overlay, o -> new TreeSet<>()).add(packByte); + overlays.computeIfAbsent(overlay, _ -> new TreeSet<>()).add(packByte); } } diff --git a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java index eaaab6694..f0bcf6b71 100644 --- a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java +++ b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java @@ -62,7 +62,7 @@ public enum PlayerLimb { scale(2.7891F,5.5938F,3.7188F, 0.25F), offset(-0.625F, 1.5F, 0, 0.25F), offset(-0.043F, 1.5F, 0, 0.25F), - (d, p) -> d.rightForeArm(), + (d, _) -> d.rightForeArm(), PlatformItemTransform.FIXED ), /** @@ -86,7 +86,7 @@ public enum PlayerLimb { scale(2.7891F,5.5938F,3.7188F, 0.25F), offset(0.625F, 1.5F, 0, 0.25F), offset(0.043F, 1.5F, 0, 0.25F), - (d, p) -> d.leftForeArm(), + (d, _) -> d.leftForeArm(), PlatformItemTransform.FIXED ), /** diff --git a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java index 79b02de47..a0a83f8a2 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java +++ b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java @@ -21,7 +21,7 @@ public interface AnimationScript extends Consumer { /** * Empty script */ - AnimationScript EMPTY = of(s -> {}); + AnimationScript EMPTY = of(_ -> {}); @Override void accept(@NotNull Tracker tracker); @@ -82,7 +82,7 @@ public void accept(@NotNull Tracker tracker) { case 1 -> scriptList.getFirst(); default -> { var sync = false; - Consumer consumer = trigger -> {}; + Consumer consumer = _ -> {}; for (AnimationScript entityScript : scriptList) { sync = sync || entityScript.isSync(); consumer = consumer.andThen(entityScript); diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java index 2e11fd31a..6fda212ff 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java @@ -100,7 +100,7 @@ public EntityTracker(@NotNull EntityTrackerRegistry registry, @NotNull RenderPip }); var baseScale = (float) (box.x() + box.z()) / 4F; var posCache = new BoneMovement(); - tick(((t, s) -> { + tick(((_, s) -> { var wPos = bone.hitBoxPosition(posCache); shadow.shadowRadius(scale.getAsFloat() * baseScale); shadow.syncPotionEffect(entity); @@ -145,8 +145,8 @@ public EntityTracker(@NotNull EntityTrackerRegistry registry, @NotNull RenderPip if (isClosed()) return; createHitBox(null, CREATE_HITBOX_PREDICATE); }); - tick((t, s) -> updateLocation()); - tick((t, s) -> { + tick((_, _) -> updateLocation()); + tick((_, _) -> { if (damageTint.getAndDecrement() == 0) update(TrackerUpdateAction.previousTint()); }); rotation(bodyRotator::bodyRotation); diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java index 662ed1a53..d4b3f9769 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java @@ -277,9 +277,9 @@ public int id() { private boolean putTracker(@NotNull String key, @NotNull EntityTracker created) { if (isClosed() || created.isClosed()) return false; - created.handleCloseEvent((t, r) -> { + created.handleCloseEvent((_, r) -> { if (isClosed()) return; - if (trackerMap.compute(key, (k, v) -> v == created ? null : v) == null) { + if (trackerMap.compute(key, (_, v) -> v == created ? null : v) == null) { LogUtil.debug(DebugConfig.DebugOption.TRACKER, () -> uuid + "'s tracker " + key + " has been removed. (" + trackerMap.size() + ")"); } if (trackerMap.isEmpty()) close(r); @@ -541,7 +541,7 @@ private boolean spawn(@NotNull PlatformPlayer player, boolean shouldNotSpawned) } private @NotNull PlayerChannelCache registerPlayer(@NotNull PlayerChannelHandler handler) { - return viewedPlayerMap.computeIfAbsent(handler.uuid(), u -> new PlayerChannelCache(handler)); + return viewedPlayerMap.computeIfAbsent(handler.uuid(), _ -> new PlayerChannelCache(handler)); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java index 9e2c567bf..42fc7027d 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java @@ -223,7 +223,7 @@ interface Getter { * @since 1.15.2 */ static @NotNull Getter of(@NotNull ModelRotation rotator) { - return (t, r) -> rotator; + return (_, _) -> rotator; } /** * Creates a supplier-based rotation getter. @@ -233,7 +233,7 @@ interface Getter { * @since 1.15.2 */ static @NotNull Getter of(@NotNull Supplier rotator) { - return (t, r) -> rotator.get(); + return (_, _) -> rotator.get(); } /** * Creates a function-based rotation getter. @@ -243,7 +243,7 @@ interface Getter { * @since 1.15.2 */ static @NotNull Getter of(@NotNull Function rotator) { - return (t, r) -> rotator.apply(r); + return (_, r) -> rotator.apply(r); } } @@ -303,10 +303,10 @@ interface BuiltInDeserializer extends Function { final class Deserializer { private final Map builderMap = CollectionUtil.newAddressingMap(); - private final BuiltInDeserializer _default = register("default", j -> Getter.of(r -> r)); - private final BuiltInDeserializer empty = register("empty", j -> Getter.of(ModelRotation.EMPTY)); - private final BuiltInDeserializer yaw = register("yaw", j -> Getter.of(ModelRotation::yaw)); - private final BuiltInDeserializer pitch = register("pitch", j -> Getter.of(ModelRotation::pitch)); + private final BuiltInDeserializer _default = register("default", _ -> Getter.of(r -> r)); + private final BuiltInDeserializer empty = register("empty", _ -> Getter.of(ModelRotation.EMPTY)); + private final BuiltInDeserializer yaw = register("yaw", _ -> Getter.of(ModelRotation::yaw)); + private final BuiltInDeserializer pitch = register("pitch", _ -> Getter.of(ModelRotation::pitch)); private final BuiltInDeserializer lazy = register("lazy", j -> { if (j.isJsonPrimitive()) { var f = j.getAsLong(); diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java b/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java index bf0a397a2..d6cac27e9 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java @@ -165,7 +165,7 @@ interface Getter { * Default getter returning 1.0. * @since 1.15.2 */ - Getter DEFAULT = t -> 1F; + Getter DEFAULT = _ -> 1F; /** * Getter using entity scale. * @since 1.15.2 @@ -189,7 +189,7 @@ interface Getter { * @since 1.15.2 */ static @NotNull Getter value(float value) { - return t -> value; + return _ -> value; } } @@ -295,8 +295,8 @@ final class Deserializer { private final Map getterMap = CollectionUtil.newAddressingMap(); - private final BuiltInDeserializer def = addScaler("default", d -> Getter.DEFAULT); - private final BuiltInDeserializer entity = addScaler("entity", d -> Getter.ENTITY); + private final BuiltInDeserializer def = addScaler("default", _ -> Getter.DEFAULT); + private final BuiltInDeserializer entity = addScaler("entity", _ -> Getter.ENTITY); private final BuiltInDeserializer value = addScaler("value", d -> d.isJsonPrimitive() ? Getter.value(d.getAsFloat()) : Getter.DEFAULT); private Deserializer() { diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java index 91d4865e9..80cbcfc1c 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java @@ -103,7 +103,7 @@ public float getAsFloat() { }); private final AnimationStateHandler scriptProcessor = new AnimationStateHandler<>( TimeScript.EMPTY, - (b, a) -> { + (b, _) -> { if (b == null) return; if (b.isSync()) { location().task(() -> b.accept(this)); @@ -155,15 +155,15 @@ public Tracker(@NotNull RenderPipeline pipeline, @NotNull TrackerModifier modifi t.rotation(), s.tickBundler )); - tick((t, s) -> { + tick((t, _) -> { var perPlayer = perPlayerHandler; if (perPlayer != null) pipeline.nonHidePlayer().forEach(p -> perPlayer.accept(t, p)); }); - pipeline.spawnPacketHandler(p -> start()); - pipeline.eventDispatcher().handleStateCreate((bone, uuid) -> bundlerSet.perPlayerViewBundler + pipeline.spawnPacketHandler(_ -> start()); + pipeline.eventDispatcher().handleStateCreate((_, uuid) -> bundlerSet.perPlayerViewBundler .computeIfAbsent(uuid, PerPlayerCache::new) .add()); - pipeline.eventDispatcher().handleStateRemove((bone, uuid) -> { + pipeline.eventDispatcher().handleStateRemove((_, uuid) -> { var get = bundlerSet.perPlayerViewBundler.get(uuid); if (get != null) get.remove(); }); @@ -550,7 +550,7 @@ public boolean animate(@NotNull BlueprintAnimation animation, @NotNull Animation * @since 1.15.2 */ public boolean stopAnimation(@NotNull String animation) { - return stopAnimation(e -> true, animation); + return stopAnimation(_ -> true, animation); } /** @@ -649,7 +649,7 @@ public void listenHitBox(@NotNull BiFunction void listenHitBox(@NotNull Class eventClass, @NotNull Consumer consumer) { - listenHitBox((bone, builder) -> builder.listen(eventClass, consumer)); + listenHitBox((_, builder) -> builder.listen(eventClass, consumer)); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java index 158385afb..4bfe41493 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java @@ -102,11 +102,11 @@ public static final class Builder { private final Class targetClass; private int priority = 0; - private @NotNull Predicate applyCondition = tracker -> true; - private @NotNull Function modifierBuilder = tracker -> AnimationModifier.DEFAULT; - private @NotNull Consumer removeTask = tracker -> {}; - private @NotNull Consumer successTask = tracker -> {}; - private @NotNull Consumer fallbackTask = tracker -> {}; + private @NotNull Predicate applyCondition = _ -> true; + private @NotNull Function modifierBuilder = _ -> AnimationModifier.DEFAULT; + private @NotNull Consumer removeTask = _ -> {}; + private @NotNull Consumer successTask = _ -> {}; + private @NotNull Consumer fallbackTask = _ -> {}; /** * Changes the target tracker type for this builder. diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java index ab18b3792..54e8f43ea 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java @@ -55,7 +55,7 @@ static void play(@NotNull Tracker tracker) { * * @since 2.2.0 */ - public static final TrackerAnimation IDLE = register("idle", b -> b.modifier(tracker -> AnimationModifier.builder() + public static final TrackerAnimation IDLE = register("idle", b -> b.modifier(_ -> AnimationModifier.builder() .start(6) .type(AnimationIterator.Type.LOOP) .build() @@ -113,7 +113,7 @@ static void play(@NotNull Tracker tracker) { * @since 2.2.0 */ public static final TrackerAnimation SPAWN = register("spawn", b -> b.type(EntityTracker.class) - .modifier(tracker -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE)); + .modifier(_ -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE)); private TrackerBuiltInAnimation() { throw new IllegalStateException("Utility class"); diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java index d58aaeb67..42997cd4a 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java @@ -45,14 +45,14 @@ public record TrackerData( * @since 1.15.2 */ public static final Gson PARSER = new GsonBuilder() - .registerTypeAdapter(ModelScaler.class, (JsonDeserializer) (json, typeOfT, context) -> json.isJsonObject() ? ModelScaler.deserialize(json.getAsJsonObject()) : ModelScaler.defaultScaler()) - .registerTypeAdapter(ModelScaler.class, (JsonSerializer) (src, typeOfSrc, context) -> src.serialize()) - .registerTypeAdapter(ModelRotator.class, (JsonDeserializer) (json, typeOfT, context) -> json.isJsonObject() ? ModelRotator.deserialize(json.getAsJsonObject()) : ModelRotator.YAW) - .registerTypeAdapter(ModelRotator.class, (JsonSerializer) (src, typeOfSrc, context) -> src.serialize()) - .registerTypeAdapter(EntityHideOption.class, (JsonDeserializer) (json, typeOfT, context) -> json.isJsonArray() ? EntityHideOption.deserialize(json.getAsJsonArray()) : EntityHideOption.DEFAULT) - .registerTypeAdapter(EntityHideOption.class, (JsonSerializer) (src, typeOfSrc, context) -> src.serialize()) - .registerTypeAdapter(UUID.class, (JsonDeserializer) (json, typeOfT, context) -> UUID.fromString(json.getAsString())) - .registerTypeAdapter(UUID.class, (JsonSerializer) (src, typeOfSrc, context) -> new JsonPrimitive(src.toString())) + .registerTypeAdapter(ModelScaler.class, (JsonDeserializer) (json, _, _) -> json.isJsonObject() ? ModelScaler.deserialize(json.getAsJsonObject()) : ModelScaler.defaultScaler()) + .registerTypeAdapter(ModelScaler.class, (JsonSerializer) (src, _, _) -> src.serialize()) + .registerTypeAdapter(ModelRotator.class, (JsonDeserializer) (json, _, _) -> json.isJsonObject() ? ModelRotator.deserialize(json.getAsJsonObject()) : ModelRotator.YAW) + .registerTypeAdapter(ModelRotator.class, (JsonSerializer) (src, _, _) -> src.serialize()) + .registerTypeAdapter(EntityHideOption.class, (JsonDeserializer) (json, _, _) -> json.isJsonArray() ? EntityHideOption.deserialize(json.getAsJsonArray()) : EntityHideOption.DEFAULT) + .registerTypeAdapter(EntityHideOption.class, (JsonSerializer) (src, _, _) -> src.serialize()) + .registerTypeAdapter(UUID.class, (JsonDeserializer) (json, _, _) -> UUID.fromString(json.getAsString())) + .registerTypeAdapter(UUID.class, (JsonSerializer) (src, _, _) -> new JsonPrimitive(src.toString())) .create(); /** diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java index 07c70242f..4cf33119c 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java @@ -23,7 +23,7 @@ public final class TrackerExtraAnimation { */ public static final TrackerAnimation DEATH = TrackerAnimation.builder("death") .type(EntityTracker.class) - .modifier(tracker -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) + .modifier(_ -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) .onRemove(Tracker::close) .onSuccess(tracker -> tracker.forRemoval(true)) .build(); @@ -35,7 +35,7 @@ public final class TrackerExtraAnimation { */ public static final TrackerAnimation DAMAGE = TrackerAnimation.builder("damage") .type(EntityTracker.class) - .modifier(tracker -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) + .modifier(_ -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) .build(); /** @@ -45,7 +45,7 @@ public final class TrackerExtraAnimation { */ public static final TrackerAnimation JUMP = TrackerAnimation.builder("jump") .type(EntityTracker.class) - .modifier(tracker -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) + .modifier(_ -> AnimationModifier.DEFAULT_WITH_PLAY_ONCE) .build(); private TrackerExtraAnimation() { diff --git a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java index bd31468c6..f2d78d8a0 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java @@ -47,8 +47,8 @@ public final class HttpUtil { .executor(Executors.newVirtualThreadPerTaskExecutor()) .build(); private static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(MinecraftVersion.class, (JsonDeserializer) (json, typeOfT, context) -> MinecraftVersion.parse(json.getAsString())) - .registerTypeAdapter(Semver.class, (JsonDeserializer) (json, typeOfT, context) -> new Semver(json.getAsString(), Semver.SemverType.LOOSE)) + .registerTypeAdapter(MinecraftVersion.class, (JsonDeserializer) (json, _, _) -> MinecraftVersion.parse(json.getAsString())) + .registerTypeAdapter(Semver.class, (JsonDeserializer) (json, _, _) -> new Semver(json.getAsString(), Semver.SemverType.LOOSE)) .create(); /** diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java b/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java index 1254921b3..5cdb1ba80 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java @@ -22,12 +22,12 @@ public interface BonePredicate extends Predicate { /** * True */ - BonePredicate TRUE = of(State.TRUE, b -> true); + BonePredicate TRUE = of(State.TRUE, _ -> true); /** * False */ - BonePredicate FALSE = of(State.FALSE, b -> false); + BonePredicate FALSE = of(State.FALSE, _ -> false); /** * Gets builder by name diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java b/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java index 4f644d7d7..58457fb84 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java @@ -53,6 +53,6 @@ public interface FloatFunction { */ default @NotNull FloatFunction memoize() { var map = new Int2ReferenceOpenHashMap(); - return f -> map.computeIfAbsent(MathUtil.similarHashCode(f), i -> apply(f)); + return f -> map.computeIfAbsent(MathUtil.similarHashCode(f), _ -> apply(f)); } } diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index 42a915c32..8d1986dc2 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -1,7 +1,7 @@ import org.gradle.accessors.dm.LibrariesForLibs import org.gradle.api.Project -const val JAVA_VERSION = 21 +const val JAVA_VERSION = 25 val BUILD_NUMBER: String? = System.getenv("BUILD_NUMBER") val Project.libs @@ -17,7 +17,8 @@ val SUPPORTED_VERSIONS = listOf( "1.21.8", "1.21.9", "1.21.10", - "1.21.11" + "1.21.11", + "26.1" ) val BUKKIT_LOADERS = listOf("spigot") diff --git a/changelog/2.2.1.md b/changelog/3.0.0.md similarity index 100% rename from changelog/2.2.1.md rename to changelog/3.0.0.md diff --git a/gradle.properties b/gradle.properties index 854fd1a56..c146b2823 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryEr fabric.loom.multiProjectOptimisation=true -parchment_version=1.21.11+build.8 +parchment_version=1.21.11+build.9 -project_version=2.2.1 -minecraft_version=1.21.11 +project_version=3.0.0 +minecraft_version=26.1-rc-2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 4fed726ff..7c0326d97 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.0" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.141.3+1.21.11" +fabric-api = "0.144.0+26.1" fabric-language-kotlin = "1.13.9+kotlin.2.3.10" cloud-bukkit = "2.0.0-beta.14" @@ -26,14 +26,14 @@ adventure-api = "net.kyori:adventure-api:4.26.1" adventure-examination = "net.kyori:examination-api:1.3.0" adventure-option = "net.kyori:option:1.1.0" adventure-platform-bukkit = "net.kyori:adventure-platform-bukkit:4.4.1" -adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.8.0" +adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0-SNAPSHOT" asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.18.4" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.15.2+1.21.11" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0-pre.1+26.1-rc-2" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index 6f56c3cc6..b9d52ab86 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -4,7 +4,7 @@ plugins { alias(libs.plugins.convention.publish) alias(libs.plugins.convention.modrinth) alias(libs.plugins.resourcefactory.fabric) - id("fabric-loom") + id("net.fabricmc.fabric-loom") } val versionString = "${rootProject.version}+${property("minecraft_version")}" @@ -21,7 +21,7 @@ sourceSets { loom { // Access winder - accessWidenerPath = file("src/main/resources/bettermodel.accesswidener") + //accessWidenerPath = file("src/main/resources/bettermodel.accesswidener") // Run runs { @@ -39,17 +39,17 @@ loom { } // Test mod - createRemapConfigurations(sourceSets["testmod"]) + //createRemapConfigurations(sourceSets["testmod"]) } dependencies { // Minecraft minecraft("com.mojang:minecraft:${property("minecraft_version")}") - mappings(loom.layered { - officialMojangMappings() - parchment("io.papermc.parchment.data:parchment:${property("parchment_version")}") - }) +// mappings(loom.layered { +// officialMojangMappings() +// parchment("io.papermc.parchment.data:parchment:${property("parchment_version")}") +// }) api(project(":api")); include(project(":api")) api(project(":core")); include(project(":core")) @@ -64,13 +64,13 @@ dependencies { "fabric-networking-api-v1", "fabric-transitive-access-wideners-v1" ).forEach { - modImplementation(fabricApi.module(it, libs.versions.fabric.api.get())) + implementation(fabricApi.module(it, libs.versions.fabric.api.get())) } - modImplementation(libs.bundles.fabric) + implementation(libs.bundles.fabric) implementation(libs.bundles.fabric.library); include(libs.bundles.fabric.library) - modApi(libs.bundles.fabric.mod); include(libs.bundles.fabric.mod) + api(libs.bundles.fabric.mod); include(libs.bundles.fabric.mod) implementation(libs.bundles.core); include(libs.bundles.core) include(libs.bundles.library) @@ -155,8 +155,6 @@ tasks { from(rootProject.layout.projectDirectory.file(".idea/icon.png")) { rename { "assets/icon.png" } } - } - remapJar { manifest { attributes( mapOf( @@ -186,7 +184,7 @@ tasks { modrinth { loaders = listOf("fabric", "quilt") uploadFile.set(jarDir.map { it.file(jarName) }) - gameVersions = listOf("1.21.11") + gameVersions = listOf("26.1") dependencies { required.version("fabric-api", libs.versions.fabric.api.get()) required.version("fabric-language-kotlin", libs.versions.fabric.language.kotlin.get()) diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java index cc5960b91..ea0da7a18 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java @@ -26,13 +26,11 @@ public abstract class EntityMixin implements EntityHook { @Shadow public abstract Level level(); - @SuppressWarnings("UnstableApiUsage") @Override public @Nullable String bettermodel$getModelData() { return ((AttachmentTarget) this).getAttached(BetterModelAttachments.MODEL_DATA); } - @SuppressWarnings("UnstableApiUsage") @Override public void bettermodel$setModelData(@Nullable String modelData) { ((AttachmentTarget) this).setAttached(BetterModelAttachments.MODEL_DATA, modelData); diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt index 38c87ef33..1dc49b7ef 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt @@ -67,7 +67,7 @@ class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterMod private val jarFile: JarFile get() = JarFile( - File(javaClass.getProtectionDomain().codeSource.location.toURI()) + File(javaClass.protectionDomain.codeSource.location.toURI()) ) private lateinit var config: BetterModelConfigImpl diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt index 1f62b6ae2..1e0504482 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt @@ -4,6 +4,8 @@ * Licensed under the MIT License. * See LICENSE.md file for full license text. */ +@file:Suppress("UnstableApiUsage") + package kr.toxicity.model.impl.fabric import kr.toxicity.model.api.BetterModel @@ -46,7 +48,7 @@ val Entity.seenBy: Set val tracker = level.chunkSource.chunkMap.entityMap.get(id) ?: return emptySet() - return tracker.playersTracking + return tracker.seenBy } var Entity.modelData: String? diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt index 9473155fc..a1efb1697 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt @@ -10,13 +10,7 @@ import kr.toxicity.model.api.bone.BoneMovement import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.fabric.platform.FabricEntity import kr.toxicity.model.api.fabric.platform.FabricLivingEntity import kr.toxicity.model.api.mount.MountController @@ -398,18 +392,19 @@ class HitBoxEntityImpl( when (hand) { ModelInteractionHand.LEFT -> InteractionHand.OFF_HAND ModelInteractionHand.RIGHT -> InteractionHand.MAIN_HAND - } + }, + Vec3.ZERO ) } override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( + interact( player.unwarp().player, - Vec3(position), when (hand) { ModelInteractionHand.LEFT -> InteractionHand.OFF_HAND ModelInteractionHand.RIGHT -> InteractionHand.MAIN_HAND - } + }, + Vec3(position) ) } @@ -421,33 +416,8 @@ class HitBoxEntityImpl( TODO("with mixin") } - override fun interact(player: Player, hand: InteractionHand): InteractionResult { - if (player === delegate) { - return InteractionResult.FAIL - } - val serverPlayer = player as ServerPlayer - - val interact = HitBoxInteractEvent( - serverPlayer.connection.wrap(), - this, - when (hand) { - InteractionHand.MAIN_HAND -> ModelInteractionHand.RIGHT - InteractionHand.OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL - - serverPlayer.connection.handleInteract( - ServerboundInteractPacket.createInteractionPacket( - delegate, - player.isShiftKeyDown, - hand - ) - ) - return InteractionResult.SUCCESS - } - override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { if (player === delegate) { return InteractionResult.FAIL } @@ -465,11 +435,11 @@ class HitBoxEntityImpl( if (!listener.handle(interact)) return InteractionResult.FAIL serverPlayer.connection.handleInteract( - ServerboundInteractPacket.createInteractionPacket( - delegate, - player.isShiftKeyDown, + ServerboundInteractPacket( + delegate.id, hand, - vec + vec, + player.isShiftKeyDown ) ) return InteractionResult.SUCCESS diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt index d6b0b8e5b..c710b3ebd 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt @@ -37,11 +37,7 @@ class InteractionEntityImpl(val delegate: HitBoxEntityImpl) : return true } - override fun interact(player: Player, hand: InteractionHand): InteractionResult { - return InteractionResult.FAIL - } - - override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { return InteractionResult.FAIL } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt index dc381d1b1..d7eed4c5f 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt @@ -23,7 +23,7 @@ import kr.toxicity.model.impl.fabric.wrap import kr.toxicity.model.manager.GlobalManager import kr.toxicity.model.manager.ReloadPipeline import kr.toxicity.model.util.PLATFORM -import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents +import net.fabricmc.fabric.api.entity.event.v1.ServerEntityLevelChangeEvents import net.fabricmc.fabric.api.entity.event.v1.ServerLivingEntityEvents import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents @@ -113,7 +113,7 @@ object EntityManager : GlobalManager { } private fun registerLifecycleEvents() { - ServerEntityWorldChangeEvents.AFTER_ENTITY_CHANGE_WORLD.register { oldEntity, newEntity, _, _ -> + ServerEntityLevelChangeEvents.AFTER_ENTITY_CHANGE_LEVEL.register { oldEntity, newEntity, _, _ -> BetterModel.registryOrNull(oldEntity.uuid)?.let { registry -> (registry.entity() as BaseFabricEntity).entity(newEntity) } @@ -130,7 +130,7 @@ object EntityManager : GlobalManager { } // same as PlayerChangedWorldEvent - ServerEntityWorldChangeEvents.AFTER_PLAYER_CHANGE_WORLD.register { player, _, _ -> + ServerEntityLevelChangeEvents.AFTER_PLAYER_CHANGE_LEVEL.register { player, _, _ -> BetterModel.registryOrNull(player.uuid)?.let { registry -> registry.despawn() registry.refresh() diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt index 2b292f270..05fef7a18 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt @@ -124,7 +124,7 @@ object FabricModelSchedulerImpl : FabricModelScheduler, FabricRegionHolder { } fun init() { - ServerTickEvents.START_WORLD_TICK.register { + ServerTickEvents.START_LEVEL_TICK.register { tick() } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt index d5000e5cf..0d98a34f6 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt @@ -4,6 +4,8 @@ * Licensed under the MIT License. * See LICENSE.md file for full license text. */ +@file:Suppress("UnstableApiUsage") + package kr.toxicity.model.impl.fabric.world import it.unimi.dsi.fastutil.ints.Int2ObjectMap @@ -13,5 +15,5 @@ import net.minecraft.server.level.ChunkMap val ChunkMap.entityMap: Int2ObjectMap get() { - return (this as ChunkMapAccessor).entityTrackers + return (this as ChunkMapAccessor).entityMap } diff --git a/renovate.json b/renovate.json index 18189ff30..630b392ac 100644 --- a/renovate.json +++ b/renovate.json @@ -9,7 +9,7 @@ "org.incendo:cloud-fabric", "io.papermc.parchment.data:parchment", "net.fabricmc.fabric-api:fabric-api", - "fabric-loom", + "net.fabricmc.fabric-loom-repositories", "eu.pb4:polymer-resource-pack" ], "baseBranches": [ diff --git a/settings.gradle.kts b/settings.gradle.kts index 9da365add..aa845ccb8 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,7 +11,7 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" - id("fabric-loom") version "1.15-SNAPSHOT" + id("net.fabricmc.fabric-loom-repositories") version "1.15-SNAPSHOT" } dependencyResolutionManagement { @@ -28,6 +28,11 @@ dependencyResolutionManagement { maven("https://mvn.lumine.io/repository/maven-public/") maven("https://repo.nexomc.com/releases/") maven("https://maven.nucleoid.xyz/") + // for development builds + maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { + name = "central-snapshots" + mavenContent { snapshotsOnly() } + } } } @@ -36,26 +41,26 @@ rootProject.name = "BetterModel" include( //api "api", - "api:bukkit-api", +// "api:bukkit-api", //core "core", - "core:bukkit-core", +// "core:bukkit-core", - "purpur", +// "purpur", - "platform:spigot", - "platform:paper", +// "platform:spigot", +// "platform:paper", "platform:fabric", - //nms - "nms:v1_21_R1", - "nms:v1_21_R3", - "nms:v1_21_R4", - "nms:v1_21_R5", - "nms:v1_21_R6", - "nms:v1_21_R7", - - //test - "test-plugin" +// //nms +// "nms:v1_21_R1", +// "nms:v1_21_R3", +// "nms:v1_21_R4", +// "nms:v1_21_R5", +// "nms:v1_21_R6", +// "nms:v1_21_R7", +// +// //test +// "test-plugin" ) From 88813a5ea90ed45175360bc8a481fb4d8d303388 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 29 Mar 2026 15:07:04 +0900 Subject: [PATCH 02/91] feat: mesh support --- .github/workflows/package.yml | 2 +- .github/workflows/pr-test.yml | 2 +- .github/workflows/publish.yml | 2 +- LICENSE_HEADER | 4 +- .../model/api/bukkit/BetterModelBukkit.java | 5 +- .../model/api/bukkit/BukkitModelEventBus.java | 5 +- .../api/bukkit/entity/BaseBukkitEntity.java | 5 +- .../api/bukkit/entity/BaseBukkitPlayer.java | 5 +- .../bukkit/event/BetterModelBukkitEvent.java | 5 +- .../bukkit/event/BukkitEventApplication.java | 5 +- .../api/bukkit/platform/BukkitAdapter.java | 5 +- .../api/bukkit/platform/BukkitEntity.java | 5 +- .../api/bukkit/platform/BukkitItemStack.java | 5 +- .../bukkit/platform/BukkitLivingEntity.java | 5 +- .../api/bukkit/platform/BukkitLocation.java | 5 +- .../bukkit/platform/BukkitOfflinePlayer.java | 5 +- .../api/bukkit/platform/BukkitPlayer.java | 5 +- .../api/bukkit/platform/BukkitWorld.java | 5 +- .../scheduler/BukkitModelScheduler.java | 5 +- .../kr/toxicity/model/api/BetterModel.java | 5 +- .../toxicity/model/api/BetterModelConfig.java | 5 +- .../model/api/BetterModelEvaluator.java | 5 +- .../model/api/BetterModelEventBus.java | 5 +- .../toxicity/model/api/BetterModelLogger.java | 5 +- .../model/api/BetterModelPlatform.java | 5 +- .../api/animation/AnimationIterator.java | 5 +- .../api/animation/AnimationKeyframe.java | 5 +- .../api/animation/AnimationModifier.java | 21 ++- .../api/animation/AnimationOverrideState.java | 5 +- .../api/animation/AnimationProgress.java | 5 +- .../api/animation/AnimationStateHandler.java | 5 +- .../model/api/animation/RunningAnimation.java | 7 +- .../toxicity/model/api/animation/Timed.java | 5 +- .../model/api/animation/TimedStorage.java | 5 +- .../model/api/animation/VectorPoint.java | 5 +- .../toxicity/model/api/armor/ArmorItem.java | 5 +- .../toxicity/model/api/armor/PlayerArmor.java | 5 +- .../model/api/bone/BoneEventDispatcher.java | 5 +- .../model/api/bone/BoneEventHandler.java | 5 +- .../toxicity/model/api/bone/BoneIKSolver.java | 5 +- .../model/api/bone/BoneItemMapper.java | 5 +- .../toxicity/model/api/bone/BoneMovement.java | 5 +- .../kr/toxicity/model/api/bone/BoneName.java | 5 +- .../toxicity/model/api/bone/BonePosition.java | 5 +- .../model/api/bone/BoneRenderContext.java | 5 +- .../kr/toxicity/model/api/bone/BoneTag.java | 5 +- .../model/api/bone/BoneTagRegistry.java | 5 +- .../kr/toxicity/model/api/bone/BoneTags.java | 5 +- .../toxicity/model/api/bone/RenderedBone.java | 5 +- .../model/api/config/DebugConfig.java | 5 +- .../model/api/config/IndicatorConfig.java | 5 +- .../model/api/config/ModuleConfig.java | 5 +- .../toxicity/model/api/config/PackConfig.java | 5 +- .../kr/toxicity/model/api/data/Float2.java | 30 ++++ .../kr/toxicity/model/api/data/Float3.java | 27 +++- .../kr/toxicity/model/api/data/Float4.java | 7 +- .../toxicity/model/api/data/ModelAsset.java | 5 +- .../data/blueprint/AnimationGenerator.java | 5 +- .../data/blueprint/BlueprintAnimation.java | 5 +- .../api/data/blueprint/BlueprintAnimator.java | 5 +- .../api/data/blueprint/BlueprintElement.java | 117 +++++++++++--- .../api/data/blueprint/BlueprintImage.java | 5 +- .../api/data/blueprint/BlueprintJson.java | 5 +- .../data/blueprint/BlueprintLoadContext.java | 149 ++++++++++++++++++ .../api/data/blueprint/BlueprintTexture.java | 5 +- .../api/data/blueprint/ModelBlueprint.java | 39 ++--- .../api/data/blueprint/ModelBoundingBox.java | 5 +- .../model/api/data/raw/KeyframeChannel.java | 5 +- .../model/api/data/raw/ModelAnimation.java | 5 +- .../model/api/data/raw/ModelAnimator.java | 5 +- .../model/api/data/raw/ModelData.java | 7 +- .../model/api/data/raw/ModelDatapoint.java | 5 +- .../model/api/data/raw/ModelElement.java | 74 ++++++++- .../model/api/data/raw/ModelFace.java | 22 ++- .../model/api/data/raw/ModelGroup.java | 5 +- .../model/api/data/raw/ModelKeyframe.java | 5 +- .../model/api/data/raw/ModelLoadContext.java | 5 +- .../model/api/data/raw/ModelLoadResult.java | 5 +- .../model/api/data/raw/ModelMeta.java | 5 +- .../model/api/data/raw/ModelOutliner.java | 5 +- .../model/api/data/raw/ModelPlaceholder.java | 5 +- .../model/api/data/raw/ModelResolution.java | 5 +- .../model/api/data/raw/ModelTexture.java | 5 +- .../toxicity/model/api/data/raw/ModelUV.java | 12 +- .../api/data/renderer/ModelRenderer.java | 5 +- .../api/data/renderer/RenderPipeline.java | 5 +- .../model/api/data/renderer/RenderSource.java | 5 +- .../api/data/renderer/RendererGroup.java | 5 +- .../toxicity/model/api/entity/BaseEntity.java | 5 +- .../toxicity/model/api/entity/BasePlayer.java | 5 +- .../model/api/event/AnimationSignalEvent.java | 5 +- .../model/api/event/CancellableEvent.java | 5 +- .../model/api/event/CloseTrackerEvent.java | 5 +- .../api/event/CreateDummyTrackerEvent.java | 5 +- .../api/event/CreateEntityTrackerEvent.java | 5 +- .../api/event/CreatePlayerSkinEvent.java | 5 +- .../model/api/event/DismountModelEvent.java | 5 +- .../model/api/event/ModelAssetsEvent.java | 5 +- .../model/api/event/ModelDamageSource.java | 5 +- .../api/event/ModelDespawnAtPlayerEvent.java | 5 +- .../toxicity/model/api/event/ModelEvent.java | 5 +- .../api/event/ModelEventApplication.java | 5 +- .../model/api/event/ModelEventListener.java | 5 +- .../model/api/event/ModelImportedEvent.java | 5 +- .../api/event/ModelSpawnAtPlayerEvent.java | 5 +- .../model/api/event/MountModelEvent.java | 5 +- .../api/event/PlayerHideTrackerEvent.java | 5 +- .../api/event/PlayerPerAnimationEndEvent.java | 5 +- .../event/PlayerPerAnimationStartEvent.java | 5 +- .../api/event/PlayerShowTrackerEvent.java | 5 +- .../model/api/event/PluginEndReloadEvent.java | 5 +- .../api/event/PluginStartReloadEvent.java | 5 +- .../api/event/RemovePlayerSkinEvent.java | 5 +- .../api/event/hitbox/HitBoxCreateEvent.java | 5 +- .../api/event/hitbox/HitBoxDamagedEvent.java | 5 +- .../api/event/hitbox/HitBoxDismountEvent.java | 5 +- .../model/api/event/hitbox/HitBoxEvent.java | 5 +- .../event/hitbox/HitBoxInteractAtEvent.java | 5 +- .../api/event/hitbox/HitBoxInteractEvent.java | 5 +- .../api/event/hitbox/HitBoxMountEvent.java | 5 +- .../api/event/hitbox/HitBoxRemoveEvent.java | 5 +- .../model/api/manager/ModelManager.java | 5 +- .../model/api/manager/PlayerManager.java | 5 +- .../model/api/manager/ProfileManager.java | 5 +- .../model/api/manager/ReloadInfo.java | 5 +- .../model/api/manager/ScriptManager.java | 5 +- .../model/api/manager/SkinManager.java | 5 +- .../model/api/mount/MountController.java | 5 +- .../model/api/mount/MountControllers.java | 5 +- .../model/api/nms/DisplayTransformer.java | 5 +- .../kr/toxicity/model/api/nms/HitBox.java | 5 +- .../model/api/nms/HitBoxListener.java | 5 +- .../toxicity/model/api/nms/Identifiable.java | 5 +- .../toxicity/model/api/nms/ModelDisplay.java | 5 +- .../model/api/nms/ModelInteractionHand.java | 5 +- .../toxicity/model/api/nms/ModelNametag.java | 5 +- .../java/kr/toxicity/model/api/nms/NMS.java | 5 +- .../kr/toxicity/model/api/nms/NMSVersion.java | 28 ++-- .../toxicity/model/api/nms/PacketBundler.java | 5 +- .../model/api/nms/PlayerChannelHandler.java | 5 +- .../kr/toxicity/model/api/nms/Profiled.java | 5 +- .../toxicity/model/api/pack/PackAssets.java | 5 +- .../toxicity/model/api/pack/PackBuilder.java | 5 +- .../model/api/pack/PackBuiltInAssets.java | 99 ++++++++++++ .../kr/toxicity/model/api/pack/PackByte.java | 5 +- .../kr/toxicity/model/api/pack/PackMeta.java | 8 +- .../model/api/pack/PackNamespace.java | 5 +- .../model/api/pack/PackObfuscator.java | 5 +- .../toxicity/model/api/pack/PackOverlay.java | 5 +- .../kr/toxicity/model/api/pack/PackPath.java | 5 +- .../toxicity/model/api/pack/PackResource.java | 5 +- .../toxicity/model/api/pack/PackResult.java | 5 +- .../toxicity/model/api/pack/PackZipper.java | 12 +- .../model/api/platform/PlatformAdapter.java | 5 +- .../model/api/platform/PlatformBillboard.java | 5 +- .../model/api/platform/PlatformEntity.java | 5 +- .../model/api/platform/PlatformItemStack.java | 5 +- .../api/platform/PlatformItemTransform.java | 5 +- .../api/platform/PlatformLivingEntity.java | 5 +- .../model/api/platform/PlatformLocation.java | 5 +- .../model/api/platform/PlatformNamespace.java | 5 +- .../api/platform/PlatformOfflinePlayer.java | 5 +- .../model/api/platform/PlatformPlayer.java | 5 +- .../api/platform/PlatformRegionHolder.java | 5 +- .../model/api/platform/PlatformWorld.java | 5 +- .../toxicity/model/api/player/PlayerLimb.java | 5 +- .../model/api/player/PlayerSkinParts.java | 5 +- .../model/api/profile/ModelProfile.java | 5 +- .../model/api/profile/ModelProfileInfo.java | 5 +- .../model/api/profile/ModelProfileSkin.java | 5 +- .../api/profile/ModelProfileSupplier.java | 5 +- .../model/api/scheduler/ModelScheduler.java | 5 +- .../model/api/scheduler/ModelTask.java | 5 +- .../model/api/script/AnimationScript.java | 5 +- .../model/api/script/BlueprintScript.java | 5 +- .../model/api/script/ScriptBuilder.java | 5 +- .../toxicity/model/api/script/TimeScript.java | 5 +- .../kr/toxicity/model/api/skin/SkinData.java | 5 +- .../model/api/tracker/DummyTracker.java | 5 +- .../model/api/tracker/EntityBodyRotator.java | 5 +- .../model/api/tracker/EntityHideOption.java | 5 +- .../model/api/tracker/EntityTracker.java | 5 +- .../api/tracker/EntityTrackerRegistry.java | 5 +- .../model/api/tracker/ModelRotation.java | 5 +- .../model/api/tracker/ModelRotator.java | 5 +- .../model/api/tracker/ModelScaler.java | 5 +- .../model/api/tracker/PlayerTracker.java | 5 +- .../toxicity/model/api/tracker/Tracker.java | 5 +- .../model/api/tracker/TrackerAnimation.java | 5 +- .../api/tracker/TrackerBuiltInAnimation.java | 5 +- .../model/api/tracker/TrackerData.java | 5 +- .../api/tracker/TrackerExtraAnimation.java | 5 +- .../model/api/tracker/TrackerModifier.java | 5 +- .../api/tracker/TrackerUpdateAction.java | 5 +- .../model/api/util/CollectionUtil.java | 17 +- .../toxicity/model/api/util/EntityUtil.java | 5 +- .../kr/toxicity/model/api/util/EventUtil.java | 5 +- .../toxicity/model/api/util/FunctionUtil.java | 5 +- .../kr/toxicity/model/api/util/HttpUtil.java | 5 +- .../model/api/util/InterpolationUtil.java | 5 +- .../kr/toxicity/model/api/util/LogUtil.java | 5 +- .../kr/toxicity/model/api/util/MathUtil.java | 5 +- .../kr/toxicity/model/api/util/PackUtil.java | 5 +- .../model/api/util/ReflectionUtil.java | 5 +- .../model/api/util/TransformedItemStack.java | 5 +- .../api/util/collection/PriorityMap.java | 65 ++++++++ .../collection/SingletonSequencedSet.java | 5 +- .../api/util/function/BonePredicate.java | 5 +- .../function/BooleanConstantSupplier.java | 5 +- .../function/Float2FloatConstantFunction.java | 5 +- .../util/function/Float2FloatFunction.java | 5 +- .../util/function/FloatConstantFunction.java | 5 +- .../util/function/FloatConstantSupplier.java | 5 +- .../api/util/function/FloatFunction.java | 5 +- .../api/util/function/FloatSupplier.java | 5 +- .../util/interpolator/VectorInterpolator.java | 5 +- .../model/api/util/json/JsonArrayBuilder.java | 39 +++++ .../api/util/json/JsonObjectBuilder.java | 56 ++++++- .../api/util/lazy/LazyFloatProvider.java | 5 +- .../model/api/util/lock/DuplexLock.java | 5 +- .../model/api/util/lock/SingleLock.java | 5 +- .../model/api/version/MinecraftVersion.java | 19 ++- build.gradle.kts | 6 +- buildSrc/build.gradle.kts | 2 +- .../main/kotlin/bukkit-conventions.gradle.kts | 2 +- .../kotlin/standard-conventions.gradle.kts | 11 +- .../bukkit/AbstractBetterModelPlugin.java | 5 +- .../model/bukkit/BetterModelLibrary.java | 5 +- .../bukkit/BetterModelLibraryManager.java | 5 +- .../model/bukkit/BetterModelConfigImpl.kt | 5 +- .../model/bukkit/BetterModelPlugin.kt | 5 +- .../model/bukkit/BetterModelProperties.kt | 5 +- .../model/bukkit/BukkitModelEventBusImpl.kt | 5 +- .../model/bukkit/audience/AudiencePlayer.kt | 5 +- .../model/bukkit/audience/AudienceSender.kt | 5 +- .../model/bukkit/audience/BukkitAudience.kt | 5 +- .../toxicity/model/bukkit/command/Commands.kt | 5 +- .../bukkit/compatibility/Compatibility.kt | 5 +- .../citizens/CitizensCompatibility.kt | 5 +- .../citizens/command/AnimateCommand.kt | 5 +- .../citizens/command/LimbCommand.kt | 5 +- .../citizens/command/ModelCommand.kt | 5 +- .../citizens/trait/ModelTrait.kt | 5 +- .../mythicmobs/MythicMobsCompatibility.kt | 5 +- .../mythicmobs/MythicMobsValue.kt | 5 +- .../condition/ModelHasPassengerCondition.kt | 5 +- .../mechanic/AbstractSkillMechanic.kt | 5 +- .../mythicmobs/mechanic/BillboardMechanic.kt | 5 +- .../mythicmobs/mechanic/BindHitBoxMechanic.kt | 5 +- .../mechanic/BodyRotationMechanic.kt | 5 +- .../mythicmobs/mechanic/BrightnessMechanic.kt | 5 +- .../mythicmobs/mechanic/ChangePartMechanic.kt | 5 +- .../mechanic/DefaultStateMechanic.kt | 5 +- .../mechanic/DismountAllModelMechanic.kt | 5 +- .../mechanic/DismountModelMechanic.kt | 5 +- .../mythicmobs/mechanic/EnchantMechanic.kt | 5 +- .../mythicmobs/mechanic/GlowMechanic.kt | 5 +- .../mythicmobs/mechanic/LockModelMechanic.kt | 5 +- .../mythicmobs/mechanic/ModelMechanic.kt | 5 +- .../mythicmobs/mechanic/MountModelMechanic.kt | 5 +- .../mythicmobs/mechanic/PairModelMechanic.kt | 5 +- .../mechanic/PartVisibilityMechanic.kt | 5 +- .../mechanic/PlayLimbAnimMechanic.kt | 5 +- .../mythicmobs/mechanic/RemapModelMechanic.kt | 5 +- .../mythicmobs/mechanic/StateMechanic.kt | 5 +- .../mythicmobs/mechanic/TintMechanic.kt | 5 +- .../mythicmobs/targeter/ModelPartTargeter.kt | 5 +- .../compatibility/nexo/NexoCompatibility.kt | 5 +- .../SkinsRestorerCompatibility.kt | 5 +- .../configuration/PluginConfiguration.kt | 5 +- .../bukkit/manager/CompatibilityManager.kt | 5 +- .../model/bukkit/manager/EntityManager.kt | 5 +- .../model/bukkit/manager/PlayerManagerImpl.kt | 5 +- .../model/bukkit/scheduler/BukkitScheduler.kt | 5 +- .../model/bukkit/scheduler/PaperScheduler.kt | 5 +- .../model/bukkit/util/BukkitWrappers.kt | 5 +- .../kr/toxicity/model/bukkit/util/Entities.kt | 5 +- .../kr/toxicity/model/bukkit/util/Events.kt | 5 +- .../kr/toxicity/model/bukkit/util/Plugins.kt | 5 +- .../kr/toxicity/model/bukkit/util/Senders.kt | 5 +- .../kr/toxicity/model/bukkit/util/Yamls.kt | 5 +- .../model/BetterModelPlatformImpl.java | 5 +- .../model/BetterModelEvaluatorImpl.kt | 7 +- .../toxicity/model/BetterModelEventBusImpl.kt | 5 +- .../model/command/CommandBuildContext.kt | 5 +- .../toxicity/model/command/CommandBuilder.kt | 5 +- .../model/command/CommandExtensions.kt | 5 +- .../kr/toxicity/model/command/CommandLike.kt | 5 +- .../kr/toxicity/model/manager/ArmorManager.kt | 5 +- .../toxicity/model/manager/GlobalManager.kt | 7 +- .../model/manager/ModelManagerImpl.kt | 45 +++--- .../model/manager/ProfileManagerImpl.kt | 5 +- .../toxicity/model/manager/ReloadPipeline.kt | 5 +- .../model/manager/ScriptManagerImpl.kt | 5 +- .../toxicity/model/manager/SkinManagerImpl.kt | 5 +- .../model/manager/debug/BossBarIndicator.kt | 7 +- .../model/manager/debug/ReloadIndicator.kt | 7 +- .../DefaultHttpModelProfileSupplier.kt | 5 +- .../model/profile/HttpModelProfileSupplier.kt | 5 +- .../toxicity/model/script/BrightnessScript.kt | 5 +- .../toxicity/model/script/ChangePartScript.kt | 7 +- .../kr/toxicity/model/script/EnchantScript.kt | 7 +- .../model/script/PartVisibilityScript.kt | 7 +- .../kr/toxicity/model/script/RemapScript.kt | 5 +- .../kr/toxicity/model/script/TintScript.kt | 7 +- .../kotlin/kr/toxicity/model/util/Buffers.kt | 7 +- .../kr/toxicity/model/util/Collections.kt | 38 ++++- .../kotlin/kr/toxicity/model/util/Events.kt | 5 +- .../kotlin/kr/toxicity/model/util/Files.kt | 5 +- .../kr/toxicity/model/util/Functions.kt | 5 +- .../kotlin/kr/toxicity/model/util/Gsons.kt | 5 +- .../kr/toxicity/model/util/Indicators.kt | 5 +- .../kotlin/kr/toxicity/model/util/Packs.kt | 5 +- .../kr/toxicity/model/util/Platforms.kt | 5 +- .../kotlin/kr/toxicity/model/util/Scripts.kt | 7 +- .../kotlin/kr/toxicity/model/util/Senders.kt | 5 +- gradle.properties | 5 +- gradle/libs.versions.toml | 10 +- .../bukkit/nms/v1_21_R1/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R1/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R1/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R1/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R1/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R1/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R1/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R1/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R1/PacketBundlers.kt | 5 +- .../model/bukkit/nms/v1_21_R1/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R1/TypeAliases.kt | 5 +- .../bukkit/nms/v1_21_R3/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R3/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R3/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R3/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R3/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R3/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R3/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R3/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R3/PacketBundlers.kt | 5 +- .../bukkit/nms/v1_21_R3/PlayerArmorImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R3/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R3/TypeAliases.kt | 5 +- .../bukkit/nms/v1_21_R4/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R4/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R4/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R4/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R4/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R4/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R4/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R4/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R4/PacketBundlers.kt | 5 +- .../bukkit/nms/v1_21_R4/PlayerArmorImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R4/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R4/TypeAliases.kt | 5 +- .../bukkit/nms/v1_21_R5/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R5/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R5/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R5/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R5/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R5/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R5/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R5/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R5/PacketBundlers.kt | 5 +- .../bukkit/nms/v1_21_R5/PlayerArmorImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R5/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R5/TypeAliases.kt | 5 +- .../bukkit/nms/v1_21_R6/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R6/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R6/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R6/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R6/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R6/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R6/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R6/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R6/PacketBundlers.kt | 5 +- .../bukkit/nms/v1_21_R6/PlayerArmorImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R6/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R6/TypeAliases.kt | 5 +- .../bukkit/nms/v1_21_R7/AbstractHitBox.java | 5 +- .../bukkit/nms/v1_21_R7/BaseEntityImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/BasePlayerImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/BukkitWrappers.kt | 5 +- .../model/bukkit/nms/v1_21_R7/EntityData.kt | 5 +- .../model/bukkit/nms/v1_21_R7/Functions.kt | 5 +- .../model/bukkit/nms/v1_21_R7/HitBoxImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/HitBoxInteraction.kt | 5 +- .../nms/v1_21_R7/ModelDamageSourceImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/ModelDisplayImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/ModelGameProfile.kt | 5 +- .../bukkit/nms/v1_21_R7/ModelNametagImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R7/NMSImpl.kt | 5 +- .../bukkit/nms/v1_21_R7/PacketBundlers.kt | 5 +- .../bukkit/nms/v1_21_R7/PlayerArmorImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R7/ProfiledImpl.kt | 5 +- .../model/bukkit/nms/v1_21_R7/TypeAliases.kt | 5 +- platform/fabric/build.gradle.kts | 33 ++-- .../model/api/fabric/BetterModelFabric.java | 5 +- .../api/fabric/entity/BaseFabricEntity.java | 5 +- .../api/fabric/entity/BaseFabricPlayer.java | 5 +- .../api/fabric/platform/FabricAdapter.java | 5 +- .../api/fabric/platform/FabricEntity.java | 5 +- .../api/fabric/platform/FabricItemStack.java | 5 +- .../fabric/platform/FabricLivingEntity.java | 5 +- .../api/fabric/platform/FabricLocation.java | 5 +- .../fabric/platform/FabricOfflinePlayer.java | 5 +- .../api/fabric/platform/FabricPlayer.java | 5 +- .../fabric/platform/FabricRegionHolder.java | 5 +- .../api/fabric/platform/FabricWorld.java | 5 +- .../scheduler/FabricModelScheduler.java | 5 +- .../fabric/entity/AbstractArmorStand.java | 5 +- .../model/impl/fabric/entity/EntityHook.java | 5 +- .../network/BetterModelBundlePacket.java | 5 +- .../toxicity/model/mixin/AvatarAccessor.java | 5 +- .../mixin/ClientboundBundlePacketMixin.java | 5 +- .../model/mixin/ConnectionAccessor.java | 5 +- .../toxicity/model/mixin/DisplayAccessor.java | 5 +- .../toxicity/model/mixin/EntityAccessor.java | 5 +- .../kr/toxicity/model/mixin/EntityMixin.java | 5 +- .../model/mixin/ItemDisplayAccessor.java | 5 +- .../model/mixin/LivingEntityMixin.java | 5 +- .../kr/toxicity/model/mixin/MobAccessor.java | 5 +- ...erverCommonPacketListenerImplAccessor.java | 5 +- .../ServerLevelEntityCallbacksMixin.java | 5 +- .../mixin/SynchedEntityDataAccessor.java | 5 +- .../impl/fabric/BetterModelFabricImpl.kt | 5 +- .../impl/fabric/BetterModelLoggerImpl.kt | 5 +- .../model/impl/fabric/BetterModelNMSImpl.kt | 7 +- .../toxicity/model/impl/fabric/Constants.kt | 5 +- .../kr/toxicity/model/impl/fabric/Entities.kt | 4 +- .../model/impl/fabric/FabricWrappers.kt | 5 +- .../toxicity/model/impl/fabric/Functions.kt | 5 +- .../impl/fabric/armor/PlayerArmorImpl.kt | 5 +- .../attachment/BetterModelAttachments.kt | 4 +- .../fabric/audience/AudienceCommandSource.kt | 5 +- .../impl/fabric/audience/AudiencePlayer.kt | 5 +- .../fabric/audience/AudienceSourceStack.kt | 5 +- .../model/impl/fabric/chat/Components.kt | 5 +- .../model/impl/fabric/command/Commands.kt | 5 +- .../fabric/config/BetterModelConfigImpl.kt | 5 +- .../fabric/entity/BaseFabricEntityImpl.kt | 5 +- .../fabric/entity/BaseFabricPlayerImpl.kt | 5 +- .../fabric/entity/DisplayTransformerImpl.kt | 5 +- .../impl/fabric/entity/HitBoxEntityImpl.kt | 5 +- .../fabric/entity/InteractionEntityImpl.kt | 5 +- .../fabric/entity/ModelDisplayEntityImpl.kt | 5 +- .../impl/fabric/entity/ModelNametagImpl.kt | 5 +- .../fabric/entity/PlayerChannelHandlerImpl.kt | 5 +- .../model/impl/fabric/entity/ProfiledImpl.kt | 5 +- .../impl/fabric/entity/TransformationData.kt | 5 +- .../events/ServerEntityDismountCallback.kt | 5 +- .../events/ServerLivingEntityJumpCallback.kt | 5 +- .../events/ServerMobEffectLoadCallback.kt | 5 +- .../events/ServerMobEffectUnloadCallback.kt | 5 +- .../impl/fabric/manager/EntityManager.kt | 5 +- .../impl/fabric/manager/PlayerManagerImpl.kt | 5 +- .../model/impl/fabric/manager/Syncers.kt | 5 +- .../impl/fabric/network/PacketBundlers.kt | 5 +- .../model/impl/fabric/network/Packets.kt | 5 +- .../impl/fabric/profile/ModelProfileImpl.kt | 5 +- .../scheduler/FabricModelSchedulerImpl.kt | 5 +- .../model/impl/fabric/world/Chunks.kt | 4 +- .../damagesource/ModelDamageSourceImpl.kt | 5 +- .../kotlin/kr/toxicity/model/test/RollTest.kt | 5 +- platform/paper/build.gradle.kts | 13 +- .../model/paper/BetterModelLoader.java | 5 +- .../toxicity/model/paper/BetterModelPaper.kt | 5 +- purpur/build.gradle.kts | 3 +- .../model/bukkit/purpur/PurpurHook.kt | 5 +- settings.gradle.kts | 30 ++-- .../toxicity/model/test/BetterModelTest.java | 5 +- .../kr/toxicity/model/test/FightTester.java | 5 +- .../kr/toxicity/model/test/ModelTester.java | 5 +- .../kr/toxicity/model/test/RollTester.java | 5 +- 497 files changed, 2245 insertions(+), 1137 deletions(-) create mode 100644 api/src/main/java/kr/toxicity/model/api/data/Float2.java create mode 100644 api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java create mode 100644 api/src/main/java/kr/toxicity/model/api/pack/PackBuiltInAssets.java create mode 100644 api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java create mode 100644 api/src/main/java/kr/toxicity/model/api/util/json/JsonArrayBuilder.java diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 42c1ab6ac..d6aaeac20 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -2,7 +2,7 @@ name: Package plugin on: push: - branches: [ "master", "v2" ] + branches: [ "master", "v2", "v3" ] permissions: contents: read diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index e3f578994..7286f48a0 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -2,7 +2,7 @@ name: PR Test on: pull_request: - branches: [ "dev", "v2-dev" ] + branches: [ "dev", "v2-dev", "v3-dev" ] permissions: contents: read diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b26705be3..b3771c9a5 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -2,7 +2,7 @@ name: Publish plugin on: push: - branches: [ "master", "v2" ] + branches: [ "master", "v2", "v3" ] permissions: contents: read diff --git a/LICENSE_HEADER b/LICENSE_HEADER index 20e7517cd..1969cde02 100644 --- a/LICENSE_HEADER +++ b/LICENSE_HEADER @@ -1,4 +1,6 @@ This source file is part of BetterModel. -Copyright (c) 2024–2026 toxicity188 +Copyright (c) ${CREATION_YEAR} toxicity188 Licensed under the MIT License. See LICENSE.md file for full license text. + +#year_selection file diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BetterModelBukkit.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BetterModelBukkit.java index 9ee6bfc07..e8f577eec 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BetterModelBukkit.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BetterModelBukkit.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit; import kr.toxicity.model.api.BetterModel; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BukkitModelEventBus.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BukkitModelEventBus.java index cc5cdb264..087f270f4 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BukkitModelEventBus.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/BukkitModelEventBus.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit; import kr.toxicity.model.api.BetterModelEventBus; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitEntity.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitEntity.java index db9c4237b..3d7cca24d 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitEntity.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.entity; import kr.toxicity.model.api.bukkit.platform.BukkitAdapter; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitPlayer.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitPlayer.java index cfd2dafcb..851bcbdaf 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitPlayer.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/entity/BaseBukkitPlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.entity; import kr.toxicity.model.api.bukkit.platform.BukkitPlayer; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BetterModelBukkitEvent.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BetterModelBukkitEvent.java index d2661f771..2670850c2 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BetterModelBukkitEvent.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BetterModelBukkitEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.event; import kr.toxicity.model.api.event.ModelEvent; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BukkitEventApplication.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BukkitEventApplication.java index 14fb61c97..1580b411c 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BukkitEventApplication.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/event/BukkitEventApplication.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.event; import kr.toxicity.model.api.event.ModelEventApplication; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitAdapter.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitAdapter.java index 76e31eceb..53ee1b51d 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitAdapter.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitAdapter.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.bukkit.BetterModelBukkit; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitEntity.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitEntity.java index 5e290c42b..04021ff8b 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitEntity.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.platform.PlatformEntity; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java index b7b83b8fc..37f79a932 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.BetterModel; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLivingEntity.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLivingEntity.java index f12b11a8e..36fdc787c 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLivingEntity.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLivingEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.platform.PlatformLivingEntity; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLocation.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLocation.java index 1255cf936..4cd17c214 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLocation.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitLocation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.bukkit.BetterModelBukkit; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitOfflinePlayer.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitOfflinePlayer.java index 304656bd6..62c7e975f 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitOfflinePlayer.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitOfflinePlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.platform.PlatformOfflinePlayer; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitPlayer.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitPlayer.java index 4a4d269ca..5cf9ddcbd 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitPlayer.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitPlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitWorld.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitWorld.java index de2315565..9760a647e 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitWorld.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitWorld.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.platform; import kr.toxicity.model.api.platform.PlatformWorld; diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/scheduler/BukkitModelScheduler.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/scheduler/BukkitModelScheduler.java index 705ab1a15..ce785aeb8 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/scheduler/BukkitModelScheduler.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/scheduler/BukkitModelScheduler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bukkit.scheduler; import kr.toxicity.model.api.scheduler.ModelScheduler; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModel.java b/api/src/main/java/kr/toxicity/model/api/BetterModel.java index 210f5ee66..722444ba1 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModel.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModel.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import kr.toxicity.model.api.data.renderer.ModelRenderer; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelConfig.java b/api/src/main/java/kr/toxicity/model/api/BetterModelConfig.java index 5504e812a..9f8fb6254 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelConfig.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelConfig.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import kr.toxicity.model.api.config.DebugConfig; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelEvaluator.java b/api/src/main/java/kr/toxicity/model/api/BetterModelEvaluator.java index cf6f48381..620fa765b 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelEvaluator.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelEvaluator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import kr.toxicity.model.api.util.function.Float2FloatFunction; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelEventBus.java b/api/src/main/java/kr/toxicity/model/api/BetterModelEventBus.java index 9ac3c10ca..87ffb77ca 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelEventBus.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelEventBus.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import kr.toxicity.model.api.event.ModelEvent; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelLogger.java b/api/src/main/java/kr/toxicity/model/api/BetterModelLogger.java index 6814b4147..9be251860 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelLogger.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelLogger.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import net.kyori.adventure.text.Component; diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java b/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java index 46d73a7fe..b9c94838d 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api; import com.vdurmont.semver4j.Semver; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationIterator.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationIterator.java index 0d65c7f89..ae013695d 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationIterator.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationIterator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationKeyframe.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationKeyframe.java index ee7956497..d8517f5ee 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationKeyframe.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationKeyframe.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import kr.toxicity.model.api.bone.BoneMovement; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationModifier.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationModifier.java index 318ed0b01..6dabae6ae 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationModifier.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationModifier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import kr.toxicity.model.api.platform.PlatformPlayer; @@ -20,6 +21,7 @@ * @param predicate predicate * @param start start lerp * @param end end lerp + * @param priority priority * @param type animation type * @param speed speed modifier * @param override override @@ -29,6 +31,7 @@ public record AnimationModifier( @Nullable BooleanSupplier predicate, int start, int end, + int priority, @Nullable AnimationIterator.Type type, @Nullable FloatSupplier speed, @Nullable Boolean override, @@ -76,6 +79,7 @@ public static final class Builder { private BooleanSupplier predicate = null; private int start = 1; private int end = 0; + private int priority = 0; private AnimationIterator.Type type = null; private FloatSupplier speed = null; private Boolean override = null; @@ -117,6 +121,16 @@ private Builder() { return this; } + /** + * Sets the priority of this modifier + * @param priority priority + * @return self + */ + public @NotNull Builder priority(int priority) { + this.priority = priority; + return this; + } + /** * Sets the animation type of this modifier * @param type animation type @@ -192,6 +206,7 @@ private Builder() { predicate, start, end, + priority, type, speed, override, @@ -266,7 +281,7 @@ public AnimationModifier(int start, int end, @Nullable AnimationIterator.Type ty * @param speed speed */ public AnimationModifier(@Nullable BooleanSupplier predicate, int start, int end, @Nullable AnimationIterator.Type type, @Nullable FloatSupplier speed) { - this(predicate, start, end, type, speed, null, null); + this(predicate, start, end, 0, type, speed, null, null); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationOverrideState.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationOverrideState.java index 871be165b..d7f5722c2 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationOverrideState.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationOverrideState.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; public enum AnimationOverrideState { diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationProgress.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationProgress.java index 78b9c3252..fb9083b47 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationProgress.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationProgress.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import kr.toxicity.model.api.bone.BoneMovement; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index 17f500c3f..3e09f7177 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import kr.toxicity.model.api.tracker.Tracker; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/RunningAnimation.java b/api/src/main/java/kr/toxicity/model/api/animation/RunningAnimation.java index 30e600698..a5212888a 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/RunningAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/RunningAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import org.jetbrains.annotations.NotNull; @@ -14,4 +15,4 @@ * @param type type */ public record RunningAnimation(@NotNull String name, @NotNull AnimationIterator.Type type) { -} \ No newline at end of file +} diff --git a/api/src/main/java/kr/toxicity/model/api/animation/Timed.java b/api/src/main/java/kr/toxicity/model/api/animation/Timed.java index 93747f7ce..535e9dc23 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/Timed.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/Timed.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/TimedStorage.java b/api/src/main/java/kr/toxicity/model/api/animation/TimedStorage.java index b69322bd3..99ec1543c 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/TimedStorage.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/TimedStorage.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/animation/VectorPoint.java b/api/src/main/java/kr/toxicity/model/api/animation/VectorPoint.java index 3e43eb5f9..30a9fe985 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/VectorPoint.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/VectorPoint.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.animation; import kr.toxicity.model.api.util.function.FloatFunction; diff --git a/api/src/main/java/kr/toxicity/model/api/armor/ArmorItem.java b/api/src/main/java/kr/toxicity/model/api/armor/ArmorItem.java index 8c4a1d853..f323031c9 100644 --- a/api/src/main/java/kr/toxicity/model/api/armor/ArmorItem.java +++ b/api/src/main/java/kr/toxicity/model/api/armor/ArmorItem.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.armor; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/armor/PlayerArmor.java b/api/src/main/java/kr/toxicity/model/api/armor/PlayerArmor.java index 80092f8ec..23e103da9 100644 --- a/api/src/main/java/kr/toxicity/model/api/armor/PlayerArmor.java +++ b/api/src/main/java/kr/toxicity/model/api/armor/PlayerArmor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.armor; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java index 856e66735..0b209393d 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventDispatcher.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import kr.toxicity.model.api.nms.HitBoxListener; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventHandler.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventHandler.java index 5bce21539..ecf1d8ce2 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneEventHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneEventHandler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneIKSolver.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneIKSolver.java index 5b92f3c9c..48c8b101a 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneIKSolver.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneIKSolver.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneItemMapper.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneItemMapper.java index f9aaf3100..1d09d5e63 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneItemMapper.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneItemMapper.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import kr.toxicity.model.api.data.renderer.RenderSource; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneMovement.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneMovement.java index 750c515f4..5046ba525 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneMovement.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneMovement.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import kr.toxicity.model.api.util.InterpolationUtil; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java index 365fe215d..5ddc0df72 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneName.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import com.google.gson.JsonDeserializer; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BonePosition.java b/api/src/main/java/kr/toxicity/model/api/bone/BonePosition.java index df4965665..840ac3fa4 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BonePosition.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BonePosition.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneRenderContext.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneRenderContext.java index e758e90d6..02bb3b603 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneRenderContext.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneRenderContext.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTag.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTag.java index fc192b75d..0dd3bf729 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTag.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTag.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java index 0d2e1fbcb..81aea9906 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import it.unimi.dsi.fastutil.objects.*; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java index 103b432be..61ebd163e 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java index 91fc2a5ec..cbf71bdf8 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.bone; import it.unimi.dsi.fastutil.ints.Int2ObjectMap; diff --git a/api/src/main/java/kr/toxicity/model/api/config/DebugConfig.java b/api/src/main/java/kr/toxicity/model/api/config/DebugConfig.java index 904e2e36a..d83894979 100644 --- a/api/src/main/java/kr/toxicity/model/api/config/DebugConfig.java +++ b/api/src/main/java/kr/toxicity/model/api/config/DebugConfig.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.config; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/kr/toxicity/model/api/config/IndicatorConfig.java b/api/src/main/java/kr/toxicity/model/api/config/IndicatorConfig.java index ffb50127f..7403b3293 100644 --- a/api/src/main/java/kr/toxicity/model/api/config/IndicatorConfig.java +++ b/api/src/main/java/kr/toxicity/model/api/config/IndicatorConfig.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.config; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/kr/toxicity/model/api/config/ModuleConfig.java b/api/src/main/java/kr/toxicity/model/api/config/ModuleConfig.java index 89db55d6a..5cd6b8b00 100644 --- a/api/src/main/java/kr/toxicity/model/api/config/ModuleConfig.java +++ b/api/src/main/java/kr/toxicity/model/api/config/ModuleConfig.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.config; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/config/PackConfig.java b/api/src/main/java/kr/toxicity/model/api/config/PackConfig.java index 575c4be7e..8a47112d1 100644 --- a/api/src/main/java/kr/toxicity/model/api/config/PackConfig.java +++ b/api/src/main/java/kr/toxicity/model/api/config/PackConfig.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.config; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float2.java b/api/src/main/java/kr/toxicity/model/api/data/Float2.java new file mode 100644 index 000000000..40f0f59b5 --- /dev/null +++ b/api/src/main/java/kr/toxicity/model/api/data/Float2.java @@ -0,0 +1,30 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.api.data; + +import com.google.gson.JsonDeserializer; +import org.jetbrains.annotations.NotNull; +import org.joml.Vector2f; + +public record Float2( + float x, + float y +) { + + public static final JsonDeserializer PARSER = (json, _, _) -> { + var array = json.getAsJsonArray(); + return new Float2( + array.get(0).getAsFloat(), + array.get(1).getAsFloat() + ); + }; + + public @NotNull Vector2f toVector() { + return new Vector2f(x, y); + } +} diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float3.java b/api/src/main/java/kr/toxicity/model/api/data/Float3.java index c6b977216..360474799 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float3.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float3.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data; import com.google.gson.JsonArray; @@ -43,6 +44,10 @@ public Float3(float value) { */ public static final Float3 ZERO = new Float3(0, 0, 0); + public static final Float3 MESH_TRIANGLE_FROM = new Float3(-8, 0, 0); + + public static final Float3 MESH_TRIANGLE_TO = new Float3(0, 8, 0); + /** * Parser */ @@ -158,6 +163,24 @@ public Float3(float value) { return array; } + public @NotNull Quaternionf toQuaternionZYX() { + return new Quaternionf() + .rotateZYX( + z * MathUtil.DEGREES_TO_RADIANS, + y * MathUtil.DEGREES_TO_RADIANS, + x * MathUtil.DEGREES_TO_RADIANS + ); + } + + public @NotNull Quaternionf toQuaternionXYZ() { + return new Quaternionf() + .rotateXYZ( + x * MathUtil.DEGREES_TO_RADIANS, + y * MathUtil.DEGREES_TO_RADIANS, + z * MathUtil.DEGREES_TO_RADIANS + ); + } + /** * Converts floats to vector. * @return vector diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float4.java b/api/src/main/java/kr/toxicity/model/api/data/Float4.java index a7b0efe7a..20c992975 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float4.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float4.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data; import com.google.gson.JsonArray; @@ -41,6 +42,8 @@ public record Float4( ); }; + public static final Float4 MAX_UV = new Float4(0, 0, 16, 16); + /** * Divides floats by resolution. * @param resolution model resolution diff --git a/api/src/main/java/kr/toxicity/model/api/data/ModelAsset.java b/api/src/main/java/kr/toxicity/model/api/data/ModelAsset.java index 15463d464..6de0f5311 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/ModelAsset.java +++ b/api/src/main/java/kr/toxicity/model/api/data/ModelAsset.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data; import com.google.gson.JsonParseException; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index 6bcadb36f..b1b174861 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import it.unimi.dsi.fastutil.floats.*; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java index 3c8f41b6d..c00f40ffa 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import kr.toxicity.model.api.animation.*; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java index 2ef158ba7..12a9a48c1 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import kr.toxicity.model.api.animation.*; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java index 67fe65846..1e936bb21 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java @@ -1,14 +1,19 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import com.google.gson.JsonObject; +import io.github.toxicity188.javamesh.MeshBuilder; +import io.github.toxicity188.javamesh.MeshPoint; +import io.github.toxicity188.javamesh.MeshShape; import kr.toxicity.model.api.bone.BoneName; import kr.toxicity.model.api.bone.BoneTags; +import kr.toxicity.model.api.data.Float2; import kr.toxicity.model.api.data.Float3; import kr.toxicity.model.api.data.raw.ModelFace; import kr.toxicity.model.api.pack.PackObfuscator; @@ -36,6 +41,12 @@ */ public sealed interface BlueprintElement { + String MESH_TRIANGLE_SINGLE = "mesh_triangle_single"; + + String MESH_TRIANGLE_DUPLEX = "mesh_triangle_duplex"; + + String MESH_PIXEL = "mesh_pixel"; + /** * Represents an element that acts as a bone in the model's armature. * @@ -120,8 +131,8 @@ public Float3 origin() { return origin.invertXZ(); } - private @NotNull String jsonName(@NotNull ModelBlueprint parent) { - return PackUtil.toPackName(parent.name() + "_" + name.rawName()); + private @NotNull String jsonName(@NotNull BlueprintLoadContext context) { + return PackUtil.toPackName(context.name() + "_" + name.rawName()); } /** @@ -129,28 +140,28 @@ public Float3 origin() { * * @param skipLog whether to skip logging warnings for invalid rotations * @param obfuscator the obfuscator for model and texture names - * @param parent the parent model blueprint + * @param context the load context * @return the generated blueprint JSON, or null if not applicable * @since 1.15.2 */ public @Nullable BlueprintJson buildLegacyJson( boolean skipLog, @NotNull PackObfuscator.Pair obfuscator, - @NotNull ModelBlueprint parent + @NotNull BlueprintLoadContext context ) { Predicate filter = element -> MathUtil.checkValidDegree(element.identifierDegree()); if (!skipLog) filter = filterWithWarning( filter, - element -> "The model " + parent.name() + "'s cube \"" + element.name() + "\" has an invalid rotation which does not supported in legacy client (<=1.21.3) " + element.rotation() + element -> "The model " + context.name() + "'s cube \"" + element.name() + "\" has an invalid rotation which does not supported in legacy client (<=1.21.3) " + element.rotation() ); - return buildJson(-2, 1, scale(), obfuscator, parent, Float3.ZERO, filterIsInstance(children, Cube.class).filter(filter)); + return buildJson(-2, 1, scale(), obfuscator, context, Float3.ZERO, filterIsInstance(children, Cube.class).filter(filter)); } /** * Builds the JSON representation for modern clients. * * @param obfuscator the obfuscator for model and texture names - * @param parent the parent model blueprint + * @param context the load context * @return a list of generated blueprint JSONs, or null if not applicable * @since 1.15.2 */ @@ -158,7 +169,7 @@ public Float3 origin() { @Unmodifiable public List buildModernJson( @NotNull PackObfuscator.Pair obfuscator, - @NotNull ModelBlueprint parent + @NotNull BlueprintLoadContext context ) { var scale = scale(); var list = mapIndexed( @@ -166,35 +177,49 @@ public List buildModernJson( filterIsInstance(children, Cube.class), Cube::identifierDegree ), - (i, entry) -> buildJson(0, i + 1, scale, obfuscator, parent, entry.getKey(), entry.getValue().stream()) + (i, entry) -> buildJson(0, i + 1, scale, obfuscator, context, entry.getKey(), entry.getValue().stream()) ).filter(Objects::nonNull) .toList(); return list.isEmpty() ? null : list; } + public @Nullable JsonObject buildMeshItemModel( + @NotNull BlueprintLoadContext context + ) { + var scale = 1F / scale(); + var meshes = filterIsInstance(children, Mesh.class).toList(); + if (meshes.isEmpty()) return null; + var builder = MeshBuilder.of(context.triangleName()) + .matrixModifier(mat -> mat.scale(scale)) + .image(context.imageByIndex()); + meshes.forEach(mesh -> builder.load(mesh.toShape(origin))); + return builder.toJson(); + } + private @Nullable BlueprintJson buildJson( int tint, int number, float scale, @NotNull PackObfuscator.Pair obfuscator, - @NotNull ModelBlueprint parent, + @NotNull BlueprintLoadContext context, @NotNull Float3 identifier, @NotNull Stream cubes ) { - if (parent.textures().isEmpty()) return null; var cubeElement = cubes .filter(Cube::hasTexture) .toList(); - if (cubeElement.isEmpty()) return null; - return new BlueprintJson(obfuscator.models().obfuscate(jsonName(parent) + "_" + number), () -> JsonObjectBuilder.builder() - .jsonObject("textures", textures -> { - var index = 0; - for (BlueprintTexture texture : parent.textures()) { - textures.property(Integer.toString(index++), texture.packNamespace(obfuscator.textures())); - } - textures.property("particle", parent.textures().getFirst().packNamespace(obfuscator.textures())); - }) - .jsonArray("elements", mapToJson(cubeElement, cube -> cube.buildJson(tint, scale, parent, this, identifier))) + var selectedTextures = cubeElement.stream() + .flatMapToInt(tex -> tex.faces().textureIndex()) + .distinct() + .sorted() + .mapToObj(i -> Map.entry(Integer.toString(i), context.texture(i).packNamespace(obfuscator.textures()))) + .toList(); + if (selectedTextures.isEmpty()) return null; + return new BlueprintJson(obfuscator.models().obfuscate(jsonName(context) + "_" + number), () -> JsonObjectBuilder.builder() + .jsonObject("textures", textures -> textures + .stringProperties(selectedTextures) + .property("particle", selectedTextures.getFirst().getValue())) + .jsonArray("elements", mapToJson(cubeElement, cube -> cube.buildJson(tint, scale, context, this, identifier))) .jsonObject("display", display -> display.jsonObject("fixed", fixed -> { if (!identifier.equals(Float3.ZERO)) { fixed.jsonArray("rotation", identifier.convertToMinecraftDegree().toJson()); @@ -353,11 +378,11 @@ record Cube( private @NotNull JsonObject buildJson( int tint, float scale, - @NotNull ModelBlueprint parent, + @NotNull BlueprintLoadContext parent, @NotNull BlueprintElement.Group group, @NotNull Float3 identifier ) { - var qua = MathUtil.toQuaternion(identifier.toVector()).invert(); + var qua = identifier.toQuaternionZYX().invert(); var centerOrigin = centralize(origin(), group.origin, scale); var groupDelta = deltaPosition(centerOrigin, qua); var inflate = new Float3(inflate() / scale); @@ -373,7 +398,7 @@ record Cube( .plus(Float3.CENTER) .plus(inflate) .toJson()) - .jsonObject("faces", Objects.requireNonNull(faces()).toJson(parent, tint)) + .jsonObject("faces", faces().toJson(parent, tint)) .jsonObject("rotation", Optional.of(rotation().minus(identifier)) .filter(r -> !Float3.ZERO.equals(r)) .map(rot -> { @@ -408,6 +433,11 @@ public float max(@NotNull Float3 origin) { return max; } + @Override + public @NotNull ModelFace faces() { + return Objects.requireNonNull(faces); + } + /** * Checks if this cube has any textures defined. * @@ -433,4 +463,39 @@ public boolean hasTexture() { return rotation; } } + + record Mesh( + @NotNull Float3 origin, + @NotNull Float3 rotation, + @NotNull List faces, + boolean visibility + ) implements BlueprintElement { + + @NotNull + @Unmodifiable + public List toShape(@NotNull Float3 parentOrigin) { + var deltaOrigin = origin().minus(parentOrigin).toVector(); + var pointRotation = rotation().toQuaternionXYZ(); + return faces.stream() + .map(face -> new MeshShape( + face.points.stream() + .map(p -> new MeshPoint( + p.vertices.toVector() + .rotate(pointRotation) + .add(deltaOrigin) + .mul(-1F, 1F, -1F) + .div(MathUtil.MODEL_TO_BLOCK_MULTIPLIER), + p.uv.toVector() + .div(MathUtil.MODEL_TO_BLOCK_MULTIPLIER) + )) + .toList(), + Integer.toString(face.texture) + )) + .toList(); + } + + public record Face(@NotNull @Unmodifiable List points, int texture) {} + + public record Point(@NotNull Float3 vertices, @NotNull Float2 uv) {} + } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintImage.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintImage.java index aa539685f..3d55d3598 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintImage.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintImage.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import com.google.gson.JsonObject; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintJson.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintJson.java index 2a4c3f7cd..63a02ac5a 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintJson.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintJson.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import com.google.gson.JsonElement; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java new file mode 100644 index 000000000..3a4855f76 --- /dev/null +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java @@ -0,0 +1,149 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.api.data.blueprint; + +import io.github.toxicity188.javamesh.MeshImage; +import io.github.toxicity188.javamesh.MeshTriangleName; +import kr.toxicity.model.api.BetterModel; +import kr.toxicity.model.api.data.raw.ModelResolution; +import kr.toxicity.model.api.pack.PackObfuscator; +import org.jetbrains.annotations.ApiStatus; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; + +import javax.imageio.ImageIO; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; +import java.util.stream.IntStream; +import java.util.stream.Stream; + +@ApiStatus.Internal +public final class BlueprintLoadContext { + + private final String name; + private final ModelResolution resolution; + private final TextureRef[] textureRefs; + private final boolean canBeRendered; + + private volatile Map imageRefMap; + + private final MeshTriangleName triangleName = new MeshTriangleName( + BetterModel.config().namespace() + ":" + BlueprintElement.MESH_TRIANGLE_SINGLE, + BetterModel.config().namespace() + ":" + BlueprintElement.MESH_TRIANGLE_DUPLEX + ); + + BlueprintLoadContext( + @NotNull String name, + @NotNull ModelResolution resolution, + @NotNull List textures + ) { + this.name = name; + this.resolution = resolution; + this.textureRefs = new TextureRef[textures.size()]; + var i = 0; + var canBeRendered = false; + for (BlueprintTexture texture : textures) { + canBeRendered |= texture.canBeRendered(); + this.textureRefs[i++] = new TextureRef(texture); + } + this.canBeRendered = canBeRendered; + } + + public @NotNull String name() { + return name; + } + + public @NotNull MeshTriangleName triangleName() { + return triangleName; + } + + public @NotNull ModelResolution resolution() { + return resolution; + } + + public @NotNull BlueprintTexture texture(int index) { + return Objects.requireNonNull(textureRefs[index]).texture(); + } + + @NotNull + @Unmodifiable + Map imageByIndex() { + Map map; + if ((map = imageRefMap) != null) return map; + synchronized (this) { + if ((map = imageRefMap) != null) return map; + return imageRefMap = Collections.unmodifiableMap(new AbstractMap<>() { + @Override + public MeshImage get(Object key) { + var get = textureRefs[Integer.parseInt(key.toString())]; + return get != null ? get.image() : null; + } + + @Override + @Unmodifiable + public @NotNull Set> entrySet() { + return IntStream.range(0, textureRefs.length) + .mapToObj(i -> Map.entry(Integer.toString(i), textureRefs[i].image())) + .collect(Collectors.toUnmodifiableSet()); + } + }); + } + } + + public boolean canBeRendered() { + return canBeRendered; + } + + @NotNull + public Stream buildImage(@NotNull PackObfuscator obfuscator) { + if (!canBeRendered()) return Stream.empty(); + return Arrays.stream(textureRefs) + .filter(TextureRef::canBeRendered) + .map(ref -> new BlueprintImage( + ref.texture.packName(obfuscator), + ref.texture.image(), + ref.texture.isAnimatedTexture() ? ref.texture.toMcmeta() : null) + ); + } + + private static final class TextureRef { + + private final BlueprintTexture texture; + private final AtomicBoolean referenced = new AtomicBoolean(); + private volatile MeshImage image; + + private TextureRef(BlueprintTexture texture) { + this.texture = texture; + } + + public boolean canBeRendered() { + return referenced.get() && texture.canBeRendered(); + } + + public @NotNull BlueprintTexture texture() { + referenced.set(true); + return texture; + } + + public @NotNull MeshImage image() { + MeshImage img; + if ((img = image) != null) return img; + synchronized (this) { + if ((img = image) != null) return img; + try (var input = new ByteArrayInputStream(texture.image())) { + return image = MeshImage.from(ImageIO.read(input)); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + } +} diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintTexture.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintTexture.java index e63c0a060..a42c121bc 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintTexture.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintTexture.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import com.google.gson.JsonObject; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java index 83082113a..f1b7b9531 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java @@ -1,19 +1,18 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import kr.toxicity.model.api.data.raw.ModelResolution; -import kr.toxicity.model.api.pack.PackObfuscator; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import java.util.List; import java.util.Map; -import java.util.stream.Stream; /** * Represents a fully processed model blueprint, ready for generation and rendering. @@ -38,31 +37,11 @@ public record ModelBlueprint( @NotNull Map animations ) { - /** - * Checks if this blueprint contains any renderable textures. - * - * @return true if at least one texture is renderable, false otherwise - * @since 1.15.2 - */ - public boolean hasTexture() { - return textures.stream().anyMatch(BlueprintTexture::canBeRendered); - } - - /** - * Generates a stream of {@link BlueprintImage} objects for resource pack generation. - * - * @param obfuscator the obfuscator to use for texture names - * @return a stream of blueprint images - * @since 1.15.2 - */ - @NotNull - public Stream buildImage(@NotNull PackObfuscator obfuscator) { - return textures.stream() - .filter(BlueprintTexture::canBeRendered) - .map(texture -> new BlueprintImage( - texture.packName(obfuscator), - texture.image(), - texture.isAnimatedTexture() ? texture.toMcmeta() : null) - ); + public @NotNull BlueprintLoadContext context() { + return new BlueprintLoadContext( + name(), + resolution(), + textures() + ); } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBoundingBox.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBoundingBox.java index d214a8159..07bb8c291 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBoundingBox.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBoundingBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.blueprint; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/KeyframeChannel.java b/api/src/main/java/kr/toxicity/model/api/data/raw/KeyframeChannel.java index 172cd3de8..e38cc0d47 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/KeyframeChannel.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/KeyframeChannel.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java index 568f9795b..1b63c2924 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimator.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimator.java index 33faf8b13..0b16dbfab 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java index ee89cb2a5..b4d2e5fe8 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.Gson; @@ -11,6 +12,7 @@ import com.google.gson.annotations.SerializedName; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.bone.BoneName; +import kr.toxicity.model.api.data.Float2; import kr.toxicity.model.api.data.Float3; import kr.toxicity.model.api.data.Float4; import kr.toxicity.model.api.data.blueprint.BlueprintAnimation; @@ -57,6 +59,7 @@ public record ModelData( * @since 1.15.2 */ public static final Gson GSON = new GsonBuilder() + .registerTypeAdapter(Float2.class, Float2.PARSER) .registerTypeAdapter(Float3.class, Float3.PARSER) .registerTypeAdapter(Float4.class, Float4.PARSER) .registerTypeAdapter(BoneName.class, BoneName.PARSER) diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java index f87aa4c1b..3115c9a30 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonPrimitive; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java index ef2575ed1..c33fa0f17 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java @@ -1,22 +1,23 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonDeserializer; import com.google.gson.annotations.SerializedName; import kr.toxicity.model.api.bone.BoneName; +import kr.toxicity.model.api.data.Float2; import kr.toxicity.model.api.data.Float3; import kr.toxicity.model.api.data.blueprint.BlueprintElement; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.Optional; -import java.util.UUID; +import java.util.*; /** * Represents a raw element within a model file. @@ -50,12 +51,17 @@ public sealed interface ModelElement { * @since 2.2.1 */ String CUBE = "cube"; + /** + * The type identifier for a mesh element. + * @since 3.0.0 + */ + String MESH = "mesh"; /** * A JSON deserializer that automatically dispatches to the correct {@link ModelElement} implementation based on the "type" field. * @since 1.15.2 */ - JsonDeserializer PARSER = (json, type, context) -> { + JsonDeserializer PARSER = (json, _, context) -> { var t = json.getAsJsonObject().getAsJsonPrimitive("type"); var select = t != null ? t.getAsString() : CUBE; return switch (select) { @@ -63,6 +69,7 @@ public sealed interface ModelElement { case LOCATOR -> context.deserialize(json, Locator.class); case CAMERA -> context.deserialize(json, Camera.class); case CUBE -> context.deserialize(json, Cube.class); + case MESH -> context.deserialize(json, Mesh.class); default -> new Unsupported(select); }; }; @@ -338,4 +345,61 @@ public int lightEmission() { ); } } + + record Mesh( + @NotNull String uuid, + @Nullable Float3 origin, + @Nullable Float3 rotation, + @NotNull Map vertices, + @NotNull Map faces, + @SerializedName("visibility") @Nullable Boolean _visibility + ) implements ModelElement { + @Override + public @NotNull Float3 origin() { + return origin != null ? origin : Float3.ZERO; + } + + @Override + public @NotNull Float3 rotation() { + return rotation != null ? rotation : Float3.ZERO; + } + + @Override + public @NotNull String type() { + return MESH; + } + + /** + * Checks if the cube is visible. + * + * @return true if visible, false otherwise + * @since 3.0.0 + */ + public boolean visibility() { + return !Boolean.FALSE.equals(_visibility); + } + + @Override + public @NotNull BlueprintElement toBlueprint() { + return new BlueprintElement.Mesh( + origin(), + rotation(), + faces.values() + .stream() + .map(face -> new BlueprintElement.Mesh.Face( + face.vertices.stream() + .map(n -> new BlueprintElement.Mesh.Point( + Objects.requireNonNull(vertices.get(n)), + Objects.requireNonNull(face.uv.get(n)) + )) + .toList(), + face.texture + )) + .toList(), + visibility() + ); + } + + public record Face(@NotNull Map uv, @NotNull Set vertices, int texture) {} + } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java index a6f4e46ef..a4a57b159 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java @@ -1,16 +1,19 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonObject; -import kr.toxicity.model.api.data.blueprint.ModelBlueprint; +import kr.toxicity.model.api.data.blueprint.BlueprintLoadContext; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; +import java.util.stream.IntStream; + /** * Represents the UV mappings for all six faces of a cube element. * @@ -42,7 +45,7 @@ public record ModelFace( * @return the generated JSON object * @since 1.15.2 */ - public @NotNull JsonObject toJson(@NotNull ModelBlueprint parent, int tint) { + public @NotNull JsonObject toJson(@NotNull BlueprintLoadContext parent, int tint) { var object = new JsonObject(); if (north.hasTexture()) object.add("north", north.toJson(parent, tint)); if (east.hasTexture()) object.add("east", east.toJson(parent, tint)); @@ -67,4 +70,15 @@ public boolean hasTexture() { || up.hasTexture() || down.hasTexture(); } + + public @NotNull IntStream textureIndex() { + var builder = IntStream.builder(); + if (north.hasTexture()) builder.add(north.textureIndex()); + if (east.hasTexture()) builder.add(east.textureIndex()); + if (south.hasTexture()) builder.add(south.textureIndex()); + if (west.hasTexture()) builder.add(west.textureIndex()); + if (up.hasTexture()) builder.add(up.textureIndex()); + if (down.hasTexture()) builder.add(down.textureIndex()); + return builder.build(); + } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelGroup.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelGroup.java index 51f22cbf6..ec3047e35 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelGroup.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelGroup.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelKeyframe.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelKeyframe.java index 09f551f38..ecf1056b6 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelKeyframe.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelKeyframe.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadContext.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadContext.java index 487139fd7..0d283f44e 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadContext.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadContext.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadResult.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadResult.java index 2557873ed..b117f05b6 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadResult.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelLoadResult.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import kr.toxicity.model.api.data.blueprint.ModelBlueprint; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java index 8219b4623..d6d423731 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonDeserializer; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java index aff165a2f..07dc52ad0 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelOutliner.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonDeserializer; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java index c64268d39..a5e60fd94 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelPlaceholder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonDeserializer; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelResolution.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelResolution.java index 05acb9263..357b2b172 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelResolution.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelResolution.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelTexture.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelTexture.java index f62cf8ec7..97893e01e 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelTexture.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelTexture.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java index 40e109920..e1e3e5381 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java @@ -1,14 +1,16 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.raw; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import kr.toxicity.model.api.data.Float4; +import kr.toxicity.model.api.data.blueprint.BlueprintLoadContext; import kr.toxicity.model.api.data.blueprint.ModelBlueprint; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -56,14 +58,14 @@ public int textureIndex() { /** * Converts this UV data to a JSON object for the Minecraft model file. * - * @param parent the parent model blueprint, used for texture resolution + * @param context the blueprint context, used for texture resolution * @param tint the tint index to apply * @return the generated JSON object * @since 1.15.2 */ - public @NotNull JsonObject toJson(@NotNull ModelBlueprint parent, int tint) { + public @NotNull JsonObject toJson(@NotNull BlueprintLoadContext context, int tint) { var object = new JsonObject(); - object.add("uv", uv.div(parent.textures().get(textureIndex()).resolution(parent.resolution())).toJson()); + object.add("uv", uv.div(context.texture(textureIndex()).resolution(context.resolution())).toJson()); if (rotation != 0) object.addProperty("rotation", rotation); object.addProperty("tintindex", tint); object.addProperty("texture", "#" + texture); diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java index 9406a6307..f96137c85 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/ModelRenderer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.renderer; import kr.toxicity.model.api.bone.BoneName; diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java index be36c6cb6..d12eceda0 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.renderer; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderSource.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderSource.java index 6e92e4687..5f4494169 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderSource.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderSource.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.renderer; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RendererGroup.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RendererGroup.java index 53e11e3a6..b8bf8573c 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RendererGroup.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RendererGroup.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.data.renderer; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/entity/BaseEntity.java b/api/src/main/java/kr/toxicity/model/api/entity/BaseEntity.java index ce1414014..f73a788de 100644 --- a/api/src/main/java/kr/toxicity/model/api/entity/BaseEntity.java +++ b/api/src/main/java/kr/toxicity/model/api/entity/BaseEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.entity; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/entity/BasePlayer.java b/api/src/main/java/kr/toxicity/model/api/entity/BasePlayer.java index 15f2527c1..f38efe17a 100644 --- a/api/src/main/java/kr/toxicity/model/api/entity/BasePlayer.java +++ b/api/src/main/java/kr/toxicity/model/api/entity/BasePlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.entity; import kr.toxicity.model.api.nms.Profiled; diff --git a/api/src/main/java/kr/toxicity/model/api/event/AnimationSignalEvent.java b/api/src/main/java/kr/toxicity/model/api/event/AnimationSignalEvent.java index 31678d8eb..66ecb7759 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/AnimationSignalEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/AnimationSignalEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/CancellableEvent.java b/api/src/main/java/kr/toxicity/model/api/event/CancellableEvent.java index 07c95de66..2d9c0946c 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/CancellableEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/CancellableEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; /** diff --git a/api/src/main/java/kr/toxicity/model/api/event/CloseTrackerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/CloseTrackerEvent.java index 00007e90f..21658f764 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/CloseTrackerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/CloseTrackerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.tracker.Tracker; diff --git a/api/src/main/java/kr/toxicity/model/api/event/CreateDummyTrackerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/CreateDummyTrackerEvent.java index 1fab04bb6..3e40fbb57 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/CreateDummyTrackerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/CreateDummyTrackerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.tracker.DummyTracker; diff --git a/api/src/main/java/kr/toxicity/model/api/event/CreateEntityTrackerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/CreateEntityTrackerEvent.java index d595ddcaf..ac0492bd1 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/CreateEntityTrackerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/CreateEntityTrackerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.tracker.EntityTracker; diff --git a/api/src/main/java/kr/toxicity/model/api/event/CreatePlayerSkinEvent.java b/api/src/main/java/kr/toxicity/model/api/event/CreatePlayerSkinEvent.java index 234a95622..862b83c5b 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/CreatePlayerSkinEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/CreatePlayerSkinEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.profile.ModelProfile; diff --git a/api/src/main/java/kr/toxicity/model/api/event/DismountModelEvent.java b/api/src/main/java/kr/toxicity/model/api/event/DismountModelEvent.java index 4509b872c..2a8aab9fc 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/DismountModelEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/DismountModelEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.bone.RenderedBone; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelAssetsEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelAssetsEvent.java index 7d4ea22be..fc271f192 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelAssetsEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelAssetsEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.data.ModelAsset; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelDamageSource.java b/api/src/main/java/kr/toxicity/model/api/event/ModelDamageSource.java index 0feb2d08a..6c987b33d 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelDamageSource.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelDamageSource.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformEntity; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelDespawnAtPlayerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelDespawnAtPlayerEvent.java index 90dd0c58c..fefc45445 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelDespawnAtPlayerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelDespawnAtPlayerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java index 227c195c4..839c75f2b 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelEventApplication.java b/api/src/main/java/kr/toxicity/model/api/event/ModelEventApplication.java index 5ffefac5f..709b619ef 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelEventApplication.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelEventApplication.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; /** diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelEventListener.java b/api/src/main/java/kr/toxicity/model/api/event/ModelEventListener.java index a65beb933..9d7b0e372 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelEventListener.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelEventListener.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; /** diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelImportedEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelImportedEvent.java index 6250aba4f..906044880 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelImportedEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelImportedEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; diff --git a/api/src/main/java/kr/toxicity/model/api/event/ModelSpawnAtPlayerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/ModelSpawnAtPlayerEvent.java index 8a1b20971..4afbe5038 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/ModelSpawnAtPlayerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/ModelSpawnAtPlayerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/MountModelEvent.java b/api/src/main/java/kr/toxicity/model/api/event/MountModelEvent.java index 02ee7b529..774cbd5ce 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/MountModelEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/MountModelEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.bone.RenderedBone; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PlayerHideTrackerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PlayerHideTrackerEvent.java index 21dc9e931..ebb371156 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PlayerHideTrackerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PlayerHideTrackerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationEndEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationEndEvent.java index bae33f90b..43008303d 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationEndEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationEndEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationStartEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationStartEvent.java index ff76ce1a0..e496a3bf5 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationStartEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PlayerPerAnimationStartEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PlayerShowTrackerEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PlayerShowTrackerEvent.java index 31ceb9194..edeeba442 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PlayerShowTrackerEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PlayerShowTrackerEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PluginEndReloadEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PluginEndReloadEvent.java index 8aed1151a..5dc012960 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PluginEndReloadEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PluginEndReloadEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.BetterModelPlatform; diff --git a/api/src/main/java/kr/toxicity/model/api/event/PluginStartReloadEvent.java b/api/src/main/java/kr/toxicity/model/api/event/PluginStartReloadEvent.java index 4d2ec6249..304367520 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/PluginStartReloadEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/PluginStartReloadEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.pack.PackZipper; diff --git a/api/src/main/java/kr/toxicity/model/api/event/RemovePlayerSkinEvent.java b/api/src/main/java/kr/toxicity/model/api/event/RemovePlayerSkinEvent.java index 20d731555..cc6d92106 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/RemovePlayerSkinEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/RemovePlayerSkinEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event; import kr.toxicity.model.api.profile.ModelProfile; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxCreateEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxCreateEvent.java index 4cff97fa9..655834d5c 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxCreateEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxCreateEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.nms.HitBox; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDamagedEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDamagedEvent.java index 4a1b40677..33c40e4f3 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDamagedEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDamagedEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.event.CancellableEvent; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDismountEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDismountEvent.java index b7d5e84fe..4ea9a42a5 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDismountEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxDismountEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.nms.HitBox; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxEvent.java index 4ec82775b..47e73442b 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.event.ModelEvent; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java index e40deb5cd..79364ef40 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.event.CancellableEvent; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java index 9fa86d9cd..50b1896b8 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.event.CancellableEvent; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxMountEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxMountEvent.java index fec7b4b90..e27cd0f3a 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxMountEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxMountEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.nms.HitBox; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxRemoveEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxRemoveEvent.java index 1ccd1b7b8..400ae8d4e 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxRemoveEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxRemoveEvent.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.event.hitbox; import kr.toxicity.model.api.nms.HitBox; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java b/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java index acc4bb4bf..809d32094 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/ModelManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import kr.toxicity.model.api.animation.AnimationModifier; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/PlayerManager.java b/api/src/main/java/kr/toxicity/model/api/manager/PlayerManager.java index fe76334b4..68cb09045 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/PlayerManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/PlayerManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import kr.toxicity.model.api.nms.PlayerChannelHandler; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/ProfileManager.java b/api/src/main/java/kr/toxicity/model/api/manager/ProfileManager.java index 0701ddd87..c474a940d 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/ProfileManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/ProfileManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import kr.toxicity.model.api.profile.ModelProfileSkin; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/ReloadInfo.java b/api/src/main/java/kr/toxicity/model/api/manager/ReloadInfo.java index d4757a9bd..d5ca475d1 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/ReloadInfo.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/ReloadInfo.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import lombok.Builder; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/ScriptManager.java b/api/src/main/java/kr/toxicity/model/api/manager/ScriptManager.java index 258ee5c67..7f705ef29 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/ScriptManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/ScriptManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import kr.toxicity.model.api.script.AnimationScript; diff --git a/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java b/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java index 68053fd12..4f917b4a4 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.manager; import kr.toxicity.model.api.profile.ModelProfile; diff --git a/api/src/main/java/kr/toxicity/model/api/mount/MountController.java b/api/src/main/java/kr/toxicity/model/api/mount/MountController.java index 00ed24b18..b03a4d73b 100644 --- a/api/src/main/java/kr/toxicity/model/api/mount/MountController.java +++ b/api/src/main/java/kr/toxicity/model/api/mount/MountController.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.mount; import kr.toxicity.model.api.platform.PlatformLivingEntity; diff --git a/api/src/main/java/kr/toxicity/model/api/mount/MountControllers.java b/api/src/main/java/kr/toxicity/model/api/mount/MountControllers.java index 702c64040..53f1701d7 100644 --- a/api/src/main/java/kr/toxicity/model/api/mount/MountControllers.java +++ b/api/src/main/java/kr/toxicity/model/api/mount/MountControllers.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.mount; import kr.toxicity.model.api.platform.PlatformLivingEntity; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/DisplayTransformer.java b/api/src/main/java/kr/toxicity/model/api/nms/DisplayTransformer.java index 876f99128..8309f9186 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/DisplayTransformer.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/DisplayTransformer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java index 5a8648ccf..74cf388f7 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java index bcc020f87..2d268ca00 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import com.google.common.collect.ImmutableMap; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/Identifiable.java b/api/src/main/java/kr/toxicity/model/api/nms/Identifiable.java index 1fd913160..7318c6bfa 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/Identifiable.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/Identifiable.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/ModelDisplay.java b/api/src/main/java/kr/toxicity/model/api/nms/ModelDisplay.java index 764a7ed2c..74f2af20a 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/ModelDisplay.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/ModelDisplay.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.entity.BaseEntity; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/ModelInteractionHand.java b/api/src/main/java/kr/toxicity/model/api/nms/ModelInteractionHand.java index 12098dcb5..e237aef27 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/ModelInteractionHand.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/ModelInteractionHand.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; /** diff --git a/api/src/main/java/kr/toxicity/model/api/nms/ModelNametag.java b/api/src/main/java/kr/toxicity/model/api/nms/ModelNametag.java index 0ae4b16a9..9d3c65cf9 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/ModelNametag.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/ModelNametag.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.platform.PlatformLocation; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java index 8ba215276..3c641fb91 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java index ab6a857e5..1654751b9 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import lombok.Getter; @@ -25,41 +26,38 @@ public enum NMSVersion { * Minecraft 1.21 - 1.21.1 * @since 1.15.2 */ - V1_21_R1(21,1, 34), + V1_21_R1(34), /** * Minecraft 1.21.4 * @since 1.15.2 */ - V1_21_R3(21,3, 46), + V1_21_R3(46), /** * Minecraft 1.21.5 * @since 1.15.2 */ - V1_21_R4(21,4, 55), + V1_21_R4(55), /** * Minecraft 1.21.6 - 1.21.8 * @since 1.15.2 */ - V1_21_R5(21,5, 64), + V1_21_R5(64), /** * Minecraft 1.21.9 - 1.21.10 * @since 1.15.2 */ - V1_21_R6(21,6, 69), + V1_21_R6(69), /** * Minecraft 1.21.11 * @since 1.15.2 */ - V1_21_R7(21,7, 75) - ; - /** - * The major version number (e.g., 21 for 1.21). - */ - private final int version; + V1_21_R7(75), /** - * The sub-version number. + * Minecraft 26.1 + * @since 3.0.0 */ - private final int subVersion; + V26_R1(84) + ; /** * The resource pack format version (pack.mcmeta). */ diff --git a/api/src/main/java/kr/toxicity/model/api/nms/PacketBundler.java b/api/src/main/java/kr/toxicity/model/api/nms/PacketBundler.java index 8115d2b33..88c167353 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/PacketBundler.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/PacketBundler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/PlayerChannelHandler.java b/api/src/main/java/kr/toxicity/model/api/nms/PlayerChannelHandler.java index f03839aee..2a9122dcb 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/PlayerChannelHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/PlayerChannelHandler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.entity.BasePlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/Profiled.java b/api/src/main/java/kr/toxicity/model/api/nms/Profiled.java index 0dc677f13..dbccc4a02 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/Profiled.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/Profiled.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.armor.PlayerArmor; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackAssets.java b/api/src/main/java/kr/toxicity/model/api/pack/PackAssets.java index 859bcc0ff..339298373 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackAssets.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackAssets.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackBuilder.java b/api/src/main/java/kr/toxicity/model/api/pack/PackBuilder.java index 853729c30..743d5bd05 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackBuilder.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackBuilder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import lombok.AccessLevel; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackBuiltInAssets.java b/api/src/main/java/kr/toxicity/model/api/pack/PackBuiltInAssets.java new file mode 100644 index 000000000..bea62fa22 --- /dev/null +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackBuiltInAssets.java @@ -0,0 +1,99 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.api.pack; + +import com.google.gson.JsonObject; +import kr.toxicity.model.api.BetterModel; +import kr.toxicity.model.api.data.Float3; +import kr.toxicity.model.api.data.Float4; +import kr.toxicity.model.api.data.blueprint.BlueprintElement; +import kr.toxicity.model.api.util.json.JsonObjectBuilder; +import org.jetbrains.annotations.NotNull; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.awt.image.DataBufferInt; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Arrays; +import java.util.Set; +import java.util.function.Function; +import java.util.function.Supplier; + +record PackBuiltInAssets( + @NotNull String path, + @NotNull Function builderFunction, + @NotNull Supplier supplier +) { + + private static final byte[] MESH_PIXEL_IMAGE; + + static { + var image = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB); + Arrays.fill(((DataBufferInt) image.getRaster().getDataBuffer()).getData(), 0xFFFFFF); + try (var output = new ByteArrayOutputStream()) { + ImageIO.write(image, "png", output); + MESH_PIXEL_IMAGE = output.toByteArray(); + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + private static final Set ASSETS = Set.of( + new PackBuiltInAssets( + BlueprintElement.MESH_TRIANGLE_SINGLE + ".json", + zipper -> zipper.modern().bettermodel().models(), + () -> PackMeta.GSON.toJson(meshTriangle(faces -> faces + .jsonObject("north", north -> north + .jsonArray("uv", Float4.MAX_UV.toJson()) + .property("texture", "#0") + .property("tintindex", 0)) + )).getBytes(StandardCharsets.UTF_8) + ), + new PackBuiltInAssets( + BlueprintElement.MESH_TRIANGLE_DUPLEX + ".json", + zipper -> zipper.modern().bettermodel().models(), + () -> PackMeta.GSON.toJson(meshTriangle(faces -> faces + .jsonObject("north", north -> north + .jsonArray("uv", Float4.MAX_UV.toJson()) + .property("texture", "#0") + .property("tintindex", 0)) + .jsonObject("south", north -> north + .jsonArray("uv", Float4.MAX_UV.toJson()) + .property("texture", "#0") + .property("tintindex", 0)) + )).getBytes(StandardCharsets.UTF_8) + ), + new PackBuiltInAssets( + BlueprintElement.MESH_PIXEL + ".png", + zipper -> zipper.modern().bettermodel().textures(), + () -> MESH_PIXEL_IMAGE + ) + ); + + static void applyAs(@NotNull PackZipper zipper) { + for (PackBuiltInAssets asset : ASSETS) { + asset.builderFunction.apply(zipper).add(asset.path, asset.supplier); + } + } + + private static @NotNull JsonObject meshTriangle(@NotNull Function faceBuilder) { + var pixel = BetterModel.config().namespace() + ":item/" + BlueprintElement.MESH_PIXEL; + return JsonObjectBuilder.builder() + .jsonObject("textures", textures -> textures + .property("0", pixel) + .property("particle", pixel)) + .jsonArray("elements", elements -> elements + .jsonObject(element -> element + .jsonArray("from", Float3.MESH_TRIANGLE_FROM.toJson()) + .jsonArray("to", Float3.MESH_TRIANGLE_TO.toJson()) + .jsonObject("faces", faceBuilder::apply))) + .build(); + } +} diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackByte.java b/api/src/main/java/kr/toxicity/model/api/pack/PackByte.java index 0a071a2ab..4f52afc0f 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackByte.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackByte.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java b/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java index 4dcb72eef..1ff41e24d 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackMeta.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import com.google.gson.*; @@ -41,7 +42,8 @@ public record PackMeta( * @since 1.15.2 */ public static final PackPath PATH = new PackPath("pack.mcmeta"); - private static final Gson GSON = new GsonBuilder() + + static final Gson GSON = new GsonBuilder() .registerTypeAdapter(PackVersion.class, (JsonDeserializer) (json, _, _) -> { if (json.isJsonPrimitive()) return new PackVersion(json.getAsInt()); else if (json.isJsonArray()) { diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackNamespace.java b/api/src/main/java/kr/toxicity/model/api/pack/PackNamespace.java index 0d55428bc..7f657c2a6 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackNamespace.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackNamespace.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java b/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java index 2e9babd89..2f566ed65 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackObfuscator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackOverlay.java b/api/src/main/java/kr/toxicity/model/api/pack/PackOverlay.java index 1ce86f651..74314a034 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackOverlay.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackOverlay.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java b/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java index d5201291a..1693bcdb9 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackResource.java b/api/src/main/java/kr/toxicity/model/api/pack/PackResource.java index fc8ec9882..300f8c78f 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackResource.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackResource.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java b/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java index b1c90f89e..61b3a68a9 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackResult.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackZipper.java b/api/src/main/java/kr/toxicity/model/api/pack/PackZipper.java index f9f633914..5d22c3d86 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackZipper.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackZipper.java @@ -1,15 +1,14 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.pack; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.util.LogUtil; -import lombok.AccessLevel; -import lombok.NoArgsConstructor; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -29,9 +28,12 @@ * * @since 1.15.2 */ -@NoArgsConstructor(access = AccessLevel.PRIVATE) public final class PackZipper { + private PackZipper() { + PackBuiltInAssets.applyAs(this); + } + private static final PackPath PACK_ICON = new PackPath("pack.png"); /** diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformAdapter.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformAdapter.java index 24d86035f..a8dcc6385 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformAdapter.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformAdapter.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformBillboard.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformBillboard.java index f3e8e4c9a..6eccfe414 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformBillboard.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformBillboard.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; /** diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformEntity.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformEntity.java index f2ab92893..95d644fe1 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformEntity.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemStack.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemStack.java index 99a596f27..d5df9856e 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemStack.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemStack.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemTransform.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemTransform.java index fc6982b67..db9b8f2dc 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemTransform.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformItemTransform.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; /** diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLivingEntity.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLivingEntity.java index b8b3a4827..7358e6fd2 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLivingEntity.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLivingEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java index 5338c7e1a..ee2fc6ad4 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformNamespace.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformNamespace.java index 6f45277e9..efdc7db28 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformNamespace.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformNamespace.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformOfflinePlayer.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformOfflinePlayer.java index 7c9a8beba..c6d8e017e 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformOfflinePlayer.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformOfflinePlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformPlayer.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformPlayer.java index f7b923ca0..870951b3d 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformPlayer.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformPlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformRegionHolder.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformRegionHolder.java index 116e6ec63..eab9f1089 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformRegionHolder.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformRegionHolder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; import kr.toxicity.model.api.scheduler.ModelTask; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformWorld.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformWorld.java index d63fcc131..db3f3ccbd 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformWorld.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformWorld.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.platform; /** diff --git a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java index f0bcf6b71..21754bede 100644 --- a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java +++ b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.player; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/player/PlayerSkinParts.java b/api/src/main/java/kr/toxicity/model/api/player/PlayerSkinParts.java index e6afa679c..5470d2ef5 100644 --- a/api/src/main/java/kr/toxicity/model/api/player/PlayerSkinParts.java +++ b/api/src/main/java/kr/toxicity/model/api/player/PlayerSkinParts.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.player; /** diff --git a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfile.java b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfile.java index 160a03364..434922fe6 100644 --- a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfile.java +++ b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfile.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.profile; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileInfo.java b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileInfo.java index 72b00691d..b35782058 100644 --- a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileInfo.java +++ b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileInfo.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.profile; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSkin.java b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSkin.java index 1c2308701..42e49ee7d 100644 --- a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSkin.java +++ b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSkin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.profile; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSupplier.java b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSupplier.java index 84f11f484..ef26e3a40 100644 --- a/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSupplier.java +++ b/api/src/main/java/kr/toxicity/model/api/profile/ModelProfileSupplier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.profile; import kr.toxicity.model.api.platform.PlatformOfflinePlayer; diff --git a/api/src/main/java/kr/toxicity/model/api/scheduler/ModelScheduler.java b/api/src/main/java/kr/toxicity/model/api/scheduler/ModelScheduler.java index 6ce069cff..2be7f49df 100644 --- a/api/src/main/java/kr/toxicity/model/api/scheduler/ModelScheduler.java +++ b/api/src/main/java/kr/toxicity/model/api/scheduler/ModelScheduler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.scheduler; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/scheduler/ModelTask.java b/api/src/main/java/kr/toxicity/model/api/scheduler/ModelTask.java index 218ff19a4..40f1e6be8 100644 --- a/api/src/main/java/kr/toxicity/model/api/scheduler/ModelTask.java +++ b/api/src/main/java/kr/toxicity/model/api/scheduler/ModelTask.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.scheduler; /** diff --git a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java index a0a83f8a2..a0aca53b2 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java +++ b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.script; import kr.toxicity.model.api.tracker.Tracker; diff --git a/api/src/main/java/kr/toxicity/model/api/script/BlueprintScript.java b/api/src/main/java/kr/toxicity/model/api/script/BlueprintScript.java index b1b247cda..4aae171e4 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/BlueprintScript.java +++ b/api/src/main/java/kr/toxicity/model/api/script/BlueprintScript.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.script; import kr.toxicity.model.api.animation.AnimationIterator; diff --git a/api/src/main/java/kr/toxicity/model/api/script/ScriptBuilder.java b/api/src/main/java/kr/toxicity/model/api/script/ScriptBuilder.java index 628894a99..eb890fef7 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/ScriptBuilder.java +++ b/api/src/main/java/kr/toxicity/model/api/script/ScriptBuilder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.script; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/script/TimeScript.java b/api/src/main/java/kr/toxicity/model/api/script/TimeScript.java index d02e1a9e1..203b0260f 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/TimeScript.java +++ b/api/src/main/java/kr/toxicity/model/api/script/TimeScript.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.script; import kr.toxicity.model.api.animation.Timed; diff --git a/api/src/main/java/kr/toxicity/model/api/skin/SkinData.java b/api/src/main/java/kr/toxicity/model/api/skin/SkinData.java index 213c4fbe1..484a2bbdd 100644 --- a/api/src/main/java/kr/toxicity/model/api/skin/SkinData.java +++ b/api/src/main/java/kr/toxicity/model/api/skin/SkinData.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.skin; import kr.toxicity.model.api.armor.PlayerArmor; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/DummyTracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/DummyTracker.java index 3399f4797..2fc41e0ec 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/DummyTracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/DummyTracker.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.animation.AnimationModifier; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityBodyRotator.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityBodyRotator.java index d58d13153..18c485a82 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityBodyRotator.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityBodyRotator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java index d8a53dee4..2c493b79e 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.JsonArray; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java index 6fda212ff..5a0ba6d66 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java index d4b3f9769..6a6b64c1a 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.common.collect.ImmutableList; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotation.java b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotation.java index ae99f5419..9697442f2 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.util.MathUtil; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java index 42fc7027d..e3377a305 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/ModelRotator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.JsonElement; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java b/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java index d6cac27e9..b9be1b750 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/ModelScaler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.*; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/PlayerTracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/PlayerTracker.java index 53586310a..3265f19dc 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/PlayerTracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/PlayerTracker.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.data.renderer.RenderPipeline; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java index 80cbcfc1c..c6afdabf1 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.animation.*; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java index 4bfe41493..b0baf4390 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.animation.AnimationModifier; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java index 54e8f43ea..3882650cf 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.animation.AnimationIterator; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java index 42997cd4a..72e71df5e 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerData.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.*; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java index 4cf33119c..a23a03adc 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerExtraAnimation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.animation.AnimationModifier; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerModifier.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerModifier.java index 02a327207..9c8d2a0cc 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerModifier.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerModifier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java index 01e34ee20..95acb547d 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.tracker; import kr.toxicity.model.api.bone.RenderedBone; diff --git a/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java b/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java index c6b100aaa..219d03285 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import com.google.gson.JsonArray; @@ -37,18 +38,6 @@ private CollectionUtil() { throw new RuntimeException(); } - /** - * Creates a new chaining hash map. - * @return new hash map - * @param key type - * @param value type - * @since 2.2.1 - */ - @NotNull - public static Map newChainingMap() { - return new HashMap<>(); - } - /** * Creates a new addressing hash map. * @return new addressing map diff --git a/api/src/main/java/kr/toxicity/model/api/util/EntityUtil.java b/api/src/main/java/kr/toxicity/model/api/util/EntityUtil.java index d95d3421e..35a16b553 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/EntityUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/EntityUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/util/EventUtil.java b/api/src/main/java/kr/toxicity/model/api/util/EventUtil.java index 244bb5777..6b7546727 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/EventUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/EventUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/util/FunctionUtil.java b/api/src/main/java/kr/toxicity/model/api/util/FunctionUtil.java index 58ff6787d..e137d22ac 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/FunctionUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/FunctionUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import kr.toxicity.model.api.util.function.BooleanConstantSupplier; diff --git a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java index f2d78d8a0..cb7e8a945 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import com.google.gson.Gson; diff --git a/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java b/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java index e70cfbaa9..f8af3c7b8 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import it.unimi.dsi.fastutil.floats.FloatArrayList; diff --git a/api/src/main/java/kr/toxicity/model/api/util/LogUtil.java b/api/src/main/java/kr/toxicity/model/api/util/LogUtil.java index fe76e242a..dcb20d51e 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/LogUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/LogUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java b/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java index 2ba4f0e07..e779b01c7 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import it.unimi.dsi.fastutil.floats.FloatComparator; diff --git a/api/src/main/java/kr/toxicity/model/api/util/PackUtil.java b/api/src/main/java/kr/toxicity/model/api/util/PackUtil.java index 365d645f6..7aa4dff41 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/PackUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/PackUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/util/ReflectionUtil.java b/api/src/main/java/kr/toxicity/model/api/util/ReflectionUtil.java index 4e2f9e5c9..050e4d5c4 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/ReflectionUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/ReflectionUtil.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/util/TransformedItemStack.java b/api/src/main/java/kr/toxicity/model/api/util/TransformedItemStack.java index aad7fe967..63649b63d 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/TransformedItemStack.java +++ b/api/src/main/java/kr/toxicity/model/api/util/TransformedItemStack.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util; import kr.toxicity.model.api.BetterModel; diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java new file mode 100644 index 000000000..71775914d --- /dev/null +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java @@ -0,0 +1,65 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.api.util.collection; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; + +public final class PriorityMap, V> { + + private final Map> keyMap = new HashMap<>(); + private final TreeMap, V> valueMap = new TreeMap<>(); + private long counter; + + public PriorityMap() { + } + + private record Identifier>( + int priority, + long count, + @NotNull K key + ) implements Comparable> { + + @Override + public int compareTo(@NotNull Identifier o) { + int c; + if ((c = Integer.compare(o.priority, priority)) != 0) return c; + if ((c = Long.compare(o.count, count)) != 0) return c; + return key.compareTo(o.key); + } + } + + public @Nullable V put(@NotNull K key, @NotNull V value, int priority) { + return valueMap.put( + keyMap.computeIfAbsent(Objects.requireNonNull(key), _ -> new Identifier<>(priority, counter++, key)), + Objects.requireNonNull(value) + ); + } + + public @Nullable V get(@NotNull K key) { + Identifier identifier; + return (identifier = keyMap.get(Objects.requireNonNull(key))) == null ? null : valueMap.get(identifier); + } + + public @Nullable V remove(@NotNull K key) { + Identifier identifier; + return (identifier = keyMap.remove(Objects.requireNonNull(key))) == null ? null : valueMap.remove(identifier); + } + + public @Nullable V replace(@NotNull K Key, @NotNull V newValue) { + Identifier identifier; + if ((identifier = keyMap.get(Objects.requireNonNull(Key))) == null) return null; + return valueMap.put(identifier, Objects.requireNonNull(newValue)); + } + + public @NotNull Collection values() { + return valueMap.values(); + } +} diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java b/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java index 9840056b9..a33225669 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.collection; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java b/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java index 5cdb1ba80..d37cf2d00 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/BonePredicate.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import kr.toxicity.model.api.bone.BoneTag; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/BooleanConstantSupplier.java b/api/src/main/java/kr/toxicity/model/api/util/function/BooleanConstantSupplier.java index cdab77b15..8e541ff8e 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/BooleanConstantSupplier.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/BooleanConstantSupplier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import lombok.RequiredArgsConstructor; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatConstantFunction.java b/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatConstantFunction.java index be7af57f8..5ec71d575 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatConstantFunction.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatConstantFunction.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; /** diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatFunction.java b/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatFunction.java index 94a448708..5d9ee8298 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatFunction.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/Float2FloatFunction.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantFunction.java b/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantFunction.java index a2f58874f..327812f1a 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantFunction.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantFunction.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantSupplier.java b/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantSupplier.java index 4ec96575f..837436c55 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantSupplier.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/FloatConstantSupplier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; /** diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java b/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java index 58457fb84..3e2546857 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/FloatFunction.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap; diff --git a/api/src/main/java/kr/toxicity/model/api/util/function/FloatSupplier.java b/api/src/main/java/kr/toxicity/model/api/util/function/FloatSupplier.java index ffa131f65..5cb855f29 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/function/FloatSupplier.java +++ b/api/src/main/java/kr/toxicity/model/api/util/function/FloatSupplier.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.function; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/util/interpolator/VectorInterpolator.java b/api/src/main/java/kr/toxicity/model/api/util/interpolator/VectorInterpolator.java index 7e5d1136f..cbf54d6c5 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/interpolator/VectorInterpolator.java +++ b/api/src/main/java/kr/toxicity/model/api/util/interpolator/VectorInterpolator.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.interpolator; import com.google.gson.annotations.SerializedName; diff --git a/api/src/main/java/kr/toxicity/model/api/util/json/JsonArrayBuilder.java b/api/src/main/java/kr/toxicity/model/api/util/json/JsonArrayBuilder.java new file mode 100644 index 000000000..4fd40498f --- /dev/null +++ b/api/src/main/java/kr/toxicity/model/api/util/json/JsonArrayBuilder.java @@ -0,0 +1,39 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.api.util.json; + +import com.google.gson.JsonArray; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; +import java.util.function.Consumer; + +public final class JsonArrayBuilder { + + private final JsonArray array = new JsonArray(); + + /** + * Creates builder + * @return builder + */ + public static @NotNull JsonArrayBuilder builder() { + return new JsonArrayBuilder(); + } + + public @NotNull JsonArrayBuilder jsonObject(@NotNull Consumer consumer) { + var builder = JsonObjectBuilder.builder(); + Objects.requireNonNull(consumer).accept(builder); + var json = builder.build(); + if (!json.isEmpty()) array.add(json); + return this; + } + + public @NotNull JsonArray build() { + return array; + } +} diff --git a/api/src/main/java/kr/toxicity/model/api/util/json/JsonObjectBuilder.java b/api/src/main/java/kr/toxicity/model/api/util/json/JsonObjectBuilder.java index 5affb542d..d2431ab1b 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/json/JsonObjectBuilder.java +++ b/api/src/main/java/kr/toxicity/model/api/util/json/JsonObjectBuilder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.json; import com.google.gson.JsonArray; @@ -12,6 +13,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; import java.util.Objects; import java.util.function.Consumer; @@ -80,6 +82,20 @@ private JsonObjectBuilder() { return this; } + /** + * Adds JSON array + * @param name name + * @param consumer consumer + * @return self + */ + public @NotNull JsonObjectBuilder jsonArray(@NotNull String name, @NotNull Consumer consumer) { + var builder = JsonArrayBuilder.builder(); + Objects.requireNonNull(consumer).accept(builder); + var json = builder.build(); + if (!json.isEmpty()) object.add(name, json); + return this; + } + /** * Adds JSON property * @param name name @@ -112,4 +128,40 @@ private JsonObjectBuilder() { if (property != null) object.addProperty(name, property); return this; } + + /** + * Adds JSON property + * @param entries entries + * @return self + */ + public @NotNull JsonObjectBuilder stringProperties(@NotNull Iterable> entries) { + for (var entry : entries) { + property(entry.getKey(), entry.getValue()); + } + return this; + } + + /** + * Adds JSON property + * @param entries entries + * @return self + */ + public @NotNull JsonObjectBuilder booleanProperties(@NotNull Iterable> entries) { + for (var entry : entries) { + property(entry.getKey(), entry.getValue()); + } + return this; + } + + /** + * Adds JSON property + * @param entries entries + * @return self + */ + public @NotNull JsonObjectBuilder numberProperties(@NotNull Iterable> entries) { + for (var entry : entries) { + property(entry.getKey(), entry.getValue()); + } + return this; + } } diff --git a/api/src/main/java/kr/toxicity/model/api/util/lazy/LazyFloatProvider.java b/api/src/main/java/kr/toxicity/model/api/util/lazy/LazyFloatProvider.java index 5239fcc7c..817952c78 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/lazy/LazyFloatProvider.java +++ b/api/src/main/java/kr/toxicity/model/api/util/lazy/LazyFloatProvider.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.lazy; import kr.toxicity.model.api.util.InterpolationUtil; diff --git a/api/src/main/java/kr/toxicity/model/api/util/lock/DuplexLock.java b/api/src/main/java/kr/toxicity/model/api/util/lock/DuplexLock.java index 9e3657dcc..65ba70857 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/lock/DuplexLock.java +++ b/api/src/main/java/kr/toxicity/model/api/util/lock/DuplexLock.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.lock; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/util/lock/SingleLock.java b/api/src/main/java/kr/toxicity/model/api/util/lock/SingleLock.java index efec3d0d8..6317a2401 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/lock/SingleLock.java +++ b/api/src/main/java/kr/toxicity/model/api/util/lock/SingleLock.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.util.lock; import org.jetbrains.annotations.ApiStatus; diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index b5d07b928..08f9c9b29 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -1,11 +1,13 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.version; +import com.vdurmont.semver4j.Semver; import org.jetbrains.annotations.NotNull; import java.util.Comparator; @@ -17,6 +19,10 @@ * @param patch minor update */ public record MinecraftVersion(int major, int minor, int patch) implements Comparable { + /** + * 26.1 + */ + public static final MinecraftVersion V26_1 = of(26, 1, 0); /** * 1.21.11 */ @@ -75,11 +81,12 @@ public record MinecraftVersion(int major, int minor, int patch) implements Compa * @return parsed version */ public static @NotNull MinecraftVersion parse(@NotNull String version) { - var split = version.split("\\."); + var split = new Semver(version, Semver.SemverType.LOOSE); + Integer v1, v2, v3; return of( - split.length > 0 ? Integer.parseInt(split[0]) : 0, - split.length > 1 ? Integer.parseInt(split[1]) : 0, - split.length > 2 ? Integer.parseInt(split[2]) : 0 + (v1 = split.getMajor()) == null ? 0 : v1, + (v2 = split.getMinor()) == null ? 0 : v2, + (v3 = split.getPatch()) == null ? 0 : v3 ); } diff --git a/build.gradle.kts b/build.gradle.kts index 6873d6049..8ee0501dd 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { id("xyz.jpenilla.run-paper") version "3.0.2" } -val minecraft = property("minecraft_version").toString() +val minecraft = "1.21.11" //TODO change this to property("minecraft_version").toString() val versionString = version.toString() val groupString = group.toString() @@ -33,8 +33,8 @@ tasks { }) version(minecraft) downloadPlugins { - hangar("ViaVersion", "5.7.2") - hangar("ViaBackwards", "5.7.2") + hangar("ViaVersion", "5.8.0") + hangar("ViaBackwards", "5.8.0") hangar("Skript", "2.14.2") hangar("TabTPS", "1.3.30") } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 2e939a907..7400d61ff 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -17,6 +17,6 @@ dependencies { implementation(libs.build.resourcefactory) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.1.0") - implementation("com.github.hierynomus.license:com.github.hierynomus.license.gradle.plugin:0.16.1") + implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:2.2.1") implementation("com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin:0.36.0") } diff --git a/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts b/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts index 47c744fcd..0a085ab6d 100644 --- a/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts @@ -2,7 +2,7 @@ plugins { id("standard-conventions") } -val minecraft = property("minecraft_version").toString() +val minecraft = "1.21.11" //TODO change this to property("minecraft_version").toString() dependencies { compileOnly("io.papermc.paper:paper-api:$minecraft-R0.1-SNAPSHOT") diff --git a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts index 7fa034943..578324cc7 100644 --- a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts @@ -2,7 +2,7 @@ plugins { java kotlin("jvm") id("org.jetbrains.dokka") - id("com.github.hierynomus.license") + id("dev.yumi.gradle.licenser") } group = "kr.toxicity.model" @@ -33,12 +33,9 @@ tasks { } license { - header = rootProject.file("LICENSE_HEADER") - includes(setOf( - "**/*.java", - "**/*.kt" - )) - strictCheck = true + rule(rootProject.file("LICENSE_HEADER")) + include("**/*.java", "**/*.kt") + exclude("**/*.properties") } java { diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java index fc6b2c42e..4a6414061 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit; import kr.toxicity.model.BetterModelPlatformImpl; diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java index 29809eaad..bce49e110 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit; import kr.toxicity.model.api.bukkit.BetterModelBukkit; diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibraryManager.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibraryManager.java index 5ce2b5b2b..0c3d1febd 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibraryManager.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibraryManager.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit; import net.byteflux.libby.LibraryManager; diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelConfigImpl.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelConfigImpl.kt index 3d424a792..c4090afc5 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelConfigImpl.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelConfigImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit import kr.toxicity.model.api.BetterModelConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt index a2fadff52..e3d9a7b76 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit import com.vdurmont.semver4j.Semver diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index 25d77c621..f7d91515d 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit import com.vdurmont.semver4j.Semver diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BukkitModelEventBusImpl.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BukkitModelEventBusImpl.kt index d41b8522c..501a94790 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BukkitModelEventBusImpl.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BukkitModelEventBusImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit import kr.toxicity.model.BetterModelEventBusImpl diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudiencePlayer.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudiencePlayer.kt index 8032381f2..06daf076e 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudiencePlayer.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudiencePlayer.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.audience import kr.toxicity.model.bukkit.util.audience diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudienceSender.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudienceSender.kt index 8f479118c..335ae301b 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudienceSender.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/AudienceSender.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.audience import kr.toxicity.model.bukkit.util.audience diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/BukkitAudience.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/BukkitAudience.kt index e12be8db6..d84691297 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/BukkitAudience.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/audience/BukkitAudience.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.audience import net.kyori.adventure.audience.Audience diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt index 442ddb890..d7a5beb8a 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.command import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/Compatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/Compatibility.kt index 51b0b4089..319ba79ef 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/Compatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/Compatibility.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility fun interface Compatibility { diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/CitizensCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/CitizensCompatibility.kt index 861dfb676..f232ede17 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/CitizensCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/CitizensCompatibility.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.citizens import kr.toxicity.model.bukkit.compatibility.Compatibility diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/AnimateCommand.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/AnimateCommand.kt index 2ab3f3612..68cf51285 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/AnimateCommand.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/AnimateCommand.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.citizens.command import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/LimbCommand.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/LimbCommand.kt index 4be1608bd..891fe95b6 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/LimbCommand.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/LimbCommand.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.citizens.command import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/ModelCommand.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/ModelCommand.kt index cd3913964..db3759c67 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/ModelCommand.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/command/ModelCommand.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.citizens.command import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/trait/ModelTrait.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/trait/ModelTrait.kt index 58fd2c720..d6bed7a03 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/trait/ModelTrait.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/citizens/trait/ModelTrait.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.citizens.trait import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt index 564401c8c..476c0a4df 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs import io.lumine.mythic.bukkit.MythicBukkit diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt index 90b27b2ed..9708ab146 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/condition/ModelHasPassengerCondition.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/condition/ModelHasPassengerCondition.kt index d9e0e42c3..b5c47f3f2 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/condition/ModelHasPassengerCondition.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/condition/ModelHasPassengerCondition.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.condition import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/AbstractSkillMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/AbstractSkillMechanic.kt index a170c4c74..790a14943 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/AbstractSkillMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/AbstractSkillMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BillboardMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BillboardMechanic.kt index 83480d08e..9541f221f 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BillboardMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BillboardMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BindHitBoxMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BindHitBoxMechanic.kt index e6b7a951c..08f463708 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BindHitBoxMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BindHitBoxMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BodyRotationMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BodyRotationMechanic.kt index f6a90603a..3ca70929c 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BodyRotationMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BodyRotationMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BrightnessMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BrightnessMechanic.kt index 2899598e3..729aaab5c 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BrightnessMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/BrightnessMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ChangePartMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ChangePartMechanic.kt index f4ae3dde2..8bca88f43 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ChangePartMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ChangePartMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DefaultStateMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DefaultStateMechanic.kt index 3b9074cfb..dca0658c2 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DefaultStateMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DefaultStateMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountAllModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountAllModelMechanic.kt index 8962c7c7f..0e1ef03d1 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountAllModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountAllModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountModelMechanic.kt index 5c9b1eedb..b66aa854d 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/DismountModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/EnchantMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/EnchantMechanic.kt index 9531bfbe1..4e84c0e60 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/EnchantMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/EnchantMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/GlowMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/GlowMechanic.kt index 9dac73e6a..24b281375 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/GlowMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/GlowMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/LockModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/LockModelMechanic.kt index f1d3b8e33..446c85e54 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/LockModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/LockModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ModelMechanic.kt index 34dd422dc..91bb606b5 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/ModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/MountModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/MountModelMechanic.kt index 8f65bdf9c..f365ff3dc 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/MountModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/MountModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PairModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PairModelMechanic.kt index 029e36318..2985fe1b8 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PairModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PairModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PartVisibilityMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PartVisibilityMechanic.kt index 5b599a1ee..890b91e54 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PartVisibilityMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PartVisibilityMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PlayLimbAnimMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PlayLimbAnimMechanic.kt index 2ac837ef6..892eba8a8 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PlayLimbAnimMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/PlayLimbAnimMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/RemapModelMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/RemapModelMechanic.kt index eb13c34d7..ed8b685a4 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/RemapModelMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/RemapModelMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt index 75ca95ca7..c6e7268b3 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.adapters.AbstractEntity diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/TintMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/TintMechanic.kt index 497028b1e..885ed41ef 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/TintMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/TintMechanic.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic import io.lumine.mythic.api.config.MythicLineConfig diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/targeter/ModelPartTargeter.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/targeter/ModelPartTargeter.kt index cc7c2204a..83de1ee6c 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/targeter/ModelPartTargeter.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/targeter/ModelPartTargeter.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.mythicmobs.targeter import io.lumine.mythic.api.adapters.AbstractLocation diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt index ea0b0eec1..1198740a2 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.nexo import com.nexomc.nexo.api.events.resourcepack.NexoPrePackGenerateEvent diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/skinsrestorer/SkinsRestorerCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/skinsrestorer/SkinsRestorerCompatibility.kt index e515a281d..b63fec1e8 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/skinsrestorer/SkinsRestorerCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/skinsrestorer/SkinsRestorerCompatibility.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.compatibility.skinsrestorer import kr.toxicity.model.api.profile.ModelProfile diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt index cae1973c4..7820ec7f6 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.configuration import kr.toxicity.model.util.DATA_FOLDER diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/CompatibilityManager.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/CompatibilityManager.kt index 5a7ce97b1..374679fbb 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/CompatibilityManager.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/CompatibilityManager.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.manager import kr.toxicity.model.api.bukkit.BetterModelBukkit diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt index ad86c49d2..ad9de1784 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.manager import com.destroystokyo.paper.event.entity.EntityAddToWorldEvent diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/PlayerManagerImpl.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/PlayerManagerImpl.kt index d02ed9bec..c42ffa906 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/PlayerManagerImpl.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/PlayerManagerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.manager import kr.toxicity.model.api.manager.PlayerManager diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/BukkitScheduler.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/BukkitScheduler.kt index a201d6cf3..9a05c230c 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/BukkitScheduler.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/BukkitScheduler.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.scheduler import kr.toxicity.model.api.bukkit.scheduler.BukkitModelScheduler diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/PaperScheduler.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/PaperScheduler.kt index 8e470ae2f..12bcb8fdd 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/PaperScheduler.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/scheduler/PaperScheduler.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.scheduler import io.papermc.paper.threadedregions.scheduler.ScheduledTask diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt index 38bde745d..f4939a5d9 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Entities.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Entities.kt index 6550bd525..d666856b6 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Entities.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Entities.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import kr.toxicity.model.api.BetterModel diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Events.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Events.kt index 7d7d93b9e..096368b2a 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Events.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Events.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import org.bukkit.Bukkit diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Plugins.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Plugins.kt index 33b07778f..4a9844a6e 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Plugins.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Plugins.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import kr.toxicity.model.bukkit.BetterModelPlugin diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Senders.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Senders.kt index cdbb6be5b..89061103e 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Senders.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Senders.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import kr.toxicity.model.bukkit.BetterModelLibrary diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Yamls.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Yamls.kt index d7160a10e..373550775 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Yamls.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/Yamls.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.util import org.bukkit.configuration.file.YamlConfiguration diff --git a/core/src/main/java/kr/toxicity/model/BetterModelPlatformImpl.java b/core/src/main/java/kr/toxicity/model/BetterModelPlatformImpl.java index 6f15e4b29..41c8e958f 100644 --- a/core/src/main/java/kr/toxicity/model/BetterModelPlatformImpl.java +++ b/core/src/main/java/kr/toxicity/model/BetterModelPlatformImpl.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model; import kr.toxicity.model.api.BetterModelPlatform; diff --git a/core/src/main/kotlin/kr/toxicity/model/BetterModelEvaluatorImpl.kt b/core/src/main/kotlin/kr/toxicity/model/BetterModelEvaluatorImpl.kt index 214c0420f..7fad8352c 100644 --- a/core/src/main/kotlin/kr/toxicity/model/BetterModelEvaluatorImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/BetterModelEvaluatorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model import gg.moonflower.molangcompiler.api.MolangCompiler @@ -26,4 +27,4 @@ class BetterModelEvaluatorImpl : BetterModelEvaluator { it.query().safeResolve(compiled) } } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/BetterModelEventBusImpl.kt b/core/src/main/kotlin/kr/toxicity/model/BetterModelEventBusImpl.kt index f5ffbe978..a2c6a48fc 100644 --- a/core/src/main/kotlin/kr/toxicity/model/BetterModelEventBusImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/BetterModelEventBusImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model import kr.toxicity.model.api.BetterModelEventBus diff --git a/core/src/main/kotlin/kr/toxicity/model/command/CommandBuildContext.kt b/core/src/main/kotlin/kr/toxicity/model/command/CommandBuildContext.kt index c72c2906e..cc808b230 100644 --- a/core/src/main/kotlin/kr/toxicity/model/command/CommandBuildContext.kt +++ b/core/src/main/kotlin/kr/toxicity/model/command/CommandBuildContext.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.command import net.kyori.adventure.audience.Audience diff --git a/core/src/main/kotlin/kr/toxicity/model/command/CommandBuilder.kt b/core/src/main/kotlin/kr/toxicity/model/command/CommandBuilder.kt index dde02a253..c708f36cd 100644 --- a/core/src/main/kotlin/kr/toxicity/model/command/CommandBuilder.kt +++ b/core/src/main/kotlin/kr/toxicity/model/command/CommandBuilder.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.command import kr.toxicity.model.util.* diff --git a/core/src/main/kotlin/kr/toxicity/model/command/CommandExtensions.kt b/core/src/main/kotlin/kr/toxicity/model/command/CommandExtensions.kt index aaa86d6ff..40213bbb2 100644 --- a/core/src/main/kotlin/kr/toxicity/model/command/CommandExtensions.kt +++ b/core/src/main/kotlin/kr/toxicity/model/command/CommandExtensions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.command import kr.toxicity.model.api.BetterModel diff --git a/core/src/main/kotlin/kr/toxicity/model/command/CommandLike.kt b/core/src/main/kotlin/kr/toxicity/model/command/CommandLike.kt index 3cc745d83..f6a74c2fe 100644 --- a/core/src/main/kotlin/kr/toxicity/model/command/CommandLike.kt +++ b/core/src/main/kotlin/kr/toxicity/model/command/CommandLike.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.command import kr.toxicity.model.util.* diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt index c8825e6c2..383912d68 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import kr.toxicity.library.armormodel.ArmorImage diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/GlobalManager.kt b/core/src/main/kotlin/kr/toxicity/model/manager/GlobalManager.kt index def7cef8e..00832b014 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/GlobalManager.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/GlobalManager.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import kr.toxicity.model.api.pack.PackZipper @@ -12,4 +13,4 @@ interface GlobalManager { fun start() {} fun reload(pipeline: ReloadPipeline, zipper: PackZipper) fun end() {} -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt index 89814ad52..e861acc1e 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt @@ -1,12 +1,14 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import com.google.gson.JsonArray +import com.google.gson.JsonObject import kr.toxicity.model.api.bone.BoneItemMapper import kr.toxicity.model.api.data.ModelAsset import kr.toxicity.model.api.data.blueprint.BlueprintElement @@ -128,7 +130,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { private val legacyModel = ModelBuilder( models = zipper.legacy().bettermodel().models().resolve("item"), available = CONFIG.pack().generateLegacyModel, - onBuild = { blueprints, size -> + onBuild = { blueprints, _, size -> val json = blueprints.first() entries += jsonObjectOf( "predicate" to jsonObjectOf("custom_model_data" to indexer), @@ -154,10 +156,10 @@ object ModelManagerImpl : ModelManager, GlobalManager { private val modernModel = ModelBuilder( models = zipper.modern().bettermodel().models().resolve("modern_item"), available = CONFIG.pack().generateModernModel, - onBuild = { blueprints, size -> + onBuild = { blueprints, json, size -> entries += jsonObjectOf( "threshold" to indexer, - "model" to blueprints.toModernJson() + "model" to blueprints.toModernJson(json) ) blueprints.forEach { json -> models.add(json.jsonName(), size / blueprints.size) { @@ -195,19 +197,22 @@ object ModelManagerImpl : ModelManager, GlobalManager { targetMap: MutableMap, importedModel: ImportedModel ) { + val (_, type, blueprint) = importedModel + val context = blueprint.context() val size = importedModel.jsonSize - val blueprint = importedModel.blueprint - val hasTexture = blueprint.hasTexture() - targetMap[blueprint.name] = blueprint.toRenderer(importedModel.type) render@ { group -> - if (!hasTexture) return@render null + targetMap[blueprint.name] = blueprint.toRenderer(type) render@ { group -> + if (!context.canBeRendered()) return@render null listOfNotNull( modernModel.ifAvailable { - group.buildModernJson(obfuscator, blueprint) - ?.let { build(it, size / it.size) } + val json = group.buildModernJson(obfuscator, context) + val itemModel = group.buildMeshItemModel(context) + if (json != null || itemModel != null) { + build(json ?: emptyList(), itemModel, if (json != null) size / json.size else 0) + } else null }, legacyModel.ifAvailable { - group.buildLegacyJson(PLATFORM.version().useModernResource(), obfuscator, blueprint) - ?.let { build(listOf(it), size) } + group.buildLegacyJson(PLATFORM.version().useModernResource(), obfuscator, context) + ?.let { build(listOf(it), null, size) } } ).run { if (isNotEmpty()) indexer++ else null @@ -221,7 +226,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { } callEvent { ModelImportedEvent(blueprint, this) } } - if (hasTexture) blueprint.buildImage(textures.obfuscator()).forEach { image -> + context.buildImage(textures.obfuscator()).forEach { image -> textures.add(image.pngName(), image.estimatedSize()) { image.toByteArray() } @@ -237,7 +242,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { inner class ModelBuilder( val models: PackBuilder, private val available: Boolean, - private val onBuild: ModelBuilder.(List, Long) -> Unit, + private val onBuild: ModelBuilder.(List, JsonObject?, Long) -> Unit, private val onClose: ModelBuilder.() -> Unit ) : AutoCloseable { val entries = jsonArrayOf() @@ -247,8 +252,8 @@ object ModelManagerImpl : ModelManager, GlobalManager { return if (available) block() else null } - fun build(list: List, size: Long) { - onBuild(list, size) + fun build(list: List, json: JsonObject?, size: Long) { + onBuild(list, json, size) } override fun close() { @@ -258,9 +263,11 @@ object ModelManagerImpl : ModelManager, GlobalManager { } } - private fun List.toModernJson() = if (size == 1) first().toModernJson() else jsonObjectOf( + private fun List.toModernJson(plus: JsonObject?) = if (size == 1) first().toModernJson() else jsonObjectOf( "type" to "minecraft:composite", - "models" to fold(JsonArray(size)) { array, element -> array.apply { add(element.toModernJson()) } } + "models" to fold(JsonArray(size + (if (plus != null) 1 else 0)).apply { + plus?.run(::add) + }) { array, element -> array.apply { add(element.toModernJson()) } } ) private fun BlueprintJson.toModernJson() = jsonObjectOf( diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt index b77975d00..d18c6142f 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import com.google.gson.GsonBuilder diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt index e7b628014..52946a214 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import kr.toxicity.model.manager.debug.ReloadIndicator diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt index e294732ea..f6e086a06 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import kr.toxicity.model.api.event.AnimationSignalEvent diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt index 654411dfc..bd7767877 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager import com.github.benmanes.caffeine.cache.Caffeine diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt b/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt index 71a6e85c5..16ab4b9f1 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager.debug import kr.toxicity.model.manager.ReloadPipeline @@ -44,4 +45,4 @@ class BossBarIndicator( override fun close() { if (showed) audience.hideBossBar(bossBar) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/debug/ReloadIndicator.kt b/core/src/main/kotlin/kr/toxicity/model/manager/debug/ReloadIndicator.kt index 5c4787ab2..2329b5d58 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/debug/ReloadIndicator.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/debug/ReloadIndicator.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.manager.debug import kr.toxicity.model.manager.ReloadPipeline @@ -11,4 +12,4 @@ import kr.toxicity.model.manager.ReloadPipeline interface ReloadIndicator { infix fun status(status: ReloadPipeline.Status) fun close() -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/profile/DefaultHttpModelProfileSupplier.kt b/core/src/main/kotlin/kr/toxicity/model/profile/DefaultHttpModelProfileSupplier.kt index 87b5a7b0c..30dd23744 100644 --- a/core/src/main/kotlin/kr/toxicity/model/profile/DefaultHttpModelProfileSupplier.kt +++ b/core/src/main/kotlin/kr/toxicity/model/profile/DefaultHttpModelProfileSupplier.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.profile import kr.toxicity.model.api.platform.PlatformPlayer diff --git a/core/src/main/kotlin/kr/toxicity/model/profile/HttpModelProfileSupplier.kt b/core/src/main/kotlin/kr/toxicity/model/profile/HttpModelProfileSupplier.kt index e50045b69..2224efa3d 100644 --- a/core/src/main/kotlin/kr/toxicity/model/profile/HttpModelProfileSupplier.kt +++ b/core/src/main/kotlin/kr/toxicity/model/profile/HttpModelProfileSupplier.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.profile import com.github.benmanes.caffeine.cache.Caffeine diff --git a/core/src/main/kotlin/kr/toxicity/model/script/BrightnessScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/BrightnessScript.kt index d6f8bfdc6..72e98fc83 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/BrightnessScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/BrightnessScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.script.AnimationScript diff --git a/core/src/main/kotlin/kr/toxicity/model/script/ChangePartScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/ChangePartScript.kt index fc3112956..0e2713597 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/ChangePartScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/ChangePartScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.BetterModel @@ -33,4 +34,4 @@ class ChangePartScript( } override fun isSync(): Boolean = false -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/script/EnchantScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/EnchantScript.kt index 72dcf5db6..231fc5235 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/EnchantScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/EnchantScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.script.AnimationScript @@ -24,4 +25,4 @@ class EnchantScript( } override fun isSync(): Boolean = false -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/script/PartVisibilityScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/PartVisibilityScript.kt index 7f16b5abf..819aaada3 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/PartVisibilityScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/PartVisibilityScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.script.AnimationScript @@ -24,4 +25,4 @@ class PartVisibilityScript( } override fun isSync(): Boolean = false -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/script/RemapScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/RemapScript.kt index 6a057e3b2..c7e52182a 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/RemapScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/RemapScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.BetterModel diff --git a/core/src/main/kotlin/kr/toxicity/model/script/TintScript.kt b/core/src/main/kotlin/kr/toxicity/model/script/TintScript.kt index d7966585f..68c75656b 100644 --- a/core/src/main/kotlin/kr/toxicity/model/script/TintScript.kt +++ b/core/src/main/kotlin/kr/toxicity/model/script/TintScript.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.script import kr.toxicity.model.api.script.AnimationScript @@ -31,4 +32,4 @@ class TintScript( } override fun isSync(): Boolean = false -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Buffers.kt b/core/src/main/kotlin/kr/toxicity/model/util/Buffers.kt index d140755c7..db872bbff 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Buffers.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Buffers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import com.google.gson.JsonElement @@ -27,4 +28,4 @@ fun JsonElement.toByteArray(): ByteArray { } buffer.toByteArray() } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt b/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt index 84ab0e768..142c45dfb 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt @@ -1,11 +1,28 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util +import it.unimi.dsi.fastutil.objects.Object2ObjectMap +import it.unimi.dsi.fastutil.objects.Object2ObjectMaps +import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap +import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMaps +import it.unimi.dsi.fastutil.objects.Object2ReferenceMap +import it.unimi.dsi.fastutil.objects.Object2ReferenceMaps +import it.unimi.dsi.fastutil.objects.Object2ReferenceSortedMap +import it.unimi.dsi.fastutil.objects.Object2ReferenceSortedMaps +import it.unimi.dsi.fastutil.objects.Reference2ObjectMap +import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps +import it.unimi.dsi.fastutil.objects.Reference2ObjectSortedMap +import it.unimi.dsi.fastutil.objects.Reference2ObjectSortedMaps +import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap +import it.unimi.dsi.fastutil.objects.Reference2ReferenceMaps +import it.unimi.dsi.fastutil.objects.Reference2ReferenceSortedMap +import it.unimi.dsi.fastutil.objects.Reference2ReferenceSortedMaps import kr.toxicity.model.api.util.CollectionUtil import java.util.* import java.util.concurrent.CompletableFuture @@ -21,8 +38,21 @@ fun sequencedAddressingMapOf(capacity: Int) = CollectionUtil.newSequenced fun emptySequencedMap(): SequencedMap = Collections.emptyNavigableMap() -fun MutableMap.toImmutableView(): Map = Collections.unmodifiableMap(this) -fun SequencedMap.toImmutableView(): SequencedMap = Collections.unmodifiableSequencedMap(this) +fun MutableMap.toImmutableView(): Map = when (this) { + is Object2ObjectMap -> Object2ObjectMaps.unmodifiable(this) + is Object2ReferenceMap -> Object2ReferenceMaps.unmodifiable(this) + is Reference2ObjectMap -> Reference2ObjectMaps.unmodifiable(this) + is Reference2ReferenceMap -> Reference2ReferenceMaps.unmodifiable(this) + else -> Collections.unmodifiableMap(this) +} + +fun SequencedMap.toImmutableView(): SequencedMap = when (this) { + is Object2ObjectSortedMap -> Object2ObjectSortedMaps.unmodifiable(this) + is Object2ReferenceSortedMap -> Object2ReferenceSortedMaps.unmodifiable(this) + is Reference2ObjectSortedMap -> Reference2ObjectSortedMaps.unmodifiable(this) + is Reference2ReferenceSortedMap -> Reference2ReferenceSortedMaps.unmodifiable(this) + else -> Collections.unmodifiableSequencedMap(this) +} fun Stream.toSet(): Set = collect(Collectors.toUnmodifiableSet()) fun Stream.toMutableSet(): MutableSet = collect(Collectors.toSet()) diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Events.kt b/core/src/main/kotlin/kr/toxicity/model/util/Events.kt index 71fdf9f27..62f18351d 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Events.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Events.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import kr.toxicity.model.api.event.ModelEvent diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Files.kt b/core/src/main/kotlin/kr/toxicity/model/util/Files.kt index 457c8881c..eb76fb32a 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Files.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Files.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import java.awt.image.BufferedImage diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Functions.kt b/core/src/main/kotlin/kr/toxicity/model/util/Functions.kt index 6d80a2d9f..deddf2da2 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Functions.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import kr.toxicity.model.api.bone.BoneName diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Gsons.kt b/core/src/main/kotlin/kr/toxicity/model/util/Gsons.kt index 75f832427..9f7460871 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Gsons.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Gsons.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2024 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import com.google.gson.JsonArray diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Indicators.kt b/core/src/main/kotlin/kr/toxicity/model/util/Indicators.kt index 1a5815e69..9dffa198f 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Indicators.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Indicators.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import kr.toxicity.model.api.config.IndicatorConfig diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt b/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt index 42bb95642..90d029881 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import kr.toxicity.model.api.BetterModelConfig diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Platforms.kt b/core/src/main/kotlin/kr/toxicity/model/util/Platforms.kt index 6946666a9..d615b4d5f 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Platforms.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Platforms.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import com.github.benmanes.caffeine.cache.Caffeine diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Scripts.kt b/core/src/main/kotlin/kr/toxicity/model/util/Scripts.kt index a66b77dcb..e678b2df0 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Scripts.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Scripts.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import kr.toxicity.model.api.script.ScriptBuilder @@ -24,4 +25,4 @@ val ScriptBuilder.ScriptMetaData.bonePredicate get(): BonePredicate { } }) } -} \ No newline at end of file +} diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt b/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt index 91fec3ab3..304a37c60 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.util import net.kyori.adventure.audience.Audience diff --git a/gradle.properties b/gradle.properties index c146b2823..4972c33ae 100644 --- a/gradle.properties +++ b/gradle.properties @@ -4,11 +4,10 @@ kotlin.daemon.jvmargs=-Xmx4g org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true +org.gradle.configuration-cache=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 fabric.loom.multiProjectOptimisation=true -parchment_version=1.21.11+build.9 - project_version=3.0.0 -minecraft_version=26.1-rc-2 +minecraft_version=26.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7c0326d97..45b72687f 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,11 +7,11 @@ shadow = "9.4.0" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.144.0+26.1" +fabric-api = "0.144.3+26.1" fabric-language-kotlin = "1.13.9+kotlin.2.3.10" -cloud-bukkit = "2.0.0-beta.14" -cloud-mod = "2.0.0-beta.15" +cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released +cloud-mod = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.16 when released cloud-core = "2.0.0" configurate = "4.2.0" @@ -33,7 +33,7 @@ asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.18.4" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0-pre.1+26.1-rc-2" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0-pre.4+26.1" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } @@ -52,6 +52,7 @@ lombok = "org.projectlombok:lombok:1.18.44" bStats = "org.bstats:bstats-bukkit:3.2.1" dynamicUV = "io.github.toxicity188:dynamicuv:1.2.2" armormodel = "io.github.toxicity188:armormodel:1.0.2" +javamesh = "io.github.toxicity188:java-mesh:0.0.1" molangCompiler = "gg.moonflower:molang-compiler:3.1.1.19" libby = "net.byteflux:libby-bukkit:1.3.1" @@ -89,6 +90,7 @@ fabric-mod = [ library = [ "semver4j", "dynamicUV", + "javamesh", "caffeine" ] diff --git a/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java b/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java index 960571a75..97be180a3 100644 --- a/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java +++ b/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt index 7e1d957d2..d1d842a12 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt index 8bb648d82..173edf87a 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt index 65fdf5024..3eae9c109 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt index 035f0ccb3..0e8a4a325 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt index f66f0b712..cbf8428bb 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt index e9297adb8..646c6b0bd 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.BetterModel diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt index 323d2add3..569d16980 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt index cd885d9db..c557d26b9 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt index d75dbff41..0bdcd9ada 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt index 5ffe64ca9..07edeb93a 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt index 25a9da09e..f46d7de6d 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import com.mojang.math.Transformation diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt index fce2b04ef..3e2e23117 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt index 8b62db1c6..2913489c6 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt index 3d78ec577..731302600 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt index a43f9905c..a777080b0 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import net.minecraft.network.chat.Component diff --git a/nms/v1_21_R3/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R3/AbstractHitBox.java b/nms/v1_21_R3/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R3/AbstractHitBox.java index 4aa43ac9b..6e79d439a 100644 --- a/nms/v1_21_R3/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R3/AbstractHitBox.java +++ b/nms/v1_21_R3/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R3/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BaseEntityImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BaseEntityImpl.kt index 8de0073f0..25c3436de 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BaseEntityImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BasePlayerImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BasePlayerImpl.kt index a439736bf..6937dbb6a 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BasePlayerImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt index 6f0ae1dc4..a0378c6f9 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/EntityData.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/EntityData.kt index 19eb216fd..fa8246c4c 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/EntityData.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt index 4c1be066a..13de53699 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt index d33f194b9..516b1d5af 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import io.papermc.paper.event.entity.EntityKnockbackEvent diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt index 5bbdced80..44349b966 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDamageSourceImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDamageSourceImpl.kt index 98febb94b..be56c769b 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDisplayImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDisplayImpl.kt index 84b72dea1..98cdf76a4 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDisplayImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelGameProfile.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelGameProfile.kt index fc3f9088b..263f48858 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelGameProfile.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelNametagImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelNametagImpl.kt index 87a7e6ac4..934139dc7 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelNametagImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import com.mojang.math.Transformation diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt index a5f1826bb..3020c03bf 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PacketBundlers.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PacketBundlers.kt index 799370c1e..08562e0eb 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PacketBundlers.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PlayerArmorImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PlayerArmorImpl.kt index ad54fa82c..16424acd2 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PlayerArmorImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.armor.ArmorItem diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ProfiledImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ProfiledImpl.kt index 655b8500b..a2e0659e6 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ProfiledImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/TypeAliases.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/TypeAliases.kt index 3530fecaa..5d398e124 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/TypeAliases.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import net.minecraft.network.chat.Component diff --git a/nms/v1_21_R4/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R4/AbstractHitBox.java b/nms/v1_21_R4/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R4/AbstractHitBox.java index feea29ad1..5e7380754 100644 --- a/nms/v1_21_R4/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R4/AbstractHitBox.java +++ b/nms/v1_21_R4/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R4/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BaseEntityImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BaseEntityImpl.kt index f310438af..569b909cf 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BaseEntityImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BasePlayerImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BasePlayerImpl.kt index 061f4b099..191c0b17a 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BasePlayerImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt index 5d2d389da..b88e14b26 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/EntityData.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/EntityData.kt index ba6480db7..944f5ae68 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/EntityData.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt index 99d91b49e..62321d30d 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt index 25e7d080a..989ff33c2 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import io.papermc.paper.event.entity.EntityKnockbackEvent diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt index 53527f8e6..bd13beb60 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDamageSourceImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDamageSourceImpl.kt index 9e0f9357d..e001d789c 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDisplayImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDisplayImpl.kt index 5309d24e0..1052bdf36 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDisplayImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelGameProfile.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelGameProfile.kt index cd5049c80..df27eae7c 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelGameProfile.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelNametagImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelNametagImpl.kt index 2ee7432f0..e11957432 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelNametagImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import com.mojang.math.Transformation diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt index 94d520f20..ce24980f8 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PacketBundlers.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PacketBundlers.kt index 9fb39f95d..44896f9b2 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PacketBundlers.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PlayerArmorImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PlayerArmorImpl.kt index a256b4371..328be680f 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PlayerArmorImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.armor.ArmorItem diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ProfiledImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ProfiledImpl.kt index 52b38622c..4b510ff11 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ProfiledImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/TypeAliases.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/TypeAliases.kt index d6015e775..bd0cfa798 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/TypeAliases.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import net.minecraft.network.chat.Component diff --git a/nms/v1_21_R5/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R5/AbstractHitBox.java b/nms/v1_21_R5/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R5/AbstractHitBox.java index 13c5f329d..a43bf2350 100644 --- a/nms/v1_21_R5/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R5/AbstractHitBox.java +++ b/nms/v1_21_R5/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R5/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BaseEntityImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BaseEntityImpl.kt index 03ed28bbc..2ebe08662 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BaseEntityImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BasePlayerImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BasePlayerImpl.kt index 85ab2b4a2..9c6a38df8 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BasePlayerImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt index 7af1fafcc..e287de302 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/EntityData.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/EntityData.kt index 02cf9525a..63a8c3fcb 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/EntityData.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt index 8e9f8b080..cf0c468e1 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt index 82f714fa4..48818127c 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import io.papermc.paper.event.entity.EntityKnockbackEvent diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt index 4c0b49132..d64673a69 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDamageSourceImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDamageSourceImpl.kt index ff5edb4ce..3e90d27ec 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDisplayImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDisplayImpl.kt index 8ac8be338..4a9788bc0 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDisplayImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelGameProfile.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelGameProfile.kt index a13045944..6289184e1 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelGameProfile.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelNametagImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelNametagImpl.kt index bb780d6b9..f7792b55f 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelNametagImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import com.mojang.math.Transformation diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt index ecf721f64..b2455f434 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PacketBundlers.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PacketBundlers.kt index 859e2fcd9..dcbf7dd44 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PacketBundlers.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PlayerArmorImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PlayerArmorImpl.kt index 2b21c0303..0c3933f44 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PlayerArmorImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.armor.ArmorItem diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ProfiledImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ProfiledImpl.kt index 915d8b875..032395e83 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ProfiledImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/TypeAliases.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/TypeAliases.kt index 55ce710e2..70959d1aa 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/TypeAliases.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import net.minecraft.network.chat.Component diff --git a/nms/v1_21_R6/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R6/AbstractHitBox.java b/nms/v1_21_R6/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R6/AbstractHitBox.java index 068ff053e..80ee934be 100644 --- a/nms/v1_21_R6/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R6/AbstractHitBox.java +++ b/nms/v1_21_R6/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R6/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BaseEntityImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BaseEntityImpl.kt index a9641074a..d6fccdd42 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BaseEntityImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BasePlayerImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BasePlayerImpl.kt index e154a3b06..f19fb5939 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BasePlayerImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt index b7b36eaf1..e6528659a 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/EntityData.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/EntityData.kt index 0d28c444d..7470cbb56 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/EntityData.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt index ea9695706..64e8cd32c 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt index 1d8feca9a..1f9e14185 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import io.papermc.paper.event.entity.EntityKnockbackEvent diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt index 996de5f1a..aaba034c2 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDamageSourceImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDamageSourceImpl.kt index 85a980061..f27f28e9d 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDisplayImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDisplayImpl.kt index 6a75f2544..4889968a1 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDisplayImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelGameProfile.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelGameProfile.kt index f093478e7..ec89eff15 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelGameProfile.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelNametagImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelNametagImpl.kt index fb068c55c..27a4f1761 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelNametagImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import com.mojang.math.Transformation diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt index 830653f5b..370396ae2 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PacketBundlers.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PacketBundlers.kt index fd215b1c5..a9626d0c7 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PacketBundlers.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PlayerArmorImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PlayerArmorImpl.kt index b16d30a68..f859db910 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PlayerArmorImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.armor.ArmorItem diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ProfiledImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ProfiledImpl.kt index 4b6d0faaf..5b0f09820 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ProfiledImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/TypeAliases.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/TypeAliases.kt index c37809224..916f5b880 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/TypeAliases.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import net.minecraft.network.chat.Component diff --git a/nms/v1_21_R7/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R7/AbstractHitBox.java b/nms/v1_21_R7/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R7/AbstractHitBox.java index 74625d938..5ca6238d4 100644 --- a/nms/v1_21_R7/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R7/AbstractHitBox.java +++ b/nms/v1_21_R7/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R7/AbstractHitBox.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7; import kr.toxicity.model.api.nms.HitBox; diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BaseEntityImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BaseEntityImpl.kt index ea2300d81..d41ecee3a 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BaseEntityImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BaseEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BasePlayerImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BasePlayerImpl.kt index eb236e36d..525e919b8 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BasePlayerImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BasePlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt index 1d046395c..2b289b6d8 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/EntityData.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/EntityData.kt index d93dd9b5e..edc04882a 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/EntityData.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/EntityData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.util.MathUtil diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt index 9513bacc0..72f2ea59a 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import io.netty.buffer.Unpooled diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt index 683c2d0f3..261190096 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import io.papermc.paper.event.entity.EntityKnockbackEvent diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt index 95ba4f0fa..aef838c8c 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.nms.HitBox diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDamageSourceImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDamageSourceImpl.kt index 57d654947..9661afa96 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDamageSourceImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.event.ModelDamageSource diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDisplayImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDisplayImpl.kt index 5434af7b2..294236393 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDisplayImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelDisplayImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.entity.BaseEntity diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelGameProfile.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelGameProfile.kt index d25a277d5..098577e85 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelGameProfile.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelGameProfile.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import com.mojang.authlib.GameProfile diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelNametagImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelNametagImpl.kt index dd497ccf2..8c28c180d 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelNametagImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import com.mojang.math.Transformation diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt index 7ae62934b..68b334812 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PacketBundlers.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PacketBundlers.kt index b6bfe572f..9c0b794a0 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PacketBundlers.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.nms.PacketBundler diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PlayerArmorImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PlayerArmorImpl.kt index d4ba922be..02cf31564 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PlayerArmorImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.armor.ArmorItem diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ProfiledImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ProfiledImpl.kt index 3ac6cefbf..1281b2e83 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ProfiledImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.armor.PlayerArmor diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/TypeAliases.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/TypeAliases.kt index 0ccdbfbf9..8a5f12a15 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/TypeAliases.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/TypeAliases.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import net.minecraft.network.chat.Component diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index b9d52ab86..e30dd62e8 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -10,7 +10,7 @@ plugins { val versionString = "${rootProject.version}+${property("minecraft_version")}" val jarName = "${rootProject.name}-$versionString-${project.name}.jar" -val jarDir: Provider = rootProject.layout.buildDirectory.dir("libs") +val jarDir = rootProject.layout.buildDirectory.dir("libs") sourceSets { create("testmod") { @@ -42,14 +42,9 @@ loom { //createRemapConfigurations(sourceSets["testmod"]) } - dependencies { // Minecraft minecraft("com.mojang:minecraft:${property("minecraft_version")}") -// mappings(loom.layered { -// officialMojangMappings() -// parchment("io.papermc.parchment.data:parchment:${property("parchment_version")}") -// }) api(project(":api")); include(project(":api")) api(project(":core")); include(project(":core")) @@ -74,7 +69,6 @@ dependencies { implementation(libs.bundles.core); include(libs.bundles.core) include(libs.bundles.library) - } fabricModJson { @@ -149,6 +143,23 @@ sourceSets["testmod"].resourceFactory { } } +interface FsInjected { + @get:Inject val fs: FileSystemOperations +} +val copyModJar by tasks.registering { + val injected = objects.newInstance() + val archiveFile = tasks.jar.flatMap { it.archiveFile } + val jarName = jarName + val jarDir = jarDir + doLast { + injected.fs.copy { + from(archiveFile) + rename { jarName } + into(jarDir) + } + } +} + tasks { jar { from(rootProject.layout.projectDirectory.file("LICENSE.md")) @@ -168,13 +179,7 @@ tasks { ) ) } - doLast { - copy { - from(archiveFile) - rename { jarName } - into(jarDir) - } - } + finalizedBy(copyModJar) } runServer { enabled = false diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java index 260b2c3a0..7c7f13df0 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric; import kr.toxicity.model.api.BetterModel; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java index 44c621bb5..97daac47f 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.entity; import kr.toxicity.model.api.entity.BaseEntity; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java index 688c0b6c2..652d92965 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.entity; import kr.toxicity.model.api.entity.BasePlayer; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java index 5cf3fce8b..82b105c45 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import com.mojang.authlib.GameProfile; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java index 3327f9fd2..8809454c2 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformEntity; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java index 8c809fc4a..9f5e77c5b 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformItemStack; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java index 126e42875..15bfd4dfd 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformLivingEntity; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java index 19f6f4223..acf751089 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.fabric.BetterModelFabric; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java index 0a5ce1ec5..43df9561c 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformOfflinePlayer; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java index 06cd48876..3ab486a9c 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformLocation; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java index bd2a419a9..b8fbd0729 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformRegionHolder; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java index ffe9ba896..3da38afed 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.platform; import kr.toxicity.model.api.platform.PlatformWorld; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java index 3476bfdce..168b251c2 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.fabric.scheduler; import kr.toxicity.model.api.scheduler.ModelScheduler; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/AbstractArmorStand.java b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/AbstractArmorStand.java index 7d599c582..70ac692df 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/AbstractArmorStand.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/AbstractArmorStand.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity; import net.minecraft.world.entity.EntityType; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/EntityHook.java b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/EntityHook.java index 288efc742..7b97e4a7d 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/EntityHook.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/entity/EntityHook.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity; import org.jetbrains.annotations.Nullable; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/network/BetterModelBundlePacket.java b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/network/BetterModelBundlePacket.java index ff8d24097..3ffb0cfce 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/network/BetterModelBundlePacket.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/impl/fabric/network/BetterModelBundlePacket.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.network; public interface BetterModelBundlePacket { diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/AvatarAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/AvatarAccessor.java index eeeeb76b8..2e5dcbcf7 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/AvatarAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/AvatarAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.syncher.EntityDataAccessor; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ClientboundBundlePacketMixin.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ClientboundBundlePacketMixin.java index b576cbad9..eaf0b27ea 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ClientboundBundlePacketMixin.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ClientboundBundlePacketMixin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import kr.toxicity.model.impl.fabric.network.BetterModelBundlePacket; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ConnectionAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ConnectionAccessor.java index aef828980..ecefb1d7c 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ConnectionAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ConnectionAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import io.netty.channel.Channel; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/DisplayAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/DisplayAccessor.java index 116138ff4..cc9d79963 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/DisplayAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/DisplayAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.syncher.EntityDataAccessor; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityAccessor.java index 00e52f539..88d9a5ea2 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.syncher.EntityDataAccessor; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java index ea0da7a18..a53252bc7 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/EntityMixin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import kr.toxicity.model.impl.fabric.attachment.BetterModelAttachments; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ItemDisplayAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ItemDisplayAccessor.java index 06918bd3f..04dbd4f57 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ItemDisplayAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ItemDisplayAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.syncher.EntityDataAccessor; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/LivingEntityMixin.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/LivingEntityMixin.java index 2bb7be9ed..48ee94140 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/LivingEntityMixin.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/LivingEntityMixin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import com.llamalad7.mixinextras.sugar.Local; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/MobAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/MobAccessor.java index bc78ff164..5a18c7dff 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/MobAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/MobAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.world.entity.Mob; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerCommonPacketListenerImplAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerCommonPacketListenerImplAccessor.java index 743c21e9c..25ce395c2 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerCommonPacketListenerImplAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerCommonPacketListenerImplAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.Connection; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerLevelEntityCallbacksMixin.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerLevelEntityCallbacksMixin.java index 43a4f4141..a991e2c4b 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerLevelEntityCallbacksMixin.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/ServerLevelEntityCallbacksMixin.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import kr.toxicity.model.impl.fabric.events.ServerMobEffectLoadCallback; diff --git a/platform/fabric/src/main/java/kr/toxicity/model/mixin/SynchedEntityDataAccessor.java b/platform/fabric/src/main/java/kr/toxicity/model/mixin/SynchedEntityDataAccessor.java index 5160a1b3a..1666b3cb7 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/mixin/SynchedEntityDataAccessor.java +++ b/platform/fabric/src/main/java/kr/toxicity/model/mixin/SynchedEntityDataAccessor.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.mixin; import net.minecraft.network.syncher.EntityDataAccessor; diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt index 1dc49b7ef..ef7743414 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric import com.vdurmont.semver4j.Semver diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt index ca898dfcd..0de11b565 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric import kr.toxicity.model.api.BetterModelLogger diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt index 6c2995cf2..6e06de3c7 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric import com.google.common.collect.ImmutableMultimap @@ -147,7 +148,7 @@ class BetterModelNMSImpl : NMS { ) } - override fun version(): NMSVersion = NMSVersion.V1_21_R7 + override fun version(): NMSVersion = NMSVersion.V26_R1 override fun adapt(entity: PlatformEntity): BaseEntity = BaseFabricEntityImpl(entity.unwarp()) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Constants.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Constants.kt index 88c7b35cd..8f7269011 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Constants.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Constants.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric import org.slf4j.Logger diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt index 1e0504482..e0029f604 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Entities.kt @@ -1,6 +1,6 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt index adfacd7cf..35963d9dd 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric import kr.toxicity.model.api.fabric.platform.* diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Functions.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Functions.kt index f467caf4c..65605502a 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Functions.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/Functions.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric inline fun dirtyChecked(crossinline hash: () -> H, crossinline function: (H) -> T): () -> T { diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/armor/PlayerArmorImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/armor/PlayerArmorImpl.kt index e7022efbb..579be337b 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/armor/PlayerArmorImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/armor/PlayerArmorImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.armor import kr.toxicity.model.api.armor.ArmorItem diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/attachment/BetterModelAttachments.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/attachment/BetterModelAttachments.kt index 535dbcece..8a81e3d83 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/attachment/BetterModelAttachments.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/attachment/BetterModelAttachments.kt @@ -1,6 +1,6 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceCommandSource.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceCommandSource.kt index 697064edb..d50b0e406 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceCommandSource.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceCommandSource.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.audience import net.kyori.adventure.audience.Audience diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudiencePlayer.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudiencePlayer.kt index de3dd350b..d8820f5dc 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudiencePlayer.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudiencePlayer.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.audience import net.kyori.adventure.bossbar.BossBar diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceSourceStack.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceSourceStack.kt index bcc7d9087..32744161a 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceSourceStack.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/audience/AudienceSourceStack.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.audience import net.kyori.adventure.bossbar.BossBar diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/chat/Components.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/chat/Components.kt index 042830304..8c6e12f5c 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/chat/Components.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/chat/Components.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.chat import net.kyori.adventure.platform.modcommon.impl.NonWrappingComponentSerializer diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt index 3bb2ada28..406534529 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.command import kr.toxicity.model.api.BetterModel diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/config/BetterModelConfigImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/config/BetterModelConfigImpl.kt index 2296919a0..206efd3d8 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/config/BetterModelConfigImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/config/BetterModelConfigImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.config import kr.toxicity.model.api.BetterModelConfig diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt index e3f9eb8b2..5ad9a899f 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.fabric.entity.BaseFabricEntity diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt index b7dbd3899..eb04657e2 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.fabric.entity.BaseFabricEntity diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/DisplayTransformerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/DisplayTransformerImpl.kt index 2157f5648..20f317652 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/DisplayTransformerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/DisplayTransformerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.nms.DisplayTransformer diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt index a1efb1697..ed933c846 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.bone.BoneMovement diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt index c710b3ebd..f074437eb 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import net.minecraft.world.InteractionHand diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelDisplayEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelDisplayEntityImpl.kt index eebb4db76..f0a2de97b 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelDisplayEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelDisplayEntityImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import it.unimi.dsi.fastutil.ints.IntOpenHashSet diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt index f72081ed4..dae80c4a7 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import com.mojang.math.Transformation diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt index 62f305257..75bbde77b 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import io.netty.channel.ChannelDuplexHandler diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ProfiledImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ProfiledImpl.kt index c48410d7f..aa690992c 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ProfiledImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ProfiledImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.armor.PlayerArmor diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/TransformationData.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/TransformationData.kt index dae68eefd..0e10bcb50 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/TransformationData.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/TransformationData.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.entity import kr.toxicity.model.api.util.MathUtil diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerEntityDismountCallback.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerEntityDismountCallback.kt index 2ad85cfa3..e9153cfd1 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerEntityDismountCallback.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerEntityDismountCallback.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.events import net.fabricmc.fabric.api.event.EventFactory diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerLivingEntityJumpCallback.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerLivingEntityJumpCallback.kt index 01a65b38e..0d43e5d9c 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerLivingEntityJumpCallback.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerLivingEntityJumpCallback.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.events import net.fabricmc.fabric.api.event.EventFactory diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectLoadCallback.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectLoadCallback.kt index 65ed7d5ef..e58aaa613 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectLoadCallback.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectLoadCallback.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.events import net.fabricmc.fabric.api.event.EventFactory diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectUnloadCallback.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectUnloadCallback.kt index 7a5d72bad..766488276 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectUnloadCallback.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/events/ServerMobEffectUnloadCallback.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.events import net.fabricmc.fabric.api.event.EventFactory diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt index d7eed4c5f..64f8c75c2 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.manager import kr.toxicity.model.api.BetterModel diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/PlayerManagerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/PlayerManagerImpl.kt index 3e4691f16..bfb88868d 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/PlayerManagerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/PlayerManagerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.manager import kr.toxicity.model.api.manager.PlayerManager diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/Syncers.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/Syncers.kt index 931bb49ce..4f5811fb9 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/Syncers.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/Syncers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.manager import kr.toxicity.model.mixin.SynchedEntityDataAccessor diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/PacketBundlers.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/PacketBundlers.kt index 3fc6a756e..c8729a585 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/PacketBundlers.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/PacketBundlers.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.network import kr.toxicity.model.api.nms.PacketBundler diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt index 85cd7fcae..13099d46b 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.network import com.mojang.datafixers.util.Pair.of diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/profile/ModelProfileImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/profile/ModelProfileImpl.kt index b02d2ec6a..bb9b1dbe3 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/profile/ModelProfileImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/profile/ModelProfileImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.profile import com.mojang.authlib.GameProfile diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt index 05fef7a18..263803e95 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.scheduler import kr.toxicity.model.api.fabric.platform.FabricRegionHolder diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt index 0d98a34f6..0a90b6997 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/Chunks.kt @@ -1,6 +1,6 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt index 373e92c86..8cd81f566 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.impl.fabric.world.damagesource import kr.toxicity.model.api.event.ModelDamageSource diff --git a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt index 8a3103bba..9dc7a4931 100644 --- a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt +++ b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.test import com.mojang.brigadier.builder.LiteralArgumentBuilder diff --git a/platform/paper/build.gradle.kts b/platform/paper/build.gradle.kts index 468cf8837..628cff8f6 100644 --- a/platform/paper/build.gradle.kts +++ b/platform/paper/build.gradle.kts @@ -7,6 +7,9 @@ plugins { } val libraryDir: Provider = layout.buildDirectory.file("generated/paper-library") +val dependenciesContent: String = libs.bundles.library.map { bundle -> + bundle.joinToString("\n") { dep -> dep.toString() } +}.get() dependencies { shade(project(":nms:v1_21_R1")) { isTransitive = false } @@ -26,11 +29,15 @@ tasks.modrinth { } val generatePaperLibrary by tasks.registering { - outputs.file(libraryDir) + val outputProvider = libraryDir + val contentProvider = dependenciesContent + + outputs.file(outputProvider) + doLast { - val file = libraryDir.get().asFile + val file = outputProvider.get().asFile file.parentFile.mkdirs() - file.writeText(libs.bundles.library.get().joinToString("\n") { dep -> dep.toString() }) + file.writeText(contentProvider) } } diff --git a/platform/paper/src/main/java/kr/toxicity/model/paper/BetterModelLoader.java b/platform/paper/src/main/java/kr/toxicity/model/paper/BetterModelLoader.java index 076a13410..b52e730bd 100644 --- a/platform/paper/src/main/java/kr/toxicity/model/paper/BetterModelLoader.java +++ b/platform/paper/src/main/java/kr/toxicity/model/paper/BetterModelLoader.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.paper; import io.papermc.paper.plugin.loader.PluginClasspathBuilder; diff --git a/platform/paper/src/main/kotlin/kr/toxicity/model/paper/BetterModelPaper.kt b/platform/paper/src/main/kotlin/kr/toxicity/model/paper/BetterModelPaper.kt index 4553e242c..343fa5eef 100644 --- a/platform/paper/src/main/kotlin/kr/toxicity/model/paper/BetterModelPaper.kt +++ b/platform/paper/src/main/kotlin/kr/toxicity/model/paper/BetterModelPaper.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.paper import kr.toxicity.model.api.BetterModelPlatform diff --git a/purpur/build.gradle.kts b/purpur/build.gradle.kts index b1c363e87..30d5ab1ca 100644 --- a/purpur/build.gradle.kts +++ b/purpur/build.gradle.kts @@ -3,5 +3,6 @@ plugins { } dependencies { - compileOnly("org.purpurmc.purpur:purpur-api:${property("minecraft_version")}-R0.1-SNAPSHOT") + //TODO change this to compileOnly("org.purpurmc.purpur:purpur-api:${property("minecraft_version")}-R0.1-SNAPSHOT") + compileOnly("org.purpurmc.purpur:purpur-api:1.21.11-R0.1-SNAPSHOT") } diff --git a/purpur/src/main/kotlin/kr/toxicity/model/bukkit/purpur/PurpurHook.kt b/purpur/src/main/kotlin/kr/toxicity/model/bukkit/purpur/PurpurHook.kt index 26146a758..e135ee5b0 100644 --- a/purpur/src/main/kotlin/kr/toxicity/model/bukkit/purpur/PurpurHook.kt +++ b/purpur/src/main/kotlin/kr/toxicity/model/bukkit/purpur/PurpurHook.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.purpur import kr.toxicity.model.api.BetterModel diff --git a/settings.gradle.kts b/settings.gradle.kts index aa845ccb8..0b9383e52 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -41,26 +41,26 @@ rootProject.name = "BetterModel" include( //api "api", -// "api:bukkit-api", + "api:bukkit-api", //core "core", -// "core:bukkit-core", + "core:bukkit-core", -// "purpur", + "purpur", -// "platform:spigot", -// "platform:paper", + //"platform:spigot", TODO reobf does not work in Java 25 + "platform:paper", "platform:fabric", -// //nms -// "nms:v1_21_R1", -// "nms:v1_21_R3", -// "nms:v1_21_R4", -// "nms:v1_21_R5", -// "nms:v1_21_R6", -// "nms:v1_21_R7", -// -// //test -// "test-plugin" + //nms + "nms:v1_21_R1", + "nms:v1_21_R3", + "nms:v1_21_R4", + "nms:v1_21_R5", + "nms:v1_21_R6", + "nms:v1_21_R7", + + //test + "test-plugin" ) diff --git a/test-plugin/src/main/java/kr/toxicity/model/test/BetterModelTest.java b/test-plugin/src/main/java/kr/toxicity/model/test/BetterModelTest.java index 2a63f206a..757c922fb 100644 --- a/test-plugin/src/main/java/kr/toxicity/model/test/BetterModelTest.java +++ b/test-plugin/src/main/java/kr/toxicity/model/test/BetterModelTest.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.test; import org.bukkit.plugin.java.JavaPlugin; diff --git a/test-plugin/src/main/java/kr/toxicity/model/test/FightTester.java b/test-plugin/src/main/java/kr/toxicity/model/test/FightTester.java index 917517450..1d0f176fe 100644 --- a/test-plugin/src/main/java/kr/toxicity/model/test/FightTester.java +++ b/test-plugin/src/main/java/kr/toxicity/model/test/FightTester.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.test; import com.google.gson.JsonObject; diff --git a/test-plugin/src/main/java/kr/toxicity/model/test/ModelTester.java b/test-plugin/src/main/java/kr/toxicity/model/test/ModelTester.java index 8faf9d8ef..fbf125f92 100644 --- a/test-plugin/src/main/java/kr/toxicity/model/test/ModelTester.java +++ b/test-plugin/src/main/java/kr/toxicity/model/test/ModelTester.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.test; import org.jetbrains.annotations.NotNull; diff --git a/test-plugin/src/main/java/kr/toxicity/model/test/RollTester.java b/test-plugin/src/main/java/kr/toxicity/model/test/RollTester.java index 91ddc5cd7..627c20a13 100644 --- a/test-plugin/src/main/java/kr/toxicity/model/test/RollTester.java +++ b/test-plugin/src/main/java/kr/toxicity/model/test/RollTester.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2025 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.test; import io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent; From 533a77a68685b26f3ca5932382095df27dfa0f44 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 29 Mar 2026 15:14:46 +0900 Subject: [PATCH 03/91] fix: commit problem --- api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java | 1 - .../model/api/util/collection/SingletonSequencedSet.java | 2 ++ .../main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt | 2 +- gradle.properties | 3 --- gradle/libs.versions.toml | 2 ++ .../src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt | 1 - 6 files changed, 5 insertions(+), 6 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java index e1e3e5381..48f59ec0e 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java @@ -11,7 +11,6 @@ import com.google.gson.JsonObject; import kr.toxicity.model.api.data.Float4; import kr.toxicity.model.api.data.blueprint.BlueprintLoadContext; -import kr.toxicity.model.api.data.blueprint.ModelBlueprint; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java b/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java index a33225669..2da6052f3 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/SingletonSequencedSet.java @@ -100,6 +100,8 @@ public E removeLast() { } @Override + @NotNull + @Unmodifiable public SequencedSet reversed() { return this; } diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt index f6e086a06..17528f195 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ScriptManagerImpl.kt @@ -21,7 +21,7 @@ import java.util.regex.Pattern object ScriptManagerImpl : ScriptManager, GlobalManager { private val scriptMap = hashMapOf() - private val scriptPattern = Pattern.compile("^(?[a-zA-Z]+)(:(?(\\w|_|-)+))?(\\{(?(\\w|\\W)+)})?$") + private val scriptPattern = Pattern.compile("^(?[a-zA-Z]+)(:(?([\\w_\\-])+))?(\\{(?([\\w\\W])+)})?$") private val validatePattern = Pattern.compile("^[a-z]+$") init { diff --git a/gradle.properties b/gradle.properties index 4972c33ae..10e478654 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,9 +1,6 @@ kotlin.code.style=official kotlin.daemon.jvmargs=-Xmx4g -org.jetbrains.dokka.experimental.gradle.pluginMode=V2Enabled -org.jetbrains.dokka.experimental.gradle.pluginMode.noWarn=true - org.gradle.configuration-cache=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index aa0cc9428..3fa3189ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -52,6 +52,7 @@ lombok = "org.projectlombok:lombok:1.18.44" bStats = "org.bstats:bstats-bukkit:3.2.1" dynamicUV = "io.github.toxicity188:dynamicuv:1.2.2" armormodel = "io.github.toxicity188:armormodel:1.0.2" +javamesh = "io.github.toxicity188:java-mesh:0.0.1" molangCompiler = "gg.moonflower:molang-compiler:3.1.1.19" libby = "net.byteflux:libby-bukkit:1.3.1" @@ -89,6 +90,7 @@ fabric-mod = [ library = [ "semver4j", "dynamicUV", + "javamesh", "caffeine" ] diff --git a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt index 9dc7a4931..abc132338 100644 --- a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt +++ b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt @@ -97,7 +97,6 @@ class RollTest : ModInitializer { } val isAnimated = tracker.animate( - { true }, "roll", AnimationModifier.DEFAULT_WITH_PLAY_ONCE ) { From 34df3bda02d0259a62b9f4d2654534791688bbe2 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 30 Mar 2026 01:09:21 +0900 Subject: [PATCH 04/91] feat: bettermodel-mod-api --- api/bukkit-api/build.gradle.kts | 2 +- api/mod-api/build.gradle.kts | 14 +++++ .../model/api/mod/BetterModelMod.java | 18 +++--- .../model/api/mod/entity/BaseModEntity.java | 6 +- .../model/api/mod/entity/BaseModPlayer.java | 8 +-- .../model/api/mod/platform/ModAdapter.java | 27 +++++---- .../model/api/mod/platform/ModEntity.java | 16 +++--- .../model/api/mod/platform/ModItemStack.java | 16 +++--- .../api/mod/platform/ModLivingEntity.java | 18 +++--- .../model/api/mod/platform/ModLocation.java | 56 +++++++++---------- .../api/mod/platform/ModOfflinePlayer.java | 14 ++--- .../model/api/mod/platform/ModPlayer.java | 18 +++--- .../api/mod/platform/ModRegionHolder.java | 8 +-- .../model/api/mod/platform/ModWorld.java | 10 ++-- .../api/mod/scheduler/ModModelScheduler.java | 8 +-- .../kr/toxicity/model/api/data/Float4.java | 11 ++++ .../model/api/data/raw/ModelFace.java | 13 +++-- .../toxicity/model/api/data/raw/ModelUV.java | 7 ++- build.gradle.kts | 10 ++-- .../kotlin/modrinth-conventions.gradle.kts | 4 +- .../kotlin/paperweight-conventions.gradle.kts | 4 +- .../main/kotlin/plugin-conventions.gradle.kts | 10 ++-- .../kotlin/publish-conventions.gradle.kts | 12 +--- core/build.gradle.kts | 2 +- core/bukkit-core/build.gradle.kts | 6 +- .../model/bukkit/BetterModelProperties.kt | 2 +- .../model/manager/ModelManagerImpl.kt | 8 +-- gradle.properties | 4 +- gradle/libs.versions.toml | 6 +- platform/fabric/build.gradle.kts | 10 ++-- .../impl/fabric/BetterModelFabricImpl.kt | 12 ++-- .../model/impl/fabric/BetterModelNMSImpl.kt | 4 +- .../model/impl/fabric/FabricWrappers.kt | 14 ++--- .../model/impl/fabric/command/Commands.kt | 4 +- .../fabric/entity/BaseFabricEntityImpl.kt | 4 +- .../fabric/entity/BaseFabricPlayerImpl.kt | 6 +- .../impl/fabric/entity/HitBoxEntityImpl.kt | 6 +- .../impl/fabric/entity/ModelNametagImpl.kt | 4 +- .../fabric/entity/PlayerChannelHandlerImpl.kt | 4 +- .../impl/fabric/manager/EntityManager.kt | 4 +- .../scheduler/FabricModelSchedulerImpl.kt | 6 +- .../damagesource/ModelDamageSourceImpl.kt | 12 ++-- platform/paper/build.gradle.kts | 2 +- platform/spigot/build.gradle.kts | 2 +- settings.gradle.kts | 21 +++++-- test-plugin/build.gradle.kts | 6 +- 46 files changed, 245 insertions(+), 214 deletions(-) create mode 100644 api/mod-api/build.gradle.kts rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/BetterModelMod.java (64%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModEntity.java (84%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModPlayer.java (71%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModAdapter.java (84%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModEntity.java (65%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModItemStack.java (78%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLivingEntity.java (63%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLocation.java (66%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModOfflinePlayer.java (58%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModPlayer.java (66%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModRegionHolder.java (63%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModWorld.java (72%) rename platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java => api/mod-api/src/main/java/kr/toxicity/model/api/mod/scheduler/ModModelScheduler.java (83%) diff --git a/api/bukkit-api/build.gradle.kts b/api/bukkit-api/build.gradle.kts index 7957e6ff1..f15d09155 100644 --- a/api/bukkit-api/build.gradle.kts +++ b/api/bukkit-api/build.gradle.kts @@ -4,5 +4,5 @@ plugins { } dependencies { - api(project(":api")) + api(project(":bettermodel-api")) } diff --git a/api/mod-api/build.gradle.kts b/api/mod-api/build.gradle.kts new file mode 100644 index 000000000..0cd337b28 --- /dev/null +++ b/api/mod-api/build.gradle.kts @@ -0,0 +1,14 @@ +plugins { + alias(libs.plugins.convention.publish) + id("net.neoforged.moddev") +} + +dependencies { + api(project(":bettermodel-api")) +} + +neoForge { + enable { + neoFormVersion = libs.versions.neoform.get() + } +} diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/BetterModelMod.java similarity index 64% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/BetterModelMod.java index 7c7f13df0..40ba95f36 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/BetterModelFabric.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/BetterModelMod.java @@ -5,16 +5,16 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric; +package kr.toxicity.model.api.mod; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.BetterModelPlatform; -import kr.toxicity.model.api.fabric.scheduler.FabricModelScheduler; +import kr.toxicity.model.api.mod.scheduler.ModModelScheduler; import net.minecraft.server.MinecraftServer; import org.jetbrains.annotations.NotNull; /** - * Represents the Fabric-specific platform interface for BetterModel. + * Represents the Mod-specific platform interface for BetterModel. *

* This interface extends {@link BetterModelPlatform} to provide access to the underlying * Minecraft server instance and region holder for thread-safe operations. @@ -22,16 +22,16 @@ * * @since 2.0.0 */ -public interface BetterModelFabric extends BetterModelPlatform { +public interface BetterModelMod extends BetterModelPlatform { /** - * Returns the current {@link BetterModelFabric} instance. + * Returns the current {@link BetterModelMod} instance. * * @return the current platform instance * @since 2.0.0 */ - static @NotNull BetterModelFabric platform() { - return (BetterModelFabric) BetterModel.platform(); + static @NotNull BetterModelMod platform() { + return (BetterModelMod) BetterModel.platform(); } /** @@ -43,11 +43,11 @@ public interface BetterModelFabric extends BetterModelPlatform { @NotNull MinecraftServer server(); /** - * Returns the Fabric-specific scheduler. + * Returns the Mod-specific scheduler. * * @return the scheduler * @since 2.0.0 */ @Override - @NotNull FabricModelScheduler scheduler(); + @NotNull ModModelScheduler scheduler(); } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModEntity.java similarity index 84% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModEntity.java index 97daac47f..9b057c326 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricEntity.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModEntity.java @@ -5,21 +5,21 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.entity; +package kr.toxicity.model.api.mod.entity; import kr.toxicity.model.api.entity.BaseEntity; import net.minecraft.world.entity.Entity; import org.jetbrains.annotations.NotNull; /** - * Represents a Fabric-specific entity adapter. + * Represents a Mod-specific entity adapter. *

* This interface extends {@link BaseEntity} to provide access to the underlying NMS entity. *

* * @since 2.0.0 */ -public interface BaseFabricEntity extends BaseEntity { +public interface BaseModEntity extends BaseEntity { /** * Returns the underlying NMS entity. diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModPlayer.java similarity index 71% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModPlayer.java index 652d92965..c5d98a51d 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/entity/BaseFabricPlayer.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/entity/BaseModPlayer.java @@ -5,22 +5,22 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.entity; +package kr.toxicity.model.api.mod.entity; import kr.toxicity.model.api.entity.BasePlayer; import net.minecraft.server.level.ServerPlayer; import org.jetbrains.annotations.NotNull; /** - * Represents a Fabric-specific player adapter. + * Represents a Mod-specific player adapter. *

- * This interface extends {@link BaseFabricEntity} and {@link BasePlayer} to provide + * This interface extends {@link BaseModEntity} and {@link BasePlayer} to provide * access to the underlying NMS server player. *

* * @since 2.0.0 */ -public interface BaseFabricPlayer extends BaseFabricEntity, BasePlayer { +public interface BaseModPlayer extends BaseModEntity, BasePlayer { /** * Returns the underlying NMS server player. diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModAdapter.java similarity index 84% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModAdapter.java index 82b105c45..b28c70b49 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricAdapter.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModAdapter.java @@ -5,11 +5,10 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import com.mojang.authlib.GameProfile; -import kr.toxicity.model.api.BetterModel; -import kr.toxicity.model.api.fabric.BetterModelFabric; +import kr.toxicity.model.api.mod.BetterModelMod; import kr.toxicity.model.api.platform.*; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; @@ -24,7 +23,7 @@ import java.util.UUID; /** - * Provides an adapter for converting Fabric/NMS objects to BetterModel platform objects. + * Provides an adapter for converting Mod/NMS objects to BetterModel platform objects. *

* This class implements {@link PlatformAdapter} and offers static utility methods for adapting * entities, players, items, and worlds. @@ -32,7 +31,7 @@ * * @since 2.0.0 */ -public final class FabricAdapter implements PlatformAdapter { +public final class ModAdapter implements PlatformAdapter { /** * Adapts an NMS entity to a {@link PlatformEntity}. @@ -42,7 +41,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformEntity adapt(@NotNull Entity entity) { - return FabricEntity.of(entity); + return ModEntity.of(entity); } /** @@ -53,7 +52,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformLivingEntity adapt(@NotNull LivingEntity livingEntity) { - return FabricLivingEntity.of(livingEntity); + return ModLivingEntity.of(livingEntity); } /** @@ -64,7 +63,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformPlayer adapt(@NotNull ServerPlayerConnection connection) { - return FabricPlayer.of(connection); + return ModPlayer.of(connection); } /** @@ -86,7 +85,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformOfflinePlayer adapt(@NotNull UUID uuid) { - return FabricOfflinePlayer.of(uuid, null); + return ModOfflinePlayer.of(uuid, null); } /** @@ -97,7 +96,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformOfflinePlayer adapt(@NotNull GameProfile profile) { - return FabricOfflinePlayer.of(profile.id(), profile.name()); + return ModOfflinePlayer.of(profile.id(), profile.name()); } /** @@ -108,7 +107,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformItemStack adapt(@NotNull ItemStack itemStack) { - return FabricItemStack.of(itemStack); + return ModItemStack.of(itemStack); } /** @@ -119,7 +118,7 @@ public final class FabricAdapter implements PlatformAdapter { * @since 2.0.0 */ public static @NotNull PlatformWorld adapt(@NotNull Level world) { - return FabricWorld.of(world); + return ModWorld.of(world); } @Override @@ -156,10 +155,10 @@ public boolean isRegionSafe() { @Override public @NotNull PlatformLocation zero() { - return FabricLocation.of(null, 0, 0, 0); + return ModLocation.of(null, 0, 0, 0); } private @NotNull MinecraftServer server() { - return ((BetterModelFabric) BetterModel.platform()).server(); + return BetterModelMod.platform().server(); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModEntity.java similarity index 65% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModEntity.java index 8809454c2..c69801939 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricEntity.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModEntity.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformEntity; import kr.toxicity.model.api.platform.PlatformLocation; @@ -16,25 +16,25 @@ import java.util.UUID; /** - * Represents a Fabric entity wrapped as a {@link PlatformEntity}. + * Represents a Mod entity wrapped as a {@link PlatformEntity}. * * @param source the source NMS entity * @since 2.0.0 */ -public record FabricEntity(@NotNull Entity source) implements PlatformEntity { +public record ModEntity(@NotNull Entity source) implements PlatformEntity { @ApiStatus.Internal - public FabricEntity { + public ModEntity { } /** - * Creates a FabricEntity from the source. + * Creates a ModEntity from the source. * * @param source the source entity * @return the instance * @since 2.0.0 */ - public static @NotNull FabricEntity of(@NotNull Entity source) { - return new FabricEntity(source); + public static @NotNull ModEntity of(@NotNull Entity source) { + return new ModEntity(source); } @Override @@ -44,6 +44,6 @@ public record FabricEntity(@NotNull Entity source) implements PlatformEntity { @Override public @NotNull PlatformLocation location() { - return FabricLocation.of(source); + return ModLocation.of(source); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModItemStack.java similarity index 78% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModItemStack.java index 9f5e77c5b..be88f039c 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricItemStack.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModItemStack.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformItemStack; import kr.toxicity.model.api.platform.PlatformNamespace; @@ -20,25 +20,25 @@ import java.util.List; /** - * Represents a Fabric item stack wrapped as a {@link PlatformItemStack}. + * Represents a Mod item stack wrapped as a {@link PlatformItemStack}. * * @param source the source NMS item stack * @since 2.0.0 */ -public record FabricItemStack(@NotNull ItemStack source) implements PlatformItemStack { +public record ModItemStack(@NotNull ItemStack source) implements PlatformItemStack { @ApiStatus.Internal - public FabricItemStack { + public ModItemStack { } /** - * Creates a FabricItemStack from the source. + * Creates a ModItemStack from the source. * * @param source the source item stack * @return the instance * @since 2.0.0 */ - public static @NotNull FabricItemStack of(@NotNull ItemStack source) { - return new FabricItemStack(source); + public static @NotNull ModItemStack of(@NotNull ItemStack source) { + return new ModItemStack(source); } @Override @@ -67,6 +67,6 @@ public boolean isAir() { @Override public @NotNull PlatformItemStack clone() { - return FabricAdapter.adapt(source.copy()); + return ModAdapter.adapt(source.copy()); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLivingEntity.java similarity index 63% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLivingEntity.java index 15bfd4dfd..3948e6f4a 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLivingEntity.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLivingEntity.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformLivingEntity; import kr.toxicity.model.api.platform.PlatformLocation; @@ -16,25 +16,25 @@ import java.util.UUID; /** - * Represents a Fabric living entity wrapped as a {@link PlatformLivingEntity}. + * Represents a Mod living entity wrapped as a {@link PlatformLivingEntity}. * * @param source the source NMS living entity * @since 2.0.0 */ -public record FabricLivingEntity(@NotNull LivingEntity source) implements PlatformLivingEntity { +public record ModLivingEntity(@NotNull LivingEntity source) implements PlatformLivingEntity { @ApiStatus.Internal - public FabricLivingEntity { + public ModLivingEntity { } /** - * Creates a FabricLivingEntity from the source. + * Creates a ModLivingEntity from the source. * * @param source the source living entity * @return the instance * @since 2.0.0 */ - public static @NotNull FabricLivingEntity of(@NotNull LivingEntity source) { - return new FabricLivingEntity(source); + public static @NotNull ModLivingEntity of(@NotNull LivingEntity source) { + return new ModLivingEntity(source); } @Override @@ -44,11 +44,11 @@ public record FabricLivingEntity(@NotNull LivingEntity source) implements Platfo @Override public @NotNull PlatformLocation location() { - return FabricLocation.of(source); + return ModLocation.of(source); } @Override public @NotNull PlatformLocation eyeLocation() { - return FabricLocation.ofEye(source); + return ModLocation.ofEye(source); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLocation.java similarity index 66% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLocation.java index acf751089..5ca06b22a 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricLocation.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModLocation.java @@ -5,10 +5,10 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; -import kr.toxicity.model.api.fabric.BetterModelFabric; -import kr.toxicity.model.api.fabric.scheduler.FabricModelScheduler; +import kr.toxicity.model.api.mod.BetterModelMod; +import kr.toxicity.model.api.mod.scheduler.ModModelScheduler; import kr.toxicity.model.api.platform.PlatformLocation; import kr.toxicity.model.api.platform.PlatformWorld; import kr.toxicity.model.api.scheduler.ModelTask; @@ -20,7 +20,7 @@ import org.jetbrains.annotations.Nullable; /** - * Represents a Fabric location wrapped as a {@link PlatformLocation}. + * Represents a Mod location wrapped as a {@link PlatformLocation}. * * @param level the NMS level * @param x the x coordinate @@ -30,13 +30,13 @@ * @param yaw the yaw * @since 2.0.0 */ -public record FabricLocation(@Nullable Level level, double x, double y, double z, float pitch, float yaw) implements PlatformLocation { +public record ModLocation(@Nullable Level level, double x, double y, double z, float pitch, float yaw) implements PlatformLocation { @ApiStatus.Internal - public FabricLocation { + public ModLocation { } /** - * Creates a FabricLocation from the coordinates. + * Creates a ModLocation from the coordinates. * * @param level the NMS level * @param x the x coordinate @@ -47,8 +47,8 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z * @return the instance * @since 2.0.0 */ - public static @NotNull FabricLocation of(@Nullable Level level, double x, double y, double z, float pitch, float yaw) { - return new FabricLocation( + public static @NotNull ModLocation of(@Nullable Level level, double x, double y, double z, float pitch, float yaw) { + return new ModLocation( level, x, y, @@ -59,7 +59,7 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z } /** - * Creates a FabricLocation from the coordinates with zero pitch and yaw. + * Creates a ModLocation from the coordinates with zero pitch and yaw. * * @param level the NMS level * @param x the x coordinate @@ -68,8 +68,8 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z * @return the instance * @since 2.0.0 */ - public static @NotNull FabricLocation of(@Nullable Level level, double x, double y, double z) { - return new FabricLocation( + public static @NotNull ModLocation of(@Nullable Level level, double x, double y, double z) { + return new ModLocation( level, x, y, @@ -80,7 +80,7 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z } /** - * Creates a FabricLocation from the position vector. + * Creates a ModLocation from the position vector. * * @param level the NMS level * @param position the position vector @@ -89,8 +89,8 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z * @return the instance * @since 2.0.0 */ - public static @NotNull FabricLocation of(@Nullable Level level, Vec3 position, float pitch, float yaw) { - return new FabricLocation( + public static @NotNull ModLocation of(@Nullable Level level, Vec3 position, float pitch, float yaw) { + return new ModLocation( level, position.x, position.y, @@ -101,15 +101,15 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z } /** - * Creates a FabricLocation from the position vector with zero pitch and yaw. + * Creates a ModLocation from the position vector with zero pitch and yaw. * * @param level the NMS level * @param position the position vector * @return the instance * @since 2.0.0 */ - public static @NotNull FabricLocation of(@Nullable Level level, Vec3 position) { - return new FabricLocation( + public static @NotNull ModLocation of(@Nullable Level level, Vec3 position) { + return new ModLocation( level, position.x, position.y, @@ -120,14 +120,14 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z } /** - * Creates a FabricLocation from an entity's position. + * Creates a ModLocation from an entity's position. * * @param entity the entity * @return the location * @since 2.0.0 */ - public static @NotNull FabricLocation of(@NotNull Entity entity) { - return new FabricLocation( + public static @NotNull ModLocation of(@NotNull Entity entity) { + return new ModLocation( entity.level(), entity.getX(), entity.getY(), @@ -138,14 +138,14 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z } /** - * Creates a FabricLocation from an entity's eye position. + * Creates a ModLocation from an entity's eye position. * * @param entity the entity * @return the eye location * @since 2.0.0 */ - public static @NotNull FabricLocation ofEye(@NotNull Entity entity) { - return new FabricLocation( + public static @NotNull ModLocation ofEye(@NotNull Entity entity) { + return new ModLocation( entity.level(), entity.getX(), entity.getEyeY(), @@ -161,12 +161,12 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z throw new IllegalStateException("level is not set"); } - return FabricAdapter.adapt(level); + return ModAdapter.adapt(level); } @Override public @NotNull PlatformLocation add(double x, double y, double z) { - return new FabricLocation( + return new ModLocation( this.level, this.x + x, this.y + y, @@ -186,7 +186,7 @@ public record FabricLocation(@Nullable Level level, double x, double y, double z return scheduler().taskLater(delay, runnable); } - private @NotNull FabricModelScheduler scheduler() { - return BetterModelFabric.platform().scheduler(); + private @NotNull ModModelScheduler scheduler() { + return BetterModelMod.platform().scheduler(); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModOfflinePlayer.java similarity index 58% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModOfflinePlayer.java index 43df9561c..c30e24151 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricOfflinePlayer.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModOfflinePlayer.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformOfflinePlayer; import org.jetbrains.annotations.ApiStatus; @@ -15,26 +15,26 @@ import java.util.UUID; /** - * Represents a Fabric offline player wrapped as a {@link PlatformOfflinePlayer}. + * Represents a Mod offline player wrapped as a {@link PlatformOfflinePlayer}. * * @param uuid the player UUID * @param name the player name, or null if unknown * @since 2.0.0 */ -public record FabricOfflinePlayer(@NotNull UUID uuid, @Nullable String name) implements PlatformOfflinePlayer { +public record ModOfflinePlayer(@NotNull UUID uuid, @Nullable String name) implements PlatformOfflinePlayer { @ApiStatus.Internal - public FabricOfflinePlayer { + public ModOfflinePlayer { } /** - * Creates a FabricOfflinePlayer from the UUID and name. + * Creates a ModOfflinePlayer from the UUID and name. * * @param uuid the player uuid * @param name the player name * @return the instance * @since 2.0.0 */ - public static @NotNull FabricOfflinePlayer of(@NotNull UUID uuid, @Nullable String name) { - return new FabricOfflinePlayer(uuid, name); + public static @NotNull ModOfflinePlayer of(@NotNull UUID uuid, @Nullable String name) { + return new ModOfflinePlayer(uuid, name); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModPlayer.java similarity index 66% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModPlayer.java index 3ab486a9c..741a7df89 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricPlayer.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModPlayer.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformLocation; import kr.toxicity.model.api.platform.PlatformPlayer; @@ -16,25 +16,25 @@ import java.util.UUID; /** - * Represents a Fabric player wrapped as a {@link PlatformPlayer}. + * Represents a Mod player wrapped as a {@link PlatformPlayer}. * * @param source the source NMS player connection * @since 2.0.0 */ -public record FabricPlayer(@NotNull ServerPlayerConnection source) implements PlatformPlayer { +public record ModPlayer(@NotNull ServerPlayerConnection source) implements PlatformPlayer { @ApiStatus.Internal - public FabricPlayer { + public ModPlayer { } /** - * Creates a FabricPlayer from the source. + * Creates a ModPlayer from the source. * * @param source the source player connection * @return the instance * @since 2.0.0 */ - public static @NotNull FabricPlayer of(@NotNull ServerPlayerConnection source) { - return new FabricPlayer(source); + public static @NotNull ModPlayer of(@NotNull ServerPlayerConnection source) { + return new ModPlayer(source); } @Override @@ -44,12 +44,12 @@ public record FabricPlayer(@NotNull ServerPlayerConnection source) implements Pl @Override public @NotNull PlatformLocation location() { - return FabricLocation.of(source.getPlayer()); + return ModLocation.of(source.getPlayer()); } @Override public @NotNull PlatformLocation eyeLocation() { - return FabricLocation.ofEye(source.getPlayer()); + return ModLocation.ofEye(source.getPlayer()); } @Override diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModRegionHolder.java similarity index 63% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModRegionHolder.java index b8fbd0729..a6c8de739 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricRegionHolder.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModRegionHolder.java @@ -5,18 +5,18 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformRegionHolder; /** - * Represents a Fabric-specific region holder for managing thread-safe operations. + * Represents a Mod-specific region holder for managing thread-safe operations. *

- * This interface extends {@link PlatformRegionHolder} to provide Fabric-specific functionality + * This interface extends {@link PlatformRegionHolder} to provide Mod-specific functionality * for scheduling tasks within specific regions or contexts. *

* * @since 2.0.0 */ -public interface FabricRegionHolder extends PlatformRegionHolder { +public interface ModRegionHolder extends PlatformRegionHolder { } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModWorld.java similarity index 72% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModWorld.java index 3da38afed..459fe4d77 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/platform/FabricWorld.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/platform/ModWorld.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.platform; +package kr.toxicity.model.api.mod.platform; import kr.toxicity.model.api.platform.PlatformWorld; import net.minecraft.world.level.Level; @@ -18,9 +18,9 @@ * @param level the source NMS level * @since 2.0.0 */ -public record FabricWorld(@NotNull Level level) implements PlatformWorld { +public record ModWorld(@NotNull Level level) implements PlatformWorld { @ApiStatus.Internal - public FabricWorld { + public ModWorld { } /** @@ -30,7 +30,7 @@ public record FabricWorld(@NotNull Level level) implements PlatformWorld { * @return the instance * @since 2.0.0 */ - public static @NotNull FabricWorld of(@NotNull Level level) { - return new FabricWorld(level); + public static @NotNull ModWorld of(@NotNull Level level) { + return new ModWorld(level); } } diff --git a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/scheduler/ModModelScheduler.java similarity index 83% rename from platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java rename to api/mod-api/src/main/java/kr/toxicity/model/api/mod/scheduler/ModModelScheduler.java index 168b251c2..565ed7e52 100644 --- a/platform/fabric/src/main/java/kr/toxicity/model/api/fabric/scheduler/FabricModelScheduler.java +++ b/api/mod-api/src/main/java/kr/toxicity/model/api/mod/scheduler/ModModelScheduler.java @@ -5,7 +5,7 @@ * See LICENSE.md file for full license text. */ -package kr.toxicity.model.api.fabric.scheduler; +package kr.toxicity.model.api.mod.scheduler; import kr.toxicity.model.api.scheduler.ModelScheduler; import kr.toxicity.model.api.scheduler.ModelTask; @@ -13,15 +13,15 @@ import org.jetbrains.annotations.Nullable; /** - * Represents a Fabric-specific scheduler for model tasks. + * Represents a Mod-specific scheduler for model tasks. *

* This interface extends {@link ModelScheduler} to provide methods for scheduling tasks - * within the Fabric environment. + * within the Mod environment. *

* * @since 2.0.0 */ -public interface FabricModelScheduler extends ModelScheduler { +public interface ModModelScheduler extends ModelScheduler { /** * Schedules a task to run on the next tick. diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float4.java b/api/src/main/java/kr/toxicity/model/api/data/Float4.java index 20c992975..62fd8cdfa 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float4.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float4.java @@ -68,6 +68,17 @@ public record Float4( ); } + /** + * Checks validity of this uv + * @return is valid + */ + public boolean isValid() { + return dx >= 0 && dx <= 16 + && dz >= 0 && dz <= 16 + && tx >= 0 && tx <= 16 + && tz >= 0 && tz <= 16; + } + /** * Converts floats to JSON array. * @return json array diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java index a4a57b159..086f4276a 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelFace.java @@ -47,12 +47,13 @@ public record ModelFace( */ public @NotNull JsonObject toJson(@NotNull BlueprintLoadContext parent, int tint) { var object = new JsonObject(); - if (north.hasTexture()) object.add("north", north.toJson(parent, tint)); - if (east.hasTexture()) object.add("east", east.toJson(parent, tint)); - if (south.hasTexture()) object.add("south", south.toJson(parent, tint)); - if (west.hasTexture()) object.add("west", west.toJson(parent, tint)); - if (up.hasTexture()) object.add("up", up.toJson(parent, tint)); - if (down.hasTexture()) object.add("down", down.toJson(parent, tint)); + JsonObject add; + if ((add = north.toJson(parent, tint)) != null) object.add("north", add); + if ((add = east.toJson(parent, tint)) != null) object.add("east", add); + if ((add = south.toJson(parent, tint)) != null) object.add("south", add); + if ((add = west.toJson(parent, tint)) != null) object.add("west", add); + if ((add = up.toJson(parent, tint)) != null) object.add("up", add); + if ((add = down.toJson(parent, tint)) != null) object.add("down", add); return object; } diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java index 48f59ec0e..5cd988c65 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelUV.java @@ -62,9 +62,12 @@ public int textureIndex() { * @return the generated JSON object * @since 1.15.2 */ - public @NotNull JsonObject toJson(@NotNull BlueprintLoadContext context, int tint) { + public @Nullable JsonObject toJson(@NotNull BlueprintLoadContext context, int tint) { + if (!hasTexture()) return null; + var div = uv.div(context.texture(textureIndex()).resolution(context.resolution())); + if (!div.isValid()) return null; var object = new JsonObject(); - object.add("uv", uv.div(context.texture(textureIndex()).resolution(context.resolution())).toJson()); + object.add("uv", div.toJson()); if (rotation != 0) object.addProperty("rotation", rotation); object.addProperty("tintindex", tint); object.addProperty("texture", "#" + texture); diff --git a/build.gradle.kts b/build.gradle.kts index 8ee0501dd..534b908c8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -2,8 +2,6 @@ import io.papermc.hangarpublishplugin.model.Platforms plugins { alias(libs.plugins.convention.standard) - alias(libs.plugins.minotaur) apply false - alias(libs.plugins.shadow) alias(libs.plugins.hangar) id("xyz.jpenilla.run-paper") version "3.0.2" } @@ -25,13 +23,13 @@ runPaper { tasks { runServer { pluginJars(fileTree("plugins")) - pluginJars(project(":platform:paper").tasks.shadowJar.flatMap { + pluginJars(project(":platform:bettermodel-paper").tasks.named("shadowJar").flatMap { it.archiveFile }) pluginJars(project(":test-plugin").tasks.jar.flatMap { it.archiveFile }) - version(minecraft) + minecraftVersion(minecraft) downloadPlugins { hangar("ViaVersion", "5.8.0") hangar("ViaBackwards", "5.8.0") @@ -44,7 +42,7 @@ tasks { javadocJar ) } - shadowJar { + jar { enabled = false } } @@ -64,7 +62,7 @@ hangarPublish { } platforms { register(Platforms.PAPER) { - jar = project(":platform:paper").tasks.shadowJar.flatMap { + jar = project(":platform:paper").tasks.named("shadowJar").flatMap { it.archiveFile } platformVersions = SUPPORTED_VERSIONS diff --git a/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts b/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts index fba90099a..07f8a9761 100644 --- a/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts @@ -4,6 +4,8 @@ plugins { val versionString = version.toString() val classifier = project.name + .substringAfterLast('-') + .replaceFirstChar { it.uppercase() } modrinth { token = System.getenv("MODRINTH_API_TOKEN") @@ -21,5 +23,5 @@ modrinth { javadocJar(rootProject.layout.buildDirectory.file("libs/${rootProject.name}-$versionString-javadoc.jar")) } versionNumber = versionString - versionName = "BetterModel $versionString for ${classifier.replaceFirstChar { it.uppercase() }}" + versionName = "BetterModel $versionString for $classifier" } diff --git a/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts b/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts index f8a6ada7f..d7ff1edc1 100644 --- a/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts @@ -3,6 +3,6 @@ plugins { } dependencies { - compileOnly(project(":api")) - compileOnly(project(":api:bukkit-api")) + compileOnly(project(":bettermodel-api")) + compileOnly(project(":bettermodel-api:bettermodel-bukkit-api")) } diff --git a/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts b/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts index 4b27bf622..c05ce6f39 100644 --- a/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts @@ -7,13 +7,13 @@ plugins { val shade: Configuration = configurations.getByName("shade") val versionString = version.toString() val groupString = group.toString() -val classifier: String = project.name +val classifier: String = project.name.substringAfterLast('-') dependencies { - compileOnly(project(":api")) - compileOnly(project(":api:bukkit-api")) - compileOnly(project(":core")) - shade(project(":core:bukkit-core")) { + compileOnly(project(":bettermodel-api")) + compileOnly(project(":bettermodel-api:bettermodel-bukkit-api")) + compileOnly(project(":bettermodel-core")) + shade(project(":bettermodel-core:bettermodel-bukkit-core")) { exclude("org.jetbrains.kotlin") } } diff --git a/buildSrc/src/main/kotlin/publish-conventions.gradle.kts b/buildSrc/src/main/kotlin/publish-conventions.gradle.kts index a3f6fccd5..cfa6bd305 100644 --- a/buildSrc/src/main/kotlin/publish-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/publish-conventions.gradle.kts @@ -9,17 +9,11 @@ plugins { signing } -val gitHubPackagesId = rootProject.name.lowercase() -val artifactBaseId = "$gitHubPackagesId-$name" +val artifactBaseId = name val artifactVersion = project.version.toString().run { BUILD_NUMBER?.let { substringBeforeLast("-$it") } ?: this } -java { - withSourcesJar() - withJavadocJar() -} - signing { val key = System.getenv("SIGNING_KEY")?.let { Base64.decode(it.toByteArray()).toString(Charsets.UTF_8) @@ -48,7 +42,7 @@ mavenPublishing { signAllPublications() coordinates("io.github.toxicity188", artifactBaseId, artifactVersion) configure(JavaLibrary( - javadocJar = JavadocJar.None(), + javadocJar = JavadocJar.Javadoc(), sourcesJar = SourcesJar.Sources(), )) pom { @@ -81,7 +75,7 @@ publishing { repositories { maven { name = "GitHubPackages" - url = uri("https://maven.pkg.github.com/toxicity188/$gitHubPackagesId") + url = uri("https://maven.pkg.github.com/toxicity188/${rootProject.name}") credentials { username = "toxicity188" password = System.getenv("PACKAGES_API_TOKEN") diff --git a/core/build.gradle.kts b/core/build.gradle.kts index 10f2307cf..0fefb45f9 100644 --- a/core/build.gradle.kts +++ b/core/build.gradle.kts @@ -3,7 +3,7 @@ plugins { } dependencies { - api(project(":api")) + api(project(":bettermodel-api")) compileOnly(libs.bundles.minecraft) compileOnly("com.mojang:authlib:7.0.61") diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index f61beff08..f7713d9cf 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -3,9 +3,9 @@ plugins { } dependencies { - shade(project(":api")) { isTransitive = false } - shade(project(":api:bukkit-api")) { isTransitive = false } - shade(project(":core")) { isTransitive = false } + shade(project(":bettermodel-api")) { isTransitive = false } + shade(project(":bettermodel-api:bettermodel-bukkit-api")) { isTransitive = false } + shade(project(":bettermodel-core")) { isTransitive = false } shade(project(":purpur")) rootProject.project("nms").subprojects.forEach { diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index f7d91515d..03a647921 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -38,7 +38,7 @@ internal class BetterModelProperties( private lateinit var _config: BetterModelConfig private var _metrics: Metrics? = null - val version = parse(Bukkit.getBukkitVersion().substringBefore('-')) + val version = parse(Bukkit.getMinecraftVersion()) val nms = when (version) { V1_21_11 -> Latest() V1_21_9, V1_21_10 -> kr.toxicity.model.bukkit.nms.v1_21_R6.NMSImpl() diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt index e861acc1e..8b2e287f6 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt @@ -173,7 +173,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { "type" to "range_dispatch", "property" to "custom_model_data", "fallback" to jsonObjectOf( - "type" to "minecraft:empty" + "type" to "empty" ), "entries" to entries )).toByteArray() @@ -264,18 +264,18 @@ object ModelManagerImpl : ModelManager, GlobalManager { } private fun List.toModernJson(plus: JsonObject?) = if (size == 1) first().toModernJson() else jsonObjectOf( - "type" to "minecraft:composite", + "type" to "composite", "models" to fold(JsonArray(size + (if (plus != null) 1 else 0)).apply { plus?.run(::add) }) { array, element -> array.apply { add(element.toModernJson()) } } ) private fun BlueprintJson.toModernJson() = jsonObjectOf( - "type" to "minecraft:model", + "type" to "model", "model" to "${CONFIG.namespace()}:modern_item/${name}", "tints" to jsonArrayOf( jsonObjectOf( - "type" to "minecraft:custom_model_data", + "type" to "custom_model_data", "default" to 0xFFFFFF ) ) diff --git a/gradle.properties b/gradle.properties index 10e478654..0e8c2d0da 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,10 @@ kotlin.code.style=official kotlin.daemon.jvmargs=-Xmx4g +org.gradle.caching=true org.gradle.configuration-cache=true +org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -fabric.loom.multiProjectOptimisation=true - project_version=3.0.0 minecraft_version=26.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 3fa3189ae..2334bb939 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,12 +10,14 @@ hangarPublish = "0.1.4" fabric-api = "0.144.3+26.1" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" -cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released +cloud-bukkit = "2.0.0-beta.14" #TODO update this to 2.0.0-beta.15 when released cloud-mod = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.16 when released cloud-core = "2.0.0" configurate = "4.2.0" +neoform = "26.1-1" + [libraries] kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } @@ -124,8 +126,6 @@ resourcefactory-paper = { id = "xyz.jpenilla.resource-factory-paper-convention" resourcefactory-fabric = { id = "xyz.jpenilla.resource-factory-fabric-convention" } paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" } -shadow = { id = "com.gradleup.shadow" } -minotaur = { id = "com.modrinth.minotaur" } hangar = { id = "io.papermc.hangar-publish-plugin" } convention-publish = { id = "publish-conventions" } diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index e30dd62e8..23f3d10f3 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -9,7 +9,7 @@ plugins { val versionString = "${rootProject.version}+${property("minecraft_version")}" -val jarName = "${rootProject.name}-$versionString-${project.name}.jar" +val jarName = "${rootProject.name}-$versionString-${project.name.substringAfterLast('-')}.jar" val jarDir = rootProject.layout.buildDirectory.dir("libs") sourceSets { @@ -46,8 +46,9 @@ dependencies { // Minecraft minecraft("com.mojang:minecraft:${property("minecraft_version")}") - api(project(":api")); include(project(":api")) - api(project(":core")); include(project(":core")) + api(project(":bettermodel-api")); include(project(":bettermodel-api")) + api(project(":bettermodel-api:bettermodel-mod-api")); include(project(":bettermodel-api:bettermodel-mod-api")) + api(project(":bettermodel-core")); include(project(":bettermodel-core")) setOf( "fabric-api-base", @@ -73,7 +74,7 @@ dependencies { fabricModJson { id = "bettermodel" - name = rootProject.name + name = "BetterModel" description = "Modern Bedrock model engine for Minecraft Java Edition" entrypoints = listOf( @@ -118,6 +119,7 @@ fabricModJson { contact { sources = "https://github.com/toxicity188/BetterModel/" issues = "https://github.com/toxicity188/BetterModel/issues" + homepage = "https://modrinth.com/plugin/bettermodel" } icon("assets/icon.png") mitLicense() diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt index ef7743414..369dab94f 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt @@ -17,10 +17,10 @@ import kr.toxicity.model.api.* import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.* import kr.toxicity.model.api.event.PluginEndReloadEvent import kr.toxicity.model.api.event.PluginStartReloadEvent -import kr.toxicity.model.api.fabric.BetterModelFabric -import kr.toxicity.model.api.fabric.platform.FabricAdapter -import kr.toxicity.model.api.fabric.scheduler.FabricModelScheduler import kr.toxicity.model.api.manager.* +import kr.toxicity.model.api.mod.BetterModelMod +import kr.toxicity.model.api.mod.platform.ModAdapter +import kr.toxicity.model.api.mod.scheduler.ModModelScheduler import kr.toxicity.model.api.nms.NMS import kr.toxicity.model.api.pack.PackResult import kr.toxicity.model.api.pack.PackZipper @@ -57,7 +57,7 @@ import java.util.jar.JarFile import kotlin.io.path.exists import kotlin.system.measureTimeMillis -class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterModelFabric { +class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterModelMod { private lateinit var server: MinecraftServer private val configDir: Path = FabricLoader.getInstance() @@ -92,7 +92,7 @@ class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterMod private val logger = BetterModelLoggerImpl() private val evaluator = BetterModelEvaluatorImpl() private val eventBus = BetterModelEventBusImpl() - private val adapter = FabricAdapter() + private val adapter = ModAdapter() private var reloadStartTask: (PackZipper) -> Unit = { zipper -> callEvent { @@ -328,7 +328,7 @@ class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterMod override fun server(): MinecraftServer = server - override fun scheduler(): FabricModelScheduler = FabricModelSchedulerImpl + override fun scheduler(): ModModelScheduler = FabricModelSchedulerImpl override fun adapter(): PlatformAdapter = adapter diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt index 6e06de3c7..20ece7a90 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt @@ -15,7 +15,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.entity.BaseEntity import kr.toxicity.model.api.entity.BasePlayer -import kr.toxicity.model.api.fabric.BetterModelFabric +import kr.toxicity.model.api.mod.BetterModelMod import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.* import kr.toxicity.model.api.platform.PlatformEntity @@ -182,7 +182,7 @@ class BetterModelNMSImpl : NMS { set(DataComponents.PROFILE, ResolvableProfile.createResolved(gameProfile)) }.wrap() - override fun isProxyOnlineMode(): Boolean = (PLATFORM as BetterModelFabric).server().usesAuthentication() + override fun isProxyOnlineMode(): Boolean = (PLATFORM as BetterModelMod).server().usesAuthentication() override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return ItemStack(Items.PLAYER_HEAD).run { diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt index 35963d9dd..f5de6fb80 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/FabricWrappers.kt @@ -7,22 +7,22 @@ package kr.toxicity.model.impl.fabric -import kr.toxicity.model.api.fabric.platform.* -import kr.toxicity.model.api.fabric.platform.FabricAdapter.adapt +import kr.toxicity.model.api.mod.platform.* +import kr.toxicity.model.api.mod.platform.ModAdapter.adapt import kr.toxicity.model.api.platform.* import net.minecraft.server.network.ServerPlayerConnection import net.minecraft.world.entity.Entity import net.minecraft.world.entity.LivingEntity import net.minecraft.world.item.ItemStack -val PlatformLocation.asFabric get() = this as FabricLocation +val PlatformLocation.asFabric get() = this as ModLocation fun Entity.wrap() = adapt(this) fun LivingEntity.wrap() = adapt(this) fun ServerPlayerConnection.wrap() = adapt(this) fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as FabricEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as FabricLivingEntity).source() -fun PlatformPlayer.unwarp(): ServerPlayerConnection = (this as FabricPlayer).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as FabricItemStack).source() +fun PlatformEntity.unwarp(): Entity = (this as ModEntity).source() +fun PlatformLivingEntity.unwarp(): LivingEntity = (this as ModLivingEntity).source() +fun PlatformPlayer.unwarp(): ServerPlayerConnection = (this as ModPlayer).source() +fun PlatformItemStack.unwarp(): ItemStack = (this as ModItemStack).source() diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt index 406534529..c43c34d3e 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/command/Commands.kt @@ -11,7 +11,7 @@ import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.* import kr.toxicity.model.api.animation.AnimationIterator import kr.toxicity.model.api.animation.AnimationModifier -import kr.toxicity.model.api.fabric.platform.FabricLocation +import kr.toxicity.model.api.mod.platform.ModLocation import kr.toxicity.model.api.tracker.EntityHideOption import kr.toxicity.model.api.tracker.ModelScaler import kr.toxicity.model.api.tracker.Tracker @@ -290,7 +290,7 @@ private fun test(context: CommandContext) { val location = context.nullable("location")?.position() ?: player.position() .add(Vec3(0.0, 0.0, 10.0).yRot(-Math.toRadians(player.yRot.toDouble()).toFloat())) - model.create(FabricLocation.of( + model.create(ModLocation.of( player.level(), location.x, location.y, diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt index 5ad9a899f..4ed1c55d1 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricEntityImpl.kt @@ -7,7 +7,7 @@ package kr.toxicity.model.impl.fabric.entity -import kr.toxicity.model.api.fabric.entity.BaseFabricEntity +import kr.toxicity.model.api.mod.entity.BaseModEntity import kr.toxicity.model.api.platform.PlatformEntity import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.TransformedItemStack @@ -23,7 +23,7 @@ import org.joml.Vector3f import java.util.* import java.util.stream.Stream -class BaseFabricEntityImpl(private var entity: Entity) : BaseFabricEntity { +class BaseFabricEntityImpl(private var entity: Entity) : BaseModEntity { override fun entity(entity: Entity) { this.entity = entity } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt index eb04657e2..1284ec8e1 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/BaseFabricPlayerImpl.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.impl.fabric.entity -import kr.toxicity.model.api.fabric.entity.BaseFabricEntity -import kr.toxicity.model.api.fabric.entity.BaseFabricPlayer +import kr.toxicity.model.api.mod.entity.BaseModEntity +import kr.toxicity.model.api.mod.entity.BaseModPlayer import kr.toxicity.model.api.nms.Profiled import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.player.PlayerSkinParts @@ -26,7 +26,7 @@ class BaseFabricPlayerImpl( private val connection: ServerPlayerConnection, private val profile: () -> ModelProfile, private val skinParts: () -> PlayerSkinParts -) : BaseFabricPlayer, BaseFabricEntity by BaseFabricEntityImpl(connection.player), Profiled by ProfiledImpl(PlayerArmorImpl(connection), profile, skinParts) { +) : BaseModPlayer, BaseModEntity by BaseFabricEntityImpl(connection.player), Profiled by ProfiledImpl(PlayerArmorImpl(connection), profile, skinParts) { override fun updateInventory() { connection.player.containerMenu.sendAllDataToRemote() diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt index ed933c846..1ef60f939 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt @@ -12,8 +12,6 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.event.hitbox.* -import kr.toxicity.model.api.fabric.platform.FabricEntity -import kr.toxicity.model.api.fabric.platform.FabricLivingEntity import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener @@ -108,7 +106,7 @@ class HitBoxEntityImpl( override fun uuid(): UUID = uuid - override fun source(): PlatformEntity = FabricEntity.of(delegate) + override fun source(): PlatformEntity = delegate.wrap() override fun positionSource(): RenderedBone = bone @@ -297,7 +295,7 @@ class HitBoxEntityImpl( MountController.MoveType.DEFAULT }, player.connection.wrap(), - FabricLivingEntity.of(delegate as LivingEntity), + (delegate as LivingEntity).wrap(), Vector3f( player.xMovement(), player.yMovement(), diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt index dae80c4a7..c525fb3f2 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt @@ -12,7 +12,7 @@ import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.bone.BoneMovement import kr.toxicity.model.api.bone.BonePosition import kr.toxicity.model.api.bone.RenderedBone -import kr.toxicity.model.api.fabric.BetterModelFabric +import kr.toxicity.model.api.mod.BetterModelMod import kr.toxicity.model.api.nms.ModelNametag import kr.toxicity.model.api.nms.PacketBundler import kr.toxicity.model.api.platform.PlatformLocation @@ -54,7 +54,7 @@ class ModelNametagImpl( private val viewedPlayer = ConcurrentHashMap.newKeySet() private val display = Display.TextDisplay( EntityType.TEXT_DISPLAY, - (PLATFORM as BetterModelFabric).server().overworld() + (PLATFORM as BetterModelMod).server().overworld() ).apply { entityData[DisplayAccessor.`bettermodel$getDataPosRotInterpolationDurationId`()] = 3 setTransformation(emptyTransformation) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt index 75bbde77b..f44a6492e 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt @@ -12,7 +12,7 @@ import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.entity.BasePlayer -import kr.toxicity.model.api.fabric.BetterModelFabric +import kr.toxicity.model.api.mod.BetterModelMod import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.PlayerChannelHandler import kr.toxicity.model.api.tracker.EntityTrackerRegistry @@ -233,7 +233,7 @@ class PlayerChannelHandlerImpl( private val hitBoxData by lazy { Display.ItemDisplay( EntityType.ITEM_DISPLAY, - (PLATFORM as BetterModelFabric).server().overworld() + (PLATFORM as BetterModelMod).server().overworld() ).run { entityData.set(DisplayAccessor.`bettermodel$getDataPosRotInterpolationDurationId`(), 3) entityData.nonDefaultValues!! diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt index 64f8c75c2..4fd06cde9 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt @@ -8,7 +8,7 @@ package kr.toxicity.model.impl.fabric.manager import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.fabric.entity.BaseFabricEntity +import kr.toxicity.model.api.mod.entity.BaseModEntity import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.ModelInteractionHand import kr.toxicity.model.api.pack.PackZipper @@ -116,7 +116,7 @@ object EntityManager : GlobalManager { private fun registerLifecycleEvents() { ServerEntityLevelChangeEvents.AFTER_ENTITY_CHANGE_LEVEL.register { oldEntity, newEntity, _, _ -> BetterModel.registryOrNull(oldEntity.uuid)?.let { registry -> - (registry.entity() as BaseFabricEntity).entity(newEntity) + (registry.entity() as BaseModEntity).entity(newEntity) } } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt index 263803e95..b38e86f79 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/scheduler/FabricModelSchedulerImpl.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.impl.fabric.scheduler -import kr.toxicity.model.api.fabric.platform.FabricRegionHolder -import kr.toxicity.model.api.fabric.scheduler.FabricModelScheduler +import kr.toxicity.model.api.mod.platform.ModRegionHolder +import kr.toxicity.model.api.mod.scheduler.ModModelScheduler import kr.toxicity.model.api.scheduler.ModelTask import kr.toxicity.model.api.util.LogUtil import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents @@ -18,7 +18,7 @@ import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicLong -object FabricModelSchedulerImpl : FabricModelScheduler, FabricRegionHolder { +object FabricModelSchedulerImpl : ModModelScheduler, ModRegionHolder { private val scheduler = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), object : ThreadFactory { diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt index 8cd81f566..ccf05d5d0 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/world/damagesource/ModelDamageSourceImpl.kt @@ -8,20 +8,20 @@ package kr.toxicity.model.impl.fabric.world.damagesource import kr.toxicity.model.api.event.ModelDamageSource -import kr.toxicity.model.api.fabric.platform.FabricEntity -import kr.toxicity.model.api.fabric.platform.FabricLocation +import kr.toxicity.model.api.mod.platform.ModLocation import kr.toxicity.model.api.platform.PlatformEntity import kr.toxicity.model.api.platform.PlatformLocation +import kr.toxicity.model.impl.fabric.wrap import net.minecraft.world.damagesource.DamageSource class ModelDamageSourceImpl(private val source: DamageSource) : ModelDamageSource { - override fun getCausingEntity(): PlatformEntity? = source.entity?.let { FabricEntity.of(it) } + override fun getCausingEntity(): PlatformEntity? = source.entity?.wrap() - override fun getDirectEntity(): PlatformEntity? = source.directEntity?.let { FabricEntity.of(it) } + override fun getDirectEntity(): PlatformEntity? = source.directEntity?.wrap() override fun getDamageLocation(): PlatformLocation? { return source.sourcePositionRaw()?.let { pos -> - FabricLocation.of( + ModLocation.of( source.entity?.level(), pos.x, pos.y, pos.z, 0f, 0f @@ -31,7 +31,7 @@ class ModelDamageSourceImpl(private val source: DamageSource) : ModelDamageSourc override fun getSourceLocation(): PlatformLocation? { return source.sourcePosition?.let { pos -> - FabricLocation.of( + ModLocation.of( source.entity?.level(), pos.x, pos.y, pos.z, 0f, 0f diff --git a/platform/paper/build.gradle.kts b/platform/paper/build.gradle.kts index 628cff8f6..bda536392 100644 --- a/platform/paper/build.gradle.kts +++ b/platform/paper/build.gradle.kts @@ -53,7 +53,7 @@ paperPluginYaml { main = "$group.paper.BetterModelPaper" loader = "$group.paper.BetterModelLoader" version = project.version.toString() - name = rootProject.name + name = "BetterModel" foliaSupported = true apiVersion = "1.20" author = "toxicity188" diff --git a/platform/spigot/build.gradle.kts b/platform/spigot/build.gradle.kts index 272e2394e..8468e5dfc 100644 --- a/platform/spigot/build.gradle.kts +++ b/platform/spigot/build.gradle.kts @@ -27,7 +27,7 @@ tasks.shadowJar { bukkitPluginYaml { main = "$group.spigot.BetterModelSpigot" version = project.version.toString() - name = rootProject.name + name = "BetterModel" foliaSupported = true apiVersion = "1.20" author = "toxicity188" diff --git a/settings.gradle.kts b/settings.gradle.kts index 0b9383e52..77da04af2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,6 +12,7 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" id("net.fabricmc.fabric-loom-repositories") version "1.15-SNAPSHOT" + id("net.neoforged.moddev.repositories") version "2.0.141" } dependencyResolutionManagement { @@ -36,22 +37,24 @@ dependencyResolutionManagement { } } -rootProject.name = "BetterModel" +rootProject.name = "bettermodel" -include( - //api +val published = setOf( "api", "api:bukkit-api", + "api:mod-api", - //core "core", "core:bukkit-core", - "purpur", - //"platform:spigot", TODO reobf does not work in Java 25 "platform:paper", "platform:fabric", +) + +include(published) +include( + "purpur", //nms "nms:v1_21_R1", @@ -64,3 +67,9 @@ include( //test "test-plugin" ) + +published.forEach { target -> + findProject(":$target")?.let { + it.name = "${rootProject.name}-${it.name}" + } +} diff --git a/test-plugin/build.gradle.kts b/test-plugin/build.gradle.kts index 8f9a3ec4d..8f3b8994b 100644 --- a/test-plugin/build.gradle.kts +++ b/test-plugin/build.gradle.kts @@ -4,8 +4,8 @@ plugins { } dependencies { - compileOnly(project(":api")) - compileOnly(project(":api:bukkit-api")) + compileOnly(project(":bettermodel-api")) + compileOnly(project(":bettermodel-api:bettermodel-bukkit-api")) compileOnly(libs.lombok) annotationProcessor(libs.lombok) @@ -14,7 +14,7 @@ dependencies { testAnnotationProcessor(libs.lombok) } -val pluginName = "${rootProject.name}-TestPlugin" +val pluginName = "BetterModel-TestPlugin" tasks.jar { archiveBaseName = pluginName From 6fe36a2916d2ed104d32c99e69d96302fa51451c Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 30 Mar 2026 01:29:07 +0900 Subject: [PATCH 05/91] feat: animation priority --- .../api/animation/AnimationStateHandler.java | 19 ++++++------------- .../api/util/collection/PriorityMap.java | 9 +++++++-- .../mythicmobs/mechanic/StateMechanic.kt | 2 ++ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index 3e09f7177..b7dc4b78a 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -9,6 +9,7 @@ import kr.toxicity.model.api.tracker.Tracker; import kr.toxicity.model.api.util.MathUtil; +import kr.toxicity.model.api.util.collection.PriorityMap; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.ApiStatus; @@ -16,12 +17,9 @@ import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BiConsumer; import java.util.function.BooleanSupplier; -import static kr.toxicity.model.api.util.CollectionUtil.newSequencedChainingMap; - /** * Animation state handler * @param timed value @@ -33,9 +31,7 @@ public final class AnimationStateHandler { private final T initialValue; private final BiConsumer setConsumer; - private final SequencedMap animators = newSequencedChainingMap(); - private final SequencedCollection reversedView = animators.sequencedValues().reversed(); - private final AtomicBoolean forceUpdateAnimation = new AtomicBoolean(); + private final PriorityMap animators = new PriorityMap<>(); @Getter private int delay; @@ -129,12 +125,12 @@ public float progress() { } private boolean shouldUpdateAnimation() { - return forceUpdateAnimation.compareAndSet(true, false) || (afterKeyframe != null && keyframeFinished()) || delay % Tracker.MINECRAFT_TICK_MULTIPLIER == 0; + return (afterKeyframe != null && keyframeFinished()) || delay % Tracker.MINECRAFT_TICK_MULTIPLIER == 0; } private boolean updateAnimation() { synchronized (animators) { - var iterator = reversedView.iterator(); + var iterator = animators.values().iterator(); while (iterator.hasNext()) { var next = iterator.next(); if (!next.getAsBoolean()) continue; @@ -190,9 +186,8 @@ private boolean setAfterKeyframe(@Nullable T next) { */ public void addAnimation(@NotNull String name, @NotNull AnimationIterator iterator, @NotNull AnimationModifier modifier, @NotNull Runnable removeTask) { synchronized (animators) { - animators.putLast(name, new TreeIterator(name, iterator, modifier, removeTask)); + animators.put(name, new TreeIterator(name, iterator, modifier, removeTask), modifier.priority()); } - forceUpdateAnimation.set(true); } /** @@ -203,11 +198,10 @@ public void addAnimation(@NotNull String name, @NotNull AnimationIterator ite */ public void replaceAnimation(@NotNull String name, @NotNull AnimationIterator iterator, @NotNull AnimationModifier modifier) { synchronized (animators) { - animators.computeIfPresent(name, (k, v) -> new TreeIterator(k, iterator, v.modifier.toBuilder() + animators.replace(name, v -> new TreeIterator(name, iterator, v.modifier.toBuilder() .mergeNotDefault(modifier) .build(), v.removeTask)); } - forceUpdateAnimation.set(true); } /** @@ -218,7 +212,6 @@ public void replaceAnimation(@NotNull String name, @NotNull AnimationIterator public boolean stopAnimation(@NotNull String name) { synchronized (animators) { if (animators.remove(name) != null) { - forceUpdateAnimation.set(true); return true; } } diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java index 71775914d..c30006293 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java @@ -11,6 +11,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.function.Function; public final class PriorityMap, V> { @@ -21,6 +22,10 @@ public final class PriorityMap, V> { public PriorityMap() { } + public boolean isEmpty() { + return valueMap.isEmpty(); + } + private record Identifier>( int priority, long count, @@ -53,10 +58,10 @@ public int compareTo(@NotNull Identifier o) { return (identifier = keyMap.remove(Objects.requireNonNull(key))) == null ? null : valueMap.remove(identifier); } - public @Nullable V replace(@NotNull K Key, @NotNull V newValue) { + public @Nullable V replace(@NotNull K Key, @NotNull Function function) { Identifier identifier; if ((identifier = keyMap.get(Objects.requireNonNull(Key))) == null) return null; - return valueMap.put(identifier, Objects.requireNonNull(newValue)); + return valueMap.computeIfPresent(identifier, (_, v) -> function.apply(v)); } public @NotNull Collection values() { diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt index c6e7268b3..110e655e4 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/mechanic/StateMechanic.kt @@ -27,6 +27,7 @@ class StateMechanic(mlc: MythicLineConfig) : AbstractSkillMechanic(mlc), INoTarg private val lo = mlc.toPlaceholderInteger(arrayOf("lo")) private val sp = mlc.toNullablePlaceholderFloat(arrayOf("speed", "sp")) private val remove = mlc.toPlaceholderBoolean(arrayOf("remove", "r")) + private val priority = mlc.toPlaceholderInteger(arrayOf("p", "pr", "priority")) override fun cast(p0: SkillMetadata): SkillResult { return cast(null, p0) @@ -45,6 +46,7 @@ class StateMechanic(mlc: MythicLineConfig) : AbstractSkillMechanic(mlc), INoTarg .end(lo(args)) .speed(sp(args)?.let(FloatSupplier::of)) .player(player?.wrap()) + .priority(priority(args)) .build()) SkillResult.SUCCESS } ?: SkillResult.CONDITION_FAILED From 9ea4064f3acd816985af3450648aa6c288bc79cc Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 30 Mar 2026 01:47:25 +0900 Subject: [PATCH 06/91] docs: write Javadocs --- .../api/data/blueprint/BlueprintElement.java | 37 ++++++++++++ .../data/blueprint/BlueprintLoadContext.java | 43 ++++++++++++++ .../api/data/blueprint/ModelBlueprint.java | 6 ++ .../model/api/data/raw/ModelElement.java | 43 ++++++++++++-- .../api/util/collection/PriorityMap.java | 58 ++++++++++++++++++- 5 files changed, 178 insertions(+), 9 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java index 1e936bb21..cbbe080b6 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java @@ -183,6 +183,13 @@ public List buildModernJson( return list.isEmpty() ? null : list; } + /** + * Builds the JSON representation for a mesh-based item model. + * + * @param context the load context + * @return the generated mesh JSON, or null if no meshes are present + * @since 3.0.0 + */ public @Nullable JsonObject buildMeshItemModel( @NotNull BlueprintLoadContext context ) { @@ -464,6 +471,15 @@ public boolean hasTexture() { } } + /** + * Represents a mesh element, allowing for complex geometry beyond simple cubes. + * + * @param origin the pivot point of the mesh + * @param rotation the rotation of the mesh + * @param faces the list of faces forming the mesh + * @param visibility whether the mesh is visible + * @since 3.0.0 + */ record Mesh( @NotNull Float3 origin, @NotNull Float3 rotation, @@ -471,6 +487,13 @@ record Mesh( boolean visibility ) implements BlueprintElement { + /** + * Converts this mesh into a list of {@link MeshShape} for rendering. + * + * @param parentOrigin the origin of the parent bone + * @return an unmodifiable list of mesh shapes + * @since 3.0.0 + */ @NotNull @Unmodifiable public List toShape(@NotNull Float3 parentOrigin) { @@ -494,8 +517,22 @@ public List toShape(@NotNull Float3 parentOrigin) { .toList(); } + /** + * Represents a single face of a mesh. + * + * @param points the vertices and UV coordinates of the face + * @param texture the index of the texture used by this face + * @since 3.0.0 + */ public record Face(@NotNull @Unmodifiable List points, int texture) {} + /** + * Represents a single point (vertex) in a mesh face. + * + * @param vertices the 3D coordinates of the vertex + * @param uv the 2D UV coordinates for texture mapping + * @since 3.0.0 + */ public record Point(@NotNull Float3 vertices, @NotNull Float2 uv) {} } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java index 3a4855f76..6bf3422db 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintLoadContext.java @@ -25,6 +25,11 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +/** + * A context class for loading blueprints. + * + * @since 3.0.0 + */ @ApiStatus.Internal public final class BlueprintLoadContext { @@ -57,18 +62,43 @@ public final class BlueprintLoadContext { this.canBeRendered = canBeRendered; } + /** + * Gets the name of the blueprint. + * + * @return the name + * @since 3.0.0 + */ public @NotNull String name() { return name; } + /** + * Gets the mesh triangle name. + * + * @return the triangle name + * @since 3.0.0 + */ public @NotNull MeshTriangleName triangleName() { return triangleName; } + /** + * Gets the model resolution. + * + * @return the resolution + * @since 3.0.0 + */ public @NotNull ModelResolution resolution() { return resolution; } + /** + * Gets a texture by its index. + * + * @param index the index + * @return the texture + * @since 3.0.0 + */ public @NotNull BlueprintTexture texture(int index) { return Objects.requireNonNull(textureRefs[index]).texture(); } @@ -98,10 +128,23 @@ public MeshImage get(Object key) { } } + /** + * Returns whether this context can be rendered. + * + * @return true if renderable + * @since 3.0.0 + */ public boolean canBeRendered() { return canBeRendered; } + /** + * Builds a stream of blueprint images using the provided obfuscator. + * + * @param obfuscator the obfuscator + * @return a stream of images + * @since 3.0.0 + */ @NotNull public Stream buildImage(@NotNull PackObfuscator obfuscator) { if (!canBeRendered()) return Stream.empty(); diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java index f1b7b9531..29d67ab8f 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/ModelBlueprint.java @@ -37,6 +37,12 @@ public record ModelBlueprint( @NotNull Map animations ) { + /** + * Creates a new load context for this blueprint. + * + * @since 3.0.0 + * @return a new blueprint load context + */ public @NotNull BlueprintLoadContext context() { return new BlueprintLoadContext( name(), diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java index c33fa0f17..041e6d5ca 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelElement.java @@ -346,6 +346,17 @@ public int lightEmission() { } } + /** + * Represents a mesh element, allowing for complex geometry beyond simple cubes. + * + * @param uuid the UUID of the mesh + * @param origin the pivot point (origin) of the mesh + * @param rotation the rotation of the mesh + * @param vertices a map of vertex identifiers to their 3D positions + * @param faces a map of face identifiers to their face data + * @param _visibility the visibility state (null means visible) + * @since 3.0.0 + */ record Mesh( @NotNull String uuid, @Nullable Float3 origin, @@ -354,27 +365,39 @@ record Mesh( @NotNull Map faces, @SerializedName("visibility") @Nullable Boolean _visibility ) implements ModelElement { + /** + * Returns the pivot point (origin) of the mesh. + * + * @return the origin vector, or {@link Float3#ZERO} if not specified + * @since 3.0.0 + */ @Override public @NotNull Float3 origin() { return origin != null ? origin : Float3.ZERO; } + /** + * Returns the rotation of the mesh. + * + * @return the rotation vector, or {@link Float3#ZERO} if not specified + * @since 3.0.0 + */ @Override public @NotNull Float3 rotation() { return rotation != null ? rotation : Float3.ZERO; } + /** + * Returns the type identifier of this element. + * + * @return {@link #MESH} + * @since 3.0.0 + */ @Override public @NotNull String type() { return MESH; } - /** - * Checks if the cube is visible. - * - * @return true if visible, false otherwise - * @since 3.0.0 - */ public boolean visibility() { return !Boolean.FALSE.equals(_visibility); } @@ -400,6 +423,14 @@ public boolean visibility() { ); } + /** + * Represents a single face of a mesh. + * + * @param uv a map of vertex identifiers to their UV coordinates + * @param vertices a set of vertex identifiers that form this face + * @param texture the index of the texture used by this face + * @since 3.0.0 + */ public record Face(@NotNull Map uv, @NotNull Set vertices, int texture) {} } } diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java index c30006293..94e2da0e7 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java @@ -13,25 +13,45 @@ import java.util.*; import java.util.function.Function; +/** + * A map that maintains the order of values based on priority, insertion order, and key comparison. + * + * @param the type of keys maintained by this map + * @param the type of mapped values + * @since 3.0.0 + */ public final class PriorityMap, V> { private final Map> keyMap = new HashMap<>(); private final TreeMap, V> valueMap = new TreeMap<>(); private long counter; - public PriorityMap() { - } - + /** + * Returns true if this map contains no key-value mappings. + * + * @return true if this map contains no key-value mappings + */ public boolean isEmpty() { return valueMap.isEmpty(); } + /** + * Internal identifier used to sort entries in the value map. + */ private record Identifier>( int priority, long count, @NotNull K key ) implements Comparable> { + /** + * Compares this identifier with another based on priority (descending), + * then insertion count (descending), and finally the key itself. + * + * @param o the object to be compared. + * @return a negative integer, zero, or a positive integer as this object + * is less than, equal to, or greater than the specified object. + */ @Override public int compareTo(@NotNull Identifier o) { int c; @@ -41,6 +61,14 @@ public int compareTo(@NotNull Identifier o) { } } + /** + * Associates the specified value with the specified key and priority in this map. + * + * @param key key with which the specified value is to be associated + * @param value value to be associated with the specified key + * @param priority priority of the entry + * @return the previous value associated with key, or null if there was no mapping for key. + */ public @Nullable V put(@NotNull K key, @NotNull V value, int priority) { return valueMap.put( keyMap.computeIfAbsent(Objects.requireNonNull(key), _ -> new Identifier<>(priority, counter++, key)), @@ -48,22 +76,46 @@ public int compareTo(@NotNull Identifier o) { ); } + /** + * Returns the value to which the specified key is mapped, or null if this map contains no mapping for the key. + * + * @param key the key whose associated value is to be returned + * @return the value to which the specified key is mapped, or null if this map contains no mapping for the key + */ public @Nullable V get(@NotNull K key) { Identifier identifier; return (identifier = keyMap.get(Objects.requireNonNull(key))) == null ? null : valueMap.get(identifier); } + /** + * Removes the mapping for a key from this map if it is present. + * + * @param key key whose mapping is to be removed from the map + * @return the previous value associated with key, or null if there was no mapping for key. + */ public @Nullable V remove(@NotNull K key) { Identifier identifier; return (identifier = keyMap.remove(Objects.requireNonNull(key))) == null ? null : valueMap.remove(identifier); } + /** + * Replaces the entry for the specified key only if it is currently mapped to some value. + * + * @param Key key with which the specified value is associated + * @param function the function to compute a value + * @return the previous value associated with the specified key, or null if there was no mapping for the key. + */ public @Nullable V replace(@NotNull K Key, @NotNull Function function) { Identifier identifier; if ((identifier = keyMap.get(Objects.requireNonNull(Key))) == null) return null; return valueMap.computeIfPresent(identifier, (_, v) -> function.apply(v)); } + /** + * Returns a Collection view of the values contained in this map, sorted by priority. + * + * @return a collection view of the values contained in this map + */ public @NotNull Collection values() { return valueMap.values(); } From 2ede6ed751fd96adfcb009bbddc3fe34c28c3c5d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 30 Mar 2026 02:01:43 +0900 Subject: [PATCH 07/91] docs: write Javadocs --- .../kr/toxicity/model/api/data/Float2.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/Float2.java b/api/src/main/java/kr/toxicity/model/api/data/Float2.java index 40f0f59b5..234f98a3e 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/Float2.java +++ b/api/src/main/java/kr/toxicity/model/api/data/Float2.java @@ -11,11 +11,21 @@ import org.jetbrains.annotations.NotNull; import org.joml.Vector2f; +/** + * A simple record representing two float values. + * + * @param x the x value + * @param y the y value + * @since 3.0.0 + */ public record Float2( float x, float y ) { - + /** + * A GSON deserializer for {@link Float2}. + * @since 3.0.0 + */ public static final JsonDeserializer PARSER = (json, _, _) -> { var array = json.getAsJsonArray(); return new Float2( @@ -24,6 +34,12 @@ public record Float2( ); }; + /** + * Converts this record to a {@link Vector2f}. + * + * @return a new vector instance + * @since 3.0.0 + */ public @NotNull Vector2f toVector() { return new Vector2f(x, y); } From 06ecf9ffc1f7b515971339b03f098f6e1d6bb990 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 31 Mar 2026 13:21:30 +0900 Subject: [PATCH 08/91] docs: update 3.0.0.md --- README.md | 8 ++-- changelog/3.0.0.md | 93 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c3c07fdde..f77eafc62 100644 --- a/README.md +++ b/README.md @@ -110,7 +110,7 @@ repositories { dependencies { compileOnly("io.github.toxicity188:bettermodel-bukkit-api:VERSION") // bukkit(spigot, paper, etc) api - //modApi("io.github.toxicity188:bettermodel-fabric:VERSION") // mod(fabric) + //api("io.github.toxicity188:bettermodel-fabric:VERSION") // mod(fabric) } ``` @@ -129,7 +129,7 @@ repositories { dependencies { compileOnly("io.github.toxicity188:bettermodel-bukkit-api:VERSION-SNAPSHOT") // bukkit(spigot, paper, etc) api - //modApi("io.github.toxicity188:bettermodel-fabric:VERSION-SNAPSHOT") // mod(fabric) + //api("io.github.toxicity188:bettermodel-fabric:VERSION-SNAPSHOT") // mod(fabric) } ``` @@ -147,7 +147,7 @@ repositories { dependencies { compileOnly 'io.github.toxicity188:bettermodel-bukkit-api:VERSION' // bukkit(spigot, paper, etc) api - //modApi 'io.github.toxicity188:bettermodel-fabric:VERSION' // mod(fabric) + //api 'io.github.toxicity188:bettermodel-fabric:VERSION' // mod(fabric) } ``` @@ -167,7 +167,7 @@ repositories { dependencies { compileOnly 'io.github.toxicity188:bettermodel-bukkit-api:VERSION-SNAPSHOT' // bukkit(spigot, paper, etc) api - //modApi 'io.github.toxicity188:bettermodel-fabric:VERSION-SNAPSHOT' // mod(fabric) + //api 'io.github.toxicity188:bettermodel-fabric:VERSION-SNAPSHOT' // mod(fabric) } ``` diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index bf2af9111..a4287b05a 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -1 +1,92 @@ -[Full change log](https://github.com/toxicity188/BetterModel/compare/2.2.0...2.2.1) +## 📚 Notices + +With the official release of Minecraft 26.1, BetterModel has decided to deploy a major version update to `3.0.0`. +As with 2.0.0, there are several **Breaking Changes**, so please take note when using it. + +--- + +## ✨ Feats + +### [Minecraft 26.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1) Support + +(Image placeholder) + +From now on, BetterModel supports running on Minecraft 26.1 Servers. + +--- + +### [Mesh Element](https://en.wikipedia.org/wiki/Triangle_mesh) Support (Experiment) + +(Image placeholder) + +We now support client resource pack conversion for Mesh Elements from [BlockBench](https://www.blockbench.net/). +It is available on Minecraft clients version 26.1 and above. + +--- + +### Others + +- A `priority` property has been added to the `AnimationModifier` class, allowing you to adjust the application order of animations. + +--- + +## 🚀 Breaking Changes + +### [Java 25](https://openjdk.org/projects/jdk/25/) Usage + +BetterModel is now built in a Java 25 environment, and therefore the required Java version to run it on a server has also been increased to 25. + +--- + +### [Deobfuscation](https://www.minecraft.net/en-us/article/removing-obfuscation-in-java-edition) Porting + +As obfuscation has been removed from the Minecraft jar starting from 26.1, tooling for mod platforms—which are most affected by mappings—has been changed. + +- `bettermodel-fabric`: Starting from 3.0.0, this is separated from the mod platform's API, `bettermodel-mod-api`. + +\
+\build.gradle.kts\ + +```kotlin +// Use the following dependency when referencing only the API. +// There is no need to use a separate remap configuration such as modCompileOnly. +dependencies { + compileOnly("io.github.toxicity188:bettermodel-mod-api:3.0.0") +} +``` + +```kotlin +// Use this when importing all Fabric platform modules to automate test servers, etc. +// There is no need to use a separate remap configuration such as modApi. +dependencies { + api("io.github.toxicity188:bettermodel-fabric:3.0.0") +} +``` + +\ + +--- + +## 🔧 Fixes + +- fix: swap unsupported char to hashcode +- fix: unnecessary decimal value (\#299) + +--- + +## 🧹 Chores + +- fix(deps): update dependency com.nexomc:nexo to v1.21.0 +- chore(deps): update gradle to v9.4.1 +- fix(deps): update dependency com.gradleup.shadow:com.gradleup.shadow.gradle.plugin to v9.4.1 +- fix(deps): update dependency org.jetbrains.dokka:dokka-gradle-plugin to v2.2.0 +- fix(deps): update kotlin monorepo to v2.3.20 +- fix(deps): update dependency net.fabricmc:fabric-language-kotlin to v1.13.10+kotlin.2.3.20 +- fix(deps): update dependency net.fabricmc:fabric-loader to v0.18.5 +- fix(deps): update dependency com.modrinth.minotaur:com.modrinth.minotaur.gradle.plugin to v2.9.0 +- fix(deps): update dependency org.projectlombok:lombok to v1.18.44 +- fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.11.0 + +--- + +[Full change log](https://github.com/toxicity188/BetterModel/compare/2.2.0...3.0.0) From 5e036de8fc3010afbaf316a7429fe97041b601b1 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 1 Apr 2026 21:35:10 +0900 Subject: [PATCH 09/91] fix: license header --- .../java/kr/toxicity/model/api/nms/AnimationBundler.java | 5 +++-- .../java/kr/toxicity/model/api/nms/ModAnimationBundler.java | 5 +++-- .../model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt | 5 +++-- .../model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt | 5 +++-- .../model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt | 5 +++-- .../model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt | 5 +++-- .../model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt | 5 +++-- .../model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt | 5 +++-- .../kotlin/kr/toxicity/model/spigot/BetterModelSpigot.kt | 5 +++-- 9 files changed, 27 insertions(+), 18 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/nms/AnimationBundler.java b/api/src/main/java/kr/toxicity/model/api/nms/AnimationBundler.java index 4a15ebc54..fd3e51f87 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/AnimationBundler.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/AnimationBundler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/nms/ModAnimationBundler.java b/api/src/main/java/kr/toxicity/model/api/nms/ModAnimationBundler.java index 824b6b19b..ed36407b8 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/ModAnimationBundler.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/ModAnimationBundler.java @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.api.nms; import kr.toxicity.model.api.platform.PlatformPlayer; diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt index c6580ff0b..b2df519ac 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R1 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt index 98e4d7185..1ddd702c4 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R3 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt index c157bbd97..5c0487b1d 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R4 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt index ebefb572d..f47fdaf58 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R5 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt index 0f5620f81..5c504aff5 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R6 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt index 816671b59..1779a225f 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.bukkit.nms.v1_21_R7 import kr.toxicity.model.api.nms.ModAnimationBundler diff --git a/platform/spigot/src/main/kotlin/kr/toxicity/model/spigot/BetterModelSpigot.kt b/platform/spigot/src/main/kotlin/kr/toxicity/model/spigot/BetterModelSpigot.kt index 7cf2edd0c..7ee6df08b 100644 --- a/platform/spigot/src/main/kotlin/kr/toxicity/model/spigot/BetterModelSpigot.kt +++ b/platform/spigot/src/main/kotlin/kr/toxicity/model/spigot/BetterModelSpigot.kt @@ -1,9 +1,10 @@ -/** +/* * This source file is part of BetterModel. - * Copyright (c) 2024–2026 toxicity188 + * Copyright (c) 2026 toxicity188 * Licensed under the MIT License. * See LICENSE.md file for full license text. */ + package kr.toxicity.model.spigot import kr.toxicity.model.api.BetterModelPlatform From b737e39876a2ebc27293d3bdbcd17a08cd78c576 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 1 Apr 2026 21:43:27 +0900 Subject: [PATCH 10/91] chore: Minecraft 26.1.1 --- .../java/kr/toxicity/model/api/version/MinecraftVersion.java | 4 ++++ buildSrc/src/main/kotlin/Extensions.kt | 3 ++- .../kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt | 1 + gradle.properties | 2 +- gradle/libs.versions.toml | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index 08f9c9b29..a965c7cc8 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -19,6 +19,10 @@ * @param patch minor update */ public record MinecraftVersion(int major, int minor, int patch) implements Comparable { + /** + * 26.1.1 + */ + public static final MinecraftVersion V26_1_1 = of(26, 1, 1); /** * 26.1 */ diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index 8d1986dc2..f264bb340 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -18,7 +18,8 @@ val SUPPORTED_VERSIONS = listOf( "1.21.9", "1.21.10", "1.21.11", - "26.1" + "26.1", + "26.1.1" ) val BUKKIT_LOADERS = listOf("spigot") diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index 03a647921..f4c35ac42 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -40,6 +40,7 @@ internal class BetterModelProperties( val version = parse(Bukkit.getMinecraftVersion()) val nms = when (version) { + //V26_1, V26_1_1 -> Latest() TODO implement this when Paper 26.1.1 is out V1_21_11 -> Latest() V1_21_9, V1_21_10 -> kr.toxicity.model.bukkit.nms.v1_21_R6.NMSImpl() V1_21_6, V1_21_7, V1_21_8 -> kr.toxicity.model.bukkit.nms.v1_21_R5.NMSImpl() diff --git a/gradle.properties b/gradle.properties index 0e8c2d0da..12c79f11b 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 project_version=3.0.0 -minecraft_version=26.1 +minecraft_version=26.1.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2334bb939..020e6fd2b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.144.3+26.1" +fabric-api = "0.145.2+26.1.1" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" cloud-bukkit = "2.0.0-beta.14" #TODO update this to 2.0.0-beta.15 when released From 2717ebac024a3970de8e3a171573e75eb52d4678 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 5 Apr 2026 00:01:06 +0900 Subject: [PATCH 11/91] feat: Minecraft 26.1.1 support --- build.gradle.kts | 3 +- buildSrc/src/main/kotlin/Extensions.kt | 28 +- .../main/kotlin/plugin-conventions.gradle.kts | 1 - changelog/3.0.0.md | 4 +- .../model/bukkit/BetterModelLibrary.java | 38 +- .../model/bukkit/BetterModelProperties.kt | 8 +- .../model/bukkit/manager/EntityManager.kt | 2 +- gradle/libs.versions.toml | 17 +- .../bukkit/nms/v1_21_R1/BukkitWrappers.kt | 28 +- .../nms/v1_21_R1/ModAnimationBundlerImpl.kt | 9 +- .../bukkit/nms/v1_21_R3/BukkitWrappers.kt | 28 +- .../nms/v1_21_R3/ModAnimationBundlerImpl.kt | 9 +- .../bukkit/nms/v1_21_R4/BukkitWrappers.kt | 28 +- .../nms/v1_21_R4/ModAnimationBundlerImpl.kt | 9 +- .../bukkit/nms/v1_21_R5/BukkitWrappers.kt | 28 +- .../nms/v1_21_R5/ModAnimationBundlerImpl.kt | 9 +- .../model/bukkit/nms/v1_21_R5/NMSImpl.kt | 2 +- .../bukkit/nms/v1_21_R6/BukkitWrappers.kt | 28 +- .../nms/v1_21_R6/ModAnimationBundlerImpl.kt | 9 +- .../model/bukkit/nms/v1_21_R6/NMSImpl.kt | 2 +- .../bukkit/nms/v1_21_R7/BukkitWrappers.kt | 28 +- .../nms/v1_21_R7/ModAnimationBundlerImpl.kt | 9 +- .../model/bukkit/nms/v1_21_R7/NMSImpl.kt | 2 +- nms/v26_R1/build.gradle.kts | 8 + .../bukkit/nms/v26_R1/AbstractHitBox.java | 32 ++ .../model/bukkit/nms/v26_R1/BaseEntityImpl.kt | 85 ++++ .../model/bukkit/nms/v26_R1/BasePlayerImpl.kt | 48 ++ .../model/bukkit/nms/v26_R1/BukkitWrappers.kt | 36 ++ .../model/bukkit/nms/v26_R1/EntityData.kt | 126 +++++ .../model/bukkit/nms/v26_R1/Functions.kt | 217 ++++++++ .../model/bukkit/nms/v26_R1/HitBoxImpl.kt | 465 ++++++++++++++++++ .../bukkit/nms/v26_R1/HitBoxInteraction.kt | 58 +++ .../nms/v26_R1/ModAnimationBundlerImpl.kt | 144 ++++++ .../nms/v26_R1/ModelDamageSourceImpl.kt | 30 ++ .../bukkit/nms/v26_R1/ModelDisplayImpl.kt | 261 ++++++++++ .../bukkit/nms/v26_R1/ModelGameProfile.kt | 30 ++ .../bukkit/nms/v26_R1/ModelNametagImpl.kt | 119 +++++ .../model/bukkit/nms/v26_R1/NMSImpl.kt | 398 +++++++++++++++ .../model/bukkit/nms/v26_R1/PacketBundlers.kt | 91 ++++ .../bukkit/nms/v26_R1/PlayerArmorImpl.kt | 47 ++ .../model/bukkit/nms/v26_R1/ProfiledImpl.kt | 24 + .../model/bukkit/nms/v26_R1/TypeAliases.kt | 19 + platform/fabric/build.gradle.kts | 2 +- .../model/impl/fabric/BetterModelNMSImpl.kt | 2 +- .../impl/fabric/entity/ModelNametagImpl.kt | 3 +- .../fabric/entity/PlayerChannelHandlerImpl.kt | 3 +- .../fabric/network/ModAnimationBundlerImpl.kt | 146 ++++++ platform/paper/build.gradle.kts | 2 + platform/spigot/build.gradle.kts | 24 +- settings.gradle.kts | 5 +- 50 files changed, 2554 insertions(+), 200 deletions(-) create mode 100644 nms/v26_R1/build.gradle.kts create mode 100644 nms/v26_R1/src/main/java/kr/toxicity/model/bukkit/nms/v26_R1/AbstractHitBox.java create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BaseEntityImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BasePlayerImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/EntityData.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModAnimationBundlerImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDamageSourceImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDisplayImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelGameProfile.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelNametagImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PacketBundlers.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PlayerArmorImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ProfiledImpl.kt create mode 100644 nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/TypeAliases.kt create mode 100644 platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/ModAnimationBundlerImpl.kt diff --git a/build.gradle.kts b/build.gradle.kts index 84ba7121f..0a9107672 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { id("xyz.jpenilla.run-paper") version "3.0.2" } -val minecraft = "1.21.11" //TODO change this to property("minecraft_version").toString() +val minecraft = property("minecraft_version").toString() val versionString = version.toString() val groupString = group.toString() @@ -34,7 +34,6 @@ tasks { hangar("ViaVersion", "5.8.1") hangar("ViaBackwards", "5.8.1") hangar("Skript", "2.14.2") - hangar("TabTPS", "1.3.30") } } build { diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index f264bb340..f5325e7f4 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -7,20 +7,26 @@ val BUILD_NUMBER: String? = System.getenv("BUILD_NUMBER") val Project.libs get() = rootProject.extensions.getByName("libs") as LibrariesForLibs -val SUPPORTED_VERSIONS = listOf( - "1.21", - "1.21.1", - "1.21.4", - "1.21.5", - "1.21.6", - "1.21.7", - "1.21.8", - "1.21.9", - "1.21.10", - "1.21.11", +val LATEST_VERSION = listOf( "26.1", "26.1.1" ) +val SUPPORTED_VERSIONS = buildList { + addAll(listOf( + "1.21", + "1.21.1", + "1.21.4", + "1.21.5", + "1.21.6", + "1.21.7", + "1.21.8", + "1.21.9", + "1.21.10", + "1.21.11", + )) + addAll(LATEST_VERSION) +} + val BUKKIT_LOADERS = listOf("spigot") val PAPER_LOADERS = listOf("paper", "purpur", "folia") diff --git a/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts b/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts index c05ce6f39..bbfbf5326 100644 --- a/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/plugin-conventions.gradle.kts @@ -56,7 +56,6 @@ tasks { modrinth { uploadFile.set(tasks.shadowJar) - gameVersions = SUPPORTED_VERSIONS dependencies { optional.project( "mythicmobs", diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index a4287b05a..02142cf94 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -7,11 +7,11 @@ As with 2.0.0, there are several **Breaking Changes**, so please take note when ## ✨ Feats -### [Minecraft 26.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1) Support +### [Minecraft 26.1 / 26.1.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support (Image placeholder) -From now on, BetterModel supports running on Minecraft 26.1 Servers. +From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. --- diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java index bce49e110..7461a2f28 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java @@ -39,25 +39,25 @@ public final class BetterModelLibrary { "bstats-base" ) ); - public static final LibraryData CLOUD = register( - "org{}incendo", - "cloud-paper", - builder -> builder - .subModules( - "cloud-brigadier", - "cloud-bukkit" - ) - .relocation("org{}incendo{}cloud") - ); - public static final LibraryData CLOUD_CORE = register( - "org{}incendo", - "cloud-core", - builder -> builder - .subModules( - "cloud-services" - ) - .relocation("org{}incendo{}cloud") - ); +// public static final LibraryData CLOUD = register( +// "org{}incendo", +// "cloud-paper", +// builder -> builder +// .subModules( +// "cloud-brigadier", +// "cloud-bukkit" +// ) +// .relocation("org{}incendo{}cloud") +// ); +// public static final LibraryData CLOUD_CORE = register( +// "org{}incendo", +// "cloud-core", +// builder -> builder +// .subModules( +// "cloud-services" +// ) +// .relocation("org{}incendo{}cloud") +// ); public static final LibraryData GEANTYREF = register( "io{}leangen{}geantyref", "geantyref", diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index f4c35ac42..7571a84b0 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -30,7 +30,7 @@ import kr.toxicity.model.util.warn import org.bstats.bukkit.Metrics import org.bukkit.Bukkit -private typealias Latest = kr.toxicity.model.bukkit.nms.v1_21_R7.NMSImpl +private typealias Latest = kr.toxicity.model.bukkit.nms.v26_R1.NMSImpl internal class BetterModelProperties( private val plugin: AbstractBetterModelPlugin @@ -38,10 +38,10 @@ internal class BetterModelProperties( private lateinit var _config: BetterModelConfig private var _metrics: Metrics? = null - val version = parse(Bukkit.getMinecraftVersion()) + val version = parse(Bukkit.getBukkitVersion().substringBefore('-')) val nms = when (version) { - //V26_1, V26_1_1 -> Latest() TODO implement this when Paper 26.1.1 is out - V1_21_11 -> Latest() + V26_1, V26_1_1 -> Latest() + V1_21_11 -> kr.toxicity.model.bukkit.nms.v1_21_R7.NMSImpl() V1_21_9, V1_21_10 -> kr.toxicity.model.bukkit.nms.v1_21_R6.NMSImpl() V1_21_6, V1_21_7, V1_21_8 -> kr.toxicity.model.bukkit.nms.v1_21_R5.NMSImpl() V1_21_5 -> kr.toxicity.model.bukkit.nms.v1_21_R4.NMSImpl() diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt index ad9de1784..3a1e2c074 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt @@ -21,8 +21,8 @@ import kr.toxicity.model.api.tracker.EntityTracker import kr.toxicity.model.api.tracker.EntityTrackerRegistry import kr.toxicity.model.api.tracker.Tracker import kr.toxicity.model.api.tracker.TrackerExtraAnimation -import kr.toxicity.model.bukkit.nms.v1_21_R4.wrap import kr.toxicity.model.bukkit.util.registerListener +import kr.toxicity.model.bukkit.util.wrap import kr.toxicity.model.manager.GlobalManager import kr.toxicity.model.manager.ReloadPipeline import kr.toxicity.model.util.PLATFORM diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 020e6fd2b..62d5247fa 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,22 +1,22 @@ [versions] kotlin = "2.3.20" -paperweight = "2.0.0-beta.19" +paperweight = "2.0.0-beta.21" resourcefactory = "1.3.1" shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.145.2+26.1.1" +fabric-api = "0.145.3+26.1.1" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" -cloud-bukkit = "2.0.0-beta.14" #TODO update this to 2.0.0-beta.15 when released +cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released cloud-mod = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.16 when released cloud-core = "2.0.0" configurate = "4.2.0" -neoform = "26.1-1" +neoform = "26.1.1-1" [libraries] kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } @@ -32,10 +32,10 @@ adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0-SNAPSHOT" asm-tree = "org.ow2.asm:asm-tree:9.9.1" -fabric-loader = "net.fabricmc:fabric-loader:0.18.5" +fabric-loader = "net.fabricmc:fabric-loader:0.18.6" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0-pre.4+26.1" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0+26.1.1" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } @@ -105,7 +105,7 @@ manifestLibrary = [ "kotlin", "bStats", "molangCompiler", - "cloud-paper", + #"cloud-paper", "cloud-core", "geantyref", "adventure-api", @@ -117,7 +117,8 @@ manifestLibrary = [ shadedLibrary = [ "armormodel", - "libby" + "libby", + "cloud-paper" ] [plugins] diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt index 3eae9c109..0751f3ffc 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt index b2df519ac..46d0c7d78 100644 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt index a0378c6f9..da9992eab 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt index 1ddd702c4..2bc0a01df 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt index b88e14b26..eb413b60b 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt index 5c0487b1d..afdc84bea 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt index e287de302..483b1a3a5 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt index f47fdaf58..81ce5fd22 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt index ba17eae60..8e6b574f8 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt @@ -151,7 +151,7 @@ class NMSImpl : NMS { } override fun base(): BasePlayer = base - override fun isModEnabled(): Boolean = player.channels().contains("modelengine:bulk_data") + override fun isModEnabled(): Boolean = (if (BetterModelBukkit.IS_PAPER) player.channels() else player.listeningPluginChannels).contains(ModAnimationBundlerImpl.KEY) private val playerModel get() = connection.player.id.toRegistry() diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt index e6528659a..983216259 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt index 5c504aff5..3baaac221 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt index bd7b18bf3..ad8058cf0 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt @@ -153,7 +153,7 @@ class NMSImpl : NMS { } override fun base(): BasePlayer = base - override fun isModEnabled(): Boolean = player.channels().contains("modelengine:bulk_data") + override fun isModEnabled(): Boolean = (if (BetterModelBukkit.IS_PAPER) player.channels() else player.listeningPluginChannels).contains(ModAnimationBundlerImpl.KEY) private val playerModel get() = connection.player.id.toRegistry() diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt index 2b289b6d8..31f08842d 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt @@ -19,18 +19,18 @@ import org.bukkit.entity.LivingEntity import org.bukkit.entity.Player import org.bukkit.inventory.ItemStack -fun Entity.wrap() = adapt(this) -fun LivingEntity.wrap() = adapt(this) -fun OfflinePlayer.wrap() = adapt(this) -fun Player.wrap() = adapt(this) -fun Location.wrap() = adapt(this) -fun World.wrap() = adapt(this) -fun ItemStack.wrap() = adapt(this) +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) -fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt index 1779a225f..c01624de2 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/ModAnimationBundlerImpl.kt @@ -12,7 +12,6 @@ import kr.toxicity.model.api.platform.PlatformPlayer import kr.toxicity.model.api.util.MathUtil import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.codec.StreamCodec import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket import net.minecraft.server.MinecraftServer import org.bukkit.craftbukkit.entity.CraftPlayer @@ -32,18 +31,12 @@ internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundl const val FIELD_SCALE = 1 shl 2 const val FIELD_TRANSFORM_DURATION = 1 shl 4 - @Suppress("UNCHECKED_CAST") - private val createPayload = (ClientboundCustomPayloadPacket::class.java.fields[0].apply { - isAccessible = true - }.get(null) as StreamCodec).let { - { buf: RegistryFriendlyByteBuf -> it.decode(buf) } - } private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} } private val packet by lazy { useByteBuf { buffer -> - createPayload( + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( RegistryFriendlyByteBuf( buffer, MinecraftServer.getServer().registryAccess() diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt index 787dd8797..7fd5a000e 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt @@ -152,7 +152,7 @@ class NMSImpl : NMS { } override fun base(): BasePlayer = base - override fun isModEnabled(): Boolean = player.channels().contains(ModAnimationBundlerImpl.KEY) + override fun isModEnabled(): Boolean = (if (BetterModelBukkit.IS_PAPER) player.channels() else player.listeningPluginChannels).contains(ModAnimationBundlerImpl.KEY) private val playerModel get() = connection.player.id.toRegistry() diff --git a/nms/v26_R1/build.gradle.kts b/nms/v26_R1/build.gradle.kts new file mode 100644 index 000000000..6d88914c3 --- /dev/null +++ b/nms/v26_R1/build.gradle.kts @@ -0,0 +1,8 @@ +plugins { + alias(libs.plugins.convention.paperweight) + alias(libs.plugins.paperweight) +} + +dependencies { + paperweight.paperDevBundle("26.1.1.build.15-alpha") +} diff --git a/nms/v26_R1/src/main/java/kr/toxicity/model/bukkit/nms/v26_R1/AbstractHitBox.java b/nms/v26_R1/src/main/java/kr/toxicity/model/bukkit/nms/v26_R1/AbstractHitBox.java new file mode 100644 index 000000000..abe8e7c9a --- /dev/null +++ b/nms/v26_R1/src/main/java/kr/toxicity/model/bukkit/nms/v26_R1/AbstractHitBox.java @@ -0,0 +1,32 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1; + +import kr.toxicity.model.api.nms.HitBox; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.decoration.ArmorStand; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class AbstractHitBox extends ArmorStand implements HitBox { + + AbstractHitBox(@NotNull Level level) { + super(EntityType.ARMOR_STAND, level); + } + + @Override //Only for provide compiler hint for Kotlin jvm + public final boolean equals(@Nullable Object other) { + return super.equals(other); + } + + @Override //Only for provide compiler hint for Kotlin jvm + public final int hashCode() { + return super.hashCode(); + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BaseEntityImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BaseEntityImpl.kt new file mode 100644 index 000000000..2767b543b --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BaseEntityImpl.kt @@ -0,0 +1,85 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity +import kr.toxicity.model.api.platform.PlatformEntity +import kr.toxicity.model.api.platform.PlatformLocation +import kr.toxicity.model.api.platform.PlatformPlayer +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.effect.MobEffects +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.entity.ai.attributes.Attributes +import org.bukkit.craftbukkit.entity.CraftEntity +import org.bukkit.persistence.PersistentDataHolder +import org.joml.Vector3f +import java.util.* +import java.util.stream.Stream + +internal data class BaseEntityImpl( + private val delegate: CraftEntity +) : BaseBukkitEntity, PersistentDataHolder by delegate { + override fun customName(): AdventureComponent? = handle().run { + if (this is ServerPlayer) (customName ?: name).asAdventure() else customName?.asAdventure()?.takeIf { + isCustomNameVisible + } + } + + override fun entity(): org.bukkit.entity.Entity = delegate + override fun handle(): Entity = delegate.vanillaEntity + override fun uuid(): UUID = delegate.uniqueId + override fun id(): Int = handle().id + override fun dead(): Boolean = (handle() as? LivingEntity)?.isDeadOrDying == true || handle().removalReason != null || !handle().valid + override fun invisible(): Boolean = handle().isInvisible || (handle() as? LivingEntity)?.hasEffect(MobEffects.INVISIBILITY) == true + override fun glow(): Boolean = handle().isCurrentlyGlowing + + override fun onWalk(): Boolean { + return handle().isWalking() + } + + override fun scale(): Double { + val handle = handle() + return if (handle is LivingEntity) handle.scale.toDouble() else 1.0 + } + + override fun pitch(): Float = handle().xRot + override fun ground(): Boolean = handle().onGround() + override fun bodyYaw(): Float = handle().let { if (it is LivingEntity) it.yBodyRot else it.yRot } + override fun yaw(): Float = handle().yRot + override fun headYaw(): Float = handle().let { if (it is LivingEntity) it.yHeadRot else it.yRot } + override fun fly(): Boolean = handle().isFlying + + override fun damageTick(): Float { + val handle = handle() + if (handle !is LivingEntity) return 0F + val duration = handle.invulnerableDuration.toFloat() + if (duration <= 0F) return 0F + val knockBack = 1 - (handle.getAttribute(Attributes.KNOCKBACK_RESISTANCE)?.value?.toFloat() ?: 0F) + return handle.invulnerableTime.toFloat() / duration * knockBack + } + + override fun walkSpeed(): Float { + val handle = handle() + if (handle !is LivingEntity) return 0F + if (!handle.onGround) return 1F + val speed = handle.getEffect(MobEffects.SPEED)?.amplifier ?: 0 + val slow = handle.getEffect(MobEffects.SLOWNESS)?.amplifier ?: 0 + return (1F + (speed - slow) * 0.2F) + .coerceAtLeast(0.2F) + .coerceAtMost(2F) + } + + override fun passengerPosition(dest: Vector3f): Vector3f { + return handle().passengerPosition(dest) + } + + override fun platform(): PlatformEntity = delegate.wrap() + override fun trackedBy(): Stream = delegate.trackedBy.stream().map { it.wrap() } + override fun location(): PlatformLocation = delegate.location.wrap() +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BasePlayerImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BasePlayerImpl.kt new file mode 100644 index 000000000..6863d9707 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BasePlayerImpl.kt @@ -0,0 +1,48 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity +import kr.toxicity.model.api.bukkit.entity.BaseBukkitPlayer +import kr.toxicity.model.api.nms.Profiled +import kr.toxicity.model.api.platform.PlatformPlayer +import kr.toxicity.model.api.player.PlayerSkinParts +import kr.toxicity.model.api.profile.ModelProfile +import net.minecraft.util.Mth +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.bukkit.entity.Player +import java.util.stream.Stream + +internal data class BasePlayerImpl( + private val delegate: CraftPlayer, + private val profile: () -> ModelProfile, + private val skinParts: () -> PlayerSkinParts +) : BaseBukkitEntity by BaseEntityImpl(delegate), BaseBukkitPlayer, Profiled by ProfiledImpl(PlayerArmorImpl(delegate), profile, skinParts) { + + override fun entity(): Player = delegate + + override fun updateInventory() { + delegate.handle.containerMenu.sendAllDataToRemote() + } + + override fun platform(): PlatformPlayer = delegate.wrap() + + override fun trackedBy(): Stream = Stream.concat( + Stream.of(delegate), + delegate.trackedBy.stream() + ).map { + it.wrap() + } + + override fun bodyYaw(): Float { + val handle = delegate.handle + var yaw = -45 * handle.xMovement() + if (handle.zMovement() < 0) yaw *= -1 + return Mth.wrapDegrees(handle.yHeadRot + yaw) + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt new file mode 100644 index 000000000..9f0cd873b --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt @@ -0,0 +1,36 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* +import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitItemStack +import kr.toxicity.model.api.platform.* +import org.bukkit.Location +import org.bukkit.OfflinePlayer +import org.bukkit.World +import org.bukkit.entity.Entity +import org.bukkit.entity.LivingEntity +import org.bukkit.entity.Player +import org.bukkit.inventory.ItemStack + +internal fun Entity.wrap() = adapt(this) +internal fun LivingEntity.wrap() = adapt(this) +internal fun OfflinePlayer.wrap() = adapt(this) +internal fun Player.wrap() = adapt(this) +internal fun Location.wrap() = adapt(this) +internal fun World.wrap() = adapt(this) +internal fun ItemStack.wrap() = adapt(this) + +internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() +internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() +internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() +internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() +internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() +internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() +internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/EntityData.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/EntityData.kt new file mode 100644 index 000000000..40185675f --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/EntityData.kt @@ -0,0 +1,126 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.nms.AnimationBundler +import kr.toxicity.model.api.util.MathUtil +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket +import net.minecraft.network.syncher.EntityDataAccessor +import net.minecraft.network.syncher.SynchedEntityData +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.Display.ItemDisplay +import net.minecraft.world.entity.Entity +import org.joml.Quaternionf +import org.joml.Vector3f +import java.lang.reflect.Field + +internal fun Field.toEntityDataAccessor() = run { + isAccessible = true + get(null) as EntityDataAccessor<*> +} + +internal fun Class<*>.accessors() = declaredFields.filter { f -> + EntityDataAccessor::class.java.isAssignableFrom(f.type) +}.map { + it.toEntityDataAccessor() +} + +internal val DISPLAY_SET = Display::class.java.accessors() +internal val SHARED_FLAG = Entity::class.java.accessors().first().id +internal val ITEM_DISPLAY_ID = ItemDisplay::class.java.accessors().map { + it.id +} +internal val ITEM_SERIALIZER = ItemDisplay::class.java.accessors().first() +internal val ITEM_ENTITY_DATA = buildList { + add(SHARED_FLAG) + addAll(ITEM_DISPLAY_ID) + add(Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID.id) + DISPLAY_SET.subList(7, DISPLAY_SET.size).mapTo(this) { it.id } +}.toIntSet() + +@Suppress("UNCHECKED_CAST") +private val DISPLAY_INTERPOLATION_DELAY = (DISPLAY_SET.first() as EntityDataAccessor).run { + SynchedEntityData.DataValue(id, serializer, 0) +} +@Suppress("UNCHECKED_CAST") +internal val DISPLAY_INTERPOLATION_DURATION = DISPLAY_SET[1] as EntityDataAccessor +@Suppress("UNCHECKED_CAST") +internal val DISPLAY_TRANSLATION = DISPLAY_SET[3] as EntityDataAccessor +@Suppress("UNCHECKED_CAST") +internal val DISPLAY_SCALE = DISPLAY_SET[4] as EntityDataAccessor +@Suppress("UNCHECKED_CAST") +internal val DISPLAY_ROTATION = DISPLAY_SET[5] as EntityDataAccessor + + +internal class TransformationData { + + private var _duration = 0 + private val duration get() = SynchedEntityData.DataValue(DISPLAY_INTERPOLATION_DURATION.id, DISPLAY_INTERPOLATION_DURATION.serializer, _duration) + private val translation = Item(Vector3f(), DISPLAY_TRANSLATION, MathUtil::isSimilar, Vector3f::set) + private val scale = Item(Vector3f(), DISPLAY_SCALE, MathUtil::isSimilar, Vector3f::set) + private val rotation = Item(Quaternionf(), DISPLAY_ROTATION, MathUtil::isSimilar, Quaternionf::set) + + fun packDirty(entityId: Int, dest: AnimationBundler) { + val i = translation.cleanIndex + scale.cleanIndex + rotation.cleanIndex + if (i == 0) return + (dest.mod as ModAnimationBundlerImpl).append(entityId) { + dest.standard += ClientboundSetEntityDataPacket(entityId, buildList(i + 2) { + add(DISPLAY_INTERPOLATION_DELAY) + translation.value?.let { appendPosition(it.value); add(it) } + rotation.value?.let { appendRotation(it.value); add(it) } + scale.value?.let { appendScale(it.value); add(it) } + appendDuration(_duration); add(duration) + }) + } + } + + fun transform( + duration: Int, + translation: Vector3f, + scale: Vector3f, + rotation: Quaternionf + ) { + _duration = duration + this.translation.set(translation) + this.scale.set(scale) + this.rotation.set(rotation) + } + + fun pack() = listOf( + DISPLAY_INTERPOLATION_DELAY, + duration, + translation.forceValue, + scale.forceValue, + rotation.forceValue + ) + + private class Item( + initialValue: T, + private val accessor: EntityDataAccessor, + private val dirtyChecker: (T, T) -> Boolean, + private val setter: (T, T) -> Unit + ) { + private val _t: T = initialValue + private var _dirty = false + + val dirty get() = _dirty + val cleanIndex get() = if (dirty) 1 else 0 + val value get() = if (_dirty) { + _dirty = false + forceValue + } else null + val forceValue get() = SynchedEntityData.DataValue(accessor.id, accessor.serializer, _t) + + fun set(other: T) { + if (dirtyChecker(_t, other)) return + _dirty = true + setter(_t, other) + } + } +} + diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt new file mode 100644 index 000000000..47018fa62 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt @@ -0,0 +1,217 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import io.netty.buffer.Unpooled +import io.papermc.paper.adventure.PaperAdventure +import io.papermc.paper.configuration.GlobalConfiguration +import it.unimi.dsi.fastutil.ints.IntSet +import kr.toxicity.model.api.BetterModel +import kr.toxicity.model.api.bukkit.BetterModelBukkit +import kr.toxicity.model.api.tracker.EntityTrackerRegistry +import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket +import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket +import net.minecraft.network.syncher.SynchedEntityData +import net.minecraft.network.syncher.SynchedEntityData.DataItem +import net.minecraft.network.syncher.SynchedEntityData.DataValue +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.entity.* +import net.minecraft.world.entity.ai.goal.RangedAttackGoal +import net.minecraft.world.entity.ai.goal.RangedBowAttackGoal +import net.minecraft.world.entity.ai.goal.RangedCrossbowAttackGoal +import net.minecraft.world.entity.animal.FlyingAnimal +import net.minecraft.world.entity.player.Player +import net.minecraft.world.item.ItemStack +import net.minecraft.world.phys.Vec3 +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.entity.CraftEntity +import org.bukkit.craftbukkit.inventory.CraftItemStack +import org.bukkit.craftbukkit.util.CraftChatMessage +import org.joml.Vector3f +import java.util.* + +internal inline fun createAdaptedFieldGetter(noinline paperGetter: (T) -> R): (T) -> R { + return if (BetterModelBukkit.IS_PAPER) paperGetter else createAdaptedFieldGetter() +} +internal inline fun createAdaptedFieldGetter(): (T) -> R { + return T::class.java.declaredFields.first { + R::class.java.isAssignableFrom(it.type) + }.apply { + isAccessible = true + }.let { getter -> + { t -> + getter[t] as R + } + } +} + +internal fun dirtyChecked(hash: () -> H, function: (H) -> T): () -> T { + val lock = Any() + var h = hash() + var value = function(h) + return { + val newH = hash() + when { + h === newH -> value + h == newH -> value + else -> synchronized(lock) { + h = newH + value = function(h) + value + } + } + } +} + +internal val CONFIG get() = BetterModel.config() +internal val EMPTY_ITEM = VanillaItemStack.EMPTY +internal fun BukkitItemStack.asVanilla() = CraftItemStack.asNMSCopy(this) +internal fun VanillaItemStack.asBukkit() = CraftItemStack.asCraftMirror(this) + +internal val ONLINE_MODE by lazy(LazyThreadSafetyMode.NONE) { + if (BetterModelBukkit.IS_PAPER) GlobalConfiguration.get().proxies.isProxyOnlineMode else Bukkit.getOnlineMode() +} + +internal fun List.toIntSet(): IntSet = IntSet.of(*toIntArray()) + +internal fun Entity.passengerPosition(dest: Vector3f): Vector3f { + return attachments.get(EntityAttachment.PASSENGER, 0, yRot).let { v -> + dest.set(v.x.toFloat(), v.y.toFloat(), v.z.toFloat()) + } +} + +private val DATA_ITEMS = SynchedEntityData::class.java.declaredFields.first { + it.type.isArray +}.apply { + isAccessible = true +} + +internal fun SynchedEntityData.pack( + clean: Boolean = false, + itemFilter: (DataItem<*>) -> Boolean = { true }, + valueFilter: (DataValue<*>) -> Boolean = { true }, + required: (List, DataValue<*>>>) -> Boolean = { it.isNotEmpty() } +): List>? = (DATA_ITEMS[this] as Array<*>) + .mapNotNull map@ { + val item = (it as? DataItem<*>)?.takeIf(itemFilter) ?: return@map null + val value = item.value().takeIf(valueFilter) ?: return@map null + item to value + } + .takeIf(required) + ?.map { + if (clean) it.first.isDirty = false + it.second + } + +internal fun Entity.isWalking(): Boolean { + return controllingPassenger?.isWalking() ?: when (this) { + is Mob -> navigation.isInProgress || goalSelector.availableGoals.any { + it.isRunning && when (it.goal) { + is RangedAttackGoal, is RangedCrossbowAttackGoal<*>, is RangedBowAttackGoal<*> -> true + else -> false + } + } + is ServerPlayer -> xMovement() != 0F || zMovement() != 0F + else -> false + } +} + +internal fun ServerPlayer.xMovement(): Float { + val leftMovement: Boolean = lastClientInput.left() + val rightMovement: Boolean = lastClientInput.right() + return if (leftMovement == rightMovement) 0F else if (leftMovement) 1F else -1F +} + +internal fun ServerPlayer.yMovement(): Float = if (isJump()) 1F else if (lastClientInput.shift) -1F else 0F + +internal fun ServerPlayer.zMovement(): Float { + val forwardMovement: Boolean = lastClientInput.forward() + val backwardMovement: Boolean = lastClientInput.backward() + return if (forwardMovement == backwardMovement) 0F else if (forwardMovement) 1F else -1F +} + +internal fun ServerPlayer.isJump() = lastClientInput.jump() + +internal val Entity.isFlying: Boolean + get() = when (this) { + is FlyingAnimal -> isFlying + is Mob -> isNoAi + is Player -> abilities.flying + is LivingEntity -> isFallFlying + else -> false + } + +internal val CraftEntity.vanillaEntity: Entity + get() = if (BetterModelBukkit.IS_PAPER) handleRaw else handle + +internal fun Entity.moveTo(vec: Vec3) = snapTo(vec) +internal fun Entity.moveTo(x: Double, y: Double, z: Double, yaw: Float, pitch: Float) = snapTo(x, y, z, yaw, pitch) + +internal inline fun useByteBuf(block: (FriendlyByteBuf) -> T): T { + val buffer = FriendlyByteBuf(Unpooled.buffer()) + return try { + block(buffer) + } finally { + buffer.release() + } +} + +internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { + var b = byte.toInt() + val hideOption = hideOption(uuid) + if (hideOption.fire()) b = b and 1.inv() + if (hideOption.visibility()) b = b or (1 shl 5) + if (hideOption.glowing()) b = b and (1 shl 6).inv() + return b.toByte() +} + +internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) +internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) + +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { + val equip = EquipmentSlot.entries.mapNotNull { + mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } + } + return if (equip.isNotEmpty()) ClientboundSetEquipmentPacket(id, equip) else null +} +internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } + +internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) + +internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( + id, + uuid, + x, + y, + z, + xRot, + yRot, + EntityType.ITEM_DISPLAY, + 0, + deltaMovement, + yHeadRot.toDouble() +) + +internal fun Avatar.toCustomisation() = entityData.get(Avatar.DATA_PLAYER_MODE_CUSTOMISATION).toInt() + +internal fun VanillaComponent.asAdventure() = if (BetterModelBukkit.IS_PAPER) { + PaperAdventure.asAdventure(this) +} else { + GsonComponentSerializer.gson().deserialize(CraftChatMessage.toJSON(this)) +} + +internal fun AdventureComponent.asVanilla() = if (BetterModelBukkit.IS_PAPER) { + PaperAdventure.asVanilla(this) +} else { + CraftChatMessage.fromJSON(GsonComponentSerializer.gson().serialize(this)) +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt new file mode 100644 index 000000000..a21b67ce1 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt @@ -0,0 +1,465 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import io.papermc.paper.event.entity.EntityKnockbackEvent +import kr.toxicity.model.api.BetterModel +import kr.toxicity.model.api.bone.BoneMovement +import kr.toxicity.model.api.bone.RenderedBone +import kr.toxicity.model.api.bukkit.BetterModelBukkit +import kr.toxicity.model.api.config.DebugConfig +import kr.toxicity.model.api.data.blueprint.ModelBoundingBox +import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent +import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent +import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent +import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent +import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent +import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent +import kr.toxicity.model.api.mount.MountController +import kr.toxicity.model.api.nms.HitBox +import kr.toxicity.model.api.nms.HitBoxListener +import kr.toxicity.model.api.nms.ModelInteractionHand +import kr.toxicity.model.api.platform.PlatformEntity +import kr.toxicity.model.api.platform.PlatformPlayer +import net.minecraft.network.protocol.game.ServerboundInteractPacket +import net.minecraft.server.level.ServerLevel +import net.minecraft.server.level.ServerPlayer +import net.minecraft.world.InteractionHand +import net.minecraft.world.InteractionHand.MAIN_HAND +import net.minecraft.world.InteractionHand.OFF_HAND +import net.minecraft.world.InteractionResult +import net.minecraft.world.damagesource.DamageSource +import net.minecraft.world.effect.MobEffectInstance +import net.minecraft.world.entity.* +import net.minecraft.world.entity.ai.attributes.Attributes +import net.minecraft.world.entity.player.Player +import net.minecraft.world.entity.projectile.Projectile +import net.minecraft.world.entity.projectile.ProjectileDeflection +import net.minecraft.world.item.ItemStack +import net.minecraft.world.level.BlockGetter +import net.minecraft.world.phys.AABB +import net.minecraft.world.phys.Vec3 +import org.bukkit.Bukkit +import org.bukkit.Color +import org.bukkit.Particle +import org.bukkit.craftbukkit.CraftServer +import org.bukkit.craftbukkit.entity.CraftArmorStand +import org.bukkit.craftbukkit.entity.CraftLivingEntity +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.bukkit.event.entity.CreatureSpawnEvent +import org.bukkit.event.entity.EntityPotionEffectEvent +import org.bukkit.event.entity.EntityRemoveEvent +import org.bukkit.plugin.Plugin +import org.joml.Vector3f +import java.util.* + +internal class HitBoxImpl( + private val source: ModelBoundingBox, + private val bone: RenderedBone, + private val listener: HitBoxListener, + private val delegate: Entity, + private var mountController: MountController +) : AbstractHitBox(delegate.level()) { + private val posCache = BoneMovement() + private var initialized = false + private var jumpDelay = 0 + private var mounted = false + private var collision = ifLivingEntity { collides } == true + private var noGravity = if (delegate is Mob) delegate.isNoAi else delegate.isNoGravity + private var forceDismount = false + private var onFly = false + + val craftEntity: HitBox by lazy { + object : CraftArmorStand(Bukkit.getServer() as CraftServer, this), HitBox by this {} + } + val dimensions: EntityDimensions get() = source.run { + EntityDimensions( + (x() + z()).toFloat() / 2, + y().toFloat(), + delegate.eyeHeight, + EntityAttachments.createDefault(0F, 0F), + false + ).scale(bone.hitBoxScale()) + } + private val interaction by lazy { + HitBoxInteraction(this) + } + private val applier = InsideBlockEffectApplier.StepBasedCollector() + + init { + moveTo(delegate.position()) + isInvisible = true + persist = false + isSilent = true + initialized = true + level().addFreshEntity(this, CreatureSpawnEvent.SpawnReason.CUSTOM) + level().addFreshEntity(interaction.apply { + moveTo(delegate.position()) + }, CreatureSpawnEvent.SpawnReason.CUSTOM) + interaction.startRiding(this) + listener.handle(HitBoxCreateEvent(this)) + } + + private fun initialSetup() { + if (mounted) { + mounted = false + if (delegate is Mob) delegate.isNoAi = noGravity + else delegate.isNoGravity = noGravity + ifLivingEntity { collides = collision } + } + } + + override fun id(): Int = id + override fun uuid(): UUID = uuid + override fun source(): PlatformEntity = delegate.bukkitEntity.wrap() + override fun positionSource(): RenderedBone = bone + override fun forceDismount(): Boolean = forceDismount + override fun mountController(): MountController = mountController + override fun hasMountDriver(): Boolean = controllingPassenger != null + override fun mountController(controller: MountController) { + this.mountController = controller + } + override fun relativePosition(): Vector3f = delegate.position().run { + bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) + } + override fun listener(): HitBoxListener = listener + override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY + override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { + } + override fun getMainArm(): HumanoidArm = HumanoidArm.RIGHT + + override fun mount(entity: PlatformEntity) { + if (controllingPassenger != null) return + if (interaction.bukkitEntity.addPassenger(entity.unwarp())) { + if (mountController.canControl()) { + mounted = true + noGravity = delegate.isNoGravity + ifLivingEntity { + collision = collides + collides = false + } + } + listener.handle(HitBoxMountEvent(this, entity)) + } + } + + override fun dismount(entity: PlatformEntity) { + forceDismount = true + if (interaction.bukkitEntity.removePassenger(entity.unwarp())) listener.handle(HitBoxDismountEvent(this, entity)) + forceDismount = false + } + + override fun dismountAll() { + forceDismount = true + interaction.passengers.forEach { + it.stopRiding(true) + listener.handle(HitBoxDismountEvent(this, it.bukkitEntity.wrap())) + } + forceDismount = false + } + + override fun setRemainingFireTicks(remainingFireTicks: Int) { + delegate.remainingFireTicks = remainingFireTicks + } + + override fun getRemainingFireTicks(): Int { + return delegate.remainingFireTicks + } + + override fun knockback( + d0: Double, + d1: Double, + d2: Double, + attacker: Entity?, + cause: EntityKnockbackEvent.Cause + ) { + if (attacker === delegate) return + ifLivingEntity { knockback(d0, d1, d2, attacker, cause) } + } + + override fun push(pushingEntity: Entity) { + if (pushingEntity === delegate) return + delegate.push(pushingEntity) + } + + override fun push(x: Double, y: Double, z: Double, pushingEntity: Entity?) { + if (pushingEntity === delegate) return + delegate.push(x, y, z, pushingEntity) + } + + override fun isCollidable(ignoreClimbing: Boolean): Boolean { + return delegate.isCollidable(ignoreClimbing) + } + + override fun canCollideWith(entity: Entity): Boolean { + return checkCollide(entity) && delegate.canCollideWith(entity) + } + + override fun canCollideWithBukkit(entity: Entity): Boolean { + return checkCollide(entity) && delegate.canCollideWithBukkit(entity) + } + + private fun checkCollide(entity: Entity): Boolean { + return entity !== delegate + && passengers.none { it === entity } + && delegate.passengers.none { it === entity } + && (entity !is HitBoxImpl || entity.delegate !== delegate) + } + + override fun getActiveEffects(): Collection { + return ifLivingEntity { getActiveEffects() } ?: emptyList() + } + + override fun getControllingPassenger(): LivingEntity? { + return if (mounted) interaction.firstPassenger as? LivingEntity ?: super.getControllingPassenger() else null + } + + override fun onWalk(): Boolean { + return isWalking() + } + + private fun mountControl(player: ServerPlayer) { + if (delegate !is LivingEntity) return + val travelVector = Vec3(delegate.xxa.toDouble(), delegate.yya.toDouble(), delegate.zza.toDouble()) + if (!mountController.canFly() && delegate.isFallFlying) return + + updateFlyStatus(player) + val riddenInput = rideInput(player, travelVector) + if (riddenInput.length() > 0.01) { + delegate.yRot = player.yRot + if (onFly) delegate.yHeadRot = player.yRot + delegate.move(MoverType.SELF, Vec3(riddenInput.x.toDouble(), riddenInput.y.toDouble(), riddenInput.z.toDouble())) + } + val dy = delegate.deltaMovement.y + delegate.gravity + if (!onFly && mountController.canJump() && (delegate.horizontalCollision || player.isJump()) && dy in 0.0..0.01 && jumpDelay == 0) { + jumpDelay = 10 + delegate.jumpFromGround() + } + } + + private fun movementSpeed() = ifLivingEntity { + getAttribute(Attributes.MOVEMENT_SPEED)?.value?.toFloat()?.let { + if (!onFly && !shouldDiscardFriction()) level() + .getBlockState(blockPosBelowThatAffectsMyMovement) + .block + .getFriction() * it else it + } ?: 0.0F + } ?: 0.0F + + private fun updateFlyStatus(player: ServerPlayer) { + val fly = (player.isJump() && mountController.canFly()) || noGravity || onFly + if (delegate is Mob) delegate.isNoAi = fly + else delegate.isNoGravity = fly + onFly = fly && !delegate.onGround() + if (onFly) delegate.resetFallDistance() + } + + private fun rideInput(player: ServerPlayer, travelVector: Vec3) = mountController.move( + if (onFly) MountController.MoveType.FLY else MountController.MoveType.DEFAULT, + player.bukkitEntity.wrap(), + (delegate.bukkitEntity as org.bukkit.entity.LivingEntity).wrap(), + Vector3f( + player.xMovement(), + player.yMovement(), + player.zMovement() + ), + Vector3f( + travelVector.x.toFloat(), + travelVector.y.toFloat(), + travelVector.z.toFloat() + ) + ).mul(movementSpeed()).rotateY(-Math.toRadians(player.yRot.toDouble()).toFloat()) + + override fun tick() { + delegate.removalReason?.let { + if (!isRemoved) remove(it) + return + } + val controller = controllingPassenger + if (jumpDelay > 0) jumpDelay-- + interaction.isInvisible = delegate.isInvisible + if (controller is ServerPlayer && !isDeadOrDying && mountController.canControl()) { + if (delegate is Mob) delegate.navigation.stop() + mountControl(controller) + } else initialSetup() + yRot = bone.rotation().y + yHeadRot = yRot + yBodyRot = yRot + val pos = relativePosition() + val minusHeight = source.minY * bone.hitBoxScale() + setPos( + pos.x.toDouble(), + pos.y.toDouble() + minusHeight, + pos.z.toDouble() + ) + BlockGetter.forEachBlockIntersectedBetween( + oldPosition(), + position(), + boundingBox + ) { pos, step -> + if (BetterModelBukkit.IS_PAPER) applier.advanceStep(step, pos) + level().getBlockState(pos).entityInside(level(), pos, delegate, applier, true) + true + } + applier.applyAndClear(delegate) + if (isInLava) delegate.lavaHurt() + firstTick = false + listener.sync(craftEntity) + } + + override fun remove(reason: RemovalReason, cause: EntityRemoveEvent.Cause?) { + initialSetup() + listener.handle(HitBoxRemoveEvent(craftEntity)) + interaction.remove(reason) + super.remove(reason, cause) + } + + override fun getBukkitLivingEntity(): CraftLivingEntity = bukkitEntity + override fun getBukkitEntity(): CraftLivingEntity = craftEntity as CraftLivingEntity + override fun getBukkitEntityRaw(): CraftLivingEntity = bukkitEntity + override fun hasExactlyOnePlayerPassenger(): Boolean = false + + override fun isDeadOrDying(): Boolean { + return ifLivingEntity { isDeadOrDying } == true + } + + override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { + interact( + (player.unwarp() as CraftPlayer).handle, + when (hand) { + ModelInteractionHand.LEFT -> OFF_HAND + ModelInteractionHand.RIGHT -> MAIN_HAND + }, + Vec3.ZERO + ) + } + + override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { + interact( + (player.unwarp() as CraftPlayer).handle, + when (hand) { + ModelInteractionHand.LEFT -> OFF_HAND + ModelInteractionHand.RIGHT -> MAIN_HAND + }, + position.toVanilla() + ) + } + + override fun hide(player: PlatformPlayer) { + val plugin = BetterModel.platform() as Plugin + player.unwarp().run { + hideEntity(plugin, bukkitEntity) + hideEntity(plugin, interaction.bukkitEntity) + } + } + + override fun show(player: PlatformPlayer) { + val plugin = BetterModel.platform() as Plugin + player.unwarp().run { + showEntity(plugin, bukkitEntity) + showEntity(plugin, interaction.bukkitEntity) + } + } + + override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { + if (player === delegate) return InteractionResult.FAIL + val interact = HitBoxInteractAtEvent( + (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { + MAIN_HAND -> ModelInteractionHand.RIGHT + OFF_HAND -> ModelInteractionHand.LEFT + }, vec.toBukkit() + ) + if (!listener.handle(interact)) return InteractionResult.FAIL + (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket( + delegate.id, + hand, + vec, + player.isShiftKeyDown + )) + return InteractionResult.SUCCESS + } + + override fun addEffect(effectInstance: MobEffectInstance, cause: EntityPotionEffectEvent.Cause): Boolean { + return ifLivingEntity { addEffect(effectInstance, cause) } == true + } + + override fun addEffect(effectInstance: MobEffectInstance, entity: Entity?): Boolean { + if (entity === delegate) return false + return ifLivingEntity { addEffect(effectInstance, entity) } == true + } + + override fun addEffect( + effectInstance: MobEffectInstance, + entity: Entity?, + cause: EntityPotionEffectEvent.Cause + ): Boolean { + if (entity === delegate) return false + return ifLivingEntity { addEffect(effectInstance, entity, cause) } == true + } + + override fun addEffect( + effectInstance: MobEffectInstance, + entity: Entity?, + cause: EntityPotionEffectEvent.Cause, + fireEvent: Boolean + ): Boolean { + if (entity === delegate) return false + return ifLivingEntity { addEffect(effectInstance, entity, cause, fireEvent) } == true + } + + override fun hurtServer(world: ServerLevel, source: DamageSource, amount: Float): Boolean { + if (source.entity === delegate || delegate.isInvulnerable) return false + if (source.entity === controllingPassenger && !mountController.canBeDamagedByRider()) return false + val ds = ModelDamageSourceImpl(source) + val event = HitBoxDamagedEvent(craftEntity, ds, amount) + if (!listener.handle(event)) return false + return ifLivingEntity { hurtServer(world, source, event.damage) } == true + } + + override fun deflection(projectile: Projectile): ProjectileDeflection { + if (projectile.owner?.uuid == delegate.uuid) return ProjectileDeflection.NONE + return ifLivingEntity { deflection(projectile) } ?: ProjectileDeflection.NONE + } + + override fun getHealth(): Float { + return ifLivingEntity { health } ?: super.getHealth() + } + + override fun makeBoundingBox(vec3: Vec3): AABB { + return if (!initialized) { + super.makeBoundingBox(vec3) + } else { + val scale = bone.hitBoxScale() + AABB( + vec3.x + source.minX * scale, + vec3.y, + vec3.z + source.minZ * scale, + vec3.x + source.maxX * scale, + vec3.y + source.y() * scale, + vec3.z + source.maxZ * scale + ).apply { + if (CONFIG.debug().has(DebugConfig.DebugOption.HITBOX)) { + bukkitEntity.world.spawnParticle(Particle.DUST, minX, minY, minZ, 1, 0.0, 0.0, 0.0, 0.0, Particle.DustOptions(Color.RED, 1F)) + bukkitEntity.world.spawnParticle(Particle.DUST, maxX, maxY, maxZ, 1, 0.0, 0.0, 0.0, 0.0, Particle.DustOptions(Color.RED, 1F)) + } + } + } + } + override fun getDefaultDimensions(pose: Pose): EntityDimensions = if (initialized) dimensions else super.getDefaultDimensions(pose) + + override fun removeHitBox() { + source().task { + dismountAll() + remove(ifLivingEntity { removalReason } ?: RemovalReason.KILLED) + } + } + + private inline fun ifLivingEntity(block: LivingEntity.() -> T): T? { + return if (delegate.valid) (delegate as? LivingEntity)?.block() else null + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt new file mode 100644 index 000000000..774a1ad3e --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt @@ -0,0 +1,58 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.nms.HitBox +import net.minecraft.world.InteractionHand +import net.minecraft.world.InteractionResult +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.Interaction +import net.minecraft.world.entity.player.Player +import net.minecraft.world.phys.Vec3 +import org.bukkit.Bukkit +import org.bukkit.craftbukkit.CraftServer +import org.bukkit.craftbukkit.entity.CraftEntity +import org.bukkit.craftbukkit.entity.CraftInteraction + +internal class HitBoxInteraction( + val delegate: HitBoxImpl +) : Interaction(EntityType.INTERACTION, delegate.level()) { + + init { + persist = false + } + + private val craftEntity: CraftInteraction by lazy { + object : CraftInteraction(Bukkit.getServer() as CraftServer, this), HitBox by delegate {} + } + + override fun getBukkitEntity(): CraftEntity = craftEntity + override fun getBukkitEntityRaw(): CraftEntity = craftEntity + override fun hasExactlyOnePlayerPassenger(): Boolean = false + + override fun tick() { + val dimension = delegate.dimensions + width = dimension.width + height = dimension.height + yRot = delegate.yRot + xRot = delegate.xRot + setSharedFlagOnFire(delegate.remainingFireTicks > 0) + } + + override fun skipAttackInteraction(entity: Entity): Boolean { + return if (entity is Player) { + entity.attack(delegate) + true + } else false + } + + override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { + return InteractionResult.FAIL + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModAnimationBundlerImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModAnimationBundlerImpl.kt new file mode 100644 index 000000000..5a0edb13f --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModAnimationBundlerImpl.kt @@ -0,0 +1,144 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.nms.ModAnimationBundler +import kr.toxicity.model.api.platform.PlatformPlayer +import kr.toxicity.model.api.util.MathUtil +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.network.RegistryFriendlyByteBuf +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket +import net.minecraft.server.MinecraftServer +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.joml.Quaternionf +import org.joml.Vector3f + +internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundler { + + companion object { + + const val KEY = "modelengine:bulk_data" + + const val PACKET_TYPE_BULK_DATA = 0x00 + + const val FIELD_TRANSLATION = 1 shl 0 + const val FIELD_LEFT_ROTATION = 1 shl 1 + const val FIELD_SCALE = 1 shl 2 + const val FIELD_TRANSFORM_DURATION = 1 shl 4 + + private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} + } + + private val packet by lazy { + useByteBuf { buffer -> + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( + RegistryFriendlyByteBuf( + buffer, + MinecraftServer.getServer().registryAccess() + ).apply { + writeUtf(KEY) + useByteBuf { + it.writeByte(PACKET_TYPE_BULK_DATA) + it.writeVarInt(builderList.size) + builderList.forEach { builder -> builder(it) } + writeBytes(it) + } + } + ) + } + } + + private val builderList = ArrayList<(FriendlyByteBuf) -> Unit>(initialCapacity) + + override fun send(player: PlatformPlayer) { + (player.unwarp() as CraftPlayer).handle.connection.send(packet) + } + + fun append(id: Int, scope: Appender.() -> Unit) { + val build = Appender(id).apply(scope).build() + if (build !== EMPTY_BUILD_TASK) builderList += build + } + + class Appender( + val entityId: Int, + ) { + private var mask = 0 + private var buildTask = EMPTY_BUILD_TASK + private val isEmpty get() = buildTask === EMPTY_BUILD_TASK + + fun appendPosition(vector: Vector3f) { + mask = mask or FIELD_TRANSLATION + task { + writeFloat(it, vector.x) + writeFloat(it, vector.y) + writeFloat(it, vector.z) + } + } + + fun appendScale(vector: Vector3f) { + mask = mask or FIELD_SCALE + task { + writeFloat(it, vector.x) + writeFloat(it, vector.y) + writeFloat(it, vector.z) + } + } + + fun appendRotation(quaternion: Quaternionf) { + mask = mask or FIELD_LEFT_ROTATION + task { + writeFloat(it, quaternion.x) + writeFloat(it, quaternion.y) + writeFloat(it, quaternion.z) + writeFloat(it, quaternion.w) + } + } + + fun appendDuration(duration: Int) { + mask = mask or FIELD_TRANSFORM_DURATION + task { + writeVarInt(it, duration) + } + } + + fun build(): (FriendlyByteBuf) -> Unit { + if (isEmpty) return EMPTY_BUILD_TASK + val m = mask + val t = buildTask + return { + writeVarInt(it,entityId) + writeByte(it, m) + t(it) + } + } + + private fun task(task: (FriendlyByteBuf) -> Unit) { + if (isEmpty) { + buildTask = task + return + } + val last = buildTask + buildTask = { + last(it) + task(it) + } + } + + private fun writeFloat(buf: FriendlyByteBuf, float: Float) { + buf.writeShort(MathUtil.floatToHalf(float).toInt()) + } + + private fun writeVarInt(buf: FriendlyByteBuf, duration: Int) { + buf.writeVarInt(duration) + } + + private fun writeByte(buf: FriendlyByteBuf, duration: Int) { + buf.writeByte(duration) + } + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDamageSourceImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDamageSourceImpl.kt new file mode 100644 index 000000000..836ca3fbb --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDamageSourceImpl.kt @@ -0,0 +1,30 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.event.ModelDamageSource +import kr.toxicity.model.api.platform.PlatformEntity +import kr.toxicity.model.api.platform.PlatformLocation +import net.minecraft.world.damagesource.DamageSource +import org.bukkit.craftbukkit.util.CraftLocation + +internal class ModelDamageSourceImpl( + private val source: DamageSource +) : ModelDamageSource { + override fun getCausingEntity(): PlatformEntity? = source.entity?.bukkitEntity?.wrap() + override fun getDirectEntity(): PlatformEntity? = source.directEntity?.bukkitEntity?.wrap() + override fun getDamageLocation(): PlatformLocation? = source.sourcePositionRaw()?.let { + CraftLocation.toBukkit(it, causingEntity?.unwarp()?.world).wrap() + } + override fun getSourceLocation(): PlatformLocation? = source.sourcePosition?.let { + CraftLocation.toBukkit(it, causingEntity?.unwarp()?.world).wrap() + } + override fun isIndirect(): Boolean = !source.isDirect + override fun getFoodExhaustion(): Float = source.foodExhaustion + override fun scalesWithDifficulty(): Boolean = source.scalesWithDifficulty() +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDisplayImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDisplayImpl.kt new file mode 100644 index 000000000..850488490 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelDisplayImpl.kt @@ -0,0 +1,261 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.entity.BaseEntity +import kr.toxicity.model.api.nms.AnimationBundler +import kr.toxicity.model.api.nms.DisplayTransformer +import kr.toxicity.model.api.nms.ModelDisplay +import kr.toxicity.model.api.nms.PacketBundler +import kr.toxicity.model.api.platform.PlatformBillboard +import kr.toxicity.model.api.platform.PlatformItemStack +import kr.toxicity.model.api.platform.PlatformItemTransform +import kr.toxicity.model.api.platform.PlatformLocation +import kr.toxicity.model.api.tracker.ModelRotation +import kr.toxicity.model.api.util.lock.SingleLock +import net.minecraft.network.protocol.game.* +import net.minecraft.network.syncher.EntityDataSerializers +import net.minecraft.network.syncher.SynchedEntityData +import net.minecraft.util.Brightness +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.Display.ItemDisplay +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.PositionMoveRotation +import net.minecraft.world.item.ItemDisplayContext +import net.minecraft.world.item.Items +import org.joml.Quaternionf +import org.joml.Vector3d +import org.joml.Vector3f +import java.util.* +import java.util.concurrent.atomic.AtomicBoolean + +internal class ModelDisplayImpl( + private val pos: Vector3d, + val display: ItemDisplay, + val yOffset: Double +) : ModelDisplay { + + private val entityData = display.entityData + private val entityDataLock = SingleLock() + private val forceGlow = AtomicBoolean() + private val forceInvisibility = AtomicBoolean() + + private val oldPos = Vector3d(pos) + + override fun id(): Int = display.id + override fun uuid(): UUID = display.uuid + override fun rotate(rotation: ModelRotation, bundler: PacketBundler) { + display.xRot = rotation.x + display.yRot = rotation.y + bundler += ClientboundMoveEntityPacket.Rot( + display.id, + rotation.packedY(), + rotation.packedX(), + display.onGround + ) + } + + override fun invisible(invisible: Boolean) { + if (forceInvisibility.compareAndSet(!invisible, invisible)) { + entityDataLock.accessToLock { + entityData.markDirty(ITEM_SERIALIZER) + } + } + } + + override fun syncPotionEffect(entity: BaseEntity) { + val beforeInvisible = display.isInvisible + val afterInvisible = entity.invisible() + entityDataLock.accessToLock { + display.setGlowingTag(entity.glow() || forceGlow.get()) + if (CONFIG.followMobInvisibility() && beforeInvisible != afterInvisible) { + display.isInvisible = afterInvisible + entityData.markDirty(ITEM_SERIALIZER) + } + } + } + + override fun syncPosition(location: PlatformLocation) { + oldPos.set(pos) + pos.set(location.x(), location.y(), location.z()) + } + + override fun spawn(showItem: Boolean, bundler: PacketBundler) { + bundler += addPacket + } + + override fun remove(bundler: PacketBundler) { + bundler += removePacket + } + + override fun teleport(location: PlatformLocation, bundler: PacketBundler) { + display.moveTo( + location.x(), + location.y(), + location.z(), + location.yaw(), + 0F + ) + bundler += ClientboundTeleportEntityPacket.teleport(display.id, PositionMoveRotation.of(display), emptySet(), display.onGround) + } + + override fun sendPosition(adapter: BaseEntity, bundler: PacketBundler) { + val handle = adapter.handle() as Entity + if (oldPos.distanceSquared(pos) < 1e-8) return + bundler += ClientboundEntityPositionSyncPacket( + display.id, + PositionMoveRotation.of(handle), + handle.onGround() + ) + } + + override fun display(transform: PlatformItemTransform) { + entityDataLock.accessToLock { + display.itemTransform = ItemDisplayContext.BY_ID.apply(transform.ordinal) + } + } + + override fun moveDuration(duration: Int) { + entityDataLock.accessToLock { + entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = duration + } + } + + override fun item(itemStack: PlatformItemStack) { + entityDataLock.accessToLock { + display.itemStack = itemStack.unwarp().asVanilla() + } + } + + override fun brightness(block: Int, sky: Int) { + entityDataLock.accessToLock { + display.brightnessOverride = if (block < 0 && sky < 0) null else Brightness( + block, + sky + ) + } + } + + override fun viewRange(range: Float) { + entityDataLock.accessToLock { + display.viewRange = range + } + } + + override fun shadowRadius(radius: Float) { + entityDataLock.accessToLock { + display.shadowRadius = radius + } + } + + override fun glow(glow: Boolean) { + if (!forceGlow.compareAndSet(!glow, glow)) return + entityDataLock.accessToLock { + display.setGlowingTag(display.isCurrentlyGlowing || glow) + } + } + + override fun glowColor(glowColor: Int) { + entityDataLock.accessToLock { + display.glowColorOverride = glowColor + } + } + + override fun billboard(billboard: PlatformBillboard) { + entityDataLock.accessToLock { + display.billboardConstraints = Display.BillboardConstraints.BY_ID.apply(billboard.ordinal) + } + } + + override fun createTransformer(): DisplayTransformer = DisplayTransformerImpl(display) + + override fun invisible(): Boolean = entityDataLock.accessToLock { + display.isInvisible || forceInvisibility.get() || display.itemStack.`is`(Items.AIR) + } + + override fun sendDirtyEntityData(bundler: PacketBundler) { + entityDataLock.accessToLock { + entityData.pack( + clean = true, + itemFilter = { it.isDirty }, + valueFilter = { ITEM_ENTITY_DATA.contains(it.id) } + ) + }?.markVisible(!invisible())?.run { + bundler += ClientboundSetEntityDataPacket(display.id, this) + } + } + + override fun sendEntityData(showItem: Boolean, bundler: PacketBundler) { + entityDataLock.accessToLock { + entityData.pack( + valueFilter = { ITEM_ENTITY_DATA.contains(it.id) } + ) + }?.markVisible(showItem && !invisible())?.run { + bundler += ClientboundSetEntityDataPacket(display.id, this) + } + } + + private fun List>.markVisible(showItem: Boolean) = map { + if (it.id == ITEM_SERIALIZER.id) SynchedEntityData.DataValue( + it.id, + EntityDataSerializers.ITEM_STACK, + if (showItem) display.itemStack else EMPTY_ITEM + ) else it + } + + private val addPacket + get() = ClientboundAddEntityPacket( + display.id, + display.uuid, + pos.x, + pos.y + yOffset, + pos.z, + display.xRot, + display.yRot, + display.type, + 0, + display.deltaMovement, + display.yHeadRot.toDouble() + ) + + private val removePacket = ClientboundRemoveEntitiesPacket(display.id) + + private class DisplayTransformerImpl( + source: ItemDisplay + ) : DisplayTransformer { + private val id = source.id + private val entityData = TransformationData() + private val entityDataLock = SingleLock() + + override fun transform( + duration: Int, + position: Vector3f, + scale: Vector3f, + rotation: Quaternionf, + bundler: AnimationBundler + ) { + entityDataLock.accessToLock { + entityData.transform( + duration, + position, + scale, + rotation + ) + entityData.packDirty(id, bundler) + } + } + + override fun sendTransformation(bundler: PacketBundler) { + entityDataLock.accessToLock { + entityData.pack() + }?.run { + bundler += ClientboundSetEntityDataPacket(id, this) + } + } + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelGameProfile.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelGameProfile.kt new file mode 100644 index 000000000..d96d92b91 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelGameProfile.kt @@ -0,0 +1,30 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import com.mojang.authlib.GameProfile +import kr.toxicity.model.api.BetterModel +import kr.toxicity.model.api.profile.ModelProfile +import kr.toxicity.model.api.profile.ModelProfileInfo +import kr.toxicity.model.api.profile.ModelProfileSkin + +internal data class ModelGameProfile( + private val gameProfile: GameProfile +) : ModelProfile { + + private val info = ModelProfileInfo(gameProfile.id, gameProfile.name) + private val skin by lazy { + gameProfile.properties["textures"].firstOrNull()?.let { + BetterModel.platform().profileManager().skin(it.value) + } ?: ModelProfileSkin.EMPTY + } + + override fun info(): ModelProfileInfo = info + + override fun skin(): ModelProfileSkin = skin +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelNametagImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelNametagImpl.kt new file mode 100644 index 000000000..9a28140b7 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ModelNametagImpl.kt @@ -0,0 +1,119 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import com.mojang.math.Transformation +import kr.toxicity.model.api.BetterModel +import kr.toxicity.model.api.bone.BoneMovement +import kr.toxicity.model.api.bone.BonePosition +import kr.toxicity.model.api.bone.RenderedBone +import kr.toxicity.model.api.nms.ModelNametag +import kr.toxicity.model.api.nms.PacketBundler +import kr.toxicity.model.api.platform.PlatformLocation +import kr.toxicity.model.api.platform.PlatformPlayer +import kr.toxicity.model.api.util.EntityUtil +import net.kyori.adventure.text.Component +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket +import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket +import net.minecraft.server.MinecraftServer +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.PositionMoveRotation +import net.minecraft.world.phys.Vec3 +import org.joml.Vector3f +import java.util.* +import java.util.concurrent.ConcurrentHashMap + +internal class ModelNametagImpl( + private val bone: RenderedBone +) : ModelNametag { + private companion object { + private val emptyVector = Vector3f() + private val emptyTransformation = Transformation( + Vector3f(-1F / 40F, -0.2F - 1F / 40F, 0F), + null, + null, + null + ) + } + + private val viewedPlayer = ConcurrentHashMap.newKeySet() + private val display = Display.TextDisplay( + EntityType.TEXT_DISPLAY, + MinecraftServer.getServer().overworld() + ).apply { + entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 + setTransformation(emptyTransformation) + billboardConstraints = Display.BillboardConstraints.CENTER + } + private val posCache = BoneMovement() + private var alwaysVisible = false + private var location = BetterModel.platform().adapter().zero() + + override fun component(component: Component?) { + display.text = component?.asVanilla() ?: VanillaComponent.empty() + } + + override fun teleport(location: PlatformLocation) { + this.location = location + } + + override fun alwaysVisible(alwaysVisible: Boolean) { + this.alwaysVisible = alwaysVisible + } + + override fun send(player: PlatformPlayer) { + if (display.text == VanillaComponent.empty()) return + val hb = bone.group.hitBoxPoint + val pos = bone.worldPosition(BonePosition(emptyVector, hb, player.uuid()), posCache) + display.moveTo(Vec3( + location.x() + pos.x, + location.y() + pos.y, + location.z() + pos.z + )) + val inPoint = alwaysVisible || EntityUtil.isCustomNameVisible(player.location(), location) + when { + inPoint && viewedPlayer.add(player.uuid()) -> bundlerOfNotNull( + addPacket, + display.entityData.pack()?.let { + ClientboundSetEntityDataPacket(display.id, it) + } + ) + inPoint -> bundlerOfNotNull( + ClientboundEntityPositionSyncPacket(display.id, PositionMoveRotation.of(display), false), + display.entityData.packDirty()?.let { + ClientboundSetEntityDataPacket(display.id, it) + } + ) + viewedPlayer.remove(player.uuid()) -> bundlerOf(removePacket) + else -> null + }?.send(player) + } + + override fun remove(bundler: PacketBundler) { + bundler += removePacket + } + + private val addPacket get() = ClientboundAddEntityPacket( + display.id, + display.uuid, + display.x, + display.y, + display.z, + display.xRot, + display.yRot, + display.type, + 0, + display.deltaMovement, + display.yHeadRot.toDouble() + ) + + private val removePacket get() = ClientboundRemoveEntitiesPacket(display.id) +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt new file mode 100644 index 000000000..e89445255 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt @@ -0,0 +1,398 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup +import com.google.common.collect.ImmutableMultimap +import com.mojang.authlib.GameProfile +import com.mojang.authlib.properties.Property +import com.mojang.authlib.properties.PropertyMap +import io.netty.channel.ChannelDuplexHandler +import io.netty.channel.ChannelHandlerContext +import io.netty.channel.ChannelPromise +import kr.toxicity.model.api.BetterModel +import kr.toxicity.model.api.bone.RenderedBone +import kr.toxicity.model.api.bukkit.BetterModelBukkit +import kr.toxicity.model.api.data.blueprint.ModelBoundingBox +import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity +import kr.toxicity.model.api.entity.BaseEntity +import kr.toxicity.model.api.entity.BasePlayer +import kr.toxicity.model.api.mount.MountController +import kr.toxicity.model.api.nms.* +import kr.toxicity.model.api.platform.PlatformEntity +import kr.toxicity.model.api.platform.PlatformItemStack +import kr.toxicity.model.api.platform.PlatformLocation +import kr.toxicity.model.api.platform.PlatformPlayer +import kr.toxicity.model.api.player.PlayerSkinParts +import kr.toxicity.model.api.profile.ModelProfile +import kr.toxicity.model.api.tracker.EntityTrackerRegistry +import kr.toxicity.model.api.tracker.TrackerUpdateAction +import kr.toxicity.model.api.util.TransformedItemStack +import net.kyori.adventure.key.Keyed +import net.minecraft.core.component.DataComponents +import net.minecraft.network.Connection +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.* +import net.minecraft.network.syncher.EntityDataSerializers +import net.minecraft.network.syncher.SynchedEntityData +import net.minecraft.resources.Identifier +import net.minecraft.server.MinecraftServer +import net.minecraft.server.level.ServerLevel +import net.minecraft.server.network.ServerCommonPacketListenerImpl +import net.minecraft.util.ARGB +import net.minecraft.world.entity.Display +import net.minecraft.world.entity.Display.ItemDisplay +import net.minecraft.world.entity.Entity +import net.minecraft.world.entity.EntityType +import net.minecraft.world.entity.LivingEntity +import net.minecraft.world.item.ItemDisplayContext +import net.minecraft.world.item.Items +import net.minecraft.world.item.component.CustomModelData +import net.minecraft.world.item.component.DyedItemColor +import net.minecraft.world.item.component.ResolvableProfile +import net.minecraft.world.level.entity.LevelEntityGetter +import net.minecraft.world.level.entity.LevelEntityGetterAdapter +import net.minecraft.world.level.entity.PersistentEntitySectionManager +import org.bukkit.craftbukkit.CraftWorld +import org.bukkit.craftbukkit.entity.CraftEntity +import org.bukkit.craftbukkit.entity.CraftPlayer +import org.joml.Vector3d +import java.util.* +import java.util.function.Consumer + +class NMSImpl : NMS { + + companion object { + private const val INJECT_NAME = "bettermodel_channel_handler" + + //Spigot + private val getGameProfile: (net.minecraft.world.entity.player.Player) -> GameProfile = createAdaptedFieldGetter { it.gameProfile } + private val getConnection: (ServerCommonPacketListenerImpl) -> Connection = createAdaptedFieldGetter { it.connection } + private val spigotChunkAccess = ServerLevel::class.java.fields.firstOrNull { + it.type == PersistentEntitySectionManager::class.java + }?.apply { + isAccessible = true + } + @Suppress("UNCHECKED_CAST") + private val ServerLevel.levelGetter + get(): LevelEntityGetter { + return if (BetterModelBukkit.IS_PAPER) { + `moonrise$getEntityLookup`() + } else { + spigotChunkAccess?.get(this)?.let { + (it as PersistentEntitySectionManager<*>).entityGetter as LevelEntityGetter + } ?: throw RuntimeException("LevelEntityGetter") + } + } + private val getEntityById: (LevelEntityGetter, Int) -> Entity? = if (BetterModelBukkit.IS_PAPER) { g, i -> + (g as EntityLookup)[i] + } else LevelEntityGetterAdapter::class.java.declaredFields.first { + net.minecraft.world.level.entity.EntityLookup::class.java.isAssignableFrom(it.type) + }.let { + it.isAccessible = true + { e, i -> + (it[e] as net.minecraft.world.level.entity.EntityLookup<*>).getEntity(i) as? Entity + } + } + private fun Int.toEntity(level: ServerLevel) = getEntityById(level.levelGetter, this) + //Spigot + private val hitBoxData by lazy { + ItemDisplay(EntityType.ITEM_DISPLAY, MinecraftServer.getServer().overworld()).run { + entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 + entityData.nonDefaultValues!! + } + } + } + + override fun hide(channel: PlayerChannelHandler, registry: EntityTrackerRegistry) { + val target = registry.entity().handle() as? Entity ?: return + val list = bundlerOf() + target.entityData.pack( + valueFilter = { it.id == SHARED_FLAG } + )?.let { + list += ClientboundSetEntityDataPacket(target.id, it).toRegistryDataPacket(channel.uuid(), registry) + } + if (target is LivingEntity) { + val packet = if (registry.hideOption(channel.uuid()).equipment) target.toEmptyEquipmentPacket() else target.toEquipmentPacket() + packet?.let { list += it } + } + list.send(channel.player()) + } + + private fun ClientboundSetEntityDataPacket.toRegistryDataPacket(uuid: UUID, registry: EntityTrackerRegistry) = ClientboundSetEntityDataPacket(id, packedItems().map { + if (it.id == SHARED_FLAG) SynchedEntityData.DataValue( + it.id, + EntityDataSerializers.BYTE, + registry.entityFlag(uuid, it.value() as Byte) + ) else it + }) + + inner class PlayerChannelHandlerImpl( + private val player: CraftPlayer + ) : PlayerChannelHandler, ChannelDuplexHandler() { + private val connection = player.handle.connection + private val uuid = player.uniqueId + private val base = adapt(player.wrap()) + + init { + val pipeline = getConnection(connection).channel.pipeline() + pipeline.addBefore(pipeline.first { it.value is Connection }.key, INJECT_NAME, this) + } + + override fun close() { + val channel = getConnection(connection).channel + channel.eventLoop().submit { + channel.pipeline().remove(INJECT_NAME) + } + } + + override fun base(): BasePlayer = base + override fun isModEnabled(): Boolean = (if (BetterModelBukkit.IS_PAPER) player.channels() else player.listeningPluginChannels).contains(ModAnimationBundlerImpl.KEY) + + private val playerModel get() = connection.player.id.toRegistry() + + private fun Int.toPlayerEntity() = toEntity(connection.player.level()) + private fun Entity.toRegistry() = BetterModel.registryOrNull(uuid) + private inline fun Int.toRegistry( + ifHitBox: (Entity) -> Unit = {} + ) = (EntityTrackerRegistry.registry(this) ?: toPlayerEntity()?.let { + if (it is HitBox) ifHitBox(it) + it.toRegistry() + })?.takeIf { + it.isSpawned(player.uniqueId) + } + + override fun sendEntityData(registry: EntityTrackerRegistry) { + val handle = registry.entity().handle() as? Entity ?: return + val list = bundlerOf( + ClientboundSetPassengersPacket(handle) + ) + handle.entityData.pack( + valueFilter = { it.id == SHARED_FLAG } + )?.let { + list += ClientboundSetEntityDataPacket(handle.id, it) + } + if (handle is LivingEntity) handle.toEquipmentPacket()?.let { + list += it + } + list.send(player.wrap()) + } + + private fun Packet.handle(): Packet? { + when (this) { + is ClientboundBundlePacket -> return if (subPackets() is Keyed) this else ClientboundBundlePacket(subPackets().mapNotNull { + it.handle() + }) + is ClientboundAddEntityPacket -> { + val entity = id.toPlayerEntity() ?: return this + if (entity is HitBox) return entity.toFakeAddPacket() + val wrap = entity.bukkitEntity.wrap() + BetterModel.registry(wrap).ifPresent { + wrap.taskLater(1) { + it.spawn(player.wrap()) + } + } + } + is ClientboundRemoveEntitiesPacket -> { + entityIds + .asSequence() + .mapNotNull map@ { + it.toRegistry { + return@map null + } + } + .forEach { + it.remove() + } + } + is ClientboundSetPassengersPacket -> { + vehicle.toRegistry()?.let { + return it.mountPacket(it.entity().handle() as? Entity ?: return this, array = passengers) + } + } + is ClientboundUpdateAttributesPacket if entityId.toPlayerEntity() is HitBox -> return null + is ClientboundSetEntityDataPacket -> id.toRegistry { + return ClientboundSetEntityDataPacket(id, hitBoxData) + }?.let { registry -> + return toRegistryDataPacket(uuid, registry) + } + is ClientboundSetEquipmentPacket -> entity.toRegistry { + return null + }?.let { + if (it.hideOption(uuid).equipment()) (it.entity().handle() as? LivingEntity)?.toEmptyEquipmentPacket()?.let { packet -> + return packet + } + } + is ClientboundRespawnPacket -> playerModel?.let { + bundlerOf(it.mountPacket(connection.player)).send(player.wrap()) + } + is ClientboundContainerSetSlotPacket if isEquipment(connection.player) && playerModel?.hideOption(uuid)?.equipment() == true -> { + return ClientboundContainerSetSlotPacket(containerId, stateId, slot, EMPTY_ITEM) + } + is ClientboundContainerSetContentPacket if containerId == 0 && playerModel?.hideOption(uuid)?.equipment() == true -> { + return ClientboundContainerSetContentPacket( + containerId, + stateId, + items.apply { + PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + set(connection.player.hotbarSlot, EMPTY_ITEM) + }, + carriedItem + ) + } + } + return this + } + + override fun write(ctx: ChannelHandlerContext, msg: Any, promise: ChannelPromise) { + super.write(ctx, if (msg is Packet<*>) msg.handle() ?: return else msg, promise) + } + + override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { + fun EntityTrackerRegistry.updatePlayerLimb() = BetterModel.platform().scheduler().asyncTaskLater(1) { + if (isClosed) return@asyncTaskLater + player.handle.containerMenu.sendAllDataToRemote() + trackers().forEach { tracker -> + tracker.update(TrackerUpdateAction.itemMapping()) { bone -> + !bone.itemMapper.fixed() + } + } + } + when (msg) { + is ServerboundSetCarriedItemPacket -> { + playerModel?.let { registry -> + if (!registry.hideOption(uuid).equipment()) return super.channelRead(ctx, msg) + if (CONFIG.cancelPlayerModelInventory()) { + connection.send(ClientboundSetHeldSlotPacket(player.inventory.heldItemSlot)) + return + } + registry.updatePlayerLimb() + } + } + is ServerboundPlayerActionPacket -> { + playerModel?.let { registry -> + if (!registry.hideOption(uuid).equipment()) return super.channelRead(ctx, msg) + if (CONFIG.cancelPlayerModelInventory()) return + registry.updatePlayerLimb() + } + } + } + super.channelRead(ctx, msg) + } + + private fun EntityTrackerRegistry.remove() { + remove(player.wrap()) + } + } + + override fun mount(registry: EntityTrackerRegistry, bundler: PacketBundler) { + val entity = registry.entity().handle() + if (entity is Entity) bundler += registry.mountPacket(entity) + } + + private fun EntityTrackerRegistry.mountPacket(entity: Entity, array: IntArray = entity.passengers.filter { + EntityTrackerRegistry.registry(it.uuid) == null + }.map { + it.id + }.toIntArray()): ClientboundSetPassengersPacket { + return useByteBuf { buffer -> + buffer.writeVarInt(entity.id) + buffer.writeVarIntArray(displays() + .mapToInt { + (it as ModelDisplayImpl).display.id + }.toArray() + array) + ClientboundSetPassengersPacket.STREAM_CODEC.decode(buffer) + } + } + + override fun inject(player: PlatformPlayer): PlayerChannelHandlerImpl = PlayerChannelHandlerImpl(player.unwarp() as CraftPlayer) + + override fun createBundler(initialCapacity: Int): PacketBundler = bundlerOf(initialCapacity) + override fun createParallelBundler(threshold: Int): PacketBundler = parallelBundlerOf(threshold) + override fun createModAnimationBuilder(initialCapacity: Int): ModAnimationBundler = ModAnimationBundlerImpl(initialCapacity) + + override fun create(location: PlatformLocation, yOffset: Double, initialConsumer: Consumer): ModelDisplay = ModelDisplayImpl( + Vector3d(location.x(), location.y(), location.z()), + ItemDisplay(EntityType.ITEM_DISPLAY, (location.world().unwarp() as CraftWorld).handle).apply { + entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 + billboardConstraints = Display.BillboardConstraints.FIXED + valid = true + yRot = location.yaw() + itemTransform = ItemDisplayContext.FIXED + }, + yOffset + ).apply { + initialConsumer.accept(this) + display.entityData.packDirty() + } + + override fun createNametag(bone: RenderedBone): ModelNametag = ModelNametagImpl(bone) + + override fun tint(itemStack: PlatformItemStack, rgb: Int): PlatformItemStack { + return itemStack.unwarp().asVanilla().apply { + set(DataComponents.DYED_COLOR, DyedItemColor(rgb)) + set(DataComponents.CUSTOM_MODEL_DATA, get(DataComponents.CUSTOM_MODEL_DATA)?.let { + CustomModelData(it.floats, it.flags, it.strings, it.colors + .run { + if (rgb == 0xFFFFFF) this else map { color -> + ARGB.multiply(color, rgb) and 0xFFFFFF + } + } + .ifEmpty { listOf(rgb) }) + }) + }.asBukkit().wrap() + } + + override fun createHitBox(entity: BaseEntity, bone: RenderedBone, boundingBox: ModelBoundingBox, mountController: MountController, listener: HitBoxListener): HitBox? { + val handle = entity.handle() as? Entity ?: return null + return HitBoxImpl( + boundingBox.center(), + bone, + listener, + handle, + mountController + ).craftEntity + } + override fun version(): NMSVersion = NMSVersion.V26_R1 + + override fun adapt(entity: PlatformEntity): BaseBukkitEntity { + val craft = entity.unwarp() as CraftEntity + return BaseEntityImpl(craft) + } + + override fun adapt(player: PlatformPlayer): BasePlayer { + val craft = player.unwarp() as CraftPlayer + return BasePlayerImpl( + craft, + dirtyChecked({ getGameProfile(craft.handle) }, { ModelGameProfile(it) }), + dirtyChecked({ craft.handle.toCustomisation() }, { PlayerSkinParts(it) }) + ) + } + + override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) + + override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { + set(DataComponents.PROFILE, ResolvableProfile.createResolved(GameProfile( + profile.info().id, + profile.info().name ?: "", + PropertyMap(ImmutableMultimap.of( + "textures", Property("textures", profile.skin().raw) + )) + ))) + }.asBukkit().wrap() + + override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { + return VanillaItemStack(Items.PLAYER_HEAD).run { + set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) + set(DataComponents.ITEM_MODEL, Identifier.parse(model)) + TransformedItemStack.of(asBukkit().wrap()) + } + } + + override fun isProxyOnlineMode(): Boolean = ONLINE_MODE +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PacketBundlers.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PacketBundlers.kt new file mode 100644 index 000000000..5877a978f --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PacketBundlers.kt @@ -0,0 +1,91 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.nms.PacketBundler +import kr.toxicity.model.api.platform.PlatformPlayer +import net.kyori.adventure.key.Key +import net.kyori.adventure.key.Keyed +import net.minecraft.network.PacketSendListener +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientboundBundlePacket +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket +import org.bukkit.craftbukkit.entity.CraftPlayer + +private val KEY = Key.key("bettermodel") + +internal fun bundlerOfNotNull(vararg packets: ClientPacket?) = SimpleBundler(if (packets.isEmpty()) arrayListOf() else packets.filterNotNull().toMutableList()) +internal fun bundlerOf(vararg packets: ClientPacket) = SimpleBundler(if (packets.isEmpty()) arrayListOf() else packets.toMutableList()) +internal fun bundlerOf(size: Int) = SimpleBundler(ArrayList(size)) +internal fun parallelBundlerOf(threshold: Int) = ParallelBundler(threshold) + +internal operator fun PacketBundler.plusAssign(other: ClientPacket) { + when (this) { + is SimpleBundler -> add(other) + is ParallelBundler -> add(other) + else -> throw RuntimeException("unsupported bundler.") + } +} +internal fun Packet<*>.assumeSize() = when (this) { + is ClientboundSetEntityDataPacket -> packedItems.size + is ClientboundSetEquipmentPacket -> slots.size + else -> 1 +} + +internal interface PluginBundlePacketImpl : Iterable, Keyed { + val bundlePacket: ClientboundBundlePacket + fun size(): Int + fun isEmpty(): Boolean + fun add(other: ClientPacket) +} + +internal class SimpleBundler( + private val list: MutableList +) : PacketBundler, PluginBundlePacketImpl { + override val bundlePacket = ClientboundBundlePacket(this) + override fun send(player: PlatformPlayer, onSuccess: Runnable) { + if (isEmpty) return + val connection = (player.unwarp() as CraftPlayer).handle.connection + connection.send(bundlePacket, PacketSendListener.thenRun(onSuccess)) + } + override fun isEmpty(): Boolean = list.isEmpty() + override fun size(): Int = list.size + override fun key(): Key = KEY + override fun iterator(): MutableIterator = list.iterator() + override fun add(other: ClientPacket) { + list += other + } +} + +internal class ParallelBundler( + private val threshold: Int +) : PacketBundler { + private val subBundlers = mutableListOf() + private var sizeAssume = 0 + private val newBundler get() = bundlerOf().apply { + sizeAssume = 0 + subBundlers += this + } + private var selectedBundler = newBundler + override fun send(player: PlatformPlayer, onSuccess: Runnable) { + if (isEmpty) return + val connection = (player.unwarp() as CraftPlayer).handle.connection + subBundlers.forEach { + connection.send(it.bundlePacket) + } + } + override fun isEmpty(): Boolean = selectedBundler.isEmpty() + override fun size(): Int = subBundlers.sumOf(PluginBundlePacketImpl::size) + fun add(other: ClientPacket) { + (if (sizeAssume > threshold) newBundler else selectedBundler) + .apply { selectedBundler = this } + .add(other) + sizeAssume += other.assumeSize() + } +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PlayerArmorImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PlayerArmorImpl.kt new file mode 100644 index 000000000..6bec07d8f --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/PlayerArmorImpl.kt @@ -0,0 +1,47 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.armor.ArmorItem +import kr.toxicity.model.api.armor.PlayerArmor +import net.minecraft.core.component.DataComponents +import net.minecraft.world.entity.EquipmentSlot +import net.minecraft.world.item.component.DyedItemColor +import net.minecraft.world.item.equipment.EquipmentAssets +import org.bukkit.craftbukkit.entity.CraftPlayer + +internal data class PlayerArmorImpl( + private val player: CraftPlayer +) : PlayerArmor { + + override fun helmet(): ArmorItem? { + return player.handle.getItemBySlot(EquipmentSlot.HEAD).toArmorItem() + } + + override fun leggings(): ArmorItem? { + return player.handle.getItemBySlot(EquipmentSlot.LEGS).toArmorItem() + } + + override fun chestplate(): ArmorItem? { + return player.handle.getItemBySlot(EquipmentSlot.CHEST).toArmorItem() + } + + override fun boots(): ArmorItem? { + return player.handle.getItemBySlot(EquipmentSlot.FEET).toArmorItem() + } + + private fun VanillaItemStack.toArmorItem(): ArmorItem? = get(DataComponents.EQUIPPABLE)?.assetId?.map { + val trim = get(DataComponents.TRIM) + ArmorItem( + get(DataComponents.DYED_COLOR)?.rgb ?: if (it === EquipmentAssets.LEATHER) DyedItemColor.LEATHER_COLOR else 0xFFFFFF, + it.identifier().path, + trim?.pattern?.value()?.assetId?.path, + trim?.material?.value()?.assets?.base?.suffix + ) + }?.orElse(null) +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ProfiledImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ProfiledImpl.kt new file mode 100644 index 000000000..56b30a974 --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/ProfiledImpl.kt @@ -0,0 +1,24 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import kr.toxicity.model.api.armor.PlayerArmor +import kr.toxicity.model.api.nms.Profiled +import kr.toxicity.model.api.player.PlayerSkinParts +import kr.toxicity.model.api.profile.ModelProfile + +internal class ProfiledImpl( + private val playerArmor: PlayerArmor, + private val modelProfile: () -> ModelProfile, + private val playerSkinParts: () -> PlayerSkinParts +) : Profiled { + + override fun profile(): ModelProfile = modelProfile() + override fun armors(): PlayerArmor = playerArmor + override fun skinParts(): PlayerSkinParts = playerSkinParts() +} diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/TypeAliases.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/TypeAliases.kt new file mode 100644 index 000000000..7e9a7eabe --- /dev/null +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/TypeAliases.kt @@ -0,0 +1,19 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.bukkit.nms.v26_R1 + +import net.minecraft.network.chat.Component +import net.minecraft.network.protocol.Packet +import net.minecraft.network.protocol.game.ClientGamePacketListener +import net.minecraft.world.item.ItemStack + +internal typealias VanillaItemStack = ItemStack +internal typealias BukkitItemStack = org.bukkit.inventory.ItemStack +internal typealias ClientPacket = Packet +internal typealias VanillaComponent = Component +internal typealias AdventureComponent = net.kyori.adventure.text.Component diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index 23f3d10f3..ca20fd485 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -191,7 +191,7 @@ tasks { modrinth { loaders = listOf("fabric", "quilt") uploadFile.set(jarDir.map { it.file(jarName) }) - gameVersions = listOf("26.1") + gameVersions = LATEST_VERSION dependencies { required.version("fabric-api", libs.versions.fabric.api.get()) required.version("fabric-language-kotlin", libs.versions.fabric.language.kotlin.get()) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt index 5c228644d..7bd0cb9a7 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt @@ -81,7 +81,7 @@ class BetterModelNMSImpl : NMS { override fun createParallelBundler(threshold: Int): PacketBundler = parallelBundlerOf(threshold) - override fun createModAnimationBuilder(initialCapacity: Int): ModAnimationBundler = {} + override fun createModAnimationBuilder(initialCapacity: Int): ModAnimationBundler = ModAnimationBundlerImpl(initialCapacity) override fun tint(itemStack: PlatformItemStack, rgb: Int): PlatformItemStack { return itemStack.clone().unwarp().apply { diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt index c525fb3f2..014c39fa9 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/ModelNametagImpl.kt @@ -24,7 +24,6 @@ import kr.toxicity.model.impl.fabric.network.bundlerOfNotNull import kr.toxicity.model.impl.fabric.network.pack import kr.toxicity.model.impl.fabric.network.plusAssign import kr.toxicity.model.mixin.DisplayAccessor -import kr.toxicity.model.util.PLATFORM import net.minecraft.network.chat.Component import net.minecraft.network.protocol.game.ClientboundAddEntityPacket import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket @@ -54,7 +53,7 @@ class ModelNametagImpl( private val viewedPlayer = ConcurrentHashMap.newKeySet() private val display = Display.TextDisplay( EntityType.TEXT_DISPLAY, - (PLATFORM as BetterModelMod).server().overworld() + BetterModelMod.platform().server().overworld() ).apply { entityData[DisplayAccessor.`bettermodel$getDataPosRotInterpolationDurationId`()] = 3 setTransformation(emptyTransformation) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt index 1949ccf69..0b6022c54 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/PlayerChannelHandlerImpl.kt @@ -23,6 +23,7 @@ import kr.toxicity.model.mixin.DisplayAccessor import kr.toxicity.model.mixin.EntityAccessor import kr.toxicity.model.util.CONFIG import kr.toxicity.model.util.PLATFORM +import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking import net.minecraft.network.Connection import net.minecraft.network.protocol.Packet import net.minecraft.network.protocol.game.* @@ -56,7 +57,7 @@ class PlayerChannelHandlerImpl( } override fun base(): BasePlayer = basePlayer - override fun isModEnabled(): Boolean = false + override fun isModEnabled(): Boolean = ServerPlayNetworking.getReceived(player).contains(ModAnimationBundlerImpl.IDENTIFIER) private val playerModel get() = connection.player.id.toRegistry() diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/ModAnimationBundlerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/ModAnimationBundlerImpl.kt new file mode 100644 index 000000000..ae6198974 --- /dev/null +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/ModAnimationBundlerImpl.kt @@ -0,0 +1,146 @@ +/* + * This source file is part of BetterModel. + * Copyright (c) 2026 toxicity188 + * Licensed under the MIT License. + * See LICENSE.md file for full license text. + */ + +package kr.toxicity.model.impl.fabric.network + +import kr.toxicity.model.api.mod.BetterModelMod +import kr.toxicity.model.api.nms.ModAnimationBundler +import kr.toxicity.model.api.platform.PlatformPlayer +import kr.toxicity.model.api.util.MathUtil +import kr.toxicity.model.impl.fabric.unwarp +import net.minecraft.network.FriendlyByteBuf +import net.minecraft.network.RegistryFriendlyByteBuf +import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket +import net.minecraft.resources.Identifier +import org.joml.Quaternionf +import org.joml.Vector3f + +internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundler { + + companion object { + + const val KEY = "modelengine:bulk_data" + val IDENTIFIER = Identifier.parse(KEY) + + const val PACKET_TYPE_BULK_DATA = 0x00 + + const val FIELD_TRANSLATION = 1 shl 0 + const val FIELD_LEFT_ROTATION = 1 shl 1 + const val FIELD_SCALE = 1 shl 2 + const val FIELD_TRANSFORM_DURATION = 1 shl 4 + + private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} + } + + private val packet by lazy { + useByteBuf { buffer -> + ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( + RegistryFriendlyByteBuf( + buffer, + BetterModelMod.platform().server().registryAccess() + ).apply { + writeUtf(KEY) + useByteBuf { + it.writeByte(PACKET_TYPE_BULK_DATA) + it.writeVarInt(builderList.size) + builderList.forEach { builder -> builder(it) } + writeBytes(it) + } + } + ) + } + } + + private val builderList = ArrayList<(FriendlyByteBuf) -> Unit>(initialCapacity) + + override fun send(player: PlatformPlayer) { + player.unwarp().send(packet) + } + + fun append(id: Int, scope: Appender.() -> Unit) { + val build = Appender(id).apply(scope).build() + if (build !== EMPTY_BUILD_TASK) builderList += build + } + + class Appender( + val entityId: Int, + ) { + private var mask = 0 + private var buildTask = EMPTY_BUILD_TASK + private val isEmpty get() = buildTask === EMPTY_BUILD_TASK + + fun appendPosition(vector: Vector3f) { + mask = mask or FIELD_TRANSLATION + task { + writeFloat(it, vector.x) + writeFloat(it, vector.y) + writeFloat(it, vector.z) + } + } + + fun appendScale(vector: Vector3f) { + mask = mask or FIELD_SCALE + task { + writeFloat(it, vector.x) + writeFloat(it, vector.y) + writeFloat(it, vector.z) + } + } + + fun appendRotation(quaternion: Quaternionf) { + mask = mask or FIELD_LEFT_ROTATION + task { + writeFloat(it, quaternion.x) + writeFloat(it, quaternion.y) + writeFloat(it, quaternion.z) + writeFloat(it, quaternion.w) + } + } + + fun appendDuration(duration: Int) { + mask = mask or FIELD_TRANSFORM_DURATION + task { + writeVarInt(it, duration) + } + } + + fun build(): (FriendlyByteBuf) -> Unit { + if (isEmpty) return EMPTY_BUILD_TASK + val m = mask + val t = buildTask + return { + writeVarInt(it,entityId) + writeByte(it, m) + t(it) + } + } + + private fun task(task: (FriendlyByteBuf) -> Unit) { + if (isEmpty) { + buildTask = task + return + } + val last = buildTask + buildTask = { + last(it) + task(it) + } + } + + private fun writeFloat(buf: FriendlyByteBuf, float: Float) { + buf.writeShort(MathUtil.floatToHalf(float).toInt()) + } + + private fun writeVarInt(buf: FriendlyByteBuf, duration: Int) { + buf.writeVarInt(duration) + } + + private fun writeByte(buf: FriendlyByteBuf, duration: Int) { + buf.writeByte(duration) + } + } +} diff --git a/platform/paper/build.gradle.kts b/platform/paper/build.gradle.kts index bda536392..ad7eb43ee 100644 --- a/platform/paper/build.gradle.kts +++ b/platform/paper/build.gradle.kts @@ -18,9 +18,11 @@ dependencies { shade(project(":nms:v1_21_R5")) { isTransitive = false } shade(project(":nms:v1_21_R6")) { isTransitive = false } shade(project(":nms:v1_21_R7")) { isTransitive = false } + shade(project(":nms:v26_R1")) { isTransitive = false } } modrinth { + gameVersions = SUPPORTED_VERSIONS loaders = PAPER_LOADERS } diff --git a/platform/spigot/build.gradle.kts b/platform/spigot/build.gradle.kts index 8468e5dfc..d0a0345f4 100644 --- a/platform/spigot/build.gradle.kts +++ b/platform/spigot/build.gradle.kts @@ -5,16 +5,22 @@ plugins { alias(libs.plugins.resourcefactory.bukkit) } +val dependenciesContent: List = libs.bundles.library.map { + it.map(Any::toString) +}.get() + dependencies { - shade(project(":nms:v1_21_R1", configuration = "reobf")) { isTransitive = false } - shade(project(":nms:v1_21_R3", configuration = "reobf")) { isTransitive = false } - shade(project(":nms:v1_21_R4", configuration = "reobf")) { isTransitive = false } - shade(project(":nms:v1_21_R5", configuration = "reobf")) { isTransitive = false } - shade(project(":nms:v1_21_R6", configuration = "reobf")) { isTransitive = false } - shade(project(":nms:v1_21_R7", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R1", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R3", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R4", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R5", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R6", configuration = "reobf")) { isTransitive = false } +// shade(project(":nms:v1_21_R7", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v26_R1")) { isTransitive = false } } modrinth { + gameVersions = LATEST_VERSION loaders = BUKKIT_LOADERS } @@ -29,7 +35,7 @@ bukkitPluginYaml { version = project.version.toString() name = "BetterModel" foliaSupported = true - apiVersion = "1.20" + apiVersion = "26.1" author = "toxicity188" description = "Modern Bedrock model engine for Minecraft Java Edition" website = "https://modrinth.com/plugin/bettermodel" @@ -38,9 +44,7 @@ bukkitPluginYaml { "Citizens", "SkinsRestorer" ) - libraries = libs.bundles.library.map { - it.map(Any::toString) - } + libraries = dependenciesContent permissions.create("bettermodel") { default = Permission.Default.OP description = "Accesses to command." diff --git a/settings.gradle.kts b/settings.gradle.kts index 77da04af2..72ced8cb7 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -27,8 +27,8 @@ dependencyResolutionManagement { maven("https://repo.purpurmc.org/snapshots") maven("https://maven.citizensnpcs.co/repo/") maven("https://mvn.lumine.io/repository/maven-public/") - maven("https://repo.nexomc.com/releases/") maven("https://maven.nucleoid.xyz/") + maven("https://repo.nexomc.com/releases/") // for development builds maven(url = "https://central.sonatype.com/repository/maven-snapshots/") { name = "central-snapshots" @@ -47,7 +47,7 @@ val published = setOf( "core", "core:bukkit-core", - //"platform:spigot", TODO reobf does not work in Java 25 + "platform:spigot", "platform:paper", "platform:fabric", ) @@ -63,6 +63,7 @@ include( "nms:v1_21_R5", "nms:v1_21_R6", "nms:v1_21_R7", + "nms:v26_R1", //test "test-plugin" From 0e01f3d6fdf1ed35629df296b76a5aaad6057a21 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 5 Apr 2026 00:10:23 +0900 Subject: [PATCH 12/91] chore: write 3.0.0.md --- changelog/3.0.0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 02142cf94..4dfeb3f74 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -9,7 +9,7 @@ As with 2.0.0, there are several **Breaking Changes**, so please take note when ### [Minecraft 26.1 / 26.1.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support -(Image placeholder) +![](https://github.com/user-attachments/assets/b841ef93-4b16-486e-b443-d104a9c7bae4) From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. @@ -17,7 +17,7 @@ From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. ### [Mesh Element](https://en.wikipedia.org/wiki/Triangle_mesh) Support (Experiment) -(Image placeholder) +![](https://github.com/user-attachments/assets/a7883caa-ed7d-4889-8b7f-4407fc3a9df6) We now support client resource pack conversion for Mesh Elements from [BlockBench](https://www.blockbench.net/). It is available on Minecraft clients version 26.1 and above. From f80c8afd840bd6ab5fa86949472e5c8b97e056e5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 5 Apr 2026 00:21:16 +0900 Subject: [PATCH 13/91] chore: [ci skip] hangar publish --- build.gradle.kts | 2 +- renovate.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 0a9107672..9ea06ff5e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -61,7 +61,7 @@ hangarPublish { } platforms { register(Platforms.PAPER) { - jar = project(":platform:paper").tasks.named("shadowJar").flatMap { + jar = project(":platform:bettermodel-paper").tasks.named("shadowJar").flatMap { it.archiveFile } platformVersions = SUPPORTED_VERSIONS diff --git a/renovate.json b/renovate.json index 630b392ac..bc49992cc 100644 --- a/renovate.json +++ b/renovate.json @@ -13,6 +13,6 @@ "eu.pb4:polymer-resource-pack" ], "baseBranches": [ - "v2-dev" + "v3-dev" ] } From dd2bf6c6f19204ff4960227c2d5636264a47f5a3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:22:47 +0000 Subject: [PATCH 14/91] fix(deps): update dependency dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin to v2.2.2 --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 84e99948b..fc3d8bc1f 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -17,6 +17,6 @@ dependencies { implementation(libs.build.resourcefactory) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.2.0") - implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:2.2.1") + implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:2.2.2") implementation("com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin:0.36.0") } From 4c109b5a7e3debc5fc32d607ae3ddd75104ecfde Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 4 Apr 2026 15:22:50 +0000 Subject: [PATCH 15/91] fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.11.1 --- core/bukkit-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index f7713d9cf..4ca320e4c 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { compileOnly("net.citizensnpcs:citizens-main:2.0.41-SNAPSHOT") { exclude("net.byteflux") } - compileOnly("net.skinsrestorer:skinsrestorer-api:15.11.0") + compileOnly("net.skinsrestorer:skinsrestorer-api:15.11.1") compileOnly("io.lumine:Mythic-Dist:5.11.2") compileOnly("com.nexomc:nexo:1.21.0") } From 584555a30fec4df4c835a8a9ed5307bb0311f73d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 5 Apr 2026 00:26:39 +0900 Subject: [PATCH 16/91] chore: [ci skip] edit 3.0.0.md --- changelog/3.0.0.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 4dfeb3f74..3c8ba0c9e 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -44,8 +44,8 @@ As obfuscation has been removed from the Minecraft jar starting from 26.1, tooli - `bettermodel-fabric`: Starting from 3.0.0, this is separated from the mod platform's API, `bettermodel-mod-api`. -\
-\build.gradle.kts\ +
+build.gradle.kts ```kotlin // Use the following dependency when referencing only the API. @@ -63,7 +63,7 @@ dependencies { } ``` -\ +
--- From 1ab904c2e31c78b6207f27095a5222ea7b7f62cc Mon Sep 17 00:00:00 2001 From: toxicity188 <114675706+toxicity188@users.noreply.github.com> Date: Sun, 5 Apr 2026 00:35:01 +0900 Subject: [PATCH 17/91] chore: [ci skip] edit 3.0.0.md --- changelog/3.0.0.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 3c8ba0c9e..9173fb9d0 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -9,7 +9,8 @@ As with 2.0.0, there are several **Breaking Changes**, so please take note when ### [Minecraft 26.1 / 26.1.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support -![](https://github.com/user-attachments/assets/b841ef93-4b16-486e-b443-d104a9c7bae4) +![](https://github.com/user-attachments/assets/0153e97a-e320-41d1-8d94-ed626127b0cc) + From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. @@ -17,7 +18,7 @@ From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. ### [Mesh Element](https://en.wikipedia.org/wiki/Triangle_mesh) Support (Experiment) -![](https://github.com/user-attachments/assets/a7883caa-ed7d-4889-8b7f-4407fc3a9df6) +![](https://github.com/user-attachments/assets/facf34a2-31d3-4ebd-a7ff-9fe86c651ff8) We now support client resource pack conversion for Mesh Elements from [BlockBench](https://www.blockbench.net/). It is available on Minecraft clients version 26.1 and above. From a8389d25fcf03daa42d8c42b7d527e2e3a2a6949 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 5 Apr 2026 16:04:13 +0900 Subject: [PATCH 18/91] chore: com.vdurmont:semver4j -> org.semver4j:semver4j --- README.md | 3 ++- .../kr/toxicity/model/api/BetterModelPlatform.java | 2 +- .../kr/toxicity/model/api/data/raw/ModelMeta.java | 5 +++-- .../java/kr/toxicity/model/api/util/HttpUtil.java | 6 +++--- .../toxicity/model/api/version/MinecraftVersion.java | 12 ++++-------- buildSrc/build.gradle.kts | 1 + .../main/kotlin/paperweight-conventions.gradle.kts | 1 + changelog/3.0.0.md | 5 +++-- .../kr/toxicity/model/bukkit/BetterModelPlugin.kt | 2 +- .../toxicity/model/bukkit/BetterModelProperties.kt | 5 +++-- gradle/libs.versions.toml | 4 ++-- nms/v1_21_R1/build.gradle.kts | 3 +-- nms/v1_21_R3/build.gradle.kts | 3 +-- nms/v1_21_R4/build.gradle.kts | 3 +-- nms/v1_21_R5/build.gradle.kts | 3 +-- nms/v1_21_R6/build.gradle.kts | 3 +-- nms/v1_21_R7/build.gradle.kts | 1 - nms/v26_R1/build.gradle.kts | 3 +-- .../model/impl/fabric/BetterModelFabricImpl.kt | 8 +++----- purpur/build.gradle.kts | 4 +++- 20 files changed, 36 insertions(+), 41 deletions(-) diff --git a/README.md b/README.md index f77eafc62..cfd772cf6 100644 --- a/README.md +++ b/README.md @@ -69,13 +69,14 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim #### Library - [Kotlin stdlib](https://github.com/JetBrains/kotlin): modern functional programming -- [semver4j](https://github.com/vdurmont/semver4j): semver parser +- [semver4j](https://github.com/semver4j/semver4j): semver parser - [cloud](https://github.com/Incendo/cloud-minecraft): command - [adventure](https://github.com/KyoriPowered/adventure): component - [stable player display](https://github.com/bradleyq/stable_player_display): player animation - [caffeine](https://github.com/ben-manes/caffeine): concurrent map cache - [DynamicUV](https://github.com/toxicity188/DynamicUV): player model - [ArmorModel](https://github.com/toxicity188/ArmorModel): armor in player model +- [java-mesh](https://github.com/toxicity188/java-mesh): mesh rendering - [molang-compiler](https://github.com/Ocelot5836/molang-compiler): compiling and evaluating molang expression - [libby](https://github.com/AlessioDP/libby): runtime library downloader diff --git a/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java b/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java index b9c94838d..375a26fed 100644 --- a/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java +++ b/api/src/main/java/kr/toxicity/model/api/BetterModelPlatform.java @@ -7,7 +7,6 @@ package kr.toxicity.model.api; -import com.vdurmont.semver4j.Semver; import kr.toxicity.model.api.event.ModelEventApplication; import kr.toxicity.model.api.manager.*; import kr.toxicity.model.api.nms.NMS; @@ -20,6 +19,7 @@ import net.kyori.adventure.audience.Audience; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.semver4j.Semver; import java.io.File; import java.io.InputStream; diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java index d6d423731..066e45d8b 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelMeta.java @@ -8,13 +8,14 @@ package kr.toxicity.model.api.data.raw; import com.google.gson.JsonDeserializer; -import com.vdurmont.semver4j.Semver; import kr.toxicity.model.api.util.MathUtil; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; import org.joml.Vector3f; +import org.semver4j.Semver; import java.util.Arrays; +import java.util.Objects; /** * Represents metadata about the model file, specifically the format version. @@ -33,7 +34,7 @@ public record ModelMeta( * @since 1.15.2 */ public static final JsonDeserializer PARSER = (json, _, _) -> new ModelMeta( - FormatVersion.find(new Semver(json.getAsJsonObject().getAsJsonPrimitive("format_version").getAsString(), Semver.SemverType.LOOSE).getMajor()) + FormatVersion.find(Objects.requireNonNull(Semver.coerce(json.getAsJsonObject().getAsJsonPrimitive("format_version").getAsString())).getMajor()) ); /** diff --git a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java index cb7e8a945..04016a04c 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/HttpUtil.java @@ -13,7 +13,6 @@ import com.google.gson.JsonParser; import com.google.gson.annotations.SerializedName; import com.google.gson.stream.JsonReader; -import com.vdurmont.semver4j.Semver; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.version.MinecraftVersion; import net.kyori.adventure.text.Component; @@ -23,6 +22,7 @@ import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.semver4j.Semver; import java.io.InputStreamReader; import java.net.URI; @@ -49,7 +49,7 @@ public final class HttpUtil { .build(); private static final Gson GSON = new GsonBuilder() .registerTypeAdapter(MinecraftVersion.class, (JsonDeserializer) (json, _, _) -> MinecraftVersion.parse(json.getAsString())) - .registerTypeAdapter(Semver.class, (JsonDeserializer) (json, _, _) -> new Semver(json.getAsString(), Semver.SemverType.LOOSE)) + .registerTypeAdapter(Semver.class, (JsonDeserializer) (json, _, _) -> Semver.coerce(json.getAsString())) .create(); /** @@ -142,7 +142,7 @@ public record PluginVersion( public @NotNull Component toURLComponent() { var url = "https://modrinth.com/plugin/bettermodel/version/" + id; return Component.text() - .content(versionNumber.getOriginalValue()) + .content(versionNumber.getVersion()) .color(NamedTextColor.AQUA) .hoverEvent( HoverEvent.showText(Component.text() diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index a965c7cc8..1d8071ec0 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -7,10 +7,11 @@ package kr.toxicity.model.api.version; -import com.vdurmont.semver4j.Semver; import org.jetbrains.annotations.NotNull; +import org.semver4j.Semver; import java.util.Comparator; +import java.util.Objects; /** * Minecraft version. @@ -85,13 +86,8 @@ public record MinecraftVersion(int major, int minor, int patch) implements Compa * @return parsed version */ public static @NotNull MinecraftVersion parse(@NotNull String version) { - var split = new Semver(version, Semver.SemverType.LOOSE); - Integer v1, v2, v3; - return of( - (v1 = split.getMajor()) == null ? 0 : v1, - (v2 = split.getMinor()) == null ? 0 : v2, - (v3 = split.getPatch()) == null ? 0 : v3 - ); + var split = Objects.requireNonNull(Semver.coerce(version)); + return of(split.getMajor(), split.getMinor(), split.getPatch()); } /** diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index fc3d8bc1f..198918c9c 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -15,6 +15,7 @@ dependencies { implementation(libs.build.hangarPublish) implementation(libs.build.minotaur) implementation(libs.build.resourcefactory) + implementation(libs.build.paperweight) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.2.0") implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:2.2.2") diff --git a/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts b/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts index d7ff1edc1..b69d58fc4 100644 --- a/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/paperweight-conventions.gradle.kts @@ -1,5 +1,6 @@ plugins { id("standard-conventions") + id("io.papermc.paperweight.userdev") } dependencies { diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 9173fb9d0..5a2e5ed31 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -27,6 +27,7 @@ It is available on Minecraft clients version 26.1 and above. ### Others +- Support meg-client-mod. - A `priority` property has been added to the `AnimationModifier` class, allowing you to adjust the application order of animations. --- @@ -83,10 +84,10 @@ dependencies { - fix(deps): update dependency org.jetbrains.dokka:dokka-gradle-plugin to v2.2.0 - fix(deps): update kotlin monorepo to v2.3.20 - fix(deps): update dependency net.fabricmc:fabric-language-kotlin to v1.13.10+kotlin.2.3.20 -- fix(deps): update dependency net.fabricmc:fabric-loader to v0.18.5 +- fix(deps): update dependency net.fabricmc:fabric-loader to v0.18.6 - fix(deps): update dependency com.modrinth.minotaur:com.modrinth.minotaur.gradle.plugin to v2.9.0 - fix(deps): update dependency org.projectlombok:lombok to v1.18.44 -- fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.11.0 +- fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.11.1 --- diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt index e3d9a7b76..1c2ffb857 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt @@ -7,7 +7,6 @@ package kr.toxicity.model.bukkit -import com.vdurmont.semver4j.Semver import kr.toxicity.model.api.BetterModelConfig import kr.toxicity.model.api.BetterModelEvaluator import kr.toxicity.model.api.BetterModelLogger @@ -34,6 +33,7 @@ import org.bukkit.event.EventHandler import org.bukkit.event.Listener import org.bukkit.event.player.PlayerJoinEvent import org.bukkit.event.server.ServerLoadEvent +import org.semver4j.Semver import java.io.File import java.io.InputStream import java.util.function.BiConsumer diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index 7571a84b0..3a433cc74 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -7,7 +7,6 @@ package kr.toxicity.model.bukkit -import com.vdurmont.semver4j.Semver import kr.toxicity.model.BetterModelEvaluatorImpl import kr.toxicity.model.api.BetterModelConfig import kr.toxicity.model.api.BetterModelPlatform.ReloadResult @@ -25,10 +24,12 @@ import kr.toxicity.model.bukkit.scheduler.PaperScheduler import kr.toxicity.model.manager.* import kr.toxicity.model.util.callEvent import kr.toxicity.model.util.handleException +import kr.toxicity.model.util.ifNull import kr.toxicity.model.util.toComponent import kr.toxicity.model.util.warn import org.bstats.bukkit.Metrics import org.bukkit.Bukkit +import org.semver4j.Semver private typealias Latest = kr.toxicity.model.bukkit.nms.v26_R1.NMSImpl @@ -60,7 +61,7 @@ internal class BetterModelProperties( val evaluator = BetterModelEvaluatorImpl() val eventbus = BukkitModelEventBusImpl() @Suppress("DEPRECATION") //To support Spigot :( - val semver = Semver(plugin.description.version, Semver.SemverType.LOOSE) + val semver = Semver.coerce(plugin.description.version).ifNull { "Unable to load BetterModel's sermver." } val snapshot = runCatching { plugin.attributes().getValue("Dev-Build").toInt() }.getOrElse { diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 62d5247fa..6b64dea9a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -21,7 +21,7 @@ neoform = "26.1.1-1" [libraries] kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } -semver4j = "com.vdurmont:semver4j:3.1.0" +semver4j = "org.semver4j:semver4j:6.0.0" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" adventure-api = "net.kyori:adventure-api:4.26.1" @@ -63,6 +63,7 @@ build-shadow = { module = "com.gradleup.shadow:com.gradleup.shadow.gradle.plugin build-minotaur = { module = "com.modrinth.minotaur:com.modrinth.minotaur.gradle.plugin", version.ref = "minotaur" } build-hangarPublish = { module = "io.papermc.hangar-publish-plugin:io.papermc.hangar-publish-plugin.gradle.plugin", version.ref = "hangarPublish" } build-resourcefactory = { module = "xyz.jpenilla:resource-factory", version.ref = "resourcefactory" } +build-paperweight = { module = "io.papermc.paperweight.userdev:io.papermc.paperweight.userdev.gradle.plugin", version.ref = "paperweight" } [bundles] minecraft = [ @@ -125,7 +126,6 @@ shadedLibrary = [ resourcefactory-bukkit = { id = "xyz.jpenilla.resource-factory-bukkit-convention" } resourcefactory-paper = { id = "xyz.jpenilla.resource-factory-paper-convention" } resourcefactory-fabric = { id = "xyz.jpenilla.resource-factory-fabric-convention" } -paperweight = { id = "io.papermc.paperweight.userdev", version.ref = "paperweight" } hangar = { id = "io.papermc.hangar-publish-plugin" } diff --git a/nms/v1_21_R1/build.gradle.kts b/nms/v1_21_R1/build.gradle.kts index a0636488e..8aa6bddd0 100644 --- a/nms/v1_21_R1/build.gradle.kts +++ b/nms/v1_21_R1/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") -} \ No newline at end of file +} diff --git a/nms/v1_21_R3/build.gradle.kts b/nms/v1_21_R3/build.gradle.kts index e2ea58d43..5ae134fbd 100644 --- a/nms/v1_21_R3/build.gradle.kts +++ b/nms/v1_21_R3/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") -} \ No newline at end of file +} diff --git a/nms/v1_21_R4/build.gradle.kts b/nms/v1_21_R4/build.gradle.kts index 8dc4df188..67c8091f5 100644 --- a/nms/v1_21_R4/build.gradle.kts +++ b/nms/v1_21_R4/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") -} \ No newline at end of file +} diff --git a/nms/v1_21_R5/build.gradle.kts b/nms/v1_21_R5/build.gradle.kts index d8a619884..588b42efc 100644 --- a/nms/v1_21_R5/build.gradle.kts +++ b/nms/v1_21_R5/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT") -} \ No newline at end of file +} diff --git a/nms/v1_21_R6/build.gradle.kts b/nms/v1_21_R6/build.gradle.kts index a8ce41ba6..42662a9c9 100644 --- a/nms/v1_21_R6/build.gradle.kts +++ b/nms/v1_21_R6/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") -} \ No newline at end of file +} diff --git a/nms/v1_21_R7/build.gradle.kts b/nms/v1_21_R7/build.gradle.kts index aa32e37f7..9efcade4e 100644 --- a/nms/v1_21_R7/build.gradle.kts +++ b/nms/v1_21_R7/build.gradle.kts @@ -1,6 +1,5 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { diff --git a/nms/v26_R1/build.gradle.kts b/nms/v26_R1/build.gradle.kts index 6d88914c3..17c87b764 100644 --- a/nms/v26_R1/build.gradle.kts +++ b/nms/v26_R1/build.gradle.kts @@ -1,8 +1,7 @@ plugins { alias(libs.plugins.convention.paperweight) - alias(libs.plugins.paperweight) } dependencies { - paperweight.paperDevBundle("26.1.1.build.15-alpha") + paperweight.paperDevBundle("26.1.1.build.20-alpha") } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt index 369dab94f..abaee5ca8 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelFabricImpl.kt @@ -7,7 +7,6 @@ package kr.toxicity.model.impl.fabric -import com.vdurmont.semver4j.Semver import eu.pb4.polymer.resourcepack.api.PolymerResourcePackUtils import eu.pb4.polymer.resourcepack.api.ResourcePackBuilder import kr.toxicity.model.BetterModelEvaluatorImpl @@ -46,6 +45,7 @@ import net.minecraft.WorldVersion import net.minecraft.server.MinecraftServer import net.minecraft.server.packs.metadata.pack.PackFormat import net.minecraft.util.InclusiveRange +import org.semver4j.Semver import java.io.File import java.io.InputStream import java.nio.file.Files @@ -79,10 +79,8 @@ class BetterModelFabricImpl : ModInitializer, BetterModelPlatformImpl, BetterMod private val semver: Semver = FabricLoader.getInstance() .getModContainer(modId()) .map { modContainer -> - Semver( - modContainer.metadata.version.friendlyString, - Semver.SemverType.LOOSE - ) + Semver.coerce(modContainer.metadata.version.friendlyString) + .ifNull { "Unable to load BetterModel's semver." } } .orElseThrow() diff --git a/purpur/build.gradle.kts b/purpur/build.gradle.kts index 30d5ab1ca..4ef20ec17 100644 --- a/purpur/build.gradle.kts +++ b/purpur/build.gradle.kts @@ -1,8 +1,10 @@ plugins { - alias(libs.plugins.convention.paperweight) + alias(libs.plugins.convention.standard) } dependencies { + compileOnly(project(":bettermodel-api")) + compileOnly(project(":bettermodel-api:bettermodel-bukkit-api")) //TODO change this to compileOnly("org.purpurmc.purpur:purpur-api:${property("minecraft_version")}-R0.1-SNAPSHOT") compileOnly("org.purpurmc.purpur:purpur-api:1.21.11-R0.1-SNAPSHOT") } From c72f553c42919c1785f6c081876c507fa6f662b5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 15:27:52 +0900 Subject: [PATCH 19/91] perf: optimize bezier --- .../model/api/util/InterpolationUtil.java | 40 +++++++++---------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java b/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java index f8af3c7b8..597b5b9a5 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/InterpolationUtil.java @@ -191,31 +191,31 @@ public static float lerp(float p0, float p1, float alpha) { } private static float cubicBezier(float p0, float p1, float p2, float p3, float t) { - float u = 1.0F - t; - float uu = u * u; - float tt = t * t; - float uuu = uu * u; - float utt = u * tt; - float uut = uu * t; - float ttt = tt * t; + var u = 1.0F - t; + var uu = u * u; + var tt = t * t; + var uuu = uu * u; + var utt = u * tt; + var uut = uu * t; + var ttt = tt * t; return fma(uuu, p0, fma(3.0F * uut, p1, fma(3.0F * utt, p2, ttt * p3))); } private static float derivativeBezier(float p1, float p2, float t) { - float u = 1.0F - t; - float uu = u * u; - float ut = u * t; - float tt = t * t; + var u = 1.0F - t; + var uu = u * u; + var ut = u * t; + var tt = t * t; return fma(3.0F * uu, p1, fma(6.0F * ut, p2 - p1, 3.0F * tt * (1 - p2))); } private static float solveBezierTForTime(float time, float h1, float h2) { - float t = 0.5F; - int maxIterations = 20; + var t = 0.5F; + var maxIterations = 20; for (int i = 0; i < maxIterations; i++) { - float bezTime = cubicBezier(0, h1, h2, 1, t); - float derivative = derivativeBezier(h1, h2, t); - float error = bezTime - time; + var bezTime = cubicBezier(0, h1, h2, 1, t); + var derivative = derivativeBezier(h1, h2, t); + var error = bezTime - time; if (Math.abs(error) < FLOAT_COMPARISON_EPSILON) { return t; } @@ -248,20 +248,18 @@ private static float solveBezierTForTime(float time, float h1, float h2) { @NotNull Vector3f bezierLeftTime, @NotNull Vector3f bezierLeftValue ) { - var p1 = start.add(bezierRightValue, new Vector3f()); - var p2 = end.add(bezierLeftValue, new Vector3f()); return new Vector3f( - cubicBezier(start.x, p1.x, p2.x, end.x, solveBezierTForTime( + cubicBezier(start.x, start.x + bezierRightValue.x, end.x + bezierLeftValue.x, end.x, solveBezierTForTime( alpha, bezierRightTime.x, 1 + bezierLeftTime.x )), - cubicBezier(start.y, p1.y, p2.y, end.y, solveBezierTForTime( + cubicBezier(start.y, start.y + bezierRightValue.y, end.y + bezierLeftValue.y, end.y, solveBezierTForTime( alpha, bezierRightTime.y, 1 + bezierLeftTime.y )), - cubicBezier(start.z, p1.z, p2.z, end.z, solveBezierTForTime( + cubicBezier(start.z, start.z + bezierRightValue.z, end.z + bezierLeftValue.z, end.z, solveBezierTForTime( alpha, bezierRightTime.z, 1 + bezierLeftTime.z From 44b70c49a02afe6e888ef11c525c3958b1cc9fef Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 15:32:36 +0900 Subject: [PATCH 20/91] chore: update fabric api --- gradle/libs.versions.toml | 2 +- nms/v26_R1/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b64dea9a..90c433548 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.145.3+26.1.1" +fabric-api = "0.145.4+26.1.1" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released diff --git a/nms/v26_R1/build.gradle.kts b/nms/v26_R1/build.gradle.kts index 17c87b764..46d254331 100644 --- a/nms/v26_R1/build.gradle.kts +++ b/nms/v26_R1/build.gradle.kts @@ -3,5 +3,5 @@ plugins { } dependencies { - paperweight.paperDevBundle("26.1.1.build.20-alpha") + paperweight.paperDevBundle("26.1.1.build.28-alpha") } From 861be9dcb8d78d27f667a3ac6d5ecf6340da7e9a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 15:34:26 +0900 Subject: [PATCH 21/91] chore: update polymer-resource-pack to 0.16.1+26.1.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 90c433548..2a9799d27 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,7 +35,7 @@ asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.18.6" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.0+26.1.1" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.1+26.1.1" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } From 4d329a669f1e2b248ca9a534c4c16b669ca7423d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 16:32:24 +0900 Subject: [PATCH 22/91] chore: update net.citizensnpcs:citizens-main to 2.0.42-SNAPSHOT --- core/bukkit-core/build.gradle.kts | 2 +- nms/v26_R1/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index 4ca320e4c..fc093db78 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -20,7 +20,7 @@ dependencies { compileOnly(libs.bundles.manifestLibrary) - compileOnly("net.citizensnpcs:citizens-main:2.0.41-SNAPSHOT") { + compileOnly("net.citizensnpcs:citizens-main:2.0.42-SNAPSHOT") { exclude("net.byteflux") } compileOnly("net.skinsrestorer:skinsrestorer-api:15.11.1") diff --git a/nms/v26_R1/build.gradle.kts b/nms/v26_R1/build.gradle.kts index 46d254331..c7140e1a4 100644 --- a/nms/v26_R1/build.gradle.kts +++ b/nms/v26_R1/build.gradle.kts @@ -3,5 +3,5 @@ plugins { } dependencies { - paperweight.paperDevBundle("26.1.1.build.28-alpha") + paperweight.paperDevBundle("26.1.1.build.+") } From 4aba081193bb35794dd33eba90e161c3670c6f7f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 16:44:24 +0900 Subject: [PATCH 23/91] fix: restore Spigot NMS --- .../main/kotlin/standard-conventions.gradle.kts | 1 + nms/v1_21_R1/build.gradle.kts | 11 +++++++++++ nms/v1_21_R3/build.gradle.kts | 11 +++++++++++ nms/v1_21_R4/build.gradle.kts | 11 +++++++++++ nms/v1_21_R5/build.gradle.kts | 11 +++++++++++ nms/v1_21_R6/build.gradle.kts | 11 +++++++++++ nms/v1_21_R7/build.gradle.kts | 11 +++++++++++ platform/spigot/build.gradle.kts | 14 +++++++------- 8 files changed, 74 insertions(+), 7 deletions(-) diff --git a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts index 578324cc7..a83a5da32 100644 --- a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts @@ -39,6 +39,7 @@ license { } java { + disableAutoTargetJvm() toolchain.languageVersion = JavaLanguageVersion.of(JAVA_VERSION) } diff --git a/nms/v1_21_R1/build.gradle.kts b/nms/v1_21_R1/build.gradle.kts index 8aa6bddd0..7daf61085 100644 --- a/nms/v1_21_R1/build.gradle.kts +++ b/nms/v1_21_R1/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/nms/v1_21_R3/build.gradle.kts b/nms/v1_21_R3/build.gradle.kts index 5ae134fbd..29e3030e6 100644 --- a/nms/v1_21_R3/build.gradle.kts +++ b/nms/v1_21_R3/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.4-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/nms/v1_21_R4/build.gradle.kts b/nms/v1_21_R4/build.gradle.kts index 67c8091f5..888a63287 100644 --- a/nms/v1_21_R4/build.gradle.kts +++ b/nms/v1_21_R4/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.5-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/nms/v1_21_R5/build.gradle.kts b/nms/v1_21_R5/build.gradle.kts index 588b42efc..43a847a14 100644 --- a/nms/v1_21_R5/build.gradle.kts +++ b/nms/v1_21_R5/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.8-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/nms/v1_21_R6/build.gradle.kts b/nms/v1_21_R6/build.gradle.kts index 42662a9c9..9aee73895 100644 --- a/nms/v1_21_R6/build.gradle.kts +++ b/nms/v1_21_R6/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.10-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/nms/v1_21_R7/build.gradle.kts b/nms/v1_21_R7/build.gradle.kts index 9efcade4e..d1245d7af 100644 --- a/nms/v1_21_R7/build.gradle.kts +++ b/nms/v1_21_R7/build.gradle.kts @@ -1,3 +1,5 @@ +import org.jetbrains.kotlin.gradle.dsl.JvmTarget + plugins { alias(libs.plugins.convention.paperweight) } @@ -5,3 +7,12 @@ plugins { dependencies { paperweight.paperDevBundle("1.21.11-R0.1-SNAPSHOT") } + +tasks { + compileJava { + options.release = 21 + } + compileKotlin { + compilerOptions.jvmTarget = JvmTarget.JVM_21 + } +} diff --git a/platform/spigot/build.gradle.kts b/platform/spigot/build.gradle.kts index d0a0345f4..99b09d1cd 100644 --- a/platform/spigot/build.gradle.kts +++ b/platform/spigot/build.gradle.kts @@ -10,17 +10,17 @@ val dependenciesContent: List = libs.bundles.library.map { }.get() dependencies { -// shade(project(":nms:v1_21_R1", configuration = "reobf")) { isTransitive = false } -// shade(project(":nms:v1_21_R3", configuration = "reobf")) { isTransitive = false } -// shade(project(":nms:v1_21_R4", configuration = "reobf")) { isTransitive = false } -// shade(project(":nms:v1_21_R5", configuration = "reobf")) { isTransitive = false } -// shade(project(":nms:v1_21_R6", configuration = "reobf")) { isTransitive = false } -// shade(project(":nms:v1_21_R7", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R1", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R3", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R4", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R5", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R6", configuration = "reobf")) { isTransitive = false } + shade(project(":nms:v1_21_R7", configuration = "reobf")) { isTransitive = false } shade(project(":nms:v26_R1")) { isTransitive = false } } modrinth { - gameVersions = LATEST_VERSION + gameVersions = SUPPORTED_VERSIONS loaders = BUKKIT_LOADERS } From fd83c2220812450385584c8102b45883e2d7222d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 16:55:44 +0900 Subject: [PATCH 24/91] feat: drop 1.21.1 support --- BANNER.md | 2 +- README.md | 4 +- .../api/bukkit/platform/BukkitItemStack.java | 3 +- .../kr/toxicity/model/api/bone/BoneTags.java | 2 +- .../model/api/manager/SkinManager.java | 8 - .../kr/toxicity/model/api/nms/NMSVersion.java | 5 - .../toxicity/model/api/player/PlayerLimb.java | 93 +--- .../model/api/version/MinecraftVersion.java | 20 - buildSrc/src/main/kotlin/Extensions.kt | 2 - .../model/bukkit/BetterModelProperties.kt | 1 - .../toxicity/model/manager/SkinManagerImpl.kt | 10 +- .../core/rendertype_entity_translucent.fsh | 47 -- .../core/rendertype_entity_translucent.json | 39 -- .../core/rendertype_entity_translucent.vsh | 233 --------- .../shaders/rendertype_entity_translucent.fsh | 47 -- .../shaders/rendertype_entity_translucent.vsh | 233 --------- nms/v1_21_R1/build.gradle.kts | 18 - .../bukkit/nms/v1_21_R1/AbstractHitBox.java | 38 -- .../bukkit/nms/v1_21_R1/BaseEntityImpl.kt | 85 ---- .../bukkit/nms/v1_21_R1/BasePlayerImpl.kt | 50 -- .../bukkit/nms/v1_21_R1/BukkitWrappers.kt | 36 -- .../model/bukkit/nms/v1_21_R1/EntityData.kt | 126 ----- .../model/bukkit/nms/v1_21_R1/Functions.kt | 207 -------- .../model/bukkit/nms/v1_21_R1/HitBoxImpl.kt | 445 ------------------ .../bukkit/nms/v1_21_R1/HitBoxInteraction.kt | 62 --- .../nms/v1_21_R1/ModAnimationBundlerImpl.kt | 144 ------ .../nms/v1_21_R1/ModelDamageSourceImpl.kt | 30 -- .../bukkit/nms/v1_21_R1/ModelDisplayImpl.kt | 267 ----------- .../bukkit/nms/v1_21_R1/ModelGameProfile.kt | 30 -- .../bukkit/nms/v1_21_R1/ModelNametagImpl.kt | 118 ----- .../model/bukkit/nms/v1_21_R1/NMSImpl.kt | 385 --------------- .../bukkit/nms/v1_21_R1/PacketBundlers.kt | 91 ---- .../model/bukkit/nms/v1_21_R1/ProfiledImpl.kt | 25 - .../model/bukkit/nms/v1_21_R1/TypeAliases.kt | 19 - platform/paper/build.gradle.kts | 3 +- platform/spigot/build.gradle.kts | 3 +- settings.gradle.kts | 1 - 37 files changed, 10 insertions(+), 2922 deletions(-) delete mode 100644 core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.fsh delete mode 100644 core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.json delete mode 100644 core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.vsh delete mode 100644 core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.fsh delete mode 100644 core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.vsh delete mode 100644 nms/v1_21_R1/build.gradle.kts delete mode 100644 nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt delete mode 100644 nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt diff --git a/BANNER.md b/BANNER.md index c4f661412..8fc272819 100644 --- a/BANNER.md +++ b/BANNER.md @@ -69,7 +69,7 @@ BetterModel supports **player model with using user's custom skin without textur ## 🏗️ Supported environment -[![](https://img.shields.io/badge/minecraft-1.21%7E26.1-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) [![](https://img.shields.io/badge/java-25%7E-ED8B00?style=for-the-badge)](https://adoptium.net/) ### Bukkit diff --git a/README.md b/README.md index cfd772cf6..ddb9045e7 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim ## 🛠️ Build info -[![](https://img.shields.io/badge/minecraft-1.21%7E26.1-8FCA5C)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1-8FCA5C)](https://www.minecraft.net/en-us/download/server) [![](https://img.shields.io/badge/java-25%7E-ED8B00)](https://adoptium.net/) #### Build @@ -64,7 +64,7 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim `./gradlew build`: Builds all jars `./gradlew shadowJar`: Builds plugin jar -`./gradlew javadocJar`: Builds javadoc jar +`./gradlew javadocJar`: Builds Javadoc jar `./gradlew runServer`: Runs Paper test server with test plugin #### Library diff --git a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java index 37f79a932..7583ad5c9 100644 --- a/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java +++ b/api/bukkit-api/src/main/java/kr/toxicity/model/api/bukkit/platform/BukkitItemStack.java @@ -7,7 +7,6 @@ package kr.toxicity.model.api.bukkit.platform; -import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.platform.PlatformItemStack; import kr.toxicity.model.api.platform.PlatformNamespace; import org.bukkit.NamespacedKey; @@ -42,7 +41,7 @@ public boolean isAir() { var meta = source.getItemMeta(); if (meta == null) return this; meta.setCustomModelData(customModelData); - if (BetterModel.platform().version().useItemModelName()) meta.setItemModel(namespace == null ? null : new NamespacedKey(namespace.namespace(), namespace.path())); + meta.setItemModel(namespace == null ? null : new NamespacedKey(namespace.namespace(), namespace.path())); source.setItemMeta(meta); return this; } diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java index 61ebd163e..614404224 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java @@ -128,7 +128,7 @@ public enum BoneTags implements BoneTag { @Override public @NotNull TransformedItemStack apply(@NotNull BoneRenderContext context, @NotNull TransformedItemStack transformedItemStack) { TransformedItemStack cape = null; - if (BetterModel.platform().skinManager().supported() && context.source() instanceof Profiled profiled && profiled.skinParts().isCapeEnabled()) { + if (context.source() instanceof Profiled profiled && profiled.skinParts().isCapeEnabled()) { cape = context.skin().cape(profiled.armors()); } return cape != null ? cape : TransformedItemStack.empty(); diff --git a/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java b/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java index 4f917b4a4..44fdb6215 100644 --- a/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java +++ b/api/src/main/java/kr/toxicity/model/api/manager/SkinManager.java @@ -24,14 +24,6 @@ */ public interface SkinManager { - /** - * Checks if a skin provider (like SkinsRestorer) is supported and available. - * - * @return true if supported, false otherwise - * @since 1.15.2 - */ - boolean supported(); - /** * Returns the fallback skin data used when a skin cannot be resolved. * diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java index 1654751b9..f0f82b6b1 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java @@ -22,11 +22,6 @@ @RequiredArgsConstructor @Getter public enum NMSVersion { - /** - * Minecraft 1.21 - 1.21.1 - * @since 1.15.2 - */ - V1_21_R1(34), /** * Minecraft 1.21.4 * @since 1.15.2 diff --git a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java index 21754bede..e93c77fbe 100644 --- a/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java +++ b/api/src/main/java/kr/toxicity/model/api/player/PlayerLimb.java @@ -7,19 +7,16 @@ package kr.toxicity.model.api.player; -import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.armor.PlayerArmor; import kr.toxicity.model.api.bone.BoneItemMapper; import kr.toxicity.model.api.bone.BoneRenderContext; import kr.toxicity.model.api.nms.Profiled; import kr.toxicity.model.api.platform.PlatformItemTransform; import kr.toxicity.model.api.skin.SkinData; -import kr.toxicity.model.api.util.MathUtil; import kr.toxicity.model.api.util.TransformedItemStack; import lombok.Getter; import lombok.RequiredArgsConstructor; import org.jetbrains.annotations.NotNull; -import org.joml.Vector3f; import java.util.function.BiFunction; import java.util.function.Function; @@ -34,11 +31,6 @@ public enum PlayerLimb { * Head */ HEAD( - position(0), - scale(7.4688F, 0.5F), - scale(7.4688F, 0.5F), - offset(0, 7.5F, 0, 0.5F), - offset(0, 7.5F, 0, 0.5F), SkinData::head, PlatformItemTransform.FIXED ), @@ -46,11 +38,6 @@ public enum PlayerLimb { * Right arm */ RIGHT_ARM( - position(1), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(2.7891F,5.5938F,3.7188F, 0.25F), - offset(-0.625F, 1.5F, 0, 0.25F), - offset(-0.043F, 1.5F, 0, 0.25F), SkinData::rightArm, PlatformItemTransform.FIXED ), @@ -58,11 +45,6 @@ public enum PlayerLimb { * Right forearm */ RIGHT_FOREARM( - position(2), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(2.7891F,5.5938F,3.7188F, 0.25F), - offset(-0.625F, 1.5F, 0, 0.25F), - offset(-0.043F, 1.5F, 0, 0.25F), (d, _) -> d.rightForeArm(), PlatformItemTransform.FIXED ), @@ -70,11 +52,6 @@ public enum PlayerLimb { * Left arm */ LEFT_ARM( - position(3), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(2.7891F,5.5938F,3.7188F, 0.25F), - offset(0.625F, 1.5F, 0, 0.25F), - offset(0.043F, 1.5F, 0, 0.25F), SkinData::leftArm, PlatformItemTransform.FIXED ), @@ -82,11 +59,6 @@ public enum PlayerLimb { * Left forearm */ LEFT_FOREARM( - position(4), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(2.7891F,5.5938F,3.7188F, 0.25F), - offset(0.625F, 1.5F, 0, 0.25F), - offset(0.043F, 1.5F, 0, 0.25F), (d, _) -> d.leftForeArm(), PlatformItemTransform.FIXED ), @@ -94,11 +66,6 @@ public enum PlayerLimb { * Hip */ HIP( - position(5), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - offset(0, 5.75F, 0, 0.25F), - offset(0, 5.75F, 0, 0.25F), SkinData::hip, PlatformItemTransform.FIXED ), @@ -106,11 +73,6 @@ public enum PlayerLimb { * Waist */ WAIST( - position(6), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - offset(0, 5.75F, 0, 0.25F), - offset(0, 5.75F, 0, 0.25F), SkinData::waist, PlatformItemTransform.FIXED ), @@ -118,11 +80,6 @@ public enum PlayerLimb { * Chest */ CHEST( - position(7), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - scale(7.4688F,3.7188F,3.7188F, 0.25F), - offset(0, 5.75F, 0, 0.25F), - offset(0, 5.75F, 0, 0.25F), SkinData::chest, PlatformItemTransform.FIXED ), @@ -130,11 +87,6 @@ public enum PlayerLimb { * Right leg */ RIGHT_LEG( - position(8), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - offset(0, 1.12F, 0, 0.25F), - offset(0, 1.12F, 0, 0.25F), SkinData::rightLeg, PlatformItemTransform.FIXED ), @@ -142,23 +94,13 @@ public enum PlayerLimb { * Right foreleg */ RIGHT_FORELEG( - position(9), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - offset(0, 1.12F, 0, 0.25F), - offset(0, 1.12F, 0, 0.25F), SkinData::rightForeLeg, PlatformItemTransform.FIXED ), /** - * LEft leg + * Left leg */ LEFT_LEG( - position(10), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - offset(0, 1.12F, 0, 0.25F), - offset(0, 1.12F, 0, 0.25F), SkinData::leftLeg, PlatformItemTransform.FIXED ), @@ -166,37 +108,11 @@ public enum PlayerLimb { * Left foreleg */ LEFT_FORELEG( - position(11), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - scale(3.7188F,5.5938F,3.7188F, 0.25F), - offset(0, 1.12F, 0, 0.25F), - offset(0, 1.12F, 0, 0.25F), SkinData::leftForeLeg, PlatformItemTransform.FIXED ), ; - private static @NotNull Vector3f position(int mul) { - return new Vector3f(0, -512, 0).mul(mul); - } - - private static @NotNull Vector3f scale(float scale, float inflate) { - return scale(scale, scale, scale, inflate); - } - - private static @NotNull Vector3f scale(float x, float y, float z, float inflate) { - return new Vector3f(x, y, z).div(8).add(new Vector3f(inflate).div(8)); - } - - private static @NotNull Vector3f offset(float x, float y, float z, float inflate) { - return new Vector3f(0, -0.25F, 0).add(new Vector3f(x, y, z).div(MathUtil.MODEL_TO_BLOCK_MULTIPLIER)).add(new Vector3f(0, inflate, 0).div(32)); - } - - private final @NotNull Vector3f position; - private final @NotNull Vector3f scale; - private final @NotNull Vector3f slimScale; - private final @NotNull Vector3f offset; - private final @NotNull Vector3f slimOffset; private final @NotNull BiFunction skinMapper; private final @NotNull PlatformItemTransform transform; @@ -209,12 +125,7 @@ public enum PlayerLimb { * @return item */ public @NotNull TransformedItemStack createItem(@NotNull BoneRenderContext context) { - if (BetterModel.platform().skinManager().supported()) { - return skinMapper.apply(context.skin(), context.source() instanceof Profiled profiled ? profiled.armors() : PlayerArmor.EMPTY); - } - var profile = context.skin().profile(); - var isSlim = profile.skin().slim(); - return TransformedItemStack.of(position, isSlim ? slimOffset : offset, isSlim ? slimScale : scale, BetterModel.nms().createPlayerHead(profile)); + return skinMapper.apply(context.skin(), context.source() instanceof Profiled profiled ? profiled.armors() : PlayerArmor.EMPTY); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index 1d8071ec0..f3714bcaf 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -60,18 +60,6 @@ public record MinecraftVersion(int major, int minor, int patch) implements Compa * 1.21.4 */ public static final MinecraftVersion V1_21_4 = of(1, 21, 4); - /** - * 1.21.2 - */ - public static final MinecraftVersion V1_21_2 = of(1, 21, 2); - /** - * 1.21.1 - */ - public static final MinecraftVersion V1_21_1 = of(1, 21, 1); - /** - * 1.21 - */ - public static final MinecraftVersion V1_21 = of(1, 21, 0); /** * Comparator @@ -118,14 +106,6 @@ public boolean useModernResource() { return isGreaterOrEquals(V1_21_4); } - /** - * Checks this version should be use item model namespace. - * @return use item model namespace. - */ - public boolean useItemModelName() { - return isGreaterOrEquals(V1_21_2); - } - @Override public int compareTo(@NotNull MinecraftVersion o) { return COMPARATOR.compare(this, o); diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index f5325e7f4..e376d30e1 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -14,8 +14,6 @@ val LATEST_VERSION = listOf( val SUPPORTED_VERSIONS = buildList { addAll(listOf( - "1.21", - "1.21.1", "1.21.4", "1.21.5", "1.21.6", diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index 3a433cc74..fb940e2e8 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -47,7 +47,6 @@ internal class BetterModelProperties( V1_21_6, V1_21_7, V1_21_8 -> kr.toxicity.model.bukkit.nms.v1_21_R5.NMSImpl() V1_21_5 -> kr.toxicity.model.bukkit.nms.v1_21_R4.NMSImpl() V1_21_4 -> kr.toxicity.model.bukkit.nms.v1_21_R3.NMSImpl() - V1_21, V1_21_1 -> kr.toxicity.model.bukkit.nms.v1_21_R1.NMSImpl() else if BetterModelBukkit.IS_PAPER -> { warn( "Note: this version is officially untested.".toComponent(), diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt index bd7767877..f5842ceaf 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/SkinManagerImpl.kt @@ -23,7 +23,6 @@ import kr.toxicity.model.api.profile.ModelProfile import kr.toxicity.model.api.profile.ModelProfileInfo import kr.toxicity.model.api.skin.SkinData import kr.toxicity.model.api.util.TransformedItemStack -import kr.toxicity.model.api.version.MinecraftVersion import kr.toxicity.model.util.* import org.joml.Vector3f import java.awt.image.BufferedImage @@ -677,8 +676,6 @@ object SkinManagerImpl : SkinManager, GlobalManager { } } - override fun supported(): Boolean = PLATFORM.version() >= MinecraftVersion.V1_21_4 - private fun handleExpiration(key: UUID, skin: SkinDataImpl) { skin.profile().let { if (!callEvent { RemovePlayerSkinEvent(it) } || it.playerEquals()) profileCache.put(key, skin) @@ -832,15 +829,10 @@ object SkinManagerImpl : SkinManager, GlobalManager { "player_limb" ) if (!CONFIG.module().playerAnimation) return - if (supported()) write { resource -> + write { resource -> zipper.modern().add(resource.path(), resource.estimatedSize()) { resource.build() } - } else PLATFORM.loadAssets(pipeline, "pack") { s, i -> - val read = i.readAllBytes() - zipper.legacy().add(s) { - read - } } profileCache.asMap().entries.forEach { it.value.refresh() diff --git a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.fsh b/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.fsh deleted file mode 100644 index 8e90554b6..000000000 --- a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.fsh +++ /dev/null @@ -1,47 +0,0 @@ -#version 150 - -#moj_import - -uniform sampler2D Sampler0; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform mat3 IViewRotMat; - -uniform vec4 ColorModulator; -uniform float FogStart; -uniform float FogEnd; -uniform vec4 FogColor; - -in float vertexDistance; -in vec4 vertexColor; -in vec4 lightMapColor; -in vec4 overlayColor; -in vec2 texCoord0; -in vec2 texCoord1; -in vec4 normal; -in float part; - -out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1 || abs(mod(part + 0.5, 1.0) - 0.5) > 0.001) { - discard; - } - if (color.a < 1.0 && part > 0.5) { - vec4 color2 = texture(Sampler0, texCoord1); - if (color.a < 0.75 && int(gl_FragCoord.x + gl_FragCoord.y) % 2 == 0) { - discard; - } - else { - color.rgb = mix(color2.rgb, color.rgb, min(1.0, color.a * 2)); - color.a = 1.0; - } - } - - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.json b/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.json deleted file mode 100644 index e08490d74..000000000 --- a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.json +++ /dev/null @@ -1,39 +0,0 @@ -{ - "blend": { - "func": "add", - "srcrgb": "srcalpha", - "dstrgb": "1-srcalpha" - }, - "vertex": "rendertype_entity_translucent", - "fragment": "rendertype_entity_translucent", - "attributes": [ - "Position", - "Color", - "UV0", - "UV1", - "UV2", - "Normal" - ], - "defines": { - "values": { - "ALPHA_CUTOUT": "0.1" - } - }, - "samplers": [ - { "name": "Sampler0" }, - { "name": "Sampler1" }, - { "name": "Sampler2" } - ], - "uniforms": [ - { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ] }, - { "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] }, - { "name": "Light0_Direction", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] }, - { "name": "Light1_Direction", "type": "float", "count": 3, "values": [ 0.0, 0.0, 0.0 ] }, - { "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] }, - { "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] }, - { "name": "FogColor", "type": "float", "count": 4,"values": [ 0.0, 0.0, 0.0, 0.0 ]}, - { "name": "FogShape", "type": "int", "count": 1, "values": [ 0 ] } - ] -} diff --git a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.vsh b/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.vsh deleted file mode 100644 index 3e80c8a18..000000000 --- a/core/src/main/resources/pack/assets/minecraft/shaders/core/rendertype_entity_translucent.vsh +++ /dev/null @@ -1,233 +0,0 @@ -#version 150 - -#moj_import - -in vec3 Position; -in vec4 Color; -in vec2 UV0; -in ivec2 UV1; -in ivec2 UV2; -in vec3 Normal; - -uniform sampler2D Sampler0; -uniform sampler2D Sampler1; -uniform sampler2D Sampler2; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform mat3 IViewRotMat; - -uniform vec3 Light0_Direction; -uniform vec3 Light1_Direction; - -uniform int FogShape; - -out float vertexDistance; -out vec4 vertexColor; -out vec4 lightMapColor; -out vec4 overlayColor; -out vec2 texCoord0; -out vec2 texCoord1; -out vec4 normal; -out float part; - -#define SPACING 512.0 -#define MAXRANGE (0.5 * SPACING) -#define SKINRES 64 -#define FACERES 8 - -const vec4[] subuvs = vec4[]( -vec4(4.0, 0.0, 8.0, 4.0 ), // 4x4x12 -vec4(8.0, 0.0, 12.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 8.0, 16.0), -vec4(8.0, 4.0, 12.0, 16.0), -vec4(12.0, 4.0, 16.0, 16.0), -vec4(4.0, 0.0, 7.0, 4.0 ), // 4x3x12 -vec4(7.0, 0.0, 10.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 7.0, 16.0), -vec4(7.0, 4.0, 11.0, 16.0), -vec4(11.0, 4.0, 14.0, 16.0), -vec4(4.0, 0.0, 12.0, 4.0 ), // 4x8x12 -vec4(12.0, 0.0, 20.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 12.0, 16.0), -vec4(12.0, 4.0, 16.0, 16.0), -vec4(16.0, 4.0, 24.0, 16.0) -); - -const vec2[] origins = vec2[]( -vec2(40.0, 16.0), // right arm -vec2(40.0, 32.0), - -vec2(40.0, 16.0), // right arm -vec2(40.0, 32.0), - -vec2(32.0, 48.0), // left arm -vec2(48.0, 48.0), - -vec2(32.0, 48.0), // left arm -vec2(48.0, 48.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(0.0, 16.0), // right leg -vec2(0.0, 32.0), - -vec2(0.0, 16.0), // right leg -vec2(0.0, 32.0), - -vec2(16.0, 48.0), // left leg -vec2(0.0, 48.0), - -vec2(16.0, 48.0), // left leg -vec2(0.0, 48.0) -); - -const int[] faceremap = int[](0, 0, 1, 1, 2, 3, 4, 5); - -float fog_distance(vec3 pos, int shape) { - if (shape == 0) { - return length(pos); - } else { - float distXZ = length(pos.xz); - float distY = abs(pos.y); - return max(distXZ, distY); - } -} - - -void main() { - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, normalize(Normal), Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - normal = ProjMat * ModelViewMat * vec4(Normal, 0.0); - - vec3 wpos = IViewRotMat * Position; - ivec2 dim = textureSize(Sampler0, 0); - - if (ProjMat[2][3] == 0.0 || dim.x != 64 || dim.y != 64) { // short circuit if cannot be player - part = 0.0; - texCoord0 = UV0; - texCoord1 = vec2(0.0); - vertexDistance = fog_distance(IViewRotMat * Position, FogShape); - gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); - } - else if (length(inverse(ModelViewMat)[3].xyz - wpos) < 0.75) { - part = 0.0; - texCoord0 = UV0; - texCoord1 = UV1; - vertexDistance = 0; - vertexColor = vec4(0); - gl_Position = ProjMat * ModelViewMat * vec4(Position, 0.0); - } - else { - vec2 UVout = UV0; - vec2 UVout2 = vec2(0.0); - int partId = -int((wpos.y - MAXRANGE) / SPACING); - - part = float(partId); - - if (partId == 0) { // higher precision position if no translation is needed - gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); - } - else { - vec4 samp1 = texture(Sampler0, vec2(54.0 / 64.0, 20.0 / 64.0)); - vec4 samp2 = texture(Sampler0, vec2(55.0 / 64.0, 20.0 / 64.0)); - bool slim = samp1.a == 0.0 || (((samp1.r + samp1.g + samp1.b) == 0.0) && ((samp2.r + samp2.g + samp2.b) == 0.0) && samp1.a == 1.0 && samp2.a == 1.0); - int outerLayer = (gl_VertexID / 24) % 2; - int vertexId = gl_VertexID % 4; - int faceId = (gl_VertexID % 24) / 4; - ivec2 faceIdTmp = ivec2(round(UV0 * SKINRES)); - if ((faceId != 1 && vertexId >= 2) || (faceId == 1 && vertexId <= 1)) { - faceIdTmp.y -= FACERES; - } - if (vertexId == 0 || vertexId == 3) { - faceIdTmp.x -= FACERES; - } - faceIdTmp /= FACERES; - faceId = (faceIdTmp.x % 4) + 4 * faceIdTmp.y; - faceId = faceremap[faceId]; - int subuvIndex = faceId; - - wpos.y += SPACING * partId; - gl_Position = ProjMat * ModelViewMat * vec4(inverse(IViewRotMat) * wpos, 1.0); - - UVout = origins[2 * (partId - 1) + outerLayer]; - UVout2 = origins[2 * (partId - 1)]; - - bool isBody = (partId >= 5 && partId <= 7); - bool isLeg = (partId >= 8); - - if (slim && (partId >= 1 && partId <= 4)) { - subuvIndex += 6; - } - else if (isBody) { - subuvIndex += 12; - } - - vec4 subuv = vec4(subuvs[subuvIndex]); - if (faceId > 1) { - if (isBody) { - float t = (subuv.w - subuv.y) / 3.0; - int partIdKey = (partId - 5) % 3; - subuv.y += t * (2 - partIdKey); - subuv.w -= t * partIdKey; - } else { - if (((partId + (isLeg ? 1 : 0)) % 2) == 0) { - subuv.y = (subuv.w + subuv.y) / 2; - } else { - subuv.w = (subuv.w + subuv.y) / 2; - } - } - } - - vec2 offset = vec2(0.0); - if (faceId == 1) { - if (vertexId == 0) { - offset += subuv.zw; - } - else if (vertexId == 1) { - offset += subuv.xw; - } - else if (vertexId == 2) { - offset += subuv.xy; - } - else { - offset += subuv.zy; - } - } - else { - if (vertexId == 0) { - offset += subuv.zy; - } - else if (vertexId == 1) { - offset += subuv.xy; - } - else if (vertexId == 2) { - offset += subuv.xw; - } - else { - offset += subuv.zw; - } - } - - UVout += offset; - UVout2 += offset; - UVout /= float(SKINRES); - UVout2 /= float(SKINRES); - } - - vertexDistance = fog_distance(wpos, FogShape); - texCoord0 = UVout; - texCoord1 = UVout2; - } -} \ No newline at end of file diff --git a/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.fsh b/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.fsh deleted file mode 100644 index 8e90554b6..000000000 --- a/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.fsh +++ /dev/null @@ -1,47 +0,0 @@ -#version 150 - -#moj_import - -uniform sampler2D Sampler0; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform mat3 IViewRotMat; - -uniform vec4 ColorModulator; -uniform float FogStart; -uniform float FogEnd; -uniform vec4 FogColor; - -in float vertexDistance; -in vec4 vertexColor; -in vec4 lightMapColor; -in vec4 overlayColor; -in vec2 texCoord0; -in vec2 texCoord1; -in vec4 normal; -in float part; - -out vec4 fragColor; - -void main() { - vec4 color = texture(Sampler0, texCoord0); - if (color.a < 0.1 || abs(mod(part + 0.5, 1.0) - 0.5) > 0.001) { - discard; - } - if (color.a < 1.0 && part > 0.5) { - vec4 color2 = texture(Sampler0, texCoord1); - if (color.a < 0.75 && int(gl_FragCoord.x + gl_FragCoord.y) % 2 == 0) { - discard; - } - else { - color.rgb = mix(color2.rgb, color.rgb, min(1.0, color.a * 2)); - color.a = 1.0; - } - } - - color *= vertexColor * ColorModulator; - color.rgb = mix(overlayColor.rgb, color.rgb, overlayColor.a); - color *= lightMapColor; - fragColor = linear_fog(color, vertexDistance, FogStart, FogEnd, FogColor); -} diff --git a/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.vsh b/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.vsh deleted file mode 100644 index 3e80c8a18..000000000 --- a/core/src/main/resources/pack/assets/minecraft/shaders/rendertype_entity_translucent.vsh +++ /dev/null @@ -1,233 +0,0 @@ -#version 150 - -#moj_import - -in vec3 Position; -in vec4 Color; -in vec2 UV0; -in ivec2 UV1; -in ivec2 UV2; -in vec3 Normal; - -uniform sampler2D Sampler0; -uniform sampler2D Sampler1; -uniform sampler2D Sampler2; - -uniform mat4 ModelViewMat; -uniform mat4 ProjMat; -uniform mat3 IViewRotMat; - -uniform vec3 Light0_Direction; -uniform vec3 Light1_Direction; - -uniform int FogShape; - -out float vertexDistance; -out vec4 vertexColor; -out vec4 lightMapColor; -out vec4 overlayColor; -out vec2 texCoord0; -out vec2 texCoord1; -out vec4 normal; -out float part; - -#define SPACING 512.0 -#define MAXRANGE (0.5 * SPACING) -#define SKINRES 64 -#define FACERES 8 - -const vec4[] subuvs = vec4[]( -vec4(4.0, 0.0, 8.0, 4.0 ), // 4x4x12 -vec4(8.0, 0.0, 12.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 8.0, 16.0), -vec4(8.0, 4.0, 12.0, 16.0), -vec4(12.0, 4.0, 16.0, 16.0), -vec4(4.0, 0.0, 7.0, 4.0 ), // 4x3x12 -vec4(7.0, 0.0, 10.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 7.0, 16.0), -vec4(7.0, 4.0, 11.0, 16.0), -vec4(11.0, 4.0, 14.0, 16.0), -vec4(4.0, 0.0, 12.0, 4.0 ), // 4x8x12 -vec4(12.0, 0.0, 20.0, 4.0 ), -vec4(0.0, 4.0, 4.0, 16.0), -vec4(4.0, 4.0, 12.0, 16.0), -vec4(12.0, 4.0, 16.0, 16.0), -vec4(16.0, 4.0, 24.0, 16.0) -); - -const vec2[] origins = vec2[]( -vec2(40.0, 16.0), // right arm -vec2(40.0, 32.0), - -vec2(40.0, 16.0), // right arm -vec2(40.0, 32.0), - -vec2(32.0, 48.0), // left arm -vec2(48.0, 48.0), - -vec2(32.0, 48.0), // left arm -vec2(48.0, 48.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(16.0, 16.0), // hip -vec2(16.0, 32.0), - -vec2(0.0, 16.0), // right leg -vec2(0.0, 32.0), - -vec2(0.0, 16.0), // right leg -vec2(0.0, 32.0), - -vec2(16.0, 48.0), // left leg -vec2(0.0, 48.0), - -vec2(16.0, 48.0), // left leg -vec2(0.0, 48.0) -); - -const int[] faceremap = int[](0, 0, 1, 1, 2, 3, 4, 5); - -float fog_distance(vec3 pos, int shape) { - if (shape == 0) { - return length(pos); - } else { - float distXZ = length(pos.xz); - float distY = abs(pos.y); - return max(distXZ, distY); - } -} - - -void main() { - vertexColor = minecraft_mix_light(Light0_Direction, Light1_Direction, normalize(Normal), Color); - lightMapColor = texelFetch(Sampler2, UV2 / 16, 0); - overlayColor = texelFetch(Sampler1, UV1, 0); - normal = ProjMat * ModelViewMat * vec4(Normal, 0.0); - - vec3 wpos = IViewRotMat * Position; - ivec2 dim = textureSize(Sampler0, 0); - - if (ProjMat[2][3] == 0.0 || dim.x != 64 || dim.y != 64) { // short circuit if cannot be player - part = 0.0; - texCoord0 = UV0; - texCoord1 = vec2(0.0); - vertexDistance = fog_distance(IViewRotMat * Position, FogShape); - gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); - } - else if (length(inverse(ModelViewMat)[3].xyz - wpos) < 0.75) { - part = 0.0; - texCoord0 = UV0; - texCoord1 = UV1; - vertexDistance = 0; - vertexColor = vec4(0); - gl_Position = ProjMat * ModelViewMat * vec4(Position, 0.0); - } - else { - vec2 UVout = UV0; - vec2 UVout2 = vec2(0.0); - int partId = -int((wpos.y - MAXRANGE) / SPACING); - - part = float(partId); - - if (partId == 0) { // higher precision position if no translation is needed - gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); - } - else { - vec4 samp1 = texture(Sampler0, vec2(54.0 / 64.0, 20.0 / 64.0)); - vec4 samp2 = texture(Sampler0, vec2(55.0 / 64.0, 20.0 / 64.0)); - bool slim = samp1.a == 0.0 || (((samp1.r + samp1.g + samp1.b) == 0.0) && ((samp2.r + samp2.g + samp2.b) == 0.0) && samp1.a == 1.0 && samp2.a == 1.0); - int outerLayer = (gl_VertexID / 24) % 2; - int vertexId = gl_VertexID % 4; - int faceId = (gl_VertexID % 24) / 4; - ivec2 faceIdTmp = ivec2(round(UV0 * SKINRES)); - if ((faceId != 1 && vertexId >= 2) || (faceId == 1 && vertexId <= 1)) { - faceIdTmp.y -= FACERES; - } - if (vertexId == 0 || vertexId == 3) { - faceIdTmp.x -= FACERES; - } - faceIdTmp /= FACERES; - faceId = (faceIdTmp.x % 4) + 4 * faceIdTmp.y; - faceId = faceremap[faceId]; - int subuvIndex = faceId; - - wpos.y += SPACING * partId; - gl_Position = ProjMat * ModelViewMat * vec4(inverse(IViewRotMat) * wpos, 1.0); - - UVout = origins[2 * (partId - 1) + outerLayer]; - UVout2 = origins[2 * (partId - 1)]; - - bool isBody = (partId >= 5 && partId <= 7); - bool isLeg = (partId >= 8); - - if (slim && (partId >= 1 && partId <= 4)) { - subuvIndex += 6; - } - else if (isBody) { - subuvIndex += 12; - } - - vec4 subuv = vec4(subuvs[subuvIndex]); - if (faceId > 1) { - if (isBody) { - float t = (subuv.w - subuv.y) / 3.0; - int partIdKey = (partId - 5) % 3; - subuv.y += t * (2 - partIdKey); - subuv.w -= t * partIdKey; - } else { - if (((partId + (isLeg ? 1 : 0)) % 2) == 0) { - subuv.y = (subuv.w + subuv.y) / 2; - } else { - subuv.w = (subuv.w + subuv.y) / 2; - } - } - } - - vec2 offset = vec2(0.0); - if (faceId == 1) { - if (vertexId == 0) { - offset += subuv.zw; - } - else if (vertexId == 1) { - offset += subuv.xw; - } - else if (vertexId == 2) { - offset += subuv.xy; - } - else { - offset += subuv.zy; - } - } - else { - if (vertexId == 0) { - offset += subuv.zy; - } - else if (vertexId == 1) { - offset += subuv.xy; - } - else if (vertexId == 2) { - offset += subuv.xw; - } - else { - offset += subuv.zw; - } - } - - UVout += offset; - UVout2 += offset; - UVout /= float(SKINRES); - UVout2 /= float(SKINRES); - } - - vertexDistance = fog_distance(wpos, FogShape); - texCoord0 = UVout; - texCoord1 = UVout2; - } -} \ No newline at end of file diff --git a/nms/v1_21_R1/build.gradle.kts b/nms/v1_21_R1/build.gradle.kts deleted file mode 100644 index 7daf61085..000000000 --- a/nms/v1_21_R1/build.gradle.kts +++ /dev/null @@ -1,18 +0,0 @@ -import org.jetbrains.kotlin.gradle.dsl.JvmTarget - -plugins { - alias(libs.plugins.convention.paperweight) -} - -dependencies { - paperweight.paperDevBundle("1.21.1-R0.1-SNAPSHOT") -} - -tasks { - compileJava { - options.release = 21 - } - compileKotlin { - compilerOptions.jvmTarget = JvmTarget.JVM_21 - } -} diff --git a/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java b/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java deleted file mode 100644 index 97be180a3..000000000 --- a/nms/v1_21_R1/src/main/java/kr/toxicity/model/bukkit/nms/v1_21_R1/AbstractHitBox.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1; - -import kr.toxicity.model.api.nms.HitBox; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.decoration.ArmorStand; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public abstract class AbstractHitBox extends ArmorStand implements HitBox { - - AbstractHitBox(@NotNull Level level) { - super(EntityType.ARMOR_STAND, level); - } - - @Override //Only for provide compiler hint for Kotlin jvm - public final boolean equals(@Nullable Object other) { - return super.equals(other); - } - - @Override //Only for provide compiler hint for Kotlin jvm - public final int hashCode() { - return super.hashCode(); - } - - @SuppressWarnings("removal") - @Override - public void remove(@NotNull RemovalReason reason, @Nullable org.bukkit.event.entity.EntityRemoveEvent.Cause eventCause) { - super.remove(reason, eventCause); - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt deleted file mode 100644 index d1d842a12..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BaseEntityImpl.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity -import kr.toxicity.model.api.platform.PlatformEntity -import kr.toxicity.model.api.platform.PlatformLocation -import kr.toxicity.model.api.platform.PlatformPlayer -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.effect.MobEffects -import net.minecraft.world.entity.Entity -import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.ai.attributes.Attributes -import org.bukkit.craftbukkit.entity.CraftEntity -import org.bukkit.persistence.PersistentDataHolder -import org.joml.Vector3f -import java.util.* -import java.util.stream.Stream - -internal data class BaseEntityImpl( - private val delegate: CraftEntity -) : BaseBukkitEntity, PersistentDataHolder by delegate { - override fun customName(): AdventureComponent? = handle().run { - if (this is ServerPlayer) (customName ?: name).asAdventure() else customName?.asAdventure()?.takeIf { - isCustomNameVisible - } - } - - override fun entity(): org.bukkit.entity.Entity = delegate - override fun handle(): Entity = delegate.vanillaEntity - override fun uuid(): UUID = delegate.uniqueId - override fun id(): Int = handle().id - override fun dead(): Boolean = (handle() as? LivingEntity)?.isDeadOrDying == true || handle().removalReason != null || !handle().valid - override fun invisible(): Boolean = handle().isInvisible || (handle() as? LivingEntity)?.hasEffect(MobEffects.INVISIBILITY) == true - override fun glow(): Boolean = handle().isCurrentlyGlowing - - override fun onWalk(): Boolean { - return handle().isWalking() - } - - override fun scale(): Double { - val handle = handle() - return if (handle is LivingEntity) handle.scale.toDouble() else 1.0 - } - - override fun pitch(): Float = handle().xRot - override fun ground(): Boolean = handle().onGround() - override fun bodyYaw(): Float = handle().let { if (it is LivingEntity) it.yBodyRot else it.yRot } - override fun yaw(): Float = handle().yRot - override fun headYaw(): Float = handle().let { if (it is LivingEntity) it.yHeadRot else it.yRot } - override fun fly(): Boolean = handle().isFlying - - override fun damageTick(): Float { - val handle = handle() - if (handle !is LivingEntity) return 0F - val duration = handle.invulnerableDuration.toFloat() - if (duration <= 0F) return 0F - val knockBack = 1 - (handle.getAttribute(Attributes.KNOCKBACK_RESISTANCE)?.value?.toFloat() ?: 0F) - return handle.invulnerableTime.toFloat() / duration * knockBack - } - - override fun walkSpeed(): Float { - val handle = handle() - if (handle !is LivingEntity) return 0F - if (!handle.onGround) return 1F - val speed = handle.getEffect(MobEffects.MOVEMENT_SPEED)?.amplifier ?: 0 - val slow = handle.getEffect(MobEffects.MOVEMENT_SLOWDOWN)?.amplifier ?: 0 - return (1F + (speed - slow) * 0.2F) - .coerceAtLeast(0.2F) - .coerceAtMost(2F) - } - - override fun passengerPosition(dest: Vector3f): Vector3f { - return handle().passengerPosition(dest) - } - - override fun platform(): PlatformEntity = delegate.wrap() - override fun trackedBy(): Stream = delegate.trackedBy.stream().map { it.wrap() } - override fun location(): PlatformLocation = delegate.location.wrap() -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt deleted file mode 100644 index 173edf87a..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BasePlayerImpl.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.armor.PlayerArmor -import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity -import kr.toxicity.model.api.bukkit.entity.BaseBukkitPlayer -import kr.toxicity.model.api.nms.Profiled -import kr.toxicity.model.api.platform.PlatformPlayer -import kr.toxicity.model.api.player.PlayerSkinParts -import kr.toxicity.model.api.profile.ModelProfile -import net.minecraft.util.Mth -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.entity.Player -import java.util.stream.Stream - -internal data class BasePlayerImpl( - private val delegate: CraftPlayer, - private val profile: () -> ModelProfile, - private val skinParts: () -> PlayerSkinParts -) : BaseBukkitEntity by BaseEntityImpl(delegate), BaseBukkitPlayer, Profiled by ProfiledImpl(PlayerArmor.EMPTY, profile, skinParts) { - - override fun entity(): Player = delegate - - override fun updateInventory() { - delegate.handle.containerMenu.sendAllDataToRemote() - } - - override fun platform(): PlatformPlayer = delegate.wrap() - - override fun trackedBy(): Stream = Stream.concat( - Stream.of(delegate), - delegate.trackedBy.stream() - ).map { - it.wrap() - } - - override fun bodyYaw(): Float { - val handle = delegate.handle - var yaw = -45 * handle.xMovement() - if (handle.zMovement() < 0) yaw *= -1 - return Mth.wrapDegrees(handle.yHeadRot + yaw) - } -} - diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt deleted file mode 100644 index 0751f3ffc..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/BukkitWrappers.kt +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* -import kr.toxicity.model.api.bukkit.platform.* -import kr.toxicity.model.api.bukkit.platform.BukkitItemStack -import kr.toxicity.model.api.platform.* -import org.bukkit.Location -import org.bukkit.OfflinePlayer -import org.bukkit.World -import org.bukkit.entity.Entity -import org.bukkit.entity.LivingEntity -import org.bukkit.entity.Player -import org.bukkit.inventory.ItemStack - -internal fun Entity.wrap() = adapt(this) -internal fun LivingEntity.wrap() = adapt(this) -internal fun OfflinePlayer.wrap() = adapt(this) -internal fun Player.wrap() = adapt(this) -internal fun Location.wrap() = adapt(this) -internal fun World.wrap() = adapt(this) -internal fun ItemStack.wrap() = adapt(this) - -internal fun PlatformEntity.unwarp(): Entity = (this as BukkitEntity).source() -internal fun PlatformLivingEntity.unwarp(): LivingEntity = (this as BukkitLivingEntity).source() -internal fun PlatformOfflinePlayer.unwarp(): OfflinePlayer = (this as BukkitOfflinePlayer).source() -internal fun PlatformPlayer.unwarp(): Player = (this as BukkitPlayer).source() -internal fun PlatformLocation.unwarp(): Location = (this as BukkitLocation).source() -internal fun PlatformWorld.unwarp(): World = (this as BukkitWorld).source() -internal fun PlatformItemStack.unwarp(): ItemStack = (this as BukkitItemStack).source() diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt deleted file mode 100644 index f22dd86c1..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/EntityData.kt +++ /dev/null @@ -1,126 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.nms.AnimationBundler -import kr.toxicity.model.api.util.MathUtil -import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket -import net.minecraft.network.syncher.EntityDataAccessor -import net.minecraft.network.syncher.SynchedEntityData -import net.minecraft.world.entity.Display -import net.minecraft.world.entity.Display.ItemDisplay -import net.minecraft.world.entity.Entity -import org.joml.Quaternionf -import org.joml.Vector3f -import java.lang.reflect.Field - -internal fun Field.toEntityDataAccessor() = run { - isAccessible = true - get(null) as EntityDataAccessor<*> -} - -internal fun Class<*>.accessors() = declaredFields.filter { f -> - EntityDataAccessor::class.java.isAssignableFrom(f.type) -}.map { - it.toEntityDataAccessor() -} - -internal val DISPLAY_SET = Display::class.java.accessors() -internal val SHARED_FLAG = Entity::class.java.accessors().first().id -internal val ITEM_DISPLAY_ID = ItemDisplay::class.java.accessors().map { - it.id -} -internal val ITEM_SERIALIZER = ItemDisplay::class.java.accessors().first() -internal val ITEM_ENTITY_DATA = buildList { - add(SHARED_FLAG) - addAll(ITEM_DISPLAY_ID) - add(Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID.id) - DISPLAY_SET.subList(7, DISPLAY_SET.size).mapTo(this) { it.id } -}.toIntSet() - -@Suppress("UNCHECKED_CAST") -private val DISPLAY_INTERPOLATION_DELAY = (DISPLAY_SET.first() as EntityDataAccessor).run { - SynchedEntityData.DataValue(id, serializer, 0) -} -@Suppress("UNCHECKED_CAST") -internal val DISPLAY_INTERPOLATION_DURATION = DISPLAY_SET[1] as EntityDataAccessor -@Suppress("UNCHECKED_CAST") -internal val DISPLAY_TRANSLATION = DISPLAY_SET[3] as EntityDataAccessor -@Suppress("UNCHECKED_CAST") -internal val DISPLAY_SCALE = DISPLAY_SET[4] as EntityDataAccessor -@Suppress("UNCHECKED_CAST") -internal val DISPLAY_ROTATION = DISPLAY_SET[5] as EntityDataAccessor - - -internal class TransformationData { - - private var _duration = 0 - private val duration get() = SynchedEntityData.DataValue(DISPLAY_INTERPOLATION_DURATION.id, DISPLAY_INTERPOLATION_DURATION.serializer, _duration) - private val translation = Item(Vector3f(), DISPLAY_TRANSLATION, MathUtil::isSimilar, Vector3f::set) - private val scale = Item(Vector3f(), DISPLAY_SCALE, MathUtil::isSimilar, Vector3f::set) - private val rotation = Item(Quaternionf(), DISPLAY_ROTATION, MathUtil::isSimilar, Quaternionf::set) - - fun packDirty(entityId: Int, dest: AnimationBundler) { - val i = translation.cleanIndex + scale.cleanIndex + rotation.cleanIndex - if (i == 0) return - (dest.mod as ModAnimationBundlerImpl).append(entityId) { - dest.standard += ClientboundSetEntityDataPacket(entityId, buildList(i + 2) { - add(DISPLAY_INTERPOLATION_DELAY) - translation.value?.let { appendPosition(it.value); add(it) } - rotation.value?.let { appendRotation(it.value); add(it) } - scale.value?.let { appendScale(it.value); add(it) } - appendDuration(_duration); add(duration) - }) - } - } - - fun transform( - duration: Int, - translation: Vector3f, - scale: Vector3f, - rotation: Quaternionf - ) { - _duration = duration - this.translation.set(translation) - this.scale.set(scale) - this.rotation.set(rotation) - } - - fun pack() = listOf( - DISPLAY_INTERPOLATION_DELAY, - duration, - translation.forceValue, - scale.forceValue, - rotation.forceValue - ) - - private class Item( - initialValue: T, - private val accessor: EntityDataAccessor, - private val dirtyChecker: (T, T) -> Boolean, - private val setter: (T, T) -> Unit - ) { - private val _t: T = initialValue - private var _dirty = false - - val dirty get() = _dirty - val cleanIndex get() = if (dirty) 1 else 0 - val value get() = if (_dirty) { - _dirty = false - forceValue - } else null - val forceValue get() = SynchedEntityData.DataValue(accessor.id, accessor.serializer, _t) - - fun set(other: T) { - if (dirtyChecker(_t, other)) return - _dirty = true - setter(_t, other) - } - } -} - diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt deleted file mode 100644 index cbf8428bb..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/Functions.kt +++ /dev/null @@ -1,207 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import io.netty.buffer.Unpooled -import io.papermc.paper.adventure.PaperAdventure -import io.papermc.paper.configuration.GlobalConfiguration -import it.unimi.dsi.fastutil.ints.IntSet -import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.bukkit.BetterModelBukkit -import kr.toxicity.model.api.tracker.EntityTrackerRegistry -import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer -import net.minecraft.network.FriendlyByteBuf -import net.minecraft.network.protocol.game.ClientboundAddEntityPacket -import net.minecraft.network.protocol.game.ClientboundContainerSetSlotPacket -import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket -import net.minecraft.network.syncher.SynchedEntityData -import net.minecraft.network.syncher.SynchedEntityData.DataItem -import net.minecraft.network.syncher.SynchedEntityData.DataValue -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.entity.* -import net.minecraft.world.entity.ai.goal.RangedAttackGoal -import net.minecraft.world.entity.ai.goal.RangedBowAttackGoal -import net.minecraft.world.entity.ai.goal.RangedCrossbowAttackGoal -import net.minecraft.world.entity.animal.FlyingAnimal -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemStack -import net.minecraft.world.phys.Vec3 -import org.bukkit.Bukkit -import org.bukkit.craftbukkit.entity.CraftEntity -import org.bukkit.craftbukkit.inventory.CraftItemStack -import org.bukkit.craftbukkit.util.CraftChatMessage -import org.joml.Vector3f -import java.util.* - -internal inline fun createAdaptedFieldGetter(noinline paperGetter: (T) -> R): (T) -> R { - return if (BetterModelBukkit.IS_PAPER) paperGetter else createAdaptedFieldGetter() -} -internal inline fun createAdaptedFieldGetter(): (T) -> R { - return T::class.java.declaredFields.first { - R::class.java.isAssignableFrom(it.type) - }.apply { - isAccessible = true - }.let { getter -> - { t -> - getter[t] as R - } - } -} - -internal fun dirtyChecked(hash: () -> H, function: (H) -> T, equalityChecker: (H, H) -> Boolean = { a, b -> a == b }): () -> T { - val lock = Any() - var h = hash() - var value = function(h) - return { - val newH = hash() - if (equalityChecker(h, newH)) value else synchronized(lock) { - h = newH - value = function(h) - value - } - } -} - -internal val CONFIG get() = BetterModel.config() -internal val EMPTY_ITEM = VanillaItemStack.EMPTY -internal fun BukkitItemStack.asVanilla() = CraftItemStack.asNMSCopy(this) -internal fun VanillaItemStack.asBukkit() = CraftItemStack.asCraftMirror(this) - -internal val ONLINE_MODE by lazy(LazyThreadSafetyMode.NONE) { - if (BetterModelBukkit.IS_PAPER) GlobalConfiguration.get().proxies.isProxyOnlineMode else Bukkit.getOnlineMode() -} - -internal fun List.toIntSet(): IntSet = IntSet.of(*toIntArray()) - -internal fun Entity.passengerPosition(dest: Vector3f): Vector3f { - return attachments.get(EntityAttachment.PASSENGER, 0, yRot).let { v -> - dest.set(v.x.toFloat(), v.y.toFloat(), v.z.toFloat()) - } -} - -private val DATA_ITEMS = SynchedEntityData::class.java.declaredFields.first { - it.type.isArray -}.apply { - isAccessible = true -} - -internal fun SynchedEntityData.pack( - clean: Boolean = false, - itemFilter: (DataItem<*>) -> Boolean = { true }, - valueFilter: (DataValue<*>) -> Boolean = { true }, - required: (List, DataValue<*>>>) -> Boolean = { it.isNotEmpty() } -): List>? = (DATA_ITEMS[this] as Array<*>) - .mapNotNull map@ { - val item = (it as? DataItem<*>)?.takeIf(itemFilter) ?: return@map null - val value = item.value().takeIf(valueFilter) ?: return@map null - item to value - } - .takeIf(required) - ?.map { - if (clean) it.first.isDirty = false - it.second - } - -internal fun Entity.isWalking(): Boolean { - return controllingPassenger?.isWalking() ?: when (this) { - is Mob -> navigation.isInProgress || goalSelector.availableGoals.any { - it.isRunning && when (it.goal) { - is RangedAttackGoal, is RangedCrossbowAttackGoal<*>, is RangedBowAttackGoal<*> -> true - else -> false - } - } - is ServerPlayer -> xMovement() != 0F || zMovement() != 0F - else -> false - } -} - -internal fun ServerPlayer.xMovement(): Float { - return xxa -} - -internal fun ServerPlayer.yMovement(): Float = if (isJump()) 1F else if (isShiftKeyDown) -1F else 0F - -internal fun ServerPlayer.zMovement(): Float { - return zza -} - -internal fun ServerPlayer.isJump() = jumping - -internal val Entity.isFlying: Boolean - get() = when (this) { - is FlyingAnimal -> isFlying - is FlyingMob -> true - is Mob -> isNoAi - is Player -> abilities.flying - is LivingEntity -> isFallFlying - else -> false - } - -internal val CraftEntity.vanillaEntity: Entity - get() = if (BetterModelBukkit.IS_PAPER) handleRaw else handle - -internal inline fun useByteBuf(block: (FriendlyByteBuf) -> T): T { - val buffer = FriendlyByteBuf(Unpooled.buffer()) - return try { - block(buffer) - } finally { - buffer.release() - } -} - -internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { - var b = byte.toInt() - val hideOption = hideOption(uuid) - if (hideOption.fire()) b = b and 1.inv() - if (hideOption.visibility()) b = b or (1 shl 5) - if (hideOption.glowing()) b = b and (1 shl 6).inv() - return b.toByte() -} - -internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) -internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) - -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { - val equip = EquipmentSlot.entries.mapNotNull { - mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } - } - return if (equip.isNotEmpty()) ClientboundSetEquipmentPacket(id, equip) else null -} -internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } - -internal val Player.hotbarSlot get() = inventory.selected + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) -internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) - -internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( - id, - uuid, - x, - y, - z, - xRot, - yRot, - EntityType.ITEM_DISPLAY, - 0, - deltaMovement, - yHeadRot.toDouble() -) - -internal fun Player.toCustomisation() = entityData.get(Player.DATA_PLAYER_MODE_CUSTOMISATION).toInt() - -internal fun VanillaComponent.asAdventure() = if (BetterModelBukkit.IS_PAPER) { - PaperAdventure.asAdventure(this) -} else { - GsonComponentSerializer.gson().deserialize(CraftChatMessage.toJSON(this)) -} - -internal fun AdventureComponent.asVanilla() = if (BetterModelBukkit.IS_PAPER) { - PaperAdventure.asVanilla(this) -} else { - CraftChatMessage.fromJSON(GsonComponentSerializer.gson().serialize(this)) -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt deleted file mode 100644 index 646c6b0bd..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxImpl.kt +++ /dev/null @@ -1,445 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.bone.BoneMovement -import kr.toxicity.model.api.bone.RenderedBone -import kr.toxicity.model.api.config.DebugConfig -import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent -import kr.toxicity.model.api.mount.MountController -import kr.toxicity.model.api.nms.HitBox -import kr.toxicity.model.api.nms.HitBoxListener -import kr.toxicity.model.api.nms.ModelInteractionHand -import kr.toxicity.model.api.platform.PlatformEntity -import kr.toxicity.model.api.platform.PlatformPlayer -import net.minecraft.core.BlockPos -import net.minecraft.network.protocol.game.ServerboundInteractPacket -import net.minecraft.server.level.ServerPlayer -import net.minecraft.world.InteractionHand -import net.minecraft.world.InteractionHand.MAIN_HAND -import net.minecraft.world.InteractionHand.OFF_HAND -import net.minecraft.world.InteractionResult -import net.minecraft.world.damagesource.DamageSource -import net.minecraft.world.effect.MobEffectInstance -import net.minecraft.world.entity.* -import net.minecraft.world.entity.ai.attributes.Attributes -import net.minecraft.world.entity.player.Player -import net.minecraft.world.entity.projectile.Projectile -import net.minecraft.world.entity.projectile.ProjectileDeflection -import net.minecraft.world.item.ItemStack -import net.minecraft.world.phys.AABB -import net.minecraft.world.phys.Vec3 -import org.bukkit.Bukkit -import org.bukkit.Color -import org.bukkit.Particle -import org.bukkit.craftbukkit.CraftServer -import org.bukkit.craftbukkit.entity.CraftArmorStand -import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.event.entity.CreatureSpawnEvent -import org.bukkit.event.entity.EntityPotionEffectEvent -import org.bukkit.plugin.Plugin -import org.joml.Vector3f -import java.util.* - -internal class HitBoxImpl( - private val source: ModelBoundingBox, - private val bone: RenderedBone, - private val listener: HitBoxListener, - private val delegate: Entity, - private var mountController: MountController -) : AbstractHitBox(delegate.level()) { - private val posCache = BoneMovement() - private var initialized = false - private var jumpDelay = 0 - private var mounted = false - private var collision = ifLivingEntity { collides } == true - private var noGravity = if (delegate is Mob) delegate.isNoAi else delegate.isNoGravity - private var forceDismount = false - private var onFly = false - - val craftEntity: HitBox by lazy { - object : CraftArmorStand(Bukkit.getServer() as CraftServer, this), HitBox by this {} - } - val dimensions: EntityDimensions get() = source.run { - EntityDimensions( - (x() + z()).toFloat() / 2, - y().toFloat(), - delegate.eyeHeight, - EntityAttachments.createDefault(0F, 0F), - false - ).scale(bone.hitBoxScale()) - } - private val interaction by lazy { - HitBoxInteraction(this) - } - - init { - moveTo(delegate.position()) - isInvisible = true - persist = false - isSilent = true - initialized = true - level().addFreshEntity(this, CreatureSpawnEvent.SpawnReason.CUSTOM) - level().addFreshEntity(interaction.apply { - moveTo(delegate.position()) - }, CreatureSpawnEvent.SpawnReason.CUSTOM) - interaction.startRiding(this) - listener.handle(HitBoxCreateEvent(this)) - } - - private fun initialSetup() { - if (mounted) { - mounted = false - if (delegate is Mob) delegate.isNoAi = noGravity - else delegate.isNoGravity = noGravity - ifLivingEntity { collides = collision } - } - } - - override fun id(): Int = id - override fun uuid(): UUID = uuid - override fun source(): PlatformEntity = delegate.bukkitEntity.wrap() - override fun positionSource(): RenderedBone = bone - override fun forceDismount(): Boolean = forceDismount - override fun mountController(): MountController = mountController - override fun mountController(controller: MountController) { - this.mountController = controller - } - override fun relativePosition(): Vector3f = delegate.position().run { - bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) - } - override fun listener(): HitBoxListener = listener - - override fun getArmorSlots(): MutableIterable = mutableSetOf() - override fun hasMountDriver(): Boolean = controllingPassenger != null - override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY - override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { - } - override fun getMainArm(): HumanoidArm = HumanoidArm.RIGHT - - override fun mount(entity: PlatformEntity) { - if (controllingPassenger != null) return - if (interaction.bukkitEntity.addPassenger(entity.unwarp())) { - if (mountController.canControl()) { - mounted = true - noGravity = delegate.isNoGravity - ifLivingEntity { - collision = collides - collides = false - } - } - listener.handle(HitBoxMountEvent(this, entity)) - } - } - - override fun dismount(entity: PlatformEntity) { - forceDismount = true - if (interaction.bukkitEntity.removePassenger(entity.unwarp())) listener.handle(HitBoxDismountEvent(this, entity)) - forceDismount = false - } - - override fun dismountAll() { - forceDismount = true - interaction.passengers.forEach { - it.stopRiding(true) - listener.handle(HitBoxDismountEvent(this, it.bukkitEntity.wrap())) - } - forceDismount = false - } - - override fun setRemainingFireTicks(remainingFireTicks: Int) { - delegate.remainingFireTicks = remainingFireTicks - } - - override fun getRemainingFireTicks(): Int { - return delegate.remainingFireTicks - } - - override fun push(pushingEntity: Entity) { - if (pushingEntity === delegate) return - delegate.push(pushingEntity) - } - - override fun push(x: Double, y: Double, z: Double, pushingEntity: Entity?) { - if (pushingEntity === delegate) return - delegate.push(x, y, z, pushingEntity) - } - - override fun isCollidable(ignoreClimbing: Boolean): Boolean { - return delegate.isCollidable(ignoreClimbing) - } - - override fun canCollideWith(entity: Entity): Boolean { - return checkCollide(entity) && delegate.canCollideWith(entity) - } - - override fun canCollideWithBukkit(entity: Entity): Boolean { - return checkCollide(entity) && delegate.canCollideWithBukkit(entity) - } - - private fun checkCollide(entity: Entity): Boolean { - return entity !== delegate - && passengers.none { it === entity } - && delegate.passengers.none { it === entity } - && (entity !is HitBoxImpl || entity.delegate !== delegate) - } - - override fun getActiveEffects(): Collection { - return ifLivingEntity { getActiveEffects() } ?: emptyList() - } - - override fun getControllingPassenger(): LivingEntity? { - return if (mounted) interaction.firstPassenger as? LivingEntity ?: super.getControllingPassenger() else null - } - - override fun onWalk(): Boolean { - return isWalking() - } - - private fun mountControl(player: ServerPlayer) { - if (delegate !is LivingEntity) return - val travelVector = Vec3(delegate.xxa.toDouble(), delegate.yya.toDouble(), delegate.zza.toDouble()) - if (!mountController.canFly() && delegate.isFallFlying) return - - updateFlyStatus(player) - val riddenInput = rideInput(player, travelVector) - if (riddenInput.length() > 0.01) { - delegate.yRot = player.yRot - if (onFly) delegate.yHeadRot = player.yRot - delegate.move(MoverType.SELF, Vec3(riddenInput.x.toDouble(), riddenInput.y.toDouble(), riddenInput.z.toDouble())) - } - val dy = delegate.deltaMovement.y + delegate.gravity - if (!onFly && mountController.canJump() && (delegate.horizontalCollision || player.isJump()) && dy in 0.0..0.01 && jumpDelay == 0) { - jumpDelay = 10 - delegate.jumpFromGround() - } - } - - private fun movementSpeed() = ifLivingEntity { - getAttribute(Attributes.MOVEMENT_SPEED)?.value?.toFloat()?.let { - if (!onFly && !shouldDiscardFriction()) level() - .getBlockState(blockPosBelowThatAffectsMyMovement) - .block - .getFriction() * it else it - } ?: 0.0F - } ?: 0.0F - - private fun updateFlyStatus(player: ServerPlayer) { - val fly = (player.isJump() && mountController.canFly()) || noGravity || onFly - if (delegate is Mob) delegate.isNoAi = fly - else delegate.isNoGravity = fly - onFly = fly && !delegate.onGround() - if (onFly) delegate.resetFallDistance() - } - - private fun rideInput(player: ServerPlayer, travelVector: Vec3) = mountController.move( - if (onFly) MountController.MoveType.FLY else MountController.MoveType.DEFAULT, - player.bukkitEntity.wrap(), - (delegate.bukkitEntity as org.bukkit.entity.LivingEntity).wrap(), - Vector3f( - player.xMovement(), - player.yMovement(), - player.zMovement() - ), - Vector3f( - travelVector.x.toFloat(), - travelVector.y.toFloat(), - travelVector.z.toFloat() - ) - ).mul(movementSpeed()).rotateY(-Math.toRadians(player.yRot.toDouble()).toFloat()) - - override fun tick() { - delegate.removalReason?.let { - if (!isRemoved) remove(it) - return - } - val controller = controllingPassenger - if (jumpDelay > 0) jumpDelay-- - interaction.isInvisible = delegate.isInvisible - if (controller is ServerPlayer && !isDeadOrDying && mountController.canControl()) { - if (delegate is Mob) delegate.navigation.stop() - mountControl(controller) - } else initialSetup() - yRot = bone.rotation().y - yHeadRot = yRot - yBodyRot = yRot - val pos = relativePosition() - val minusHeight = source.minY * bone.hitBoxScale() - setPos( - pos.x.toDouble(), - pos.y.toDouble() + minusHeight, - pos.z.toDouble() - ) - BlockPos.betweenClosedStream(boundingBox).forEach { - level().getBlockState(it).entityInside(level(), it, delegate) - } - if (isInLava) delegate.lavaHurt() - firstTick = false - listener.sync(craftEntity) - } - - @Suppress("removal") - override fun remove(reason: RemovalReason, cause: org.bukkit.event.entity.EntityRemoveEvent.Cause?) { - initialSetup() - listener.handle(HitBoxRemoveEvent(craftEntity)) - interaction.remove(reason) - super.remove(reason, cause) - } - - override fun getBukkitLivingEntity(): CraftLivingEntity = bukkitEntity - override fun getBukkitEntity(): CraftLivingEntity = craftEntity as CraftLivingEntity - override fun getBukkitEntityRaw(): CraftLivingEntity = bukkitEntity - override fun hasExactlyOnePlayerPassenger(): Boolean = false - - override fun isDeadOrDying(): Boolean { - return ifLivingEntity { isDeadOrDying } == true - } - - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun hide(player: PlatformPlayer) { - val plugin = BetterModel.platform() as Plugin - player.unwarp().run { - hideEntity(plugin, bukkitEntity) - hideEntity(plugin, interaction.bukkitEntity) - } - } - - override fun show(player: PlatformPlayer) { - val plugin = BetterModel.platform() as Plugin - player.unwarp().run { - showEntity(plugin, bukkitEntity) - showEntity(plugin, interaction.bukkitEntity) - } - } - - override fun interact(player: Player, hand: InteractionHand): InteractionResult { - if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL - (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) - return InteractionResult.SUCCESS - } - - override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { - if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractAtEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - }, vec.toBukkit() - ) - if (!listener.handle(interact)) return InteractionResult.FAIL - (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand, vec)) - return InteractionResult.SUCCESS - } - - override fun addEffect(effectInstance: MobEffectInstance, cause: EntityPotionEffectEvent.Cause): Boolean { - return ifLivingEntity { addEffect(effectInstance, cause) } == true - } - - override fun addEffect(effectInstance: MobEffectInstance, entity: Entity?): Boolean { - if (entity === delegate) return false - return ifLivingEntity { addEffect(effectInstance, entity) } == true - } - - override fun addEffect( - effectInstance: MobEffectInstance, - entity: Entity?, - cause: EntityPotionEffectEvent.Cause - ): Boolean { - if (entity === delegate) return false - return ifLivingEntity { addEffect(effectInstance, entity, cause) } == true - } - - override fun hurt(source: DamageSource, amount: Float): Boolean { - if (source.entity === delegate || delegate.isInvulnerable) return false - if (source.entity === controllingPassenger && !mountController.canBeDamagedByRider()) return false - val ds = ModelDamageSourceImpl(source) - val event = HitBoxDamagedEvent(craftEntity, ds, amount) - if (!listener.handle(event)) return false - return ifLivingEntity { hurt(source, event.damage) } == true - } - - override fun deflection(projectile: Projectile): ProjectileDeflection { - if (projectile.owner === delegate) return ProjectileDeflection.NONE - return ifLivingEntity { deflection(projectile) } ?: ProjectileDeflection.NONE - } - - override fun getHealth(): Float { - return ifLivingEntity { health } ?: super.getHealth() - } - - override fun makeBoundingBox(): AABB { - return if (!initialized) { - super.makeBoundingBox() - } else { - val vec3 = position() - val scale = bone.hitBoxScale() - AABB( - vec3.x + source.minX * scale, - vec3.y, - vec3.z + source.minZ * scale, - vec3.x + source.maxX * scale, - vec3.y + source.y() * scale, - vec3.z + source.maxZ * scale - ).apply { - if (CONFIG.debug().has(DebugConfig.DebugOption.HITBOX)) { - bukkitEntity.world.spawnParticle(Particle.DUST, minX, minY, minZ, 1, 0.0, 0.0, 0.0, 0.0, Particle.DustOptions(Color.RED, 1F)) - bukkitEntity.world.spawnParticle(Particle.DUST, maxX, maxY, maxZ, 1, 0.0, 0.0, 0.0, 0.0, Particle.DustOptions(Color.RED, 1F)) - } - } - } - } - - override fun getDefaultDimensions(pose: Pose): EntityDimensions = if (initialized) dimensions else super.getDefaultDimensions(pose) - - override fun removeHitBox() { - source().task { - dismountAll() - remove(ifLivingEntity { removalReason } ?: RemovalReason.KILLED) - } - } - - private inline fun ifLivingEntity(block: LivingEntity.() -> T): T? { - return if (delegate.valid) (delegate as? LivingEntity)?.block() else null - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt deleted file mode 100644 index 569d16980..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/HitBoxInteraction.kt +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.nms.HitBox -import net.minecraft.world.InteractionHand -import net.minecraft.world.InteractionResult -import net.minecraft.world.entity.Entity -import net.minecraft.world.entity.EntityType -import net.minecraft.world.entity.Interaction -import net.minecraft.world.entity.player.Player -import net.minecraft.world.phys.Vec3 -import org.bukkit.Bukkit -import org.bukkit.craftbukkit.CraftServer -import org.bukkit.craftbukkit.entity.CraftEntity -import org.bukkit.craftbukkit.entity.CraftInteraction - -internal class HitBoxInteraction( - val delegate: HitBoxImpl -) : Interaction(EntityType.INTERACTION, delegate.level()) { - - init { - persist = false - } - - private val craftEntity: CraftInteraction by lazy { - object : CraftInteraction(Bukkit.getServer() as CraftServer, this), HitBox by delegate {} - } - - override fun getBukkitEntity(): CraftEntity = craftEntity - override fun getBukkitEntityRaw(): CraftEntity = craftEntity - override fun hasExactlyOnePlayerPassenger(): Boolean = false - - override fun tick() { - val dimension = delegate.dimensions - width = dimension.width - height = dimension.height - yRot = delegate.yRot - xRot = delegate.xRot - setSharedFlagOnFire(delegate.remainingFireTicks > 0) - } - - override fun skipAttackInteraction(entity: Entity): Boolean { - return if (entity is Player) { - entity.attack(delegate) - true - } else false - } - - override fun interact(player: Player, hand: InteractionHand): InteractionResult { - return InteractionResult.FAIL - } - - override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { - return InteractionResult.FAIL - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt deleted file mode 100644 index 46d0c7d78..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModAnimationBundlerImpl.kt +++ /dev/null @@ -1,144 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.nms.ModAnimationBundler -import kr.toxicity.model.api.platform.PlatformPlayer -import kr.toxicity.model.api.util.MathUtil -import net.minecraft.network.FriendlyByteBuf -import net.minecraft.network.RegistryFriendlyByteBuf -import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket -import net.minecraft.server.MinecraftServer -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.joml.Quaternionf -import org.joml.Vector3f - -internal class ModAnimationBundlerImpl(initialCapacity: Int) : ModAnimationBundler { - - companion object { - - const val KEY = "modelengine:bulk_data" - - const val PACKET_TYPE_BULK_DATA = 0x00 - - const val FIELD_TRANSLATION = 1 shl 0 - const val FIELD_LEFT_ROTATION = 1 shl 1 - const val FIELD_SCALE = 1 shl 2 - const val FIELD_TRANSFORM_DURATION = 1 shl 4 - - private val EMPTY_BUILD_TASK: (FriendlyByteBuf) -> Unit = {} - } - - private val packet by lazy { - useByteBuf { buffer -> - ClientboundCustomPayloadPacket.GAMEPLAY_STREAM_CODEC.decode( - RegistryFriendlyByteBuf( - buffer, - MinecraftServer.getServer().registryAccess() - ).apply { - writeUtf(KEY) - useByteBuf { - it.writeByte(PACKET_TYPE_BULK_DATA) - it.writeVarInt(builderList.size) - builderList.forEach { builder -> builder(it) } - writeBytes(it) - } - } - ) - } - } - - private val builderList = ArrayList<(FriendlyByteBuf) -> Unit>(initialCapacity) - - override fun send(player: PlatformPlayer) { - (player.unwarp() as CraftPlayer).handle.connection.send(packet) - } - - fun append(id: Int, scope: Appender.() -> Unit) { - val build = Appender(id).apply(scope).build() - if (build !== EMPTY_BUILD_TASK) builderList += build - } - - class Appender( - val entityId: Int, - ) { - private var mask = 0 - private var buildTask = EMPTY_BUILD_TASK - private val isEmpty get() = buildTask === EMPTY_BUILD_TASK - - fun appendPosition(vector: Vector3f) { - mask = mask or FIELD_TRANSLATION - task { - writeFloat(it, vector.x) - writeFloat(it, vector.y) - writeFloat(it, vector.z) - } - } - - fun appendScale(vector: Vector3f) { - mask = mask or FIELD_SCALE - task { - writeFloat(it, vector.x) - writeFloat(it, vector.y) - writeFloat(it, vector.z) - } - } - - fun appendRotation(quaternion: Quaternionf) { - mask = mask or FIELD_LEFT_ROTATION - task { - writeFloat(it, quaternion.x) - writeFloat(it, quaternion.y) - writeFloat(it, quaternion.z) - writeFloat(it, quaternion.w) - } - } - - fun appendDuration(duration: Int) { - mask = mask or FIELD_TRANSFORM_DURATION - task { - writeVarInt(it, duration) - } - } - - fun build(): (FriendlyByteBuf) -> Unit { - if (isEmpty) return EMPTY_BUILD_TASK - val m = mask - val t = buildTask - return { - writeVarInt(it,entityId) - writeByte(it, m) - t(it) - } - } - - private fun task(task: (FriendlyByteBuf) -> Unit) { - if (isEmpty) { - buildTask = task - return - } - val last = buildTask - buildTask = { - last(it) - task(it) - } - } - - private fun writeFloat(buf: FriendlyByteBuf, float: Float) { - buf.writeShort(MathUtil.floatToHalf(float).toInt()) - } - - private fun writeVarInt(buf: FriendlyByteBuf, duration: Int) { - buf.writeVarInt(duration) - } - - private fun writeByte(buf: FriendlyByteBuf, duration: Int) { - buf.writeByte(duration) - } - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt deleted file mode 100644 index c557d26b9..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDamageSourceImpl.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.event.ModelDamageSource -import kr.toxicity.model.api.platform.PlatformEntity -import kr.toxicity.model.api.platform.PlatformLocation -import net.minecraft.world.damagesource.DamageSource -import org.bukkit.craftbukkit.util.CraftLocation - -internal class ModelDamageSourceImpl( - private val source: DamageSource -) : ModelDamageSource { - override fun getCausingEntity(): PlatformEntity? = source.entity?.bukkitEntity?.wrap() - override fun getDirectEntity(): PlatformEntity? = source.directEntity?.bukkitEntity?.wrap() - override fun getDamageLocation(): PlatformLocation? = source.sourcePositionRaw()?.let { - CraftLocation.toBukkit(it, causingEntity?.unwarp()?.world).wrap() - } - override fun getSourceLocation(): PlatformLocation? = source.sourcePosition?.let { - CraftLocation.toBukkit(it, causingEntity?.unwarp()?.world).wrap() - } - override fun isIndirect(): Boolean = !source.isDirect - override fun getFoodExhaustion(): Float = source.foodExhaustion - override fun scalesWithDifficulty(): Boolean = source.scalesWithDifficulty() -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt deleted file mode 100644 index a9dd36138..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelDisplayImpl.kt +++ /dev/null @@ -1,267 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.entity.BaseEntity -import kr.toxicity.model.api.nms.AnimationBundler -import kr.toxicity.model.api.nms.DisplayTransformer -import kr.toxicity.model.api.nms.ModelDisplay -import kr.toxicity.model.api.nms.PacketBundler -import kr.toxicity.model.api.platform.PlatformBillboard -import kr.toxicity.model.api.platform.PlatformItemStack -import kr.toxicity.model.api.platform.PlatformItemTransform -import kr.toxicity.model.api.platform.PlatformLocation -import kr.toxicity.model.api.tracker.ModelRotation -import kr.toxicity.model.api.util.MathUtil -import kr.toxicity.model.api.util.lock.SingleLock -import net.minecraft.network.protocol.game.* -import net.minecraft.network.syncher.EntityDataSerializers -import net.minecraft.network.syncher.SynchedEntityData -import net.minecraft.util.Brightness -import net.minecraft.world.entity.Display -import net.minecraft.world.entity.Display.ItemDisplay -import net.minecraft.world.entity.Entity -import net.minecraft.world.item.ItemDisplayContext -import net.minecraft.world.item.Items -import org.joml.Quaternionf -import org.joml.Vector3d -import org.joml.Vector3f -import java.util.* -import java.util.concurrent.atomic.AtomicBoolean - -internal class ModelDisplayImpl( - private val pos: Vector3d, - val display: ItemDisplay, - val yOffset: Double -) : ModelDisplay { - - private val entityData = display.entityData - private val entityDataLock = SingleLock() - private val forceGlow = AtomicBoolean() - private val forceInvisibility = AtomicBoolean() - - private val oldPos = Vector3d(pos) - - override fun id(): Int = display.id - override fun uuid(): UUID = display.uuid - override fun rotate(rotation: ModelRotation, bundler: PacketBundler) { - display.xRot = rotation.x - display.yRot = rotation.y - bundler += ClientboundMoveEntityPacket.Rot( - display.id, - rotation.packedY(), - rotation.packedX(), - display.onGround - ) - } - - override fun invisible(invisible: Boolean) { - if (forceInvisibility.compareAndSet(!invisible, invisible)) { - entityDataLock.accessToLock { - entityData.markDirty(ITEM_SERIALIZER) - } - } - } - - override fun syncPotionEffect(entity: BaseEntity) { - val beforeInvisible = display.isInvisible - val afterInvisible = entity.invisible() - entityDataLock.accessToLock { - display.setGlowingTag(entity.glow() || forceGlow.get()) - if (CONFIG.followMobInvisibility() && beforeInvisible != afterInvisible) { - display.isInvisible = afterInvisible - entityData.markDirty(ITEM_SERIALIZER) - } - } - } - - override fun syncPosition(location: PlatformLocation) { - oldPos.set(pos) - pos.set(location.x(), location.y(), location.z()) - } - - - override fun spawn(showItem: Boolean, bundler: PacketBundler) { - bundler += addPacket - } - - override fun remove(bundler: PacketBundler) { - bundler += removePacket - } - - override fun teleport(location: PlatformLocation, bundler: PacketBundler) { - display.moveTo( - location.x(), - location.y(), - location.z(), - location.yaw(), - 0F - ) - bundler += ClientboundTeleportEntityPacket(display) - } - - override fun sendPosition(adapter: BaseEntity, bundler: PacketBundler) { - val handle = adapter.handle() as Entity - if (oldPos.distanceSquared(pos) < 1e-8) return - bundler += useByteBuf { - it.writeInt(display.id) - it.writeDouble(handle.x) - it.writeDouble(handle.y) - it.writeDouble(handle.z) - it.writeByte((handle.yRot * MathUtil.DEGREES_TO_PACKED_BYTE).toInt()) - it.writeByte((handle.xRot * MathUtil.DEGREES_TO_PACKED_BYTE).toInt()) - it.writeBoolean(handle.onGround()) - ClientboundTeleportEntityPacket.STREAM_CODEC.decode(it) - } - } - - override fun display(transform: PlatformItemTransform) { - entityDataLock.accessToLock { - display.itemTransform = ItemDisplayContext.BY_ID.apply(transform.ordinal) - } - } - - override fun moveDuration(duration: Int) { - entityDataLock.accessToLock { - entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = duration - } - } - - override fun item(itemStack: PlatformItemStack) { - entityDataLock.accessToLock { - display.itemStack = itemStack.unwarp().asVanilla() - } - } - - override fun brightness(block: Int, sky: Int) { - entityDataLock.accessToLock { - display.brightnessOverride = if (block < 0 && sky < 0) null else Brightness( - block, - sky - ) - } - } - - override fun viewRange(range: Float) { - entityDataLock.accessToLock { - display.viewRange = range - } - } - - override fun shadowRadius(radius: Float) { - entityDataLock.accessToLock { - display.shadowRadius = radius - } - } - - override fun glow(glow: Boolean) { - if (!forceGlow.compareAndSet(!glow, glow)) return - entityDataLock.accessToLock { - display.setGlowingTag(display.isCurrentlyGlowing || glow) - } - } - - override fun glowColor(glowColor: Int) { - entityDataLock.accessToLock { - display.glowColorOverride = glowColor - } - } - - override fun billboard(billboard: PlatformBillboard) { - entityDataLock.accessToLock { - display.billboardConstraints = Display.BillboardConstraints.BY_ID.apply(billboard.ordinal) - } - } - - override fun createTransformer(): DisplayTransformer = DisplayTransformerImpl(display) - - override fun invisible(): Boolean = entityDataLock.accessToLock { - display.isInvisible || forceInvisibility.get() || display.itemStack.`is`(Items.AIR) - } - - override fun sendDirtyEntityData(bundler: PacketBundler) { - entityDataLock.accessToLock { - entityData.pack( - clean = true, - itemFilter = { it.isDirty }, - valueFilter = { ITEM_ENTITY_DATA.contains(it.id) } - ) - }?.markVisible(!invisible())?.run { - bundler += ClientboundSetEntityDataPacket(display.id, this) - } - } - - override fun sendEntityData(showItem: Boolean, bundler: PacketBundler) { - entityDataLock.accessToLock { - entityData.pack( - valueFilter = { ITEM_ENTITY_DATA.contains(it.id) } - ) - }?.markVisible(showItem && !invisible())?.run { - bundler += ClientboundSetEntityDataPacket(display.id, this) - } - } - - private fun List>.markVisible(showItem: Boolean) = map { - if (it.id == ITEM_SERIALIZER.id) SynchedEntityData.DataValue( - it.id, - EntityDataSerializers.ITEM_STACK, - if (showItem) display.itemStack else EMPTY_ITEM - ) else it - } - - private val addPacket - get() = ClientboundAddEntityPacket( - display.id, - display.uuid, - pos.x, - pos.y + yOffset, - pos.z, - display.xRot, - display.yRot, - display.type, - 0, - display.deltaMovement, - display.yHeadRot.toDouble() - ) - - private val removePacket = ClientboundRemoveEntitiesPacket(display.id) - - private class DisplayTransformerImpl( - source: ItemDisplay - ) : DisplayTransformer { - private val id = source.id - private val entityData = TransformationData() - private val entityDataLock = SingleLock() - - override fun transform( - duration: Int, - position: Vector3f, - scale: Vector3f, - rotation: Quaternionf, - bundler: AnimationBundler - ) { - entityDataLock.accessToLock { - entityData.transform( - duration, - position, - scale, - rotation - ) - entityData.packDirty(id, bundler) - } - } - - override fun sendTransformation(bundler: PacketBundler) { - entityDataLock.accessToLock { - entityData.pack() - }?.run { - bundler += ClientboundSetEntityDataPacket(id, this) - } - } - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt deleted file mode 100644 index 07edeb93a..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelGameProfile.kt +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import com.mojang.authlib.GameProfile -import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.profile.ModelProfile -import kr.toxicity.model.api.profile.ModelProfileInfo -import kr.toxicity.model.api.profile.ModelProfileSkin - -internal data class ModelGameProfile( - private val gameProfile: GameProfile -) : ModelProfile { - - private val info = ModelProfileInfo(gameProfile.id, gameProfile.name) - private val skin by lazy { - gameProfile.properties["textures"].firstOrNull()?.let { - BetterModel.platform().profileManager().skin(it.value) - } ?: ModelProfileSkin.EMPTY - } - - override fun info(): ModelProfileInfo = info - - override fun skin(): ModelProfileSkin = skin -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt deleted file mode 100644 index f46d7de6d..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ModelNametagImpl.kt +++ /dev/null @@ -1,118 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import com.mojang.math.Transformation -import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.bone.BoneMovement -import kr.toxicity.model.api.bone.BonePosition -import kr.toxicity.model.api.bone.RenderedBone -import kr.toxicity.model.api.nms.ModelNametag -import kr.toxicity.model.api.nms.PacketBundler -import kr.toxicity.model.api.platform.PlatformLocation -import kr.toxicity.model.api.platform.PlatformPlayer -import kr.toxicity.model.api.util.EntityUtil -import net.kyori.adventure.text.Component -import net.minecraft.network.protocol.game.ClientboundAddEntityPacket -import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket -import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket -import net.minecraft.network.protocol.game.ClientboundTeleportEntityPacket -import net.minecraft.server.MinecraftServer -import net.minecraft.world.entity.Display -import net.minecraft.world.entity.EntityType -import net.minecraft.world.phys.Vec3 -import org.joml.Vector3f -import java.util.* -import java.util.concurrent.ConcurrentHashMap - -internal class ModelNametagImpl( - private val bone: RenderedBone -) : ModelNametag { - private companion object { - private val emptyVector = Vector3f() - private val emptyTransformation = Transformation( - Vector3f(-1F / 40F, -0.2F - 1F / 40F, 0F), - null, - null, - null - ) - } - - private val viewedPlayer = ConcurrentHashMap.newKeySet() - private val display = Display.TextDisplay( - EntityType.TEXT_DISPLAY, - MinecraftServer.getServer().overworld() - ).apply { - entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 - setTransformation(emptyTransformation) - billboardConstraints = Display.BillboardConstraints.CENTER - } - private val posCache = BoneMovement() - private var alwaysVisible = false - private var location = BetterModel.platform().adapter().zero() - - override fun component(component: Component?) { - display.text = component?.asVanilla() ?: VanillaComponent.empty() - } - - override fun teleport(location: PlatformLocation) { - this.location = location - } - - override fun alwaysVisible(alwaysVisible: Boolean) { - this.alwaysVisible = alwaysVisible - } - - override fun send(player: PlatformPlayer) { - if (display.text == VanillaComponent.empty()) return - val hb = bone.group.hitBoxPoint - val pos = bone.worldPosition(BonePosition(emptyVector, hb, player.uuid()), posCache) - display.moveTo(Vec3( - location.x() + pos.x, - location.y() + pos.y, - location.z() + pos.z - )) - val inPoint = alwaysVisible || EntityUtil.isCustomNameVisible(player.location(), location) - when { - inPoint && viewedPlayer.add(player.uuid()) -> bundlerOfNotNull( - addPacket, - display.entityData.pack()?.let { - ClientboundSetEntityDataPacket(display.id, it) - } - ) - inPoint -> bundlerOfNotNull( - ClientboundTeleportEntityPacket(display), - display.entityData.packDirty()?.let { - ClientboundSetEntityDataPacket(display.id, it) - } - ) - viewedPlayer.remove(player.uuid()) -> bundlerOf(removePacket) - else -> null - }?.send(player) - } - - override fun remove(bundler: PacketBundler) { - bundler += removePacket - } - - private val addPacket get() = ClientboundAddEntityPacket( - display.id, - display.uuid, - display.x, - display.y, - display.z, - display.xRot, - display.yRot, - display.type, - 0, - display.deltaMovement, - display.yHeadRot.toDouble() - ) - - private val removePacket get() = ClientboundRemoveEntitiesPacket(display.id) -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt deleted file mode 100644 index 5e34da81f..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/NMSImpl.kt +++ /dev/null @@ -1,385 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup -import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property -import io.netty.channel.ChannelDuplexHandler -import io.netty.channel.ChannelHandlerContext -import io.netty.channel.ChannelPromise -import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.bone.RenderedBone -import kr.toxicity.model.api.bukkit.BetterModelBukkit -import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity -import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.entity.BaseEntity -import kr.toxicity.model.api.entity.BasePlayer -import kr.toxicity.model.api.mount.MountController -import kr.toxicity.model.api.nms.* -import kr.toxicity.model.api.platform.PlatformEntity -import kr.toxicity.model.api.platform.PlatformItemStack -import kr.toxicity.model.api.platform.PlatformLocation -import kr.toxicity.model.api.platform.PlatformPlayer -import kr.toxicity.model.api.player.PlayerSkinParts -import kr.toxicity.model.api.profile.ModelProfile -import kr.toxicity.model.api.tracker.EntityTrackerRegistry -import kr.toxicity.model.api.tracker.TrackerUpdateAction -import net.kyori.adventure.key.Keyed -import net.minecraft.core.NonNullList -import net.minecraft.core.component.DataComponents -import net.minecraft.network.Connection -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.game.* -import net.minecraft.network.syncher.EntityDataSerializers -import net.minecraft.network.syncher.SynchedEntityData -import net.minecraft.server.MinecraftServer -import net.minecraft.server.level.ServerLevel -import net.minecraft.server.network.ServerCommonPacketListenerImpl -import net.minecraft.world.entity.Display -import net.minecraft.world.entity.Display.ItemDisplay -import net.minecraft.world.entity.Entity -import net.minecraft.world.entity.EntityType -import net.minecraft.world.entity.LivingEntity -import net.minecraft.world.entity.player.Player -import net.minecraft.world.item.ItemDisplayContext -import net.minecraft.world.item.Items -import net.minecraft.world.item.component.ResolvableProfile -import net.minecraft.world.level.entity.LevelEntityGetter -import net.minecraft.world.level.entity.LevelEntityGetterAdapter -import net.minecraft.world.level.entity.PersistentEntitySectionManager -import org.bukkit.Color -import org.bukkit.craftbukkit.CraftWorld -import org.bukkit.craftbukkit.entity.CraftEntity -import org.bukkit.craftbukkit.entity.CraftPlayer -import org.bukkit.inventory.meta.LeatherArmorMeta -import org.joml.Vector3d -import java.util.* -import java.util.function.Consumer - -class NMSImpl : NMS { - - companion object { - private const val INJECT_NAME = "bettermodel_channel_handler" - - //Spigot - private val getGameProfile: (Player) -> GameProfile = createAdaptedFieldGetter { it.gameProfile } - private val getConnection: (ServerCommonPacketListenerImpl) -> Connection = createAdaptedFieldGetter { it.connection } - private val spigotChunkAccess = ServerLevel::class.java.fields.firstOrNull { - it.type == PersistentEntitySectionManager::class.java - }?.apply { - isAccessible = true - } - @Suppress("UNCHECKED_CAST") - private val ServerLevel.levelGetter - get(): LevelEntityGetter { - return if (BetterModelBukkit.IS_PAPER) { - `moonrise$getEntityLookup`() - } else { - spigotChunkAccess?.get(this)?.let { - (it as PersistentEntitySectionManager<*>).entityGetter as LevelEntityGetter - } ?: throw RuntimeException("LevelEntityGetter") - } - } - private val getEntityById: (LevelEntityGetter, Int) -> Entity? = if (BetterModelBukkit.IS_PAPER) { g, i -> - (g as EntityLookup)[i] - } else LevelEntityGetterAdapter::class.java.declaredFields.first { - net.minecraft.world.level.entity.EntityLookup::class.java.isAssignableFrom(it.type) - }.let { - it.isAccessible = true - { e, i -> - (it[e] as net.minecraft.world.level.entity.EntityLookup<*>).getEntity(i) as? Entity - } - } - private fun Int.toEntity(level: ServerLevel) = getEntityById(level.levelGetter, this) - //Spigot - private val hitBoxData by lazy { - ItemDisplay(EntityType.ITEM_DISPLAY, MinecraftServer.getServer().overworld()).run { - entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 - entityData.nonDefaultValues!! - } - } - } - - override fun hide(channel: PlayerChannelHandler, registry: EntityTrackerRegistry) { - val target = registry.entity().handle() as? Entity ?: return - val list = bundlerOf() - target.entityData.pack( - valueFilter = { it.id == SHARED_FLAG } - )?.let { - list += ClientboundSetEntityDataPacket(target.id, it).toRegistryDataPacket(channel.uuid(), registry) - } - if (target is LivingEntity) { - val packet = if (registry.hideOption(channel.uuid()).equipment) target.toEmptyEquipmentPacket() else target.toEquipmentPacket() - packet?.let { list += it } - } - list.send(channel.player()) - } - - private fun ClientboundSetEntityDataPacket.toRegistryDataPacket(uuid: UUID, registry: EntityTrackerRegistry) = ClientboundSetEntityDataPacket(id, packedItems().map { - if (it.id == SHARED_FLAG) SynchedEntityData.DataValue( - it.id, - EntityDataSerializers.BYTE, - registry.entityFlag(uuid, it.value() as Byte) - ) else it - }) - - inner class PlayerChannelHandlerImpl( - private val player: CraftPlayer - ) : PlayerChannelHandler, ChannelDuplexHandler() { - private val connection = player.handle.connection - private val uuid = player.uniqueId - private val base = adapt(player.wrap()) - - init { - val pipeline = getConnection(connection).channel.pipeline() - pipeline.addBefore(pipeline.first { it.value is Connection }.key, INJECT_NAME, this) - } - - override fun close() { - val channel = getConnection(connection).channel - channel.eventLoop().submit { - channel.pipeline().remove(INJECT_NAME) - } - } - - override fun base(): BasePlayer = base - override fun isModEnabled(): Boolean = player.listeningPluginChannels.contains("modelengine:bulk_data") - - private val playerModel get() = connection.player.id.toRegistry() - - private fun Int.toPlayerEntity() = toEntity(connection.player.serverLevel()) - private fun Entity.toRegistry() = BetterModel.registryOrNull(uuid) - private inline fun Int.toRegistry( - ifHitBox: (Entity) -> Unit = {} - ) = (EntityTrackerRegistry.registry(this) ?: toPlayerEntity()?.let { - if (it is HitBox) ifHitBox(it) - it.toRegistry() - })?.takeIf { - it.isSpawned(player.uniqueId) - } - - override fun sendEntityData(registry: EntityTrackerRegistry) { - val handle = registry.entity().handle() as? Entity ?: return - val list = bundlerOf( - ClientboundSetPassengersPacket(handle) - ) - handle.entityData.pack( - valueFilter = { it.id == SHARED_FLAG } - )?.let { - list += ClientboundSetEntityDataPacket(handle.id, it) - } - if (handle is LivingEntity) handle.toEquipmentPacket()?.let { - list += it - } - list.send(player.wrap()) - } - - private fun Packet.handle(): Packet? { - when (this) { - is ClientboundBundlePacket -> return if (subPackets() is Keyed) this else ClientboundBundlePacket(subPackets().mapNotNull { - it.handle() - }) - is ClientboundAddEntityPacket -> { - val entity = id.toPlayerEntity() ?: return this - if (entity is HitBox) return entity.toFakeAddPacket() - val wrap = entity.bukkitEntity.wrap() - BetterModel.registry(wrap).ifPresent { - wrap.taskLater(1) { - it.spawn(player.wrap()) - } - } - } - is ClientboundRemoveEntitiesPacket -> { - entityIds - .asSequence() - .mapNotNull map@ { - it.toRegistry { - return@map null - } - } - .forEach { - it.remove() - } - } - is ClientboundSetPassengersPacket -> { - vehicle.toRegistry()?.let { - return it.mountPacket(it.entity().handle() as? Entity ?: return this, array = passengers) - } - } - is ClientboundUpdateAttributesPacket if entityId.toPlayerEntity() is HitBox -> return null - is ClientboundSetEntityDataPacket -> id.toRegistry { - return ClientboundSetEntityDataPacket(id, hitBoxData) - }?.let { registry -> - return toRegistryDataPacket(uuid, registry) - } - is ClientboundSetEquipmentPacket -> entity.toRegistry { - return null - }?.let { - if (it.hideOption(uuid).equipment()) (it.entity().handle() as? LivingEntity)?.toEmptyEquipmentPacket()?.let { packet -> - return packet - } - } - is ClientboundRespawnPacket -> playerModel?.let { - bundlerOf(it.mountPacket(connection.player)).send(player.wrap()) - } - is ClientboundContainerSetSlotPacket if isEquipment(connection.player) && playerModel?.hideOption(uuid)?.equipment() == true -> { - return ClientboundContainerSetSlotPacket(containerId, stateId, slot, EMPTY_ITEM) - } - is ClientboundContainerSetContentPacket if containerId == 0 && playerModel?.hideOption(uuid)?.equipment() == true -> { - return ClientboundContainerSetContentPacket( - containerId, - stateId, - (items as NonNullList).apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } - set(connection.player.hotbarSlot, EMPTY_ITEM) - }, - carriedItem - ) - } - } - return this - } - - override fun write(ctx: ChannelHandlerContext, msg: Any, promise: ChannelPromise) { - super.write(ctx, if (msg is Packet<*>) msg.handle() ?: return else msg, promise) - } - - override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { - fun EntityTrackerRegistry.updatePlayerLimb() = BetterModel.platform().scheduler().asyncTaskLater(1) { - if (isClosed) return@asyncTaskLater - player.handle.containerMenu.sendAllDataToRemote() - trackers().forEach { tracker -> - tracker.update(TrackerUpdateAction.itemMapping()) { bone -> - !bone.itemMapper.fixed() - } - } - } - when (msg) { - is ServerboundSetCarriedItemPacket -> { - playerModel?.let { registry -> - if (!registry.hideOption(uuid).equipment()) return super.channelRead(ctx, msg) - if (CONFIG.cancelPlayerModelInventory()) { - connection.send(ClientboundSetCarriedItemPacket(player.inventory.heldItemSlot)) - return - } - registry.updatePlayerLimb() - } - } - is ServerboundPlayerActionPacket -> { - playerModel?.let { registry -> - if (!registry.hideOption(uuid).equipment()) return super.channelRead(ctx, msg) - if (CONFIG.cancelPlayerModelInventory()) return - registry.updatePlayerLimb() - } - } - } - super.channelRead(ctx, msg) - } - - private fun EntityTrackerRegistry.remove() { - remove(player.wrap()) - } - } - - override fun mount(registry: EntityTrackerRegistry, bundler: PacketBundler) { - val entity = registry.entity().handle() - if (entity is Entity) bundler += registry.mountPacket(entity) - } - - private fun EntityTrackerRegistry.mountPacket(entity: Entity, array: IntArray = entity.passengers.filter { - EntityTrackerRegistry.registry(it.uuid) == null - }.map { - it.id - }.toIntArray()): ClientboundSetPassengersPacket { - return useByteBuf { buffer -> - buffer.writeVarInt(entity.id) - buffer.writeVarIntArray(displays() - .mapToInt { - (it as ModelDisplayImpl).display.id - }.toArray() + array) - ClientboundSetPassengersPacket.STREAM_CODEC.decode(buffer) - } - } - - override fun inject(player: PlatformPlayer): PlayerChannelHandlerImpl = PlayerChannelHandlerImpl(player.unwarp() as CraftPlayer) - - override fun createBundler(initialCapacity: Int): PacketBundler = bundlerOf(initialCapacity) - override fun createParallelBundler(threshold: Int): PacketBundler = parallelBundlerOf(threshold) - override fun createModAnimationBuilder(initialCapacity: Int): ModAnimationBundler = ModAnimationBundlerImpl(initialCapacity) - - override fun create(location: PlatformLocation, yOffset: Double, initialConsumer: Consumer): ModelDisplay = ModelDisplayImpl( - Vector3d(location.x(), location.y(), location.z()), - ItemDisplay(EntityType.ITEM_DISPLAY, (location.world().unwarp() as CraftWorld).handle).apply { - entityData[Display.DATA_POS_ROT_INTERPOLATION_DURATION_ID] = 3 - billboardConstraints = Display.BillboardConstraints.FIXED - valid = true - yRot = location.yaw() - itemTransform = ItemDisplayContext.FIXED - }, - yOffset - ).apply { - initialConsumer.accept(this) - display.entityData.packDirty() - } - - override fun createNametag(bone: RenderedBone): ModelNametag = ModelNametagImpl(bone) - - override fun tint(itemStack: PlatformItemStack, rgb: Int): PlatformItemStack = itemStack.unwarp().clone().apply { - val meta = itemMeta - if (meta is LeatherArmorMeta) { - itemMeta = meta.apply { - setColor(Color.fromRGB(rgb)) - } - } - }.wrap() - - override fun createHitBox(entity: BaseEntity, bone: RenderedBone, boundingBox: ModelBoundingBox, mountController: MountController, listener: HitBoxListener): HitBox? { - val handle = entity.handle() as? Entity ?: return null - return HitBoxImpl( - boundingBox.center(), - bone, - listener, - handle, - mountController - ).craftEntity - } - - override fun version(): NMSVersion = NMSVersion.V1_21_R1 - - override fun adapt(entity: PlatformEntity): BaseBukkitEntity { - val craft = entity.unwarp() as CraftEntity - return BaseEntityImpl(craft) - } - - override fun adapt(player: PlatformPlayer): BasePlayer { - val craft = player.unwarp() as CraftPlayer - return BasePlayerImpl( - craft, - dirtyChecked( - { getGameProfile(craft.handle) }, - { ModelGameProfile(it) }, - { a, b -> a == b && a.properties["texture"] === b.properties["texture"]} - ), - dirtyChecked({ craft.handle.toCustomisation() }, { PlayerSkinParts(it) }) - ) - } - - override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile(GameProfile( - profile.info().id, - profile.info().name ?: "", - ).apply { - properties.put("textures", Property("textures", profile.skin().raw)) - })) - }.asBukkit().wrap() - - override fun isProxyOnlineMode(): Boolean = ONLINE_MODE -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt deleted file mode 100644 index 2913489c6..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/PacketBundlers.kt +++ /dev/null @@ -1,91 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.nms.PacketBundler -import kr.toxicity.model.api.platform.PlatformPlayer -import net.kyori.adventure.key.Key -import net.kyori.adventure.key.Keyed -import net.minecraft.network.PacketSendListener -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.game.ClientboundBundlePacket -import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket -import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket -import org.bukkit.craftbukkit.entity.CraftPlayer - -private val KEY = Key.key("bettermodel") - -internal fun bundlerOfNotNull(vararg packets: ClientPacket?) = SimpleBundler(if (packets.isEmpty()) arrayListOf() else packets.filterNotNull().toMutableList()) -internal fun bundlerOf(vararg packets: ClientPacket) = SimpleBundler(if (packets.isEmpty()) arrayListOf() else packets.toMutableList()) -internal fun bundlerOf(size: Int) = SimpleBundler(ArrayList(size)) -internal fun parallelBundlerOf(threshold: Int) = ParallelBundler(threshold) - -internal operator fun PacketBundler.plusAssign(other: ClientPacket) { - when (this) { - is SimpleBundler -> add(other) - is ParallelBundler -> add(other) - else -> throw RuntimeException("unsupported bundler.") - } -} -internal fun Packet<*>.assumeSize() = when (this) { - is ClientboundSetEntityDataPacket -> packedItems.size - is ClientboundSetEquipmentPacket -> slots.size - else -> 1 -} - -internal interface PluginBundlePacketImpl : Iterable, Keyed { - val bundlePacket: ClientboundBundlePacket - fun size(): Int - fun isEmpty(): Boolean - fun add(other: ClientPacket) -} - -internal class SimpleBundler( - private val list: MutableList -) : PacketBundler, PluginBundlePacketImpl { - override val bundlePacket = ClientboundBundlePacket(this) - override fun send(player: PlatformPlayer, onSuccess: Runnable) { - if (isEmpty) return - val connection = (player.unwarp() as CraftPlayer).handle.connection - connection.send(bundlePacket, PacketSendListener.thenRun(onSuccess)) - } - override fun isEmpty(): Boolean = list.isEmpty() - override fun size(): Int = list.size - override fun key(): Key = KEY - override fun iterator(): MutableIterator = list.iterator() - override fun add(other: ClientPacket) { - list += other - } -} - -internal class ParallelBundler( - private val threshold: Int -) : PacketBundler { - private val subBundlers = mutableListOf() - private var sizeAssume = 0 - private val newBundler get() = bundlerOf().apply { - sizeAssume = 0 - subBundlers += this - } - private var selectedBundler = newBundler - override fun send(player: PlatformPlayer, onSuccess: Runnable) { - if (isEmpty) return - val connection = (player.unwarp() as CraftPlayer).handle.connection - subBundlers.forEach { - connection.send(it.bundlePacket) - } - } - override fun isEmpty(): Boolean = selectedBundler.isEmpty() - override fun size(): Int = subBundlers.sumOf(PluginBundlePacketImpl::size) - fun add(other: ClientPacket) { - (if (sizeAssume > threshold) newBundler else selectedBundler) - .apply { selectedBundler = this } - .add(other) - sizeAssume += other.assumeSize() - } -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt deleted file mode 100644 index 731302600..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/ProfiledImpl.kt +++ /dev/null @@ -1,25 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import kr.toxicity.model.api.armor.PlayerArmor -import kr.toxicity.model.api.nms.Profiled -import kr.toxicity.model.api.player.PlayerSkinParts -import kr.toxicity.model.api.profile.ModelProfile - - -internal class ProfiledImpl( - private val playerArmor: PlayerArmor, - private val modelProfile: () -> ModelProfile, - private val playerSkinParts: () -> PlayerSkinParts -) : Profiled { - - override fun profile(): ModelProfile = modelProfile() - override fun armors(): PlayerArmor = playerArmor - override fun skinParts(): PlayerSkinParts = playerSkinParts() -} diff --git a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt b/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt deleted file mode 100644 index a777080b0..000000000 --- a/nms/v1_21_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R1/TypeAliases.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.bukkit.nms.v1_21_R1 - -import net.minecraft.network.chat.Component -import net.minecraft.network.protocol.Packet -import net.minecraft.network.protocol.game.ClientGamePacketListener -import net.minecraft.world.item.ItemStack - -internal typealias VanillaItemStack = ItemStack -internal typealias BukkitItemStack = org.bukkit.inventory.ItemStack -internal typealias ClientPacket = Packet -internal typealias VanillaComponent = Component -internal typealias AdventureComponent = net.kyori.adventure.text.Component diff --git a/platform/paper/build.gradle.kts b/platform/paper/build.gradle.kts index ad7eb43ee..d68ddf83a 100644 --- a/platform/paper/build.gradle.kts +++ b/platform/paper/build.gradle.kts @@ -12,7 +12,6 @@ val dependenciesContent: String = libs.bundles.library.map { bundle -> }.get() dependencies { - shade(project(":nms:v1_21_R1")) { isTransitive = false } shade(project(":nms:v1_21_R3")) { isTransitive = false } shade(project(":nms:v1_21_R4")) { isTransitive = false } shade(project(":nms:v1_21_R5")) { isTransitive = false } @@ -57,7 +56,7 @@ paperPluginYaml { version = project.version.toString() name = "BetterModel" foliaSupported = true - apiVersion = "1.20" + apiVersion = "1.21.4" author = "toxicity188" contributors = listOf("https://github.com/toxicity188/BetterModel/graphs/contributors") description = "Modern Bedrock model engine for Minecraft Java Edition" diff --git a/platform/spigot/build.gradle.kts b/platform/spigot/build.gradle.kts index 99b09d1cd..109c77124 100644 --- a/platform/spigot/build.gradle.kts +++ b/platform/spigot/build.gradle.kts @@ -10,7 +10,6 @@ val dependenciesContent: List = libs.bundles.library.map { }.get() dependencies { - shade(project(":nms:v1_21_R1", configuration = "reobf")) { isTransitive = false } shade(project(":nms:v1_21_R3", configuration = "reobf")) { isTransitive = false } shade(project(":nms:v1_21_R4", configuration = "reobf")) { isTransitive = false } shade(project(":nms:v1_21_R5", configuration = "reobf")) { isTransitive = false } @@ -35,7 +34,7 @@ bukkitPluginYaml { version = project.version.toString() name = "BetterModel" foliaSupported = true - apiVersion = "26.1" + apiVersion = "1.21.4" author = "toxicity188" description = "Modern Bedrock model engine for Minecraft Java Edition" website = "https://modrinth.com/plugin/bettermodel" diff --git a/settings.gradle.kts b/settings.gradle.kts index 72ced8cb7..2bae2953e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -57,7 +57,6 @@ include( "purpur", //nms - "nms:v1_21_R1", "nms:v1_21_R3", "nms:v1_21_R4", "nms:v1_21_R5", From b08abc04bb7447f3ba74c8db4dd2c7ee1a6bcd4f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 6 Apr 2026 23:59:21 +0900 Subject: [PATCH 25/91] refactor: optimize import --- .../api/animation/AnimationStateHandler.java | 2 +- .../model/api/bone/BoneTagRegistry.java | 4 ++- .../kr/toxicity/model/api/bone/BoneTags.java | 1 - .../data/blueprint/BlueprintAnimation.java | 5 +++- .../api/data/blueprint/BlueprintAnimator.java | 5 +++- .../api/data/renderer/RenderPipeline.java | 5 +++- .../model/api/platform/PlatformLocation.java | 3 +- .../toxicity/model/api/tracker/Tracker.java | 3 +- .../model/api/tracker/TrackerAnimation.java | 3 +- .../api/tracker/TrackerBuiltInAnimation.java | 6 ++-- .../kr/toxicity/model/api/util/MathUtil.java | 3 +- .../model/bukkit/BetterModelProperties.kt | 6 +--- .../toxicity/model/bukkit/command/Commands.kt | 28 +++---------------- .../mythicmobs/MythicMobsCompatibility.kt | 7 +++-- .../mythicmobs/MythicMobsValue.kt | 4 +-- .../compatibility/nexo/NexoCompatibility.kt | 2 +- .../configuration/PluginConfiguration.kt | 2 +- .../model/bukkit/util/BukkitWrappers.kt | 2 +- .../model/manager/ProfileManagerImpl.kt | 2 +- .../kr/toxicity/model/util/Collections.kt | 17 +---------- .../bukkit/nms/v1_21_R3/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v1_21_R3/HitBoxImpl.kt | 8 +----- .../bukkit/nms/v1_21_R4/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v1_21_R4/HitBoxImpl.kt | 8 +----- .../bukkit/nms/v1_21_R5/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v1_21_R5/HitBoxImpl.kt | 8 +----- .../bukkit/nms/v1_21_R6/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v1_21_R6/HitBoxImpl.kt | 8 +----- .../bukkit/nms/v1_21_R7/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v1_21_R7/HitBoxImpl.kt | 8 +----- .../model/bukkit/nms/v1_21_R7/NMSImpl.kt | 2 +- .../model/bukkit/nms/v26_R1/BukkitWrappers.kt | 2 +- .../model/bukkit/nms/v26_R1/HitBoxImpl.kt | 7 +---- .../model/bukkit/nms/v26_R1/NMSImpl.kt | 2 +- 34 files changed, 59 insertions(+), 114 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index b7dc4b78a..c23bfc562 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.Iterator; import java.util.function.BiConsumer; import java.util.function.BooleanSupplier; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java index 81aea9906..29019b8db 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTagRegistry.java @@ -11,7 +11,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.List; +import java.util.Locale; +import java.util.Optional; import static kr.toxicity.model.api.util.CollectionUtil.newAddressingMap; diff --git a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java index 614404224..b367e9e17 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/BoneTags.java @@ -7,7 +7,6 @@ package kr.toxicity.model.api.bone; -import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.entity.BaseEntity; import kr.toxicity.model.api.nms.Profiled; import kr.toxicity.model.api.platform.PlatformItemTransform; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java index c00f40ffa..9901ad027 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimation.java @@ -7,7 +7,10 @@ package kr.toxicity.model.api.data.blueprint; -import kr.toxicity.model.api.animation.*; +import kr.toxicity.model.api.animation.AnimationIterator; +import kr.toxicity.model.api.animation.AnimationModifier; +import kr.toxicity.model.api.animation.AnimationProgress; +import kr.toxicity.model.api.animation.TimedStorage; import kr.toxicity.model.api.bone.BoneName; import kr.toxicity.model.api.script.BlueprintScript; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java index 12a9a48c1..5b9c8caf9 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintAnimator.java @@ -7,7 +7,10 @@ package kr.toxicity.model.api.data.blueprint; -import kr.toxicity.model.api.animation.*; +import kr.toxicity.model.api.animation.AnimationIterator; +import kr.toxicity.model.api.animation.AnimationKeyframe; +import kr.toxicity.model.api.animation.AnimationProgress; +import kr.toxicity.model.api.animation.VectorPoint; import kr.toxicity.model.api.bone.BoneName; import org.jetbrains.annotations.NotNull; diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java index 4414da8e6..f4853f890 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java @@ -31,7 +31,10 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import java.util.function.*; +import java.util.function.BiPredicate; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Predicate; import java.util.stream.Stream; import static kr.toxicity.model.api.util.CollectionUtil.associate; diff --git a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java index ee2fc6ad4..a053b796d 100644 --- a/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java +++ b/api/src/main/java/kr/toxicity/model/api/platform/PlatformLocation.java @@ -9,7 +9,8 @@ import org.jetbrains.annotations.NotNull; -import static java.lang.Math.*; +import static java.lang.Math.fma; +import static java.lang.Math.sqrt; /** * Represents a location in the underlying platform. diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java index f390bfc12..16eaf6dc4 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java @@ -7,7 +7,8 @@ package kr.toxicity.model.api.tracker; -import kr.toxicity.model.api.animation.*; +import kr.toxicity.model.api.animation.AnimationModifier; +import kr.toxicity.model.api.animation.AnimationStateHandler; import kr.toxicity.model.api.bone.BoneMovement; import kr.toxicity.model.api.bone.BoneName; import kr.toxicity.model.api.bone.BoneTags; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java index b0baf4390..01b777b84 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java @@ -14,7 +14,8 @@ import org.jetbrains.annotations.NotNull; import org.jspecify.annotations.NonNull; -import java.util.*; +import java.util.Comparator; +import java.util.Objects; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java index 3882650cf..60f030140 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerBuiltInAnimation.java @@ -11,10 +11,12 @@ import kr.toxicity.model.api.animation.AnimationModifier; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.Map; +import java.util.SortedSet; +import java.util.TreeSet; import java.util.function.Function; -import static kr.toxicity.model.api.util.CollectionUtil.*; +import static kr.toxicity.model.api.util.CollectionUtil.newAddressingMap; /** * A utility class for managing built-in animations for trackers. diff --git a/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java b/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java index 6ff2f7a96..927eb5f13 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/MathUtil.java @@ -16,7 +16,8 @@ import org.joml.Vector3f; import org.joml.Vector3fc; -import static java.lang.Math.*; +import static java.lang.Math.PI; +import static java.lang.Math.abs; /** * Math diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index fb940e2e8..d1ee599e6 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -22,11 +22,7 @@ import kr.toxicity.model.bukkit.manager.PlayerManagerImpl import kr.toxicity.model.bukkit.scheduler.BukkitScheduler import kr.toxicity.model.bukkit.scheduler.PaperScheduler import kr.toxicity.model.manager.* -import kr.toxicity.model.util.callEvent -import kr.toxicity.model.util.handleException -import kr.toxicity.model.util.ifNull -import kr.toxicity.model.util.toComponent -import kr.toxicity.model.util.warn +import kr.toxicity.model.util.* import org.bstats.bukkit.Metrics import org.bukkit.Bukkit import org.semver4j.Semver diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt index d7a5beb8a..ea990de19 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/command/Commands.kt @@ -8,9 +8,7 @@ package kr.toxicity.model.bukkit.command import kr.toxicity.model.api.BetterModel -import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.Failure -import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.OnReload -import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.Success +import kr.toxicity.model.api.BetterModelPlatform.ReloadResult.* import kr.toxicity.model.api.animation.AnimationIterator import kr.toxicity.model.api.animation.AnimationModifier import kr.toxicity.model.api.tracker.EntityHideOption @@ -24,28 +22,10 @@ import kr.toxicity.model.bukkit.util.PLUGIN import kr.toxicity.model.bukkit.util.toRegistry import kr.toxicity.model.bukkit.util.toTracker import kr.toxicity.model.bukkit.util.wrap -import kr.toxicity.model.command.register -import kr.toxicity.model.command.limb -import kr.toxicity.model.command.model -import kr.toxicity.model.command.nullable -import kr.toxicity.model.command.nullableString -import kr.toxicity.model.command.string -import kr.toxicity.model.util.LATEST_VERSION -import kr.toxicity.model.util.PLATFORM -import kr.toxicity.model.util.componentOf -import kr.toxicity.model.util.emptyComponentOf -import kr.toxicity.model.util.handleException -import kr.toxicity.model.util.info -import kr.toxicity.model.util.infoNotNull -import kr.toxicity.model.util.toByteFormat -import kr.toxicity.model.util.toComponent -import kr.toxicity.model.util.toHoverEvent -import kr.toxicity.model.util.warn -import kr.toxicity.model.util.withComma +import kr.toxicity.model.command.* +import kr.toxicity.model.util.* import net.kyori.adventure.audience.Audience -import net.kyori.adventure.text.format.NamedTextColor.GRAY -import net.kyori.adventure.text.format.NamedTextColor.GREEN -import net.kyori.adventure.text.format.NamedTextColor.YELLOW +import net.kyori.adventure.text.format.NamedTextColor.* import org.bukkit.command.CommandSender import org.bukkit.entity.EntityType import org.bukkit.entity.Player diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt index 476c0a4df..e3b621249 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsCompatibility.kt @@ -15,13 +15,16 @@ import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity import kr.toxicity.model.api.script.AnimationScript import kr.toxicity.model.api.tracker.EntityTracker -import kr.toxicity.model.bukkit.util.registerListener import kr.toxicity.model.bukkit.compatibility.Compatibility import kr.toxicity.model.bukkit.compatibility.mythicmobs.condition.ModelHasPassengerCondition import kr.toxicity.model.bukkit.compatibility.mythicmobs.mechanic.* import kr.toxicity.model.bukkit.compatibility.mythicmobs.targeter.ModelPartTargeter +import kr.toxicity.model.bukkit.util.registerListener import kr.toxicity.model.manager.ScriptManagerImpl -import kr.toxicity.model.util.* +import kr.toxicity.model.util.CONFIG +import kr.toxicity.model.util.componentOf +import kr.toxicity.model.util.toComponent +import kr.toxicity.model.util.warn import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.event.EventHandler import org.bukkit.event.Listener diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt index 9708ab146..52668a7ca 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt @@ -11,10 +11,10 @@ import io.lumine.mythic.api.adapters.AbstractEntity import io.lumine.mythic.api.config.MythicLineConfig import io.lumine.mythic.api.skills.SkillMetadata import kr.toxicity.model.api.util.function.BonePredicate -import kr.toxicity.model.util.boneName -import kr.toxicity.model.util.toPackName import kr.toxicity.model.bukkit.util.toRegistry import kr.toxicity.model.bukkit.util.toTracker +import kr.toxicity.model.util.boneName +import kr.toxicity.model.util.toPackName val MM_MODEL_ID = arrayOf("mid", "m", "model") val MM_PART_ID = arrayOf("partid", "p", "pid", "part") diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt index 1198740a2..34991dc9b 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/nexo/NexoCompatibility.kt @@ -9,9 +9,9 @@ package kr.toxicity.model.bukkit.compatibility.nexo import com.nexomc.nexo.api.events.resourcepack.NexoPrePackGenerateEvent import kr.toxicity.model.api.BetterModelPlatform -import kr.toxicity.model.bukkit.util.registerListener import kr.toxicity.model.bukkit.compatibility.Compatibility import kr.toxicity.model.bukkit.util.PLUGIN +import kr.toxicity.model.bukkit.util.registerListener import kr.toxicity.model.util.* import net.kyori.adventure.text.format.NamedTextColor import org.bukkit.event.EventHandler diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt index 7820ec7f6..b0bc06e7e 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/configuration/PluginConfiguration.kt @@ -7,10 +7,10 @@ package kr.toxicity.model.bukkit.configuration +import kr.toxicity.model.bukkit.util.toYaml import kr.toxicity.model.util.DATA_FOLDER import kr.toxicity.model.util.PLATFORM import kr.toxicity.model.util.ifNull -import kr.toxicity.model.bukkit.util.toYaml import org.bukkit.configuration.file.YamlConfiguration import java.io.File diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt index f4939a5d9..741cdd2c4 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/util/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.util -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.platform.* import org.bukkit.Location import org.bukkit.OfflinePlayer diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt index d18c6142f..31d5b4749 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ProfileManagerImpl.kt @@ -17,7 +17,7 @@ import kr.toxicity.model.profile.DefaultHttpModelProfileSupplier import kr.toxicity.model.profile.HttpModelProfileSupplier import kr.toxicity.model.util.PLATFORM import java.net.URI -import java.util.Base64 +import java.util.* object ProfileManagerImpl : ProfileManager, GlobalManager { diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt b/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt index 142c45dfb..6d1346ab1 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Collections.kt @@ -7,22 +7,7 @@ package kr.toxicity.model.util -import it.unimi.dsi.fastutil.objects.Object2ObjectMap -import it.unimi.dsi.fastutil.objects.Object2ObjectMaps -import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMap -import it.unimi.dsi.fastutil.objects.Object2ObjectSortedMaps -import it.unimi.dsi.fastutil.objects.Object2ReferenceMap -import it.unimi.dsi.fastutil.objects.Object2ReferenceMaps -import it.unimi.dsi.fastutil.objects.Object2ReferenceSortedMap -import it.unimi.dsi.fastutil.objects.Object2ReferenceSortedMaps -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap -import it.unimi.dsi.fastutil.objects.Reference2ObjectMaps -import it.unimi.dsi.fastutil.objects.Reference2ObjectSortedMap -import it.unimi.dsi.fastutil.objects.Reference2ObjectSortedMaps -import it.unimi.dsi.fastutil.objects.Reference2ReferenceMap -import it.unimi.dsi.fastutil.objects.Reference2ReferenceMaps -import it.unimi.dsi.fastutil.objects.Reference2ReferenceSortedMap -import it.unimi.dsi.fastutil.objects.Reference2ReferenceSortedMaps +import it.unimi.dsi.fastutil.objects.* import kr.toxicity.model.api.util.CollectionUtil import java.util.* import java.util.concurrent.CompletableFuture diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt index da9992eab..ca2b87d79 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v1_21_R3 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt index 516b1d5af..a91038f79 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt @@ -13,13 +13,7 @@ import kr.toxicity.model.api.bone.BoneMovement import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt index eb413b60b..48aa85391 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v1_21_R4 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt index 989ff33c2..8d1190941 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt @@ -14,13 +14,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt index 483b1a3a5..6485f298b 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v1_21_R5 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt index 48818127c..5b3fcde3a 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt @@ -14,13 +14,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt index 983216259..a964df191 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v1_21_R6 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt index 1f9e14185..740bcc9bc 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt @@ -14,13 +14,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt index 31f08842d..9063b506a 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v1_21_R7 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt index 261190096..4701c060d 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt @@ -14,13 +14,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt index 7fd5a000e..aa65eb220 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt @@ -18,8 +18,8 @@ import io.netty.channel.ChannelPromise import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit -import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity +import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.entity.BaseEntity import kr.toxicity.model.api.entity.BasePlayer import kr.toxicity.model.api.mount.MountController diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt index 9f0cd873b..912fc6fbf 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/BukkitWrappers.kt @@ -7,8 +7,8 @@ package kr.toxicity.model.bukkit.nms.v26_R1 -import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.* import kr.toxicity.model.api.bukkit.platform.* +import kr.toxicity.model.api.bukkit.platform.BukkitAdapter.adapt import kr.toxicity.model.api.bukkit.platform.BukkitItemStack import kr.toxicity.model.api.platform.* import org.bukkit.Location diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt index a21b67ce1..8f10e05fb 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt @@ -14,12 +14,7 @@ import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.config.DebugConfig import kr.toxicity.model.api.data.blueprint.ModelBoundingBox -import kr.toxicity.model.api.event.hitbox.HitBoxCreateEvent -import kr.toxicity.model.api.event.hitbox.HitBoxMountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxRemoveEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDismountEvent -import kr.toxicity.model.api.event.hitbox.HitBoxDamagedEvent -import kr.toxicity.model.api.event.hitbox.HitBoxInteractAtEvent +import kr.toxicity.model.api.event.hitbox.* import kr.toxicity.model.api.mount.MountController import kr.toxicity.model.api.nms.HitBox import kr.toxicity.model.api.nms.HitBoxListener diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt index e89445255..bb94daef6 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt @@ -18,8 +18,8 @@ import io.netty.channel.ChannelPromise import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.bukkit.BetterModelBukkit -import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.bukkit.entity.BaseBukkitEntity +import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.entity.BaseEntity import kr.toxicity.model.api.entity.BasePlayer import kr.toxicity.model.api.mount.MountController From 7034dee638bf6f8af431b428b42018785082f8c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 7 Apr 2026 20:31:06 +0000 Subject: [PATCH 26/91] fix(deps): update dependency net.fabricmc:fabric-loader to v0.19.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2a9799d27..8f07b96d5 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0-SNAPSHOT" asm-tree = "org.ow2.asm:asm-tree:9.9.1" -fabric-loader = "net.fabricmc:fabric-loader:0.18.6" +fabric-loader = "net.fabricmc:fabric-loader:0.19.0" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.1+26.1.1" From f1281bf9d5d40cd860bbbe2e53095eeacac84b10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 15:17:24 +0000 Subject: [PATCH 27/91] fix(deps): update dependency net.fabricmc:fabric-loader to v0.19.1 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8f07b96d5..a3e86290e 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -32,7 +32,7 @@ adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0-SNAPSHOT" asm-tree = "org.ow2.asm:asm-tree:9.9.1" -fabric-loader = "net.fabricmc:fabric-loader:0.19.0" +fabric-loader = "net.fabricmc:fabric-loader:0.19.1" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.1+26.1.1" From 1aa7a90b3e4db505a599b19b36d16869551260f7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 9 Apr 2026 20:30:02 +0000 Subject: [PATCH 28/91] fix(deps): update dependency dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin to v3 --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 198918c9c..4aead06bc 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,6 +18,6 @@ dependencies { implementation(libs.build.paperweight) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.2.0") - implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:2.2.2") + implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:3.0.0") implementation("com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin:0.36.0") } From 765f1c2b72f1b19375ea0d33ab414459412791fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 10 Apr 2026 00:35:21 +0000 Subject: [PATCH 29/91] fix(deps): update dependency dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin to v3.0.1 --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 4aead06bc..26cf6acc8 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,6 +18,6 @@ dependencies { implementation(libs.build.paperweight) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.2.0") - implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:3.0.0") + implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:3.0.1") implementation("com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin:0.36.0") } From 47f3caca10a87c5efb8937669e9ec37a034b187c Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Fri, 10 Apr 2026 11:48:37 +0900 Subject: [PATCH 30/91] feat: 26.1.2 --- BANNER.md | 2 +- README.md | 2 +- api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java | 2 +- .../kr/toxicity/model/api/version/MinecraftVersion.java | 4 ++++ changelog/3.0.0.md | 4 ++-- .../kr/toxicity/model/bukkit/BetterModelProperties.kt | 5 ++--- gradle.properties | 2 +- gradle/libs.versions.toml | 6 +++--- 8 files changed, 15 insertions(+), 12 deletions(-) diff --git a/BANNER.md b/BANNER.md index 8fc272819..64b13604f 100644 --- a/BANNER.md +++ b/BANNER.md @@ -69,7 +69,7 @@ BetterModel supports **player model with using user's custom skin without textur ## 🏗️ Supported environment -[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1.x-8FCA5C?style=for-the-badge)](https://www.minecraft.net/en-us/download/server) [![](https://img.shields.io/badge/java-25%7E-ED8B00?style=for-the-badge)](https://adoptium.net/) ### Bukkit diff --git a/README.md b/README.md index ddb9045e7..ae1c49412 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim ## 🛠️ Build info -[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1-8FCA5C)](https://www.minecraft.net/en-us/download/server) +[![](https://img.shields.io/badge/minecraft-1.21.4%7E26.1.x-8FCA5C)](https://www.minecraft.net/en-us/download/server) [![](https://img.shields.io/badge/java-25%7E-ED8B00)](https://adoptium.net/) #### Build diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java index f0f82b6b1..9fe0cb7cb 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMSVersion.java @@ -48,7 +48,7 @@ public enum NMSVersion { */ V1_21_R7(75), /** - * Minecraft 26.1 + * Minecraft 26.1.x * @since 3.0.0 */ V26_R1(84) diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index f3714bcaf..cfb970de6 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -20,6 +20,10 @@ * @param patch minor update */ public record MinecraftVersion(int major, int minor, int patch) implements Comparable { + /** + * 26.1.2 + */ + public static final MinecraftVersion V26_1_2 = of(26, 1, 2); /** * 26.1.1 */ diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 5a2e5ed31..3eadf93ad 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -7,12 +7,12 @@ As with 2.0.0, there are several **Breaking Changes**, so please take note when ## ✨ Feats -### [Minecraft 26.1 / 26.1.1](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support +### [Minecraft 26.1.x](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support ![](https://github.com/user-attachments/assets/0153e97a-e320-41d1-8d94-ed626127b0cc) -From now on, BetterModel supports running on Minecraft 26.1 / 26.1.1 Servers. +From now on, BetterModel supports running on Minecraft 26.1.x Servers. --- diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt index d1ee599e6..3ee826f35 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelProperties.kt @@ -37,20 +37,19 @@ internal class BetterModelProperties( val version = parse(Bukkit.getBukkitVersion().substringBefore('-')) val nms = when (version) { - V26_1, V26_1_1 -> Latest() + V26_1, V26_1_1, V26_1_2 -> Latest() V1_21_11 -> kr.toxicity.model.bukkit.nms.v1_21_R7.NMSImpl() V1_21_9, V1_21_10 -> kr.toxicity.model.bukkit.nms.v1_21_R6.NMSImpl() V1_21_6, V1_21_7, V1_21_8 -> kr.toxicity.model.bukkit.nms.v1_21_R5.NMSImpl() V1_21_5 -> kr.toxicity.model.bukkit.nms.v1_21_R4.NMSImpl() V1_21_4 -> kr.toxicity.model.bukkit.nms.v1_21_R3.NMSImpl() - else if BetterModelBukkit.IS_PAPER -> { + else -> { warn( "Note: this version is officially untested.".toComponent(), "So be careful to use!".toComponent() ) Latest() } - else -> throw RuntimeException("Unsupported version: $version") } val scheduler = if (BetterModelBukkit.IS_FOLIA) PaperScheduler() else BukkitScheduler() val evaluator = BetterModelEvaluatorImpl() diff --git a/gradle.properties b/gradle.properties index 12c79f11b..c64ccf548 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,4 +7,4 @@ org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 project_version=3.0.0 -minecraft_version=26.1.1 +minecraft_version=26.1.2 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a3e86290e..0154bbe32 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.145.4+26.1.1" +fabric-api = "0.145.4+26.1.2" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released @@ -16,7 +16,7 @@ cloud-core = "2.0.0" configurate = "4.2.0" -neoform = "26.1.1-1" +neoform = "26.1.2-1" [libraries] kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } @@ -35,7 +35,7 @@ asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.19.1" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.1+26.1.1" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.2+26.1.1" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } From eb1e13f54abe27d539820b57ef1e14cd1f5a28b1 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 11 Apr 2026 21:06:47 +0000 Subject: [PATCH 31/91] fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.12.0 --- core/bukkit-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index fc093db78..2871aa30a 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -23,7 +23,7 @@ dependencies { compileOnly("net.citizensnpcs:citizens-main:2.0.42-SNAPSHOT") { exclude("net.byteflux") } - compileOnly("net.skinsrestorer:skinsrestorer-api:15.11.1") + compileOnly("net.skinsrestorer:skinsrestorer-api:15.12.0") compileOnly("io.lumine:Mythic-Dist:5.11.2") compileOnly("com.nexomc:nexo:1.21.0") } From 7cb06edb23e9fae0d0477356d2e81442c9b780aa Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 12 Apr 2026 19:07:52 +0900 Subject: [PATCH 32/91] chore: update cloud --- buildSrc/src/main/kotlin/Extensions.kt | 3 +- .../main/kotlin/bukkit-conventions.gradle.kts | 6 +-- .../model/bukkit/BetterModelLibrary.java | 38 +++++++++---------- gradle/libs.versions.toml | 9 ++--- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index e376d30e1..5f3b2d582 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -9,7 +9,8 @@ val Project.libs val LATEST_VERSION = listOf( "26.1", - "26.1.1" + "26.1.1", + "26.1.2" ) val SUPPORTED_VERSIONS = buildList { diff --git a/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts b/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts index 0a085ab6d..e1e5454b4 100644 --- a/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/bukkit-conventions.gradle.kts @@ -2,9 +2,9 @@ plugins { id("standard-conventions") } -val minecraft = "1.21.11" //TODO change this to property("minecraft_version").toString() +val minecraft = property("minecraft_version").toString() dependencies { - compileOnly("io.papermc.paper:paper-api:$minecraft-R0.1-SNAPSHOT") - testImplementation("io.papermc.paper:paper-api:$minecraft-R0.1-SNAPSHOT") + compileOnly("io.papermc.paper:paper-api:$minecraft.build.+") + testImplementation("io.papermc.paper:paper-api:$minecraft.build.+") } diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java index 7461a2f28..bce49e110 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java @@ -39,25 +39,25 @@ public final class BetterModelLibrary { "bstats-base" ) ); -// public static final LibraryData CLOUD = register( -// "org{}incendo", -// "cloud-paper", -// builder -> builder -// .subModules( -// "cloud-brigadier", -// "cloud-bukkit" -// ) -// .relocation("org{}incendo{}cloud") -// ); -// public static final LibraryData CLOUD_CORE = register( -// "org{}incendo", -// "cloud-core", -// builder -> builder -// .subModules( -// "cloud-services" -// ) -// .relocation("org{}incendo{}cloud") -// ); + public static final LibraryData CLOUD = register( + "org{}incendo", + "cloud-paper", + builder -> builder + .subModules( + "cloud-brigadier", + "cloud-bukkit" + ) + .relocation("org{}incendo{}cloud") + ); + public static final LibraryData CLOUD_CORE = register( + "org{}incendo", + "cloud-core", + builder -> builder + .subModules( + "cloud-services" + ) + .relocation("org{}incendo{}cloud") + ); public static final LibraryData GEANTYREF = register( "io{}leangen{}geantyref", "geantyref", diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 0154bbe32..231c1d377 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -10,8 +10,8 @@ hangarPublish = "0.1.4" fabric-api = "0.145.4+26.1.2" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" -cloud-bukkit = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.15 when released -cloud-mod = "2.0.0-SNAPSHOT" #TODO update this to 2.0.0-beta.16 when released +cloud-bukkit = "2.0.0-beta.15" +cloud-mod = "2.0.0-beta.16" cloud-core = "2.0.0" configurate = "4.2.0" @@ -106,7 +106,7 @@ manifestLibrary = [ "kotlin", "bStats", "molangCompiler", - #"cloud-paper", + "cloud-paper", "cloud-core", "geantyref", "adventure-api", @@ -118,8 +118,7 @@ manifestLibrary = [ shadedLibrary = [ "armormodel", - "libby", - "cloud-paper" + "libby" ] [plugins] From 3914715b2bce38a89a64021e603decde1a2e3015 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 12 Apr 2026 19:09:16 +0900 Subject: [PATCH 33/91] fix: global rot (#325) --- .../toxicity/model/api/bone/RenderedBone.java | 47 ++++++++++++++----- .../api/data/renderer/RenderPipeline.java | 20 ++++++-- .../model/api/tracker/EntityTracker.java | 4 +- 3 files changed, 52 insertions(+), 19 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java index 6dd882efe..dcb947bb8 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java @@ -53,7 +53,6 @@ public final class RenderedBone implements BoneEventHandler { private static final int INITIAL_TINT_VALUE = 0xFFFFFF; private static final Vector3f EMPTY_VECTOR = new Vector3f(); - private static final Quaternionf EMPTY_QUATERNION = new Quaternionf(); private static final BonePosition EMPTY_POSITION = new BonePosition(EMPTY_VECTOR, EMPTY_VECTOR, null); @Getter @@ -106,8 +105,8 @@ public final class RenderedBone implements BoneEventHandler { private Function positionModifier = p -> p; private Vector3f lastModifiedPosition = new Vector3f(); - private Function rotationModifier = r -> r; - private Quaternionf lastModifiedRotation = new Quaternionf(); + private Function localRotModifier = r -> r, globalRotModifier = r -> r; + private Quaternionf lastModifiedLocalRot = new Quaternionf(), lastModifiedGlobalRot = new Quaternionf(); /** * Creates entity. @@ -284,14 +283,28 @@ public boolean itemStack(@NotNull Predicate predicate, @NotNull Tr } /** - * Adds rotation modifier. + * Adds local rot modifier. * @param predicate predicate * @param function animation consumer * @return whether to success */ - public synchronized boolean addRotationModifier(@NotNull Predicate predicate, @NotNull Function function) { + public synchronized boolean addLocalRotModifier(@NotNull Predicate predicate, @NotNull Function function) { if (predicate.test(this)) { - rotationModifier = rotationModifier.andThen(function); + localRotModifier = localRotModifier.andThen(function); + return true; + } + return false; + } + + /** + * Adds global rot modifier. + * @param predicate predicate + * @param function animation consumer + * @return whether to success + */ + public synchronized boolean addGlobalRotModifier(@NotNull Predicate predicate, @NotNull Function function) { + if (predicate.test(this)) { + globalRotModifier = globalRotModifier.andThen(function); return true; } return false; @@ -389,8 +402,12 @@ public void defaultPosition(@NotNull Supplier movement) { return preventModifierUpdate ? lastModifiedPosition : (lastModifiedPosition = positionModifier.apply(lastModifiedPosition.set(EMPTY_VECTOR))); } - private @NotNull Quaternionf modifiedRotation(boolean preventModifierUpdate) { - return preventModifierUpdate ? lastModifiedRotation : (lastModifiedRotation = rotationModifier.apply(lastModifiedRotation.set(EMPTY_QUATERNION))); + private @NotNull Quaternionf modifiedLocalRot(boolean preventModifierUpdate) { + return preventModifierUpdate ? lastModifiedLocalRot : (lastModifiedLocalRot = localRotModifier.apply(lastModifiedLocalRot.identity())); + } + + private @NotNull Quaternionf modifiedGlobalRot(boolean preventModifierUpdate) { + return preventModifierUpdate ? lastModifiedGlobalRot : (lastModifiedGlobalRot = globalRotModifier.apply(lastModifiedGlobalRot.identity())); } public boolean tint(@NotNull Predicate predicate) { @@ -545,7 +562,7 @@ final class BoneStateHandler { //Caches private final Vector3f positionCache = new Vector3f(), scaleCache = new Vector3f(); - private final Quaternionf rotationCache = new Quaternionf(); + private final Quaternionf localRotCache = new Quaternionf(), globalRotCache = new Quaternionf(); //Lock private final DuplexLock lock = new DuplexLock(); @@ -573,12 +590,16 @@ private BoneStateHandler(@Nullable UUID uuid, @NotNull Consumer consumer) ).sub(parent.lastModifiedPosition) .add(modifiedPosition(preventModifierUpdate)); def.scale().mul(p.scale()); - def.rotation().set((keyframe.globalRotation() ? rotationCache.identity() : p.rotation().div(parent.lastModifiedRotation, rotationCache)) - .mul(def.rotation()) - .mul(modifiedRotation(preventModifierUpdate))); + def.rotation().set(parent.lastModifiedGlobalRot.invert(globalRotCache) + .mul(modifiedGlobalRot(preventModifierUpdate)) + .mul((keyframe.globalRotation() ? localRotCache.identity() : p.rotation().div(parent.lastModifiedLocalRot, localRotCache)).mul(def.rotation())) + .mul(modifiedLocalRot(preventModifierUpdate)) + ); } else { def.position().add(modifiedPosition(preventModifierUpdate)); - def.rotation().mul(modifiedRotation(preventModifierUpdate)); + def.rotation().set(modifiedGlobalRot(preventModifierUpdate).get(globalRotCache) + .mul(def.rotation()) + .mul(modifiedLocalRot(preventModifierUpdate))); } return def; } diff --git a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java index f4853f890..2440adfd7 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java +++ b/api/src/main/java/kr/toxicity/model/api/data/renderer/RenderPipeline.java @@ -322,15 +322,27 @@ public void scale(@NotNull FloatSupplier scale) { } /** - * Adds a rotation modifier to matching bones. + * Adds a local rotation modifier to matching bones. * * @param predicate the predicate to select bones * @param mapper the rotation mapping function * @return true if any bones were modified - * @since 1.15.2 + * @since 3.0.0 + */ + public boolean addLocalRotModifier(@NotNull BonePredicate predicate, @NotNull Function mapper) { + return matchTree(predicate, (b, p) -> b.addLocalRotModifier(p, mapper)); + } + + /** + * Adds a global rotation modifier to matching bones. + * + * @param predicate the predicate to select bones + * @param mapper the rotation mapping function + * @return true if any bones were modified + * @since 3.0.0 */ - public boolean addRotationModifier(@NotNull BonePredicate predicate, @NotNull Function mapper) { - return matchTree(predicate, (b, p) -> b.addRotationModifier(p, mapper)); + public boolean addGlobalRotModifier(@NotNull BonePredicate predicate, @NotNull Function mapper) { + return matchTree(predicate, (b, p) -> b.addGlobalRotModifier(p, mapper)); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java index 5a0ba6d66..a2334725b 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTracker.java @@ -120,8 +120,8 @@ public EntityTracker(@NotNull EntityTrackerRegistry registry, @NotNull RenderPip pipeline.scale(scale); Function headRotator = r -> r.mul(bodyRotator.headRotation()); - pipeline.addRotationModifier(HEAD_PREDICATE, headRotator); - pipeline.addRotationModifier(HEAD_WITH_CHILDREN_PREDICATE, headRotator); + pipeline.addGlobalRotModifier(HEAD_PREDICATE, headRotator); + pipeline.addGlobalRotModifier(HEAD_WITH_CHILDREN_PREDICATE, headRotator); createNametag(CREATE_NAMETAG_PREDICATE, (bone, tag) -> { if (bone.name().tagged(BoneTags.PLAYER_TAG)) { From 957fb6c6ab2b36548585974d04eec98b37f90e9a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 12 Apr 2026 19:09:45 +0900 Subject: [PATCH 34/91] chore: update 3.0.0.md --- changelog/3.0.0.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index 3eadf93ad..bf05ee147 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -72,22 +72,26 @@ dependencies { ## 🔧 Fixes - fix: swap unsupported char to hashcode -- fix: unnecessary decimal value (\#299) +- fix: unnecessary decimal value (#299) +- fix: global rot (#325) --- ## 🧹 Chores +- chore: com.vdurmont:semver4j -> org.semver4j:semver4j - fix(deps): update dependency com.nexomc:nexo to v1.21.0 - chore(deps): update gradle to v9.4.1 - fix(deps): update dependency com.gradleup.shadow:com.gradleup.shadow.gradle.plugin to v9.4.1 - fix(deps): update dependency org.jetbrains.dokka:dokka-gradle-plugin to v2.2.0 - fix(deps): update kotlin monorepo to v2.3.20 - fix(deps): update dependency net.fabricmc:fabric-language-kotlin to v1.13.10+kotlin.2.3.20 -- fix(deps): update dependency net.fabricmc:fabric-loader to v0.18.6 +- fix(deps): update dependency net.fabricmc:fabric-loader to v0.19.1 - fix(deps): update dependency com.modrinth.minotaur:com.modrinth.minotaur.gradle.plugin to v2.9.0 - fix(deps): update dependency org.projectlombok:lombok to v1.18.44 -- fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.11.1 +- fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.12.0 +- chore: update net.citizensnpcs:citizens-main to 2.0.42-SNAPSHOT +- chore: update polymer-resource-pack to 0.16.2+26.1.1 --- From 41bad24c6c4a27bac39aae38fff590456da6564a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 13 Apr 2026 15:23:14 +0900 Subject: [PATCH 35/91] chore: update Purpur api --- purpur/build.gradle.kts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/purpur/build.gradle.kts b/purpur/build.gradle.kts index 4ef20ec17..57c454417 100644 --- a/purpur/build.gradle.kts +++ b/purpur/build.gradle.kts @@ -5,6 +5,5 @@ plugins { dependencies { compileOnly(project(":bettermodel-api")) compileOnly(project(":bettermodel-api:bettermodel-bukkit-api")) - //TODO change this to compileOnly("org.purpurmc.purpur:purpur-api:${property("minecraft_version")}-R0.1-SNAPSHOT") - compileOnly("org.purpurmc.purpur:purpur-api:1.21.11-R0.1-SNAPSHOT") + compileOnly("org.purpurmc.purpur:purpur-api:${property("minecraft_version")}.build.+") } From d09415041564c6a300bee89d1f19dfc246a42d1d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 13 Apr 2026 15:33:58 +0900 Subject: [PATCH 36/91] fix: close limb when reloading --- .../toxicity/model/api/animation/Timed.java | 3 ++- .../model/api/data/raw/ModelAnimation.java | 27 ++++++++++--------- .../model/api/script/AnimationScript.java | 2 +- .../model/api/tracker/EntityHideOption.java | 8 +++--- .../api/tracker/EntityTrackerRegistry.java | 3 +-- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/Timed.java b/api/src/main/java/kr/toxicity/model/api/animation/Timed.java index 535e9dc23..86a034cb4 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/Timed.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/Timed.java @@ -7,6 +7,7 @@ package kr.toxicity.model.api.animation; +import kr.toxicity.model.api.util.MathUtil; import org.jetbrains.annotations.NotNull; /** @@ -15,7 +16,7 @@ public interface Timed extends Comparable { default int compareTo(@NotNull Timed o) { - return Float.compare(time(), o.time()); + return MathUtil.FRAME_COMPARATOR.compare(time(), o.time()); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java index 1b63c2924..3f5357feb 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java @@ -7,6 +7,7 @@ package kr.toxicity.model.api.data.raw; +import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.animation.AnimationIterator; import kr.toxicity.model.api.animation.AnimationProgress; @@ -89,31 +90,31 @@ public record ModelAnimation( ); } - private @Nullable BlueprintScript toScript(@NotNull ModelAnimator animator, @NotNull ModelPlaceholder placeholder) { - var get = animator.stream() + private @NotNull BlueprintScript toScript(@NotNull ModelAnimator animator, @NotNull ModelPlaceholder placeholder) { + var set = new ObjectAVLTreeSet(); + set.add(TimeScript.EMPTY); + set.add(TimeScript.EMPTY.time(length())); + animator.stream() .filter(f -> f.point().hasScript()) .map(d -> AnimationScript.of(Arrays.stream(placeholder.parseVariable(d.point().script()).split("\n")) .map(BetterModel.platform().scriptManager()::build) .filter(Objects::nonNull) - .toList() - ).time(d.time())) - .toList(); - if (get.isEmpty()) return null; - var list = new ArrayList(get.size() + 2); - if (get.getFirst().time() > 0) list.add(TimeScript.EMPTY); + .toList()) + .time(d.time())) + .forEach(set::add); + var array = new TimeScript[set.size()]; var before = 0F; - for (TimeScript timeScript : get) { + var i = 0; + for (TimeScript timeScript : set) { var t = timeScript.time(); - list.add(timeScript.time(InterpolationUtil.roundTime(t - before))); + array[i++] = timeScript.time(InterpolationUtil.roundTime(t - before)); before = t; } - var len = InterpolationUtil.roundTime(length() - before); - if (len > 0) list.add(AnimationScript.EMPTY.time(len)); return new BlueprintScript( name(), loop(), length(), - list + List.of(array) ); } diff --git a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java index a0aca53b2..95c5c6668 100644 --- a/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java +++ b/api/src/main/java/kr/toxicity/model/api/script/AnimationScript.java @@ -85,7 +85,7 @@ public void accept(@NotNull Tracker tracker) { var sync = false; Consumer consumer = _ -> {}; for (AnimationScript entityScript : scriptList) { - sync = sync || entityScript.isSync(); + sync |= entityScript.isSync(); consumer = consumer.andThen(entityScript); } yield of(sync, consumer); diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java index 2c493b79e..b3bac28f1 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityHideOption.java @@ -138,10 +138,10 @@ private Builder() { * @since 1.15.2 */ public @NotNull Builder or(@NotNull EntityHideOption option) { - equipment = equipment || option.equipment; - fire = fire || option.fire; - visibility = visibility || option.visibility; - glowing = glowing || option.glowing; + equipment |= option.equipment; + fire |= option.fire; + visibility |= option.visibility; + glowing |= option.glowing; return this; } diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java index 6a6b64c1a..f2b0ee53f 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/EntityTrackerRegistry.java @@ -383,9 +383,8 @@ public void reload() { closed.set(true); var data = new ArrayList(trackerMap.size()); for (EntityTracker value : trackers()) { - if (!value.canBeSaved()) continue; - data.add(value.asTrackerData()); value.close(); + if (value.canBeSaved()) data.add(value.asTrackerData()); } trackerMap.clear(); closed.set(false); From 390636f17af95c391b2bc4ec2704ed19f983c24e Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 14 Apr 2026 16:16:25 +0900 Subject: [PATCH 37/91] refactor: remove unused code --- .../java/kr/toxicity/model/api/nms/NMS.java | 9 --------- .../model/bukkit/nms/v1_21_R3/NMSImpl.kt | 11 ----------- .../model/bukkit/nms/v1_21_R4/NMSImpl.kt | 11 ----------- .../model/bukkit/nms/v1_21_R5/NMSImpl.kt | 11 ----------- .../model/bukkit/nms/v1_21_R6/NMSImpl.kt | 14 -------------- .../model/bukkit/nms/v1_21_R7/NMSImpl.kt | 14 -------------- .../model/bukkit/nms/v26_R1/NMSImpl.kt | 14 -------------- .../model/impl/fabric/BetterModelNMSImpl.kt | 19 ------------------- 8 files changed, 103 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java index 129c9cf59..2f2810e1a 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/NMS.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/NMS.java @@ -227,15 +227,6 @@ default void hide(@NotNull PlayerChannelHandler channel, @NotNull EntityTrackerR */ @NotNull ModelProfile profile(@NotNull PlatformPlayer player); - /** - * Creates a player head item stack from a model profile. - * - * @param profile the model profile - * @return the player head item - * @since 1.15.2 - */ - @NotNull PlatformItemStack createPlayerHead(@NotNull ModelProfile profile); - /** * Creates a custom skin item stack. * diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt index 620b85956..0d793a6e8 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt @@ -9,7 +9,6 @@ package kr.toxicity.model.bukkit.nms.v1_21_R3 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -54,7 +53,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -378,15 +376,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile(GameProfile( - profile.info().id, - profile.info().name ?: "", - ).apply { - properties.put("textures", Property("textures", profile.skin().raw)) - })) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt index bd10ac46c..78e1a80fe 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt @@ -9,7 +9,6 @@ package kr.toxicity.model.bukkit.nms.v1_21_R4 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -53,7 +52,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -379,15 +377,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile(GameProfile( - profile.info().id, - profile.info().name ?: "", - ).apply { - properties.put("textures", Property("textures", profile.skin().raw)) - })) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt index 8e6b574f8..a64d1ba5e 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt @@ -9,7 +9,6 @@ package kr.toxicity.model.bukkit.nms.v1_21_R5 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -53,7 +52,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -379,15 +377,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile(GameProfile( - profile.info().id, - profile.info().name ?: "", - ).apply { - properties.put("textures", Property("textures", profile.skin().raw)) - })) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt index ad8058cf0..a3eabf2a6 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt @@ -8,10 +8,7 @@ package kr.toxicity.model.bukkit.nms.v1_21_R6 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup -import com.google.common.collect.ImmutableMultimap import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property -import com.mojang.authlib.properties.PropertyMap import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -55,7 +52,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -377,16 +373,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile.createResolved(GameProfile( - profile.info().id, - profile.info().name ?: "", - PropertyMap(ImmutableMultimap.of( - "textures", Property("textures", profile.skin().raw) - )) - ))) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt index aa65eb220..2e9086d20 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt @@ -8,10 +8,7 @@ package kr.toxicity.model.bukkit.nms.v1_21_R7 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup -import com.google.common.collect.ImmutableMultimap import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property -import com.mojang.authlib.properties.PropertyMap import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -54,7 +51,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -376,16 +372,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile.createResolved(GameProfile( - profile.info().id, - profile.info().name ?: "", - PropertyMap(ImmutableMultimap.of( - "textures", Property("textures", profile.skin().raw) - )) - ))) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt index bb94daef6..68c958767 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt @@ -8,10 +8,7 @@ package kr.toxicity.model.bukkit.nms.v26_R1 import ca.spottedleaf.moonrise.patches.chunk_system.level.entity.EntityLookup -import com.google.common.collect.ImmutableMultimap import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property -import com.mojang.authlib.properties.PropertyMap import io.netty.channel.ChannelDuplexHandler import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelPromise @@ -54,7 +51,6 @@ import net.minecraft.world.item.ItemDisplayContext import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import net.minecraft.world.level.entity.LevelEntityGetter import net.minecraft.world.level.entity.LevelEntityGetterAdapter import net.minecraft.world.level.entity.PersistentEntitySectionManager @@ -376,16 +372,6 @@ class NMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelGameProfile(getGameProfile((player.unwarp() as CraftPlayer).handle)) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = VanillaItemStack(Items.PLAYER_HEAD).apply { - set(DataComponents.PROFILE, ResolvableProfile.createResolved(GameProfile( - profile.info().id, - profile.info().name ?: "", - PropertyMap(ImmutableMultimap.of( - "textures", Property("textures", profile.skin().raw) - )) - ))) - }.asBukkit().wrap() - override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { return VanillaItemStack(Items.PLAYER_HEAD).run { set(DataComponents.CUSTOM_MODEL_DATA, CustomModelData(floats, flags, strings, colors)) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt index 7bd0cb9a7..82df11a3e 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelNMSImpl.kt @@ -7,10 +7,6 @@ package kr.toxicity.model.impl.fabric -import com.google.common.collect.ImmutableMultimap -import com.mojang.authlib.GameProfile -import com.mojang.authlib.properties.Property -import com.mojang.authlib.properties.PropertyMap import kr.toxicity.model.api.bone.RenderedBone import kr.toxicity.model.api.data.blueprint.ModelBoundingBox import kr.toxicity.model.api.entity.BaseEntity @@ -45,7 +41,6 @@ import net.minecraft.world.item.ItemStack import net.minecraft.world.item.Items import net.minecraft.world.item.component.CustomModelData import net.minecraft.world.item.component.DyedItemColor -import net.minecraft.world.item.component.ResolvableProfile import org.joml.Vector3d import java.util.function.Consumer @@ -170,20 +165,6 @@ class BetterModelNMSImpl : NMS { override fun profile(player: PlatformPlayer): ModelProfile = ModelProfileImpl(player.unwarp().player.gameProfile) - override fun createPlayerHead(profile: ModelProfile): PlatformItemStack = Items.PLAYER_HEAD.defaultInstance - .apply { - val gameProfileProperty = ImmutableMultimap.of( - "textures", - Property("textures", profile.skin().raw) - ) - val gameProfile = GameProfile( - profile.info().id, - profile.info().name ?: "", - PropertyMap(gameProfileProperty) - ) - set(DataComponents.PROFILE, ResolvableProfile.createResolved(gameProfile)) - }.wrap() - override fun isProxyOnlineMode(): Boolean = (PLATFORM as BetterModelMod).server().usesAuthentication() override fun createSkinItem(model: String, floats: List, flags: List, strings: List, colors: List): TransformedItemStack { From 7c3de5ff53db79e369c30d39b70c9e7ded6a3376 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 14 Apr 2026 16:57:10 +0900 Subject: [PATCH 38/91] perf: minor optimization for some method --- .../toxicity/model/api/bone/RenderedBone.java | 8 +++++--- .../model/bukkit/nms/v1_21_R3/Functions.kt | 2 +- .../model/bukkit/nms/v1_21_R3/NMSImpl.kt | 3 ++- .../model/bukkit/nms/v1_21_R4/Functions.kt | 4 ++-- .../model/bukkit/nms/v1_21_R4/NMSImpl.kt | 3 ++- .../model/bukkit/nms/v1_21_R5/Functions.kt | 4 ++-- .../model/bukkit/nms/v1_21_R5/NMSImpl.kt | 3 ++- .../model/bukkit/nms/v1_21_R6/Functions.kt | 4 ++-- .../model/bukkit/nms/v1_21_R6/NMSImpl.kt | 3 ++- .../model/bukkit/nms/v1_21_R7/Functions.kt | 4 ++-- .../model/bukkit/nms/v1_21_R7/NMSImpl.kt | 3 ++- .../model/bukkit/nms/v26_R1/Functions.kt | 4 ++-- .../toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt | 3 ++- .../model/impl/fabric/BetterModelLoggerImpl.kt | 17 ++--------------- .../model/impl/fabric/network/Packets.kt | 10 ++++++---- .../src/main/resources/bettermodel.mixins.json | 2 +- 16 files changed, 37 insertions(+), 40 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java index dcb947bb8..26bb4c2d9 100644 --- a/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java +++ b/api/src/main/java/kr/toxicity/model/api/bone/RenderedBone.java @@ -10,6 +10,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSortedSets; import kr.toxicity.model.api.BetterModel; import kr.toxicity.model.api.animation.*; import kr.toxicity.model.api.data.blueprint.BlueprintAnimation; @@ -492,15 +493,16 @@ public void remove(@NotNull PacketBundler bundler) { @Unmodifiable @NotNull public SequencedSet flattenBones() { - if (flattenBones != null) return flattenBones; + SequencedSet set; + if ((set = flattenBones) != null) return set; synchronized (this) { - if (flattenBones != null) return flattenBones; + if ((set = flattenBones) != null) return set; return flattenBones = children.length == 0 ? SingletonSequencedSet.of(this) : Stream.concat( Stream.of(this), Arrays.stream(children).flatMap(RenderedBone::flatten) ).collect(Collectors.collectingAndThen( Collectors.toCollection(ObjectLinkedOpenHashSet::new), - Collections::unmodifiableSequencedSet + ObjectSortedSets::unmodifiable )); } } diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt index 13de53699..c0c9973fd 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/Functions.kt @@ -180,7 +180,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selected + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt index 0d793a6e8..c3a8bb493 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/NMSImpl.kt @@ -62,6 +62,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -235,7 +236,7 @@ class NMSImpl : NMS { containerId, stateId, (items as NonNullList).apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt index 62321d30d..abd5914fe 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/Functions.kt @@ -173,7 +173,7 @@ internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } } @@ -182,7 +182,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt index 78e1a80fe..c308d040d 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/NMSImpl.kt @@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -236,7 +237,7 @@ class NMSImpl : NMS { containerId, stateId, items.apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt index cf0c468e1..f989f8297 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/Functions.kt @@ -172,7 +172,7 @@ internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } } @@ -181,7 +181,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt index a64d1ba5e..dbdcfaaa0 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/NMSImpl.kt @@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -236,7 +237,7 @@ class NMSImpl : NMS { containerId, stateId, items.apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt index 64e8cd32c..5a3d810f2 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/Functions.kt @@ -176,7 +176,7 @@ internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } } @@ -185,7 +185,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt index a3eabf2a6..21aa177cf 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/NMSImpl.kt @@ -61,6 +61,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -236,7 +237,7 @@ class NMSImpl : NMS { containerId, stateId, items.apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt index 72f2ea59a..819a335e8 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/Functions.kt @@ -176,7 +176,7 @@ internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } } @@ -185,7 +185,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt index 2e9086d20..78d5947c2 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/NMSImpl.kt @@ -60,6 +60,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -235,7 +236,7 @@ class NMSImpl : NMS { containerId, stateId, items.apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt index 47018fa62..6b84b5a54 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/Functions.kt @@ -176,7 +176,7 @@ internal fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { internal fun Vector3f.toVanilla() = Vec3(x.toDouble(), y.toDouble(), z.toDouble()) internal fun Vec3.toBukkit() = Vector3f(x.toFloat(), y.toFloat(), z.toFloat()) -internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> com.mojang.datafixers.util.Pair.of(it, item) } } @@ -185,7 +185,7 @@ internal inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> It internal fun LivingEntity.toEmptyEquipmentPacket() = toEquipmentPacket { ItemStack.EMPTY } internal val Player.hotbarSlot get() = inventory.selectedSlot + 36 -internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(*intArrayOf(45, 5, 6, 7, 8)) +internal val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) internal fun ClientboundContainerSetSlotPacket.isEquipment(player: Player) = containerId == 0 && (PLAYER_EQUIPMENT_SLOT.contains(slot) || slot == player.hotbarSlot) internal fun Entity.toFakeAddPacket() = ClientboundAddEntityPacket( diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt index 68c958767..733fa133f 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/NMSImpl.kt @@ -60,6 +60,7 @@ import org.bukkit.craftbukkit.entity.CraftPlayer import org.joml.Vector3d import java.util.* import java.util.function.Consumer +import java.util.function.IntConsumer class NMSImpl : NMS { @@ -235,7 +236,7 @@ class NMSImpl : NMS { containerId, stateId, items.apply { - PLAYER_EQUIPMENT_SLOT.forEach { set(it, EMPTY_ITEM) } + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { set(it, EMPTY_ITEM) }) set(connection.player.hotbarSlot, EMPTY_ITEM) }, carriedItem diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt index 0de11b565..a1bc135ab 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/BetterModelLoggerImpl.kt @@ -13,24 +13,12 @@ import net.kyori.adventure.text.logger.slf4j.ComponentLogger import java.util.logging.Logger class BetterModelLoggerImpl : BetterModelLogger { - private var logger: ComponentLogger? = null - private fun logger(): ComponentLogger { - logger?.let { logger -> - return logger - } - - synchronized(this) { - logger?.let { logger -> - return logger - } - - return ComponentLogger.logger(LOGGER.name).also { logger = it } - } + private val logger by lazy { + ComponentLogger.logger(LOGGER.name) } override fun info(vararg messages: Component) { - val logger = logger() synchronized(this) { for (message in messages) { logger.info(message) @@ -39,7 +27,6 @@ class BetterModelLoggerImpl : BetterModelLogger { } override fun warn(vararg messages: Component) { - val logger = logger() synchronized(this) { for (message in messages) { logger.warn(message) diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt index 13099d46b..88bbe78d2 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/network/Packets.kt @@ -9,6 +9,7 @@ package kr.toxicity.model.impl.fabric.network import com.mojang.datafixers.util.Pair.of import io.netty.buffer.Unpooled +import it.unimi.dsi.fastutil.ints.IntSet import kr.toxicity.model.api.tracker.EntityTrackerRegistry import kr.toxicity.model.mixin.ConnectionAccessor import kr.toxicity.model.mixin.EntityAccessor @@ -31,6 +32,7 @@ import net.minecraft.world.entity.LivingEntity import net.minecraft.world.entity.player.Player import net.minecraft.world.item.ItemStack import java.util.* +import java.util.function.IntConsumer import java.util.stream.IntStream val Connection.channel get() = (this as ConnectionAccessor).`bettermodel$getChannel`() @@ -118,7 +120,7 @@ fun EntityTrackerRegistry.entityFlag(uuid: UUID, byte: Byte): Byte { return b.toByte() } -inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { if (hasItemInSlot(it)) getItemBySlot(it) else null }): ClientboundSetEquipmentPacket? { +inline fun LivingEntity.toEquipmentPacket(mapper: (EquipmentSlot) -> ItemStack? = { getItemBySlot(it).takeUnless { item -> item.isEmpty } }): ClientboundSetEquipmentPacket? { val equip = EquipmentSlot.entries.mapNotNull { mapper(it)?.let { item -> of(it, item) } } @@ -132,9 +134,9 @@ fun ClientboundContainerSetSlotPacket.isEquipment(player: Player): Boolean { } fun eachEquipmentSlots(block: (Int) -> Unit) { - PLAYER_EQUIPMENT_SLOT.forEach { slot -> + PLAYER_EQUIPMENT_SLOT.forEach(IntConsumer { slot -> block(slot) - } + }) } -private val PLAYER_EQUIPMENT_SLOT = setOf(45, 5, 6, 7, 8) +private val PLAYER_EQUIPMENT_SLOT = IntSet.of(45, 5, 6, 7, 8) diff --git a/platform/fabric/src/main/resources/bettermodel.mixins.json b/platform/fabric/src/main/resources/bettermodel.mixins.json index 64093ced7..cce623e0b 100644 --- a/platform/fabric/src/main/resources/bettermodel.mixins.json +++ b/platform/fabric/src/main/resources/bettermodel.mixins.json @@ -1,7 +1,7 @@ { "required": true, "package": "kr.toxicity.model.mixin", - "compatibilityLevel": "JAVA_21", + "compatibilityLevel": "JAVA_25", "mixins": [ "AvatarAccessor", "ClientboundBundlePacketMixin", From 254c344a386d78049abac3f4a9390f59f26e19df Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 14 Apr 2026 20:54:33 +0000 Subject: [PATCH 39/91] fix(deps): update dependency com.google.guava:guava to v33.6.0-jre --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 231c1d377..2d2698196 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -43,7 +43,7 @@ configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref joml = "org.joml:joml:1.10.8" gson = "com.google.code.gson:gson:2.13.2" fastutil = "it.unimi.dsi:fastutil:8.5.18" -guava = "com.google.guava:guava:33.5.0-jre" +guava = "com.google.guava:guava:33.6.0-jre" cloud-paper = { module = "org.incendo:cloud-paper", version.ref = "cloud-bukkit" } cloud-fabric = { module = "org.incendo:cloud-fabric", version.ref = "cloud-mod" } From 7d1e4d05c213aa758557dd323a8b3c6ae5e6606d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 05:27:27 +0000 Subject: [PATCH 40/91] fix(deps): update dependency net.kyori:adventure-platform-fabric to v6.9.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2d2698196..db087825b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -28,7 +28,7 @@ adventure-api = "net.kyori:adventure-api:4.26.1" adventure-examination = "net.kyori:examination-api:1.3.0" adventure-option = "net.kyori:option:1.1.0" adventure-platform-bukkit = "net.kyori:adventure-platform-bukkit:4.4.1" -adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0-SNAPSHOT" +adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0" asm-tree = "org.ow2.asm:asm-tree:9.9.1" From 291fd69d6219d69fad73e8cffa69f8a603e044f5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 15 Apr 2026 14:42:27 +0900 Subject: [PATCH 41/91] chore: write 3.0.0.md --- changelog/3.0.0.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/changelog/3.0.0.md b/changelog/3.0.0.md index bf05ee147..943c66ed5 100644 --- a/changelog/3.0.0.md +++ b/changelog/3.0.0.md @@ -7,7 +7,7 @@ As with 2.0.0, there are several **Breaking Changes**, so please take note when ## ✨ Feats -### [Minecraft 26.1.x](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-1) Support +### [Minecraft 26.1.x](https://www.minecraft.net/en-us/article/minecraft-java-edition-26-1-2) Support ![](https://github.com/user-attachments/assets/0153e97a-e320-41d1-8d94-ed626127b0cc) @@ -29,6 +29,8 @@ It is available on Minecraft clients version 26.1 and above. - Support meg-client-mod. - A `priority` property has been added to the `AnimationModifier` class, allowing you to adjust the application order of animations. +- perf: minor optimization for some method +- refactor: remove unused code --- @@ -64,21 +66,28 @@ dependencies { api("io.github.toxicity188:bettermodel-fabric:3.0.0") } ``` -
--- +### Deprecation of 1.21.3 Support +To keep the project lightweight, support for versions 1.21.3 and below will be discontinued. Therefore, operation is only guaranteed on servers and clients version 1.21.4 or higher. + +--- + ## 🔧 Fixes - fix: swap unsupported char to hashcode - fix: unnecessary decimal value (#299) - fix: global rot (#325) +- fix: close limb when reloading --- ## 🧹 Chores +- chore: update cloud +- chore: update Purpur api - chore: com.vdurmont:semver4j -> org.semver4j:semver4j - fix(deps): update dependency com.nexomc:nexo to v1.21.0 - chore(deps): update gradle to v9.4.1 @@ -92,6 +101,8 @@ dependencies { - fix(deps): update dependency net.skinsrestorer:skinsrestorer-api to v15.12.0 - chore: update net.citizensnpcs:citizens-main to 2.0.42-SNAPSHOT - chore: update polymer-resource-pack to 0.16.2+26.1.1 +- fix(deps): update dependency com.google.guava:guava to v33.6.0-jre +- fix(deps): update dependency net.kyori:adventure-platform-fabric to v6.9.0 --- From 02dfef1c306b1b8ad1dda658b1f4d6db913bb3d5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 15 Apr 2026 19:23:32 +0900 Subject: [PATCH 42/91] update: 3.0.1 --- changelog/3.0.1.md | 2 ++ changelog/{ => v2}/2.2.0.md | 0 gradle.properties | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/3.0.1.md rename changelog/{ => v2}/2.2.0.md (100%) diff --git a/changelog/3.0.1.md b/changelog/3.0.1.md new file mode 100644 index 000000000..486813e34 --- /dev/null +++ b/changelog/3.0.1.md @@ -0,0 +1,2 @@ + +[Full change log](https://github.com/toxicity188/BetterModel/compare/3.0.0...3.0.1) diff --git a/changelog/2.2.0.md b/changelog/v2/2.2.0.md similarity index 100% rename from changelog/2.2.0.md rename to changelog/v2/2.2.0.md diff --git a/gradle.properties b/gradle.properties index c64ccf548..db6ac95e6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ org.gradle.configuration-cache=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -project_version=3.0.0 +project_version=3.0.1 minecraft_version=26.1.2 From 1bbf022b96a80483ec7c63d96e573952cdbad72c Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 15 Apr 2026 19:25:09 +0900 Subject: [PATCH 43/91] chore: update net.fabricmc.fabric-loom-repositories to 1.16-SNAPSHOT --- settings.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/settings.gradle.kts b/settings.gradle.kts index 2bae2953e..f19bfe09d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -11,7 +11,7 @@ pluginManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0" - id("net.fabricmc.fabric-loom-repositories") version "1.15-SNAPSHOT" + id("net.fabricmc.fabric-loom-repositories") version "1.16-SNAPSHOT" id("net.neoforged.moddev.repositories") version "2.0.141" } From 5a4438c483d9bc784d64d7c36ad49f568a51f75a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 16 Apr 2026 13:17:00 +0900 Subject: [PATCH 44/91] chore: update net.fabricmc:fabric-loader to 0.19.2 --- gradle/libs.versions.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index db087825b..fa9d1c117 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.145.4+26.1.2" +fabric-api = "0.146.0+26.1.2" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" cloud-bukkit = "2.0.0-beta.15" @@ -32,7 +32,7 @@ adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0" asm-tree = "org.ow2.asm:asm-tree:9.9.1" -fabric-loader = "net.fabricmc:fabric-loader:0.19.1" +fabric-loader = "net.fabricmc:fabric-loader:0.19.2" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.2+26.1.1" From 51b9db3c59b2151a6281ae7d7a28c4a7aa24b0a5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 18 Apr 2026 11:53:34 +0900 Subject: [PATCH 45/91] chore: update Skript to v2.15.0 for test server --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 9ea06ff5e..8cccb5785 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,7 +33,7 @@ tasks { downloadPlugins { hangar("ViaVersion", "5.8.1") hangar("ViaBackwards", "5.8.1") - hangar("Skript", "2.14.2") + hangar("Skript", "2.15.0") } } build { From 94c51e5e6545993f6c34324fbcfe5fe20a8356b7 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 18 Apr 2026 11:54:19 +0900 Subject: [PATCH 46/91] chore: update fabric-api to v0.146.1+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index fa9d1c117..8238370ae 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.146.0+26.1.2" +fabric-api = "0.146.1+26.1.2" fabric-language-kotlin = "1.13.10+kotlin.2.3.20" cloud-bukkit = "2.0.0-beta.15" From a5dabebd97d2b918b032d2b86137e78275d9e86f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 18 Apr 2026 21:45:34 +0900 Subject: [PATCH 47/91] chore: update eu.pb4:polymer-resource-pack to v0.16.3+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 8238370ae..18e9edfc6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,7 +35,7 @@ asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.19.2" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.2+26.1.1" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.3+26.1.2" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } From dc9e474300e8012a46c8b7582ff7d8f7d2f674bb Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 19 Apr 2026 13:15:52 +0900 Subject: [PATCH 48/91] fix: PriorityMap --- .../api/animation/AnimationStateHandler.java | 2 +- .../api/util/collection/PriorityMap.java | 33 ++++++++++++++++--- platform/fabric/build.gradle.kts | 2 +- .../kotlin/kr/toxicity/model/test/RollTest.kt | 4 +-- 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index c23bfc562..c8cbe7296 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -130,7 +130,7 @@ private boolean shouldUpdateAnimation() { private boolean updateAnimation() { synchronized (animators) { - var iterator = animators.values().iterator(); + var iterator = animators.valueIterator(); while (iterator.hasNext()) { var next = iterator.next(); if (!next.getAsBoolean()) continue; diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java index 94e2da0e7..32d5b3ebc 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java @@ -112,11 +112,36 @@ public int compareTo(@NotNull Identifier o) { } /** - * Returns a Collection view of the values contained in this map, sorted by priority. + * Returns an iterator over the values in this map in priority order. * - * @return a collection view of the values contained in this map + * @return a value iterator + * @since 3.0.1 */ - public @NotNull Collection values() { - return valueMap.values(); + public @NotNull Iterator valueIterator() { + return new ValueIterator(); + } + + private class ValueIterator implements Iterator { + + private final Iterator, V>> delegate = valueMap.entrySet().iterator(); + private Identifier identifier; + + @Override + public boolean hasNext() { + return delegate.hasNext(); + } + + @Override + public V next() { + var next = delegate.next(); + identifier = next.getKey(); + return next.getValue(); + } + + @Override + public void remove() { + delegate.remove(); + keyMap.remove(Objects.requireNonNull(identifier).key); + } } } diff --git a/platform/fabric/build.gradle.kts b/platform/fabric/build.gradle.kts index ca20fd485..0cde37a6d 100644 --- a/platform/fabric/build.gradle.kts +++ b/platform/fabric/build.gradle.kts @@ -86,7 +86,7 @@ fabricModJson { environment = Environment.ANY depends = mapOf( - "minecraft" to listOf("~${property("minecraft_version")}"), + "minecraft" to listOf(">=${LATEST_VERSION.first()}"), "fabricloader" to listOf("*"), "fabric-language-kotlin" to listOf(">=${libs.versions.fabric.language.kotlin.get()}"), diff --git a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt index abc132338..eb3e073d3 100644 --- a/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt +++ b/platform/fabric/src/testmod/kotlin/kr/toxicity/model/test/RollTest.kt @@ -10,7 +10,7 @@ package kr.toxicity.model.test import com.mojang.brigadier.builder.LiteralArgumentBuilder import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.animation.AnimationModifier -import kr.toxicity.model.api.fabric.platform.FabricPlayer +import kr.toxicity.model.api.mod.platform.ModPlayer import kr.toxicity.model.api.tracker.ModelRotation import kr.toxicity.model.api.tracker.TrackerModifier import net.fabricmc.api.ModInitializer @@ -85,7 +85,7 @@ class RollTest : ModInitializer { val yaw = player.lastClientInput.toYaw() val tracker = renderer.getOrCreate( - FabricPlayer.of(player.connection), + ModPlayer.of(player.connection), TrackerModifier.DEFAULT ) { tracker -> tracker.rotation { From c7c2bd646981b748fa3414f226cc7a876caa8ed8 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 19 Apr 2026 13:34:00 +0900 Subject: [PATCH 49/91] fix: PriorityMap#get --- .../toxicity/model/api/util/collection/PriorityMap.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java index 32d5b3ebc..0f6db693a 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java +++ b/api/src/main/java/kr/toxicity/model/api/util/collection/PriorityMap.java @@ -70,10 +70,11 @@ public int compareTo(@NotNull Identifier o) { * @return the previous value associated with key, or null if there was no mapping for key. */ public @Nullable V put(@NotNull K key, @NotNull V value, int priority) { - return valueMap.put( - keyMap.computeIfAbsent(Objects.requireNonNull(key), _ -> new Identifier<>(priority, counter++, key)), - Objects.requireNonNull(value) - ); + Objects.requireNonNull(key); + Objects.requireNonNull(value); + Identifier newIdentifier, oldIdentifier; + if ((oldIdentifier = keyMap.put(key, newIdentifier = new Identifier<>(priority, counter++, key))) != null) valueMap.remove(oldIdentifier); + return valueMap.put(newIdentifier, value); } /** From 1833e53f547856045090dec06e56e32795a2be28 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 19 Apr 2026 13:36:07 +0900 Subject: [PATCH 50/91] chore: write 3.0.1.md --- changelog/3.0.1.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/changelog/3.0.1.md b/changelog/3.0.1.md index 486813e34..2185f5d7c 100644 --- a/changelog/3.0.1.md +++ b/changelog/3.0.1.md @@ -1,2 +1,11 @@ +## 🔧 Fixes +- fix: PriorityMap + +## 🧹 Chores +- chore: update net.fabricmc:fabric-loader to 0.19.2 +- chore: update net.fabricmc.fabric-loom-repositories to 1.16-SNAPSHOT +- chore: update Skript to v2.15.0 for test server +- chore: update fabric-api to v0.146.1+26.1.2 +- chore: update eu.pb4:polymer-resource-pack to v0.16.3+26.1.2 [Full change log](https://github.com/toxicity188/BetterModel/compare/3.0.0...3.0.1) From 25cc080fe7335ab145676f123e08a8814327f3db Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 20 Apr 2026 14:26:23 +0900 Subject: [PATCH 51/91] update: 3.0.2 --- changelog/3.0.2.md | 1 + changelog/{ => v3}/3.0.0.md | 0 gradle.properties | 2 +- 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog/3.0.2.md rename changelog/{ => v3}/3.0.0.md (100%) diff --git a/changelog/3.0.2.md b/changelog/3.0.2.md new file mode 100644 index 000000000..97a9cb4ed --- /dev/null +++ b/changelog/3.0.2.md @@ -0,0 +1 @@ +[Full change log](https://github.com/toxicity188/BetterModel/compare/3.0.1...3.0.2) diff --git a/changelog/3.0.0.md b/changelog/v3/3.0.0.md similarity index 100% rename from changelog/3.0.0.md rename to changelog/v3/3.0.0.md diff --git a/gradle.properties b/gradle.properties index db6ac95e6..b7546f5e3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ org.gradle.configuration-cache=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -project_version=3.0.1 +project_version=3.0.2 minecraft_version=26.1.2 From 7f10de1f31aad85391b23aa931526acca4d28f25 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 20 Apr 2026 14:27:05 +0900 Subject: [PATCH 52/91] refactor: remove unused code --- .../api/data/blueprint/BlueprintElement.java | 10 +------- .../model/api/version/MinecraftVersion.java | 17 ------------- .../kr/toxicity/model/manager/ArmorManager.kt | 2 +- .../model/manager/ModelManagerImpl.kt | 25 ++++++++++--------- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java index cbbe080b6..7b342aace 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/BlueprintElement.java @@ -26,7 +26,6 @@ import org.joml.Quaternionf; import java.util.*; -import java.util.function.Predicate; import java.util.stream.Stream; import static kr.toxicity.model.api.util.CollectionUtil.*; @@ -138,23 +137,16 @@ public Float3 origin() { /** * Builds the JSON representation for legacy clients (1.21.3 or under). * - * @param skipLog whether to skip logging warnings for invalid rotations * @param obfuscator the obfuscator for model and texture names * @param context the load context * @return the generated blueprint JSON, or null if not applicable * @since 1.15.2 */ public @Nullable BlueprintJson buildLegacyJson( - boolean skipLog, @NotNull PackObfuscator.Pair obfuscator, @NotNull BlueprintLoadContext context ) { - Predicate filter = element -> MathUtil.checkValidDegree(element.identifierDegree()); - if (!skipLog) filter = filterWithWarning( - filter, - element -> "The model " + context.name() + "'s cube \"" + element.name() + "\" has an invalid rotation which does not supported in legacy client (<=1.21.3) " + element.rotation() - ); - return buildJson(-2, 1, scale(), obfuscator, context, Float3.ZERO, filterIsInstance(children, Cube.class).filter(filter)); + return buildJson(-2, 1, scale(), obfuscator, context, Float3.ZERO, filterIsInstance(children, Cube.class).filter(element -> MathUtil.checkValidDegree(element.identifierDegree()))); } /** diff --git a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java index cfb970de6..906040521 100644 --- a/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java +++ b/api/src/main/java/kr/toxicity/model/api/version/MinecraftVersion.java @@ -93,23 +93,6 @@ public record MinecraftVersion(int major, int minor, int patch) implements Compa return new MinecraftVersion(major, minor, patch); } - /** - * Checks this version is greater or equals than another. - * @param other other - * @return greater or not - */ - public boolean isGreaterOrEquals(@NotNull MinecraftVersion other) { - return compareTo(other) >= 0; - } - - /** - * Checks this version should be use modern resource. - * @return use modern resource - */ - public boolean useModernResource() { - return isGreaterOrEquals(V1_21_4); - } - @Override public int compareTo(@NotNull MinecraftVersion o) { return COMPARATOR.compare(this, o); diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt index 383912d68..9fb606c2c 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ArmorManager.kt @@ -182,7 +182,7 @@ object ArmorManager : GlobalManager { pipeline: ReloadPipeline, zipper: PackZipper ) { - if (!PLATFORM.version().useModernResource() || !CONFIG.module().playerAnimation) { + if (!CONFIG.module().playerAnimation) { armor = ArmorModel.EMPTY return } diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt index 8b2e287f6..991026383 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt @@ -81,7 +81,13 @@ object ModelManagerImpl : ModelManager, GlobalManager { return modelFileMap.values .asSequence() .sortedBy { it.first } - .map { ImportedModel(it.first.sizeAssume, type,it.second) } + .map { + ImportedModel( + it.first.sizeAssume - it.second.textures.sumOf { tex -> tex.image.size }, + type, + it.second + ) + } } private fun loadModels(pipeline: ReloadPipeline, zipper: PackZipper) { @@ -95,7 +101,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { copyRecursively(folder, overwrite = true) info("ModelEngine's models are successfully migrated.".toComponent(GREEN)) } ?: run { - if (PLATFORM.version().useModernResource()) folder.addResource("demon_knight.bbmodel") + folder.addResource("demon_knight.bbmodel") folder.addResource("blue_wizard.bbmodel") } }) @@ -110,14 +116,10 @@ object ModelManagerImpl : ModelManager, GlobalManager { } private data class ImportedModel( - val size: Long, + val jsonSize: Long, val type: ModelRenderer.Type, val blueprint: ModelBlueprint - ) { - val jsonSize = size - blueprint.textures.sumOf { - it.image.size - } - } + ) private class ModelPipeline( zipper: PackZipper @@ -197,9 +199,8 @@ object ModelManagerImpl : ModelManager, GlobalManager { targetMap: MutableMap, importedModel: ImportedModel ) { - val (_, type, blueprint) = importedModel + val (size, type, blueprint) = importedModel val context = blueprint.context() - val size = importedModel.jsonSize targetMap[blueprint.name] = blueprint.toRenderer(type) render@ { group -> if (!context.canBeRendered()) return@render null listOfNotNull( @@ -211,7 +212,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { } else null }, legacyModel.ifAvailable { - group.buildLegacyJson(PLATFORM.version().useModernResource(), obfuscator, context) + group.buildLegacyJson(obfuscator, context) ?.let { build(listOf(it), null, size) } } ).run { @@ -272,7 +273,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { private fun BlueprintJson.toModernJson() = jsonObjectOf( "type" to "model", - "model" to "${CONFIG.namespace()}:modern_item/${name}", + "model" to "${CONFIG.namespace()}:modern_item/$name", "tints" to jsonArrayOf( jsonObjectOf( "type" to "custom_model_data", From b677a391c66b62e00ef25bf8d961a016249ab30c Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 20 Apr 2026 14:28:20 +0900 Subject: [PATCH 53/91] chore: update ViaVersion to v5.9.0 for test server --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8cccb5785..d231f5066 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,8 +31,8 @@ tasks { }) minecraftVersion(minecraft) downloadPlugins { - hangar("ViaVersion", "5.8.1") - hangar("ViaBackwards", "5.8.1") + hangar("ViaVersion", "5.9.0") + hangar("ViaBackwards", "5.9.0") hangar("Skript", "2.15.0") } } From 698a7fb135b851d535dc74d578541a70e43946f8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 02:49:10 +0000 Subject: [PATCH 54/91] fix(deps): update dependency org.projectlombok:lombok to v1.18.46 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 18e9edfc6..cf4b7cac0 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -50,7 +50,7 @@ cloud-fabric = { module = "org.incendo:cloud-fabric", version.ref = "cloud-mod" cloud-core = { module = "org.incendo:cloud-core", version.ref = "cloud-core" } geantyref = "io.leangen.geantyref:geantyref:2.0.1" -lombok = "org.projectlombok:lombok:1.18.44" +lombok = "org.projectlombok:lombok:1.18.46" bStats = "org.bstats:bstats-bukkit:3.2.1" dynamicUV = "io.github.toxicity188:dynamicuv:1.2.2" armormodel = "io.github.toxicity188:armormodel:1.0.2" From 6f4c173a9dc8107861de066a486917f9b6de4eef Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 22 Apr 2026 14:07:57 +0900 Subject: [PATCH 55/91] fix: remove HitBoxInteractEvent, port to HitBoxInteractAtEvent --- .../event/hitbox/HitBoxInteractAtEvent.java | 2 +- .../api/event/hitbox/HitBoxInteractEvent.java | 50 ------------------- .../kr/toxicity/model/api/nms/HitBox.java | 45 +++++++++-------- .../model/api/nms/HitBoxListener.java | 11 ---- .../toxicity/model/api/tracker/Tracker.java | 4 ++ .../bukkit/AbstractBetterModelPlugin.java | 7 +-- .../model/bukkit/manager/EntityManager.kt | 34 +------------ .../model/bukkit/nms/v1_21_R3/HitBoxImpl.kt | 38 ++------------ .../bukkit/nms/v1_21_R3/HitBoxInteraction.kt | 2 + .../model/bukkit/nms/v1_21_R4/HitBoxImpl.kt | 34 ++----------- .../bukkit/nms/v1_21_R4/HitBoxInteraction.kt | 2 + .../model/bukkit/nms/v1_21_R5/HitBoxImpl.kt | 34 ++----------- .../bukkit/nms/v1_21_R5/HitBoxInteraction.kt | 2 + .../model/bukkit/nms/v1_21_R6/HitBoxImpl.kt | 34 ++----------- .../bukkit/nms/v1_21_R6/HitBoxInteraction.kt | 2 + .../model/bukkit/nms/v1_21_R7/HitBoxImpl.kt | 34 ++----------- .../bukkit/nms/v1_21_R7/HitBoxInteraction.kt | 2 + .../model/bukkit/nms/v26_R1/HitBoxImpl.kt | 28 ++--------- .../bukkit/nms/v26_R1/HitBoxInteraction.kt | 1 + .../impl/fabric/entity/HitBoxEntityImpl.kt | 28 ++--------- .../fabric/entity/InteractionEntityImpl.kt | 1 + .../impl/fabric/manager/EntityManager.kt | 33 +----------- 22 files changed, 79 insertions(+), 349 deletions(-) delete mode 100644 api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java index 79364ef40..cd9269491 100644 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java +++ b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractAtEvent.java @@ -26,7 +26,7 @@ * @since 2.0.0 */ @Getter -public class HitBoxInteractAtEvent implements CancellableEvent, HitBoxEvent { +public final class HitBoxInteractAtEvent implements CancellableEvent, HitBoxEvent { @Setter private boolean cancelled; diff --git a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java b/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java deleted file mode 100644 index 50b1896b8..000000000 --- a/api/src/main/java/kr/toxicity/model/api/event/hitbox/HitBoxInteractEvent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This source file is part of BetterModel. - * Copyright (c) 2026 toxicity188 - * Licensed under the MIT License. - * See LICENSE.md file for full license text. - */ - -package kr.toxicity.model.api.event.hitbox; - -import kr.toxicity.model.api.event.CancellableEvent; -import kr.toxicity.model.api.nms.HitBox; -import kr.toxicity.model.api.nms.ModelInteractionHand; -import kr.toxicity.model.api.platform.PlatformPlayer; -import lombok.Getter; -import lombok.Setter; -import org.jetbrains.annotations.ApiStatus; -import org.jetbrains.annotations.NotNull; - -/** - * Triggered when a player interacts with a model's hitbox. - *

- * This event corresponds to a right-click interaction. - *

- * - * @since 2.0.0 - */ -@Getter -public class HitBoxInteractEvent implements CancellableEvent, HitBoxEvent { - - @Setter - private boolean cancelled; - private final PlatformPlayer who; - private final @NotNull HitBox hitBox; - private final @NotNull ModelInteractionHand hand; - - /** - * Creates a new HitBoxInteractEvent. - * - * @param who the player interacting - * @param hitBox the hitbox being interacted with - * @param hand the hand used for interaction - * @since 2.0.0 - */ - @ApiStatus.Internal - public HitBoxInteractEvent(@NotNull PlatformPlayer who, @NotNull HitBox hitBox, @NotNull ModelInteractionHand hand) { - this.who = who; - this.hitBox = hitBox; - this.hand = hand; - } -} diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java index 74cf388f7..cc51b9fc6 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBox.java @@ -19,6 +19,7 @@ import org.joml.Vector3f; import java.util.Optional; +import java.util.function.Function; /** * Represents a hitbox for a model part, allowing for interaction and collision detection. @@ -31,27 +32,6 @@ */ public interface HitBox extends Identifiable { - /** - * Triggers an interaction with this hitbox. - * - * @param player the player interacting - * @param hand the hand used - * @since 1.15.2 - */ - @ApiStatus.Internal - void triggerInteract(@NotNull PlatformPlayer player, @NotNull ModelInteractionHand hand); - - /** - * Triggers an interaction with this hitbox at a specific position. - * - * @param player the player interacting - * @param hand the hand used - * @param position the interaction position - * @since 1.15.2 - */ - @ApiStatus.Internal - void triggerInteractAt(@NotNull PlatformPlayer player, @NotNull ModelInteractionHand hand, @NotNull Vector3f position); - /** * Hides this hitbox from a specific player. * @@ -184,6 +164,29 @@ default boolean hasBeenControlled() { */ @NotNull HitBoxListener listener(); + /** + * Sets the listener for this hitbox. + * + * @param listener the new listener + * @since 3.0.2 + */ + @ApiStatus.Internal + void listener(@NotNull HitBoxListener listener); + + /** + * Updates the listener for this hitbox using a builder function. + *

+ * This method retrieves the current listener, converts it to a builder, + * applies the provided function, and sets the resulting listener. + *

+ * + * @param function the function to apply to the builder + * @since 3.0.2 + */ + default void listener(@NotNull Function function) { + listener(function.apply(listener().toBuilder()).build()); + } + /** * Returns the rendered bone that acts as the position source for this hitbox. * diff --git a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java index 2d268ca00..89067e6a7 100644 --- a/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java +++ b/api/src/main/java/kr/toxicity/model/api/nms/HitBoxListener.java @@ -107,17 +107,6 @@ private Builder( return listen(HitBoxDamagedEvent.class, damage); } - /** - * Adds an interact handler. - * - * @param interact the interact handler - * @return this builder - * @since 2.1.0 - */ - public @NotNull Builder interact(@NotNull Consumer interact) { - return listen(HitBoxInteractEvent.class, interact); - } - /** * Adds an interact-at handler. * diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java index 16eaf6dc4..4e5bbbb88 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/Tracker.java @@ -630,6 +630,10 @@ public boolean replace(@NotNull String target, @NotNull BlueprintAnimation anima * @since 2.1.0 */ public void listenHitBox(@NotNull BiFunction function) { + pipeline.hitboxes().forEach(hb -> { + var bone = hb.positionSource(); + hb.listener(b -> function.apply(bone, b)); + }); pipeline.eventDispatcher().handleCreateHitBox(function); } diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java index 4a6414061..afdb9a7b2 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/AbstractBetterModelPlugin.java @@ -32,12 +32,13 @@ public abstract class AbstractBetterModelPlugin extends JavaPlugin implements Be protected final BukkitAdapter adapter = new BukkitAdapter(); protected final BetterModelLogger logger = new BetterModelLogger() { - private ComponentLogger internalLogger; + private volatile ComponentLogger internalLogger; private @NotNull ComponentLogger logger() { - if (internalLogger != null) return internalLogger; + ComponentLogger logger; + if ((logger = internalLogger) != null) return logger; synchronized (this) { - if (internalLogger != null) return internalLogger; + if ((logger = internalLogger) != null) return logger; return internalLogger = ComponentLogger.logger(getLogger().getName()); } } diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt index 3a1e2c074..7265575f8 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt @@ -15,7 +15,6 @@ import it.unimi.dsi.fastutil.objects.ReferenceSet import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.bukkit.BetterModelBukkit import kr.toxicity.model.api.nms.HitBox -import kr.toxicity.model.api.nms.ModelInteractionHand import kr.toxicity.model.api.pack.PackZipper import kr.toxicity.model.api.tracker.EntityTracker import kr.toxicity.model.api.tracker.EntityTrackerRegistry @@ -33,13 +32,11 @@ import org.bukkit.event.EventPriority import org.bukkit.event.Listener import org.bukkit.event.entity.* import org.bukkit.event.player.PlayerChangedWorldEvent -import org.bukkit.event.player.PlayerInteractAtEntityEvent import org.bukkit.event.player.PlayerInteractEntityEvent import org.bukkit.event.player.PlayerQuitEvent import org.bukkit.event.world.EntitiesUnloadEvent import org.bukkit.inventory.EquipmentSlot import org.bukkit.potion.PotionEffectType -import org.joml.Vector3f object EntityManager : GlobalManager { @@ -122,38 +119,11 @@ object EntityManager : GlobalManager { it.animate(TrackerExtraAnimation.DEATH) } } - @EventHandler(priority = EventPriority.MONITOR) - fun PlayerInteractAtEntityEvent.interact() { - val pos = clickedPosition - (rightClicked as? HitBox)?.triggerInteractAt( - player.wrap(), - when (this.hand) { - EquipmentSlot.HAND -> ModelInteractionHand.RIGHT - EquipmentSlot.OFF_HAND -> ModelInteractionHand.LEFT - else -> return - }, - Vector3f( - pos.x.toFloat(), - pos.y.toFloat(), - pos.z.toFloat() - ) - ) - } - @EventHandler(priority = EventPriority.MONITOR) + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) fun PlayerInteractEntityEvent.interact() { //Interact base entity based on interaction entity - val isRight = hand == EquipmentSlot.HAND - val dismount = isRight && player.triggerDismount(rightClicked) (rightClicked as? HitBox)?.let { - it.triggerInteract( - player.wrap(), - when (this.hand) { - EquipmentSlot.HAND -> ModelInteractionHand.RIGHT - EquipmentSlot.OFF_HAND -> ModelInteractionHand.LEFT - else -> return - } - ) - if (isRight && !dismount) player.triggerMount(it) + if (hand == EquipmentSlot.HAND && !player.triggerDismount(rightClicked)) player.triggerMount(it) } } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt index a91038f79..a92e7e8e1 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxImpl.kt @@ -44,7 +44,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -55,7 +54,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -113,6 +112,7 @@ internal class HitBoxImpl( override fun positionSource(): RenderedBone = bone override fun forceDismount(): Boolean = forceDismount override fun mountController(): MountController = mountController + override fun hasMountDriver(): Boolean = controllingPassenger != null override fun mountController(controller: MountController) { this.mountController = controller } @@ -120,9 +120,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener - - override fun getArmorSlots(): MutableIterable = mutableSetOf() - override fun hasMountDriver(): Boolean = controllingPassenger != null + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -316,27 +316,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { @@ -355,13 +334,6 @@ internal class HitBoxImpl( override fun interact(player: Player, hand: InteractionHand): InteractionResult { if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS } diff --git a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt index 44349b966..1b4f04cbd 100644 --- a/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt +++ b/nms/v1_21_R3/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R3/HitBoxInteraction.kt @@ -53,10 +53,12 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand): InteractionResult { + delegate.interact(player, hand) return InteractionResult.FAIL } override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + delegate.interactAt(player, vec, hand) return InteractionResult.FAIL } } diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt index 8d1190941..ec779f14e 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxImpl.kt @@ -45,7 +45,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -56,7 +55,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -123,6 +122,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -322,27 +324,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { @@ -361,13 +342,6 @@ internal class HitBoxImpl( override fun interact(player: Player, hand: InteractionHand): InteractionResult { if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS } diff --git a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt index bd13beb60..aa02510d9 100644 --- a/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt +++ b/nms/v1_21_R4/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R4/HitBoxInteraction.kt @@ -53,10 +53,12 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand): InteractionResult { + delegate.interact(player, hand) return InteractionResult.FAIL } override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + delegate.interactAt(player, vec, hand) return InteractionResult.FAIL } } diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt index 5b3fcde3a..18b23b4b5 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxImpl.kt @@ -45,7 +45,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -56,7 +55,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -123,6 +122,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -323,27 +325,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { @@ -362,13 +343,6 @@ internal class HitBoxImpl( override fun interact(player: Player, hand: InteractionHand): InteractionResult { if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS } diff --git a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt index d64673a69..5eb5d2c02 100644 --- a/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt +++ b/nms/v1_21_R5/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R5/HitBoxInteraction.kt @@ -53,10 +53,12 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand): InteractionResult { + delegate.interact(player, hand) return InteractionResult.FAIL } override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + delegate.interactAt(player, vec, hand) return InteractionResult.FAIL } } diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt index 740bcc9bc..9895179d4 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxImpl.kt @@ -45,7 +45,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -56,7 +55,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -123,6 +122,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -323,27 +325,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { @@ -362,13 +343,6 @@ internal class HitBoxImpl( override fun interact(player: Player, hand: InteractionHand): InteractionResult { if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS } diff --git a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt index aaba034c2..299b47a34 100644 --- a/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt +++ b/nms/v1_21_R6/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R6/HitBoxInteraction.kt @@ -53,10 +53,12 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand): InteractionResult { + delegate.interact(player, hand) return InteractionResult.FAIL } override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + delegate.interactAt(player, vec, hand) return InteractionResult.FAIL } } diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt index 4701c060d..a66217bc7 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxImpl.kt @@ -45,7 +45,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -56,7 +55,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -123,6 +122,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -323,27 +325,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interactAt( - (player.unwarp() as CraftPlayer).handle, - position.toVanilla(), - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - } - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { @@ -362,13 +343,6 @@ internal class HitBoxImpl( override fun interact(player: Player, hand: InteractionHand): InteractionResult { if (player === delegate) return InteractionResult.FAIL - val interact = HitBoxInteractEvent( - (player.bukkitEntity as org.bukkit.entity.Player).wrap(), craftEntity, when (hand) { - MAIN_HAND -> ModelInteractionHand.RIGHT - OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (!listener.handle(interact)) return InteractionResult.FAIL (player as ServerPlayer).connection.handleInteract(ServerboundInteractPacket.createInteractionPacket(delegate, player.isShiftKeyDown, hand)) return InteractionResult.SUCCESS } diff --git a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt index aef838c8c..01a47b9d4 100644 --- a/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt +++ b/nms/v1_21_R7/src/main/kotlin/kr/toxicity/model/bukkit/nms/v1_21_R7/HitBoxInteraction.kt @@ -53,10 +53,12 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand): InteractionResult { + delegate.interact(player, hand) return InteractionResult.FAIL } override fun interactAt(player: Player, vec: Vec3, hand: InteractionHand): InteractionResult { + delegate.interactAt(player, vec, hand) return InteractionResult.FAIL } } diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt index 8f10e05fb..d3c933e86 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxImpl.kt @@ -45,7 +45,6 @@ import org.bukkit.Particle import org.bukkit.craftbukkit.CraftServer import org.bukkit.craftbukkit.entity.CraftArmorStand import org.bukkit.craftbukkit.entity.CraftLivingEntity -import org.bukkit.craftbukkit.entity.CraftPlayer import org.bukkit.event.entity.CreatureSpawnEvent import org.bukkit.event.entity.EntityPotionEffectEvent import org.bukkit.event.entity.EntityRemoveEvent @@ -56,7 +55,7 @@ import java.util.* internal class HitBoxImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : AbstractHitBox(delegate.level()) { @@ -123,6 +122,9 @@ internal class HitBoxImpl( bone.hitBoxPosition(posCache).add(x.toFloat(), y.toFloat(), z.toFloat()) } override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) { } @@ -323,28 +325,6 @@ internal class HitBoxImpl( return ifLivingEntity { isDeadOrDying } == true } - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - }, - Vec3.ZERO - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interact( - (player.unwarp() as CraftPlayer).handle, - when (hand) { - ModelInteractionHand.LEFT -> OFF_HAND - ModelInteractionHand.RIGHT -> MAIN_HAND - }, - position.toVanilla() - ) - } - override fun hide(player: PlatformPlayer) { val plugin = BetterModel.platform() as Plugin player.unwarp().run { diff --git a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt index 774a1ad3e..0fd64f279 100644 --- a/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt +++ b/nms/v26_R1/src/main/kotlin/kr/toxicity/model/bukkit/nms/v26_R1/HitBoxInteraction.kt @@ -53,6 +53,7 @@ internal class HitBoxInteraction( } override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { + delegate.interact(player, hand, vec) return InteractionResult.FAIL } } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt index 1ef60f939..6a27cbc7c 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/HitBoxEntityImpl.kt @@ -45,7 +45,7 @@ import java.util.* class HitBoxEntityImpl( private val source: ModelBoundingBox, private val bone: RenderedBone, - private val listener: HitBoxListener, + private var listener: HitBoxListener, private val delegate: Entity, private var mountController: MountController ) : @@ -130,6 +130,10 @@ class HitBoxEntityImpl( override fun listener(): HitBoxListener = listener + override fun listener(listener: HitBoxListener) { + this.listener = listener + } + override fun getItemBySlot(slot: EquipmentSlot): ItemStack = ItemStack.EMPTY override fun setItemSlot(slot: EquipmentSlot, stack: ItemStack) = Unit @@ -385,28 +389,6 @@ class HitBoxEntityImpl( override fun isDeadOrDying(): Boolean = delegate is LivingEntity && delegate.isDeadOrDying - override fun triggerInteract(player: PlatformPlayer, hand: ModelInteractionHand) { - interact( - player.unwarp().player, - when (hand) { - ModelInteractionHand.LEFT -> InteractionHand.OFF_HAND - ModelInteractionHand.RIGHT -> InteractionHand.MAIN_HAND - }, - Vec3.ZERO - ) - } - - override fun triggerInteractAt(player: PlatformPlayer, hand: ModelInteractionHand, position: Vector3f) { - interact( - player.unwarp().player, - when (hand) { - ModelInteractionHand.LEFT -> InteractionHand.OFF_HAND - ModelInteractionHand.RIGHT -> InteractionHand.MAIN_HAND - }, - Vec3(position) - ) - } - override fun hide(player: PlatformPlayer) { TODO("with mixin") } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt index f074437eb..977b71795 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/entity/InteractionEntityImpl.kt @@ -39,6 +39,7 @@ class InteractionEntityImpl(val delegate: HitBoxEntityImpl) : } override fun interact(player: Player, hand: InteractionHand, vec: Vec3): InteractionResult { + delegate.interact(player, hand, vec) return InteractionResult.FAIL } diff --git a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt index 4fd06cde9..894850f91 100644 --- a/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt +++ b/platform/fabric/src/main/kotlin/kr/toxicity/model/impl/fabric/manager/EntityManager.kt @@ -10,7 +10,6 @@ package kr.toxicity.model.impl.fabric.manager import kr.toxicity.model.api.BetterModel import kr.toxicity.model.api.mod.entity.BaseModEntity import kr.toxicity.model.api.nms.HitBox -import kr.toxicity.model.api.nms.ModelInteractionHand import kr.toxicity.model.api.pack.PackZipper import kr.toxicity.model.api.tracker.EntityTracker import kr.toxicity.model.api.tracker.EntityTrackerRegistry @@ -34,7 +33,6 @@ import net.minecraft.world.InteractionHand import net.minecraft.world.InteractionResult import net.minecraft.world.effect.MobEffects import net.minecraft.world.entity.Entity -import org.joml.Vector3f object EntityManager : GlobalManager { override fun reload(pipeline: ReloadPipeline, zipper: PackZipper) { @@ -201,41 +199,14 @@ object EntityManager : GlobalManager { private fun registerInteractionEvents() { // same as PlayerInteractAtEntityEvent, PlayerInteractEntityEvent - UseEntityCallback.EVENT.register { clicker, _, hand, clicked, hitResult -> + UseEntityCallback.EVENT.register { clicker, _, hand, clicked, _ -> if (clicker !is ServerPlayer) { return@register InteractionResult.PASS } - val connection = clicker.connection // for PlayerInteractAtEntityEvent - hitResult?.let { hitResult -> - (clicked as? HitBox)?.triggerInteractAt( - connection.wrap(), - when (hand) { - InteractionHand.MAIN_HAND -> ModelInteractionHand.RIGHT - InteractionHand.OFF_HAND -> ModelInteractionHand.LEFT - }, - Vector3f( - hitResult.location.x.toFloat(), - hitResult.location.y.toFloat(), - hitResult.location.z.toFloat(), - ) - ) - } - - // for PlayerInteractEntityEvent - val isMainHand = hand == InteractionHand.MAIN_HAND - val isDismounted = isMainHand && clicker.triggerDismount(clicked) - (clicked as? HitBox)?.let { hitBox -> - hitBox.triggerInteract( - connection.wrap(), - when (hand) { - InteractionHand.MAIN_HAND -> ModelInteractionHand.RIGHT - InteractionHand.OFF_HAND -> ModelInteractionHand.LEFT - } - ) - if (isMainHand && !isDismounted) { + if (hand == InteractionHand.MAIN_HAND && !clicker.triggerDismount(clicked)) { clicker.triggerMount(hitBox) } } From a2e1a86b4358c8ad68a952ad86a11358257a10ab Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 08:49:21 +0000 Subject: [PATCH 56/91] fix(deps): update kotlin monorepo to v2.3.21 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 18e9edfc6..2d4d98d08 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,5 +1,5 @@ [versions] -kotlin = "2.3.20" +kotlin = "2.3.21" paperweight = "2.0.0-beta.21" resourcefactory = "1.3.1" From 7744bbcccf88977bab215232afcd37f06b0ad7e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 23 Apr 2026 22:18:23 +0000 Subject: [PATCH 57/91] fix(deps): update dependency com.google.code.gson:gson to v2.14.0 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9a2d48d7a..208ab2749 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -41,7 +41,7 @@ configurate-core = { module = "org.spongepowered:configurate-core", version.ref configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } joml = "org.joml:joml:1.10.8" -gson = "com.google.code.gson:gson:2.13.2" +gson = "com.google.code.gson:gson:2.14.0" fastutil = "it.unimi.dsi:fastutil:8.5.18" guava = "com.google.guava:guava:33.6.0-jre" From 37d7fae20bb1efa5bb17244daf7fe7016126cfc4 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Fri, 24 Apr 2026 19:08:42 +0900 Subject: [PATCH 58/91] chore: update net.fabricmc:fabric-language-kotlin to v1.13.11+kotlin.2.3.21 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 208ab2749..afc9d297d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -8,7 +8,7 @@ minotaur = "2.9.0" hangarPublish = "0.1.4" fabric-api = "0.146.1+26.1.2" -fabric-language-kotlin = "1.13.10+kotlin.2.3.20" +fabric-language-kotlin = "1.13.11+kotlin.2.3.21" cloud-bukkit = "2.0.0-beta.15" cloud-mod = "2.0.0-beta.16" From 58e9623252406fe0488880186eec25fc12d5d396 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 28 Apr 2026 23:24:08 +0900 Subject: [PATCH 59/91] chore: update gradle to v9.5.0 --- gradle/wrapper/gradle-wrapper.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index c61a118f7..1a704683a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip networkTimeout=10000 validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME From fe165e830462f85a2326501e2bbba77be35dc2fd Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 28 Apr 2026 23:26:01 +0900 Subject: [PATCH 60/91] chore: update fabric-api to v0.147.0+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index afc9d297d..810c49d62 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.146.1+26.1.2" +fabric-api = "0.147.0+26.1.2" fabric-language-kotlin = "1.13.11+kotlin.2.3.21" cloud-bukkit = "2.0.0-beta.15" From 50dde87dc5c456487d305a78a055cc800dc33a2e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 28 Apr 2026 15:03:39 +0000 Subject: [PATCH 61/91] fix(deps): update dependency com.nexomc:nexo to v1.23 --- core/bukkit-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index 2871aa30a..8b07c1745 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -25,5 +25,5 @@ dependencies { } compileOnly("net.skinsrestorer:skinsrestorer-api:15.12.0") compileOnly("io.lumine:Mythic-Dist:5.11.2") - compileOnly("com.nexomc:nexo:1.21.0") + compileOnly("com.nexomc:nexo:1.23") } From 6bd8d0e472bd021d92b1404040820d67eee2060d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 30 Apr 2026 15:20:20 +0900 Subject: [PATCH 62/91] Revert "fix(deps): update dependency com.nexomc:nexo to v1.23" This reverts commit 50dde87dc5c456487d305a78a055cc800dc33a2e. --- core/bukkit-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index 8b07c1745..2871aa30a 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -25,5 +25,5 @@ dependencies { } compileOnly("net.skinsrestorer:skinsrestorer-api:15.12.0") compileOnly("io.lumine:Mythic-Dist:5.11.2") - compileOnly("com.nexomc:nexo:1.23") + compileOnly("com.nexomc:nexo:1.21.0") } From 26bddd08cdad1c8329e129551e8dc0066337e38e Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 30 Apr 2026 15:21:19 +0900 Subject: [PATCH 63/91] chore: change dokka target module --- buildSrc/src/main/kotlin/publish-conventions.gradle.kts | 2 ++ buildSrc/src/main/kotlin/standard-conventions.gradle.kts | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/publish-conventions.gradle.kts b/buildSrc/src/main/kotlin/publish-conventions.gradle.kts index cfa6bd305..7bb4ed4c5 100644 --- a/buildSrc/src/main/kotlin/publish-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/publish-conventions.gradle.kts @@ -9,6 +9,8 @@ plugins { signing } +rootProject.dependencies.dokka(project) + val artifactBaseId = name val artifactVersion = project.version.toString().run { BUILD_NUMBER?.let { substringBeforeLast("-$it") } ?: this diff --git a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts index a83a5da32..c17b979e1 100644 --- a/buildSrc/src/main/kotlin/standard-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/standard-conventions.gradle.kts @@ -14,8 +14,6 @@ configurations.implementation { extendsFrom(shade) } -rootProject.dependencies.dokka(project) - dependencies { testImplementation(kotlin("test")) From 237b9624b6eae4b907b9b10c65ed34409414eb54 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 30 Apr 2026 15:46:16 +0900 Subject: [PATCH 64/91] fix: make hitbox interaction should not be canceled --- changelog/3.0.2.md | 13 +++++++++++++ .../toxicity/model/bukkit/manager/EntityManager.kt | 5 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/changelog/3.0.2.md b/changelog/3.0.2.md index 97a9cb4ed..3e41da05e 100644 --- a/changelog/3.0.2.md +++ b/changelog/3.0.2.md @@ -1 +1,14 @@ +## 🔧 Fixes +- fix: remove HitBoxInteractEvent, port to HitBoxInteractAtEvent +- fix: make hitbox interaction should not be + +## 🧹 Chores +- chore: update fabric-api to v0.147.0+26.1.2 +- chore: update gradle to v9.5.0 +- chore: update net.fabricmc:fabric-language-kotlin to v1.13.11+kotlin.2.3.21 +- fix(deps): update dependency com.google.code.gson:gson to v2.14.0 +- fix(deps): update kotlin monorepo to v2.3.21 +- fix(deps): update dependency org.projectlombok:lombok to v1.18.46 +- chore: update ViaVersion to v5.9.0 for test server + [Full change log](https://github.com/toxicity188/BetterModel/compare/3.0.1...3.0.2) diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt index 7265575f8..fb2b65dd7 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/manager/EntityManager.kt @@ -120,10 +120,11 @@ object EntityManager : GlobalManager { } } - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + @EventHandler(priority = EventPriority.MONITOR) fun PlayerInteractEntityEvent.interact() { //Interact base entity based on interaction entity (rightClicked as? HitBox)?.let { - if (hand == EquipmentSlot.HAND && !player.triggerDismount(rightClicked)) player.triggerMount(it) + if (!isCancelled && hand == EquipmentSlot.HAND && !player.triggerDismount(rightClicked)) player.triggerMount(it) + isCancelled = false } } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) From cbc59c0b65102a5460942cf7dd33551432e0e482 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 2 May 2026 02:26:13 +0000 Subject: [PATCH 65/91] fix(deps): update dependency io.lumine:mythic-dist to v5.12.0 --- core/bukkit-core/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/bukkit-core/build.gradle.kts b/core/bukkit-core/build.gradle.kts index 2871aa30a..3232a89ed 100644 --- a/core/bukkit-core/build.gradle.kts +++ b/core/bukkit-core/build.gradle.kts @@ -24,6 +24,6 @@ dependencies { exclude("net.byteflux") } compileOnly("net.skinsrestorer:skinsrestorer-api:15.12.0") - compileOnly("io.lumine:Mythic-Dist:5.11.2") + compileOnly("io.lumine:Mythic-Dist:5.12.0") compileOnly("com.nexomc:nexo:1.21.0") } From ec36f4949a856440912af57d15fefca43730bf1e Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 2 May 2026 16:17:11 +0900 Subject: [PATCH 66/91] update: 3.0.3 --- changelog/3.0.3.md | 2 ++ changelog/{ => v3}/3.0.1.md | 0 gradle.properties | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 changelog/3.0.3.md rename changelog/{ => v3}/3.0.1.md (100%) diff --git a/changelog/3.0.3.md b/changelog/3.0.3.md new file mode 100644 index 000000000..0ad7cad04 --- /dev/null +++ b/changelog/3.0.3.md @@ -0,0 +1,2 @@ + +[Full change log](https://github.com/toxicity188/BetterModel/compare/3.0.2...3.0.3) diff --git a/changelog/3.0.1.md b/changelog/v3/3.0.1.md similarity index 100% rename from changelog/3.0.1.md rename to changelog/v3/3.0.1.md diff --git a/gradle.properties b/gradle.properties index b7546f5e3..58c87580a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ org.gradle.configuration-cache=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -project_version=3.0.2 +project_version=3.0.3 minecraft_version=26.1.2 From 418b15cff5383148f1e96e70d1a1ec9b95870305 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 2 May 2026 16:18:26 +0900 Subject: [PATCH 67/91] chore: update Skript to v2.15.2 for test server --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d231f5066..7fc3427c2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -33,7 +33,7 @@ tasks { downloadPlugins { hangar("ViaVersion", "5.9.0") hangar("ViaBackwards", "5.9.0") - hangar("Skript", "2.15.0") + hangar("Skript", "2.15.2") } } build { From 7be2086c97acb7abd46b3c705864314724e494fd Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 2 May 2026 16:34:53 +0900 Subject: [PATCH 68/91] chore: update eu.pb4:polymer-resource-pack to v0.16.4+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 810c49d62..93e993d53 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -35,7 +35,7 @@ asm-tree = "org.ow2.asm:asm-tree:9.9.1" fabric-loader = "net.fabricmc:fabric-loader:0.19.2" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } -polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.3+26.1.2" +polymer-resource-pack = "eu.pb4:polymer-resource-pack:0.16.4+26.1.2" configurate-core = { module = "org.spongepowered:configurate-core", version.ref = "configurate" } configurate-yaml = { module = "org.spongepowered:configurate-yaml", version.ref = "configurate" } From 8e921987343e1b434469ee64c7400aa1155bc404 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 2 May 2026 16:38:35 +0900 Subject: [PATCH 69/91] fix: update MythicMobsValue.kt to port MythicMobs v5.12.0 --- .../mythicmobs/MythicMobsValue.kt | 54 +++++-------------- 1 file changed, 14 insertions(+), 40 deletions(-) diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt index 52668a7ca..6ddd38a5f 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/compatibility/mythicmobs/MythicMobsValue.kt @@ -10,6 +10,7 @@ package kr.toxicity.model.bukkit.compatibility.mythicmobs import io.lumine.mythic.api.adapters.AbstractEntity import io.lumine.mythic.api.config.MythicLineConfig import io.lumine.mythic.api.skills.SkillMetadata +import io.lumine.mythic.core.skills.placeholders.PlaceholderContext import kr.toxicity.model.api.util.function.BonePredicate import kr.toxicity.model.bukkit.util.toRegistry import kr.toxicity.model.bukkit.util.toTracker @@ -31,15 +32,10 @@ fun MythicLineConfig.toPlaceholderString(array: Array, defaultValue: Str fun MythicLineConfig.toPlaceholderStringList(array: Array, mapper: (List) -> T) = toPlaceholderString(array) { mapper(it?.split(",") ?: emptyList()) } -fun MythicLineConfig.toPlaceholderString(array: Array, defaultValue: String? = null, mapper: (String?) -> T): (PlaceholderArgument) -> T { +fun MythicLineConfig.toPlaceholderString(array: Array, defaultValue: String? = null, mapper: (String?) -> T): (PlaceholderContext) -> T { return getPlaceholderString(array, defaultValue)?.let { { meta -> - mapper(when (meta) { - is PlaceholderArgument.None -> it.get() - is PlaceholderArgument.SkillMeta -> it[meta.meta] - is PlaceholderArgument.TargetedSkillMeta -> it.get(meta.meta, meta.target) - is PlaceholderArgument.Entity -> it[meta.entity] - }) + mapper(it.get(meta)) } } ?: mapper(null).let { mapped -> { @@ -49,15 +45,10 @@ fun MythicLineConfig.toPlaceholderString(array: Array, defaultValue: } fun MythicLineConfig.toPlaceholderInteger(array: Array, defaultValue: Int = 0) = toPlaceholderInteger(array, defaultValue) { it ?: defaultValue } fun MythicLineConfig.toNullablePlaceholderInteger(array: Array) = toPlaceholderInteger(array, null) { it } -fun MythicLineConfig.toPlaceholderInteger(array: Array, defaultValue: Int? = null, mapper: (Int?) -> T): (PlaceholderArgument) -> T { +fun MythicLineConfig.toPlaceholderInteger(array: Array, defaultValue: Int? = null, mapper: (Int?) -> T): (PlaceholderContext) -> T { return getPlaceholderInteger(array, defaultValue?.toString())?.let { { meta -> - mapper(when (meta) { - is PlaceholderArgument.None -> it.get() - is PlaceholderArgument.SkillMeta -> it[meta.meta] - is PlaceholderArgument.TargetedSkillMeta -> it.get(meta.meta, meta.target) - is PlaceholderArgument.Entity -> it[meta.entity] - }) + mapper(it.get(meta)) } } ?: mapper(null).let { mapped -> { @@ -67,15 +58,10 @@ fun MythicLineConfig.toPlaceholderInteger(array: Array, defaultValue } fun MythicLineConfig.toPlaceholderFloat(array: Array, defaultValue: Float = 0F) = toPlaceholderFloat(array, defaultValue) { it ?: defaultValue } fun MythicLineConfig.toNullablePlaceholderFloat(array: Array) = toPlaceholderFloat(array, null) { it } -fun MythicLineConfig.toPlaceholderFloat(array: Array, defaultValue: Float? = null, mapper: (Float?) -> T): (PlaceholderArgument) -> T { +fun MythicLineConfig.toPlaceholderFloat(array: Array, defaultValue: Float? = null, mapper: (Float?) -> T): (PlaceholderContext) -> T { return getPlaceholderFloat(array, defaultValue?.toString())?.let { { meta -> - mapper(when (meta) { - is PlaceholderArgument.None -> it.get() - is PlaceholderArgument.SkillMeta -> it[meta.meta] - is PlaceholderArgument.TargetedSkillMeta -> it.get(meta.meta, meta.target) - is PlaceholderArgument.Entity -> it[meta.entity] - }) + mapper(it.get(meta)) } } ?: mapper(null).let { mapped -> { @@ -85,15 +71,10 @@ fun MythicLineConfig.toPlaceholderFloat(array: Array, defaultValue: } fun MythicLineConfig.toPlaceholderBoolean(array: Array, defaultValue: Boolean? = null) = toPlaceholderBoolean(array, defaultValue) { it == true } fun MythicLineConfig.toNullablePlaceholderBoolean(array: Array, defaultValue: Boolean? = null) = toPlaceholderBoolean(array, defaultValue) { it } -fun MythicLineConfig.toPlaceholderBoolean(array: Array, defaultValue: Boolean? = null, mapper: (Boolean?) -> T): (PlaceholderArgument) -> T { +fun MythicLineConfig.toPlaceholderBoolean(array: Array, defaultValue: Boolean? = null, mapper: (Boolean?) -> T): (PlaceholderContext) -> T { return getPlaceholderBoolean(array, defaultValue)?.let { { meta -> - mapper(when (meta) { - is PlaceholderArgument.None -> it.get() - is PlaceholderArgument.SkillMeta -> it[meta.meta] - is PlaceholderArgument.TargetedSkillMeta -> it.get(meta.meta, meta.target) - is PlaceholderArgument.Entity -> it[meta.entity] - }) + mapper(it.get(meta)) } } ?: mapper(null).let { mapped -> { @@ -102,7 +83,7 @@ fun MythicLineConfig.toPlaceholderBoolean(array: Array, defaultValue } } fun MythicLineConfig.toPlaceholderColor(array: Array, defaultValue: String = "FFFFFF") = toPlaceholderColor(array, defaultValue) { it } -fun MythicLineConfig.toPlaceholderColor(array: Array, defaultValue: String = "FFFFFF", mapper: (Int?) -> T): (PlaceholderArgument) -> T { +fun MythicLineConfig.toPlaceholderColor(array: Array, defaultValue: String = "FFFFFF", mapper: (Int?) -> T): (PlaceholderContext) -> T { return toPlaceholderString(array, defaultValue) { mapper(it?.toIntOrNull(16)) } @@ -118,7 +99,7 @@ val MythicLineConfig.modelPlaceholder it?.toPackName() } -fun MythicLineConfig.toBonePredicate(defaultPredicate: BonePredicate): (PlaceholderArgument) -> BonePredicate { +fun MythicLineConfig.toBonePredicate(defaultPredicate: BonePredicate): (PlaceholderContext) -> BonePredicate { val match = toPlaceholderBoolean(MM_EXACT_MATCH, true) val children = toPlaceholderBoolean(MM_CHILDREN, false) val partSupplier = toPlaceholderString(MM_PART_ID) { @@ -140,13 +121,6 @@ fun MythicLineConfig.toBonePredicate(defaultPredicate: BonePredicate): (Placehol } } -fun SkillMetadata.toPlaceholderArgs() = PlaceholderArgument.SkillMeta(this) -fun AbstractEntity.toPlaceholderArgs() = PlaceholderArgument.Entity(this) -fun toPlaceholderArgs(meta: SkillMetadata, target: AbstractEntity) = PlaceholderArgument.TargetedSkillMeta(meta, target) - -sealed interface PlaceholderArgument { - data object None : PlaceholderArgument - data class SkillMeta(val meta: SkillMetadata) : PlaceholderArgument - data class TargetedSkillMeta(val meta: SkillMetadata, val target: AbstractEntity) : PlaceholderArgument - data class Entity(val entity: AbstractEntity) : PlaceholderArgument -} +fun SkillMetadata.toPlaceholderArgs(): PlaceholderContext = PlaceholderContext.builder().meta(this).build() +fun AbstractEntity.toPlaceholderArgs(): PlaceholderContext = PlaceholderContext.builder().entity(this).build() +fun toPlaceholderArgs(meta: SkillMetadata, target: AbstractEntity): PlaceholderContext = PlaceholderContext.builder().meta(meta).entity(target).build() From 0051f3beab37fa3fd657a368387943f837761f77 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 3 May 2026 01:09:00 +0000 Subject: [PATCH 70/91] fix(deps): update dependency com.github.ben-manes.caffeine:caffeine to v3.2.4 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 93e993d53..6b280d9fc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -22,7 +22,7 @@ neoform = "26.1.2-1" kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" } semver4j = "org.semver4j:semver4j:6.0.0" -caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.3" +caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.4" adventure-api = "net.kyori:adventure-api:4.26.1" adventure-examination = "net.kyori:examination-api:1.3.0" From 6b731696419e69f5d70d253b7f89143f37d80448 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 4 May 2026 00:17:00 +0900 Subject: [PATCH 71/91] chore: remove stable_player_display to library list --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index ae1c49412..4d81434c1 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,6 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim - [semver4j](https://github.com/semver4j/semver4j): semver parser - [cloud](https://github.com/Incendo/cloud-minecraft): command - [adventure](https://github.com/KyoriPowered/adventure): component -- [stable player display](https://github.com/bradleyq/stable_player_display): player animation - [caffeine](https://github.com/ben-manes/caffeine): concurrent map cache - [DynamicUV](https://github.com/toxicity188/DynamicUV): player model - [ArmorModel](https://github.com/toxicity188/ArmorModel): armor in player model From a9276eb5c62cb343e8a835ab0adbd2c9c0baa718 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 May 2026 22:32:39 +0000 Subject: [PATCH 72/91] fix(deps): update dependency dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin to v4 --- buildSrc/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index 26cf6acc8..8699b96df 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -18,6 +18,6 @@ dependencies { implementation(libs.build.paperweight) implementation("org.jetbrains.dokka:dokka-gradle-plugin:2.2.0") - implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:3.0.1") + implementation("dev.yumi.gradle.licenser:dev.yumi.gradle.licenser.gradle.plugin:4.0.0") implementation("com.vanniktech.maven.publish:com.vanniktech.maven.publish.gradle.plugin:0.36.0") } From ecc09340f2b56e5ec3969a90b3e370faf4d2481f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 5 May 2026 13:57:15 +0900 Subject: [PATCH 73/91] refactor: add @NotNull annotation to some method --- .../java/kr/toxicity/model/api/tracker/TrackerAnimation.java | 1 + .../java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java index 01b777b84..12681a08a 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerAnimation.java @@ -118,6 +118,7 @@ public static final class Builder { * @return a new builder for the specified type * @since 2.2.0 */ + @NotNull public Builder type(@NotNull Class newTargetClass) { return new Builder<>(name, newTargetClass) .priority(priority) diff --git a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java index 95acb547d..623164cdf 100644 --- a/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java +++ b/api/src/main/java/kr/toxicity/model/api/tracker/TrackerUpdateAction.java @@ -174,6 +174,7 @@ public sealed interface TrackerUpdateAction extends BiPredicate none(); case 1 -> actions[0]; @@ -189,6 +190,7 @@ public sealed interface TrackerUpdateAction extends BiPredicate builder) { + Objects.requireNonNull(builder, "builder must not be null"); return new PerBone(builder); } From 539bbd76f484454b75fb1328596f4bb10aade7b8 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 5 May 2026 13:57:42 +0900 Subject: [PATCH 74/91] chore: update fabric-api to v0.148.0+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 6b280d9fc..00e5bb525 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.147.0+26.1.2" +fabric-api = "0.148.0+26.1.2" fabric-language-kotlin = "1.13.11+kotlin.2.3.21" cloud-bukkit = "2.0.0-beta.15" From 7e3a690d58e32a8eebc6536d1b4a8fb102707a0f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 5 May 2026 18:39:18 +0900 Subject: [PATCH 75/91] chore: update adventure-api to v5.0.1 --- README.md | 2 +- .../java/kr/toxicity/model/bukkit/BetterModelLibrary.java | 3 +-- .../main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt | 1 + gradle/libs.versions.toml | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 4d81434c1..8178d34f4 100644 --- a/README.md +++ b/README.md @@ -71,7 +71,7 @@ BetterModel aims to be a reliable engine that provides stable, high-quality anim - [Kotlin stdlib](https://github.com/JetBrains/kotlin): modern functional programming - [semver4j](https://github.com/semver4j/semver4j): semver parser - [cloud](https://github.com/Incendo/cloud-minecraft): command -- [adventure](https://github.com/KyoriPowered/adventure): component +- [adventure](https://github.com/PaperMC/adventure): component - [caffeine](https://github.com/ben-manes/caffeine): concurrent map cache - [DynamicUV](https://github.com/toxicity188/DynamicUV): player model - [ArmorModel](https://github.com/toxicity188/ArmorModel): armor in player model diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java index bce49e110..000c716e4 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java @@ -78,7 +78,6 @@ public final class BetterModelLibrary { "adventure-text-serializer-legacy", "adventure-nbt", "adventure-text-serializer-gson", - "adventure-text-serializer-gson-legacy-impl", "adventure-text-serializer-json", "adventure-text-serializer-json-legacy-impl" ) @@ -99,7 +98,7 @@ public final class BetterModelLibrary { builder -> builder.predicate(BooleanConstantSupplier.of(!BetterModelBukkit.IS_PAPER)) ); public static final LibraryData ADVENTURE_PLATFORM = register( - "net{}kyori", + "io{}github{}toxicity188", "adventure-platform-bukkit", builder -> builder .subModules( diff --git a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt index 1c2ffb857..de6ed35e5 100644 --- a/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt +++ b/core/bukkit-core/src/main/kotlin/kr/toxicity/model/bukkit/BetterModelPlugin.kt @@ -62,6 +62,7 @@ abstract class BetterModelPlugin : AbstractBetterModelPlugin() { override fun onEnable() { props.managers.forEach(GlobalManager::start) + ADVENTURE_PLATFORM if (isSnapshot) warn( "This build is dev version: be careful to use it!".toComponent(), "Build number: ${props.snapshot}".toComponent(LIGHT_PURPLE) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 00e5bb525..764e5fd01 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,10 +24,10 @@ kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" semver4j = "org.semver4j:semver4j:6.0.0" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.4" -adventure-api = "net.kyori:adventure-api:4.26.1" +adventure-api = "net.kyori:adventure-api:5.0.1" adventure-examination = "net.kyori:examination-api:1.3.0" adventure-option = "net.kyori:option:1.1.0" -adventure-platform-bukkit = "net.kyori:adventure-platform-bukkit:4.4.1" +adventure-platform-bukkit = "io.github.toxicity188:adventure-platform-bukkit:5.0.0" adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0" asm-tree = "org.ow2.asm:asm-tree:9.9.1" From e0c30a38fdde1f6133ab0cd925aedb6dcc4cefea Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 5 May 2026 21:34:37 +0900 Subject: [PATCH 76/91] Revert "chore: update adventure-api to v5.0.1" Paper does not use Adventure 5 yet --- .../java/kr/toxicity/model/bukkit/BetterModelLibrary.java | 3 ++- gradle/libs.versions.toml | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java index 000c716e4..bce49e110 100644 --- a/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java +++ b/core/bukkit-core/src/main/java/kr/toxicity/model/bukkit/BetterModelLibrary.java @@ -78,6 +78,7 @@ public final class BetterModelLibrary { "adventure-text-serializer-legacy", "adventure-nbt", "adventure-text-serializer-gson", + "adventure-text-serializer-gson-legacy-impl", "adventure-text-serializer-json", "adventure-text-serializer-json-legacy-impl" ) @@ -98,7 +99,7 @@ public final class BetterModelLibrary { builder -> builder.predicate(BooleanConstantSupplier.of(!BetterModelBukkit.IS_PAPER)) ); public static final LibraryData ADVENTURE_PLATFORM = register( - "io{}github{}toxicity188", + "net{}kyori", "adventure-platform-bukkit", builder -> builder .subModules( diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 764e5fd01..00e5bb525 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,10 +24,10 @@ kotlin = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" semver4j = "org.semver4j:semver4j:6.0.0" caffeine = "com.github.ben-manes.caffeine:caffeine:3.2.4" -adventure-api = "net.kyori:adventure-api:5.0.1" +adventure-api = "net.kyori:adventure-api:4.26.1" adventure-examination = "net.kyori:examination-api:1.3.0" adventure-option = "net.kyori:option:1.1.0" -adventure-platform-bukkit = "io.github.toxicity188:adventure-platform-bukkit:5.0.0" +adventure-platform-bukkit = "net.kyori:adventure-platform-bukkit:4.4.1" adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0" asm-tree = "org.ow2.asm:asm-tree:9.9.1" From 6f9de279467e5c31c94915188195bb111f93f24d Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 6 May 2026 07:44:46 +0900 Subject: [PATCH 77/91] refactor: make info component to prevent --- core/src/main/kotlin/kr/toxicity/model/util/Senders.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt b/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt index 304a37c60..e10731554 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Senders.kt @@ -16,10 +16,10 @@ import net.kyori.adventure.text.format.NamedTextColor import net.kyori.adventure.text.format.TextColor import net.kyori.adventure.text.format.TextDecoration -val INFO = " [!] ".toComponent { +private val INFO = " [!] ".toComponent { decorate(TextDecoration.BOLD).color(NamedTextColor.GREEN) } -val WARN = " [!] ".toComponent { +private val WARN = " [!] ".toComponent { decorate(TextDecoration.BOLD).color(NamedTextColor.RED) } From 02142591d61a051ab1086162a9ebea66af9b299a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Wed, 6 May 2026 07:45:20 +0900 Subject: [PATCH 78/91] chore: update ViaVersion to v5.9.1. for test server --- build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index 7fc3427c2..61a85e826 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -31,8 +31,8 @@ tasks { }) minecraftVersion(minecraft) downloadPlugins { - hangar("ViaVersion", "5.9.0") - hangar("ViaBackwards", "5.9.0") + hangar("ViaVersion", "5.9.1") + hangar("ViaBackwards", "5.9.1") hangar("Skript", "2.15.2") } } From 636bcfd26b03888d6d89a2094c8edf23a0eece6e Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 10 May 2026 17:18:59 +0900 Subject: [PATCH 79/91] update: 3.1.0 --- changelog/{3.0.3.md => 3.1.0.md} | 0 gradle.properties | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename changelog/{3.0.3.md => 3.1.0.md} (100%) diff --git a/changelog/3.0.3.md b/changelog/3.1.0.md similarity index 100% rename from changelog/3.0.3.md rename to changelog/3.1.0.md diff --git a/gradle.properties b/gradle.properties index 58c87580a..bc6928858 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ org.gradle.configuration-cache=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -project_version=3.0.3 +project_version=3.1.0 minecraft_version=26.1.2 From c6899ad1d71de12c856ca6857b55a2144b8b42e5 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 10 May 2026 17:23:03 +0900 Subject: [PATCH 80/91] feat: rewrite AnimationGenerator for parallel processing of animation import --- .../data/blueprint/AnimationGenerator.java | 164 +++++++++--------- .../model/api/data/raw/ModelAnimation.java | 2 +- .../model/api/data/raw/ModelData.java | 7 +- .../model/api/data/raw/ModelDatapoint.java | 2 +- .../kr/toxicity/model/api/pack/PackPath.java | 11 ++ .../model/api/util/CollectionUtil.java | 35 ---- .../model/manager/ModelManagerImpl.kt | 2 +- .../toxicity/model/manager/ReloadPipeline.kt | 12 +- .../model/manager/debug/BossBarIndicator.kt | 1 + .../kotlin/kr/toxicity/model/util/Packs.kt | 4 +- 10 files changed, 112 insertions(+), 128 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index b1b174861..dbc06b737 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -17,11 +17,10 @@ import org.jetbrains.annotations.Nullable; import org.joml.Vector3f; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Objects; +import java.util.*; import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; import static kr.toxicity.model.api.util.CollectionUtil.*; @@ -38,8 +37,6 @@ @ApiStatus.Internal public final class AnimationGenerator { - private static final Vector3f EMPTY = new Vector3f(); - private final Map pointMap; private final List trees; /** @@ -54,7 +51,7 @@ public final class AnimationGenerator { * @return a map of generated blueprint animators keyed by bone name * @since 1.15.2 */ - public static @NotNull Map createMovements( + public static @NotNull Map generate( float length, @NotNull List children, @NotNull Map pointMap @@ -65,35 +62,37 @@ public final class AnimationGenerator { floatSet.add(0F); floatSet.add(length); InterpolationUtil.insertLerpFrame(floatSet); - var generator = new AnimationGenerator(pointMap, children); + var generator = new AnimationGenerator(g -> pointMap.get(g.name()), children); generator.interpolateRotation(floatSet); generator.interpolateStep(floatSet); - return mapValue(pointMap, v -> new BlueprintAnimator( - v.name(), - InterpolationUtil.buildAnimation( - v.position(), - v.rotation(), - v.scale(), - v.rotationGlobal(), - floatSet - ) - )); + return associate( + pointMap.values() + .stream() + .parallel() + .map(v -> new BlueprintAnimator( + v.name(), + InterpolationUtil.buildAnimation( + v.position(), + v.rotation(), + v.scale(), + v.rotationGlobal(), + floatSet + )) + ), + BlueprintAnimator::name + ); } private AnimationGenerator( - @NotNull Map pointMap, + @NotNull Function function, @NotNull List children ) { - this.pointMap = pointMap; trees = filterIsInstance(children, BlueprintElement.Group.class) - .map(g -> new AnimationTree(g, pointMap.get(g.name()))) + .map(g -> new AnimationTree(null, g, function)) .flatMap(AnimationTree::flatten) .toList(); } - private float firstTime = 0F; - private float secondTime = 0F; - /** * Inserts additional keyframes to smooth out large rotations. *

@@ -104,29 +103,66 @@ private AnimationGenerator( * @since 1.15.2 */ public void interpolateRotation(@NotNull FloatSortedSet floats) { - var iterator = new FloatArrayList(floats).iterator(); - var time = 0.05F; - while (iterator.hasNext()) { - firstTime = secondTime; - secondTime = iterator.nextFloat(); - if (secondTime - firstTime <= 0) continue; - var minus = trees.stream() - .mapToDouble(t -> t.tree(firstTime, secondTime, BlueprintAnimator.AnimatorData::rotation)) - .max() - .orElse(0); - var length = (float) Math.ceil(minus / 90); + var list = new FloatArrayList(floats); + var map = trees.stream() + .parallel() + .map(t -> { + var d = t.data; + if (d == null) return null; + var rot = d.rotation(); + if (rot.size() < 2) return null; + var interpolator = InterpolationUtil.interpolatorFor(rot); + return new RotationVector( + t, + list.doubleStream() + .mapToObj(value -> interpolator.build((float) value).vector()) + .toList() + ); + }) + .filter(Objects::nonNull) + .collect(Collectors.toUnmodifiableMap(v -> v.tree, v -> v.vectors)); + if (map.isEmpty()) return; + var next = 0F; + for (MaxRotation maxRotation : IntStream.range(0, list.size()) + .parallel() + .mapToObj(i -> { + var cache = new IdentityHashMap(trees.size()); + for (AnimationTree t : trees) { + Vector3f current, parent; + var getVec = map.get(t); + current = getVec != null ? getVec.get(i) : VectorPoint.EMPTY.vector(); + cache.put(t, t.parent != null && (parent = cache.get(t.parent)) != null ? parent.add(current, new Vector3f()) : current); + } + return new MaxRotation(list.getFloat(i), (float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0)); + }) + .sorted() + .toList() + ) { + var previous = next; + next = maxRotation.time; + var length = (float) Math.ceil(maxRotation.maxRotation / 90F); if (length < 2) continue; - var addTime = Math.max( - InterpolationUtil.lerp(0, secondTime - firstTime, 1F / length), - time + var interpolateTime = Math.max( + InterpolationUtil.lerp(0, next - previous, 1F / length), + 0.05F ); for (float f = 1; f < length; f++) { - if (secondTime - addTime < time + MathUtil.FRAME_EPSILON) continue; - floats.add(firstTime + f * addTime); + var addTime = MathUtil.fma(f, interpolateTime, previous); + if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) continue; + floats.add(addTime); } } } + private record RotationVector(@NotNull AnimationTree tree, @NotNull List vectors) {} + + private record MaxRotation(float time, float maxRotation) implements Comparable { + @Override + public int compareTo(@NotNull AnimationGenerator.MaxRotation o) { + return Float.compare(time, o.time); + } + } + /** * Inserts keyframes for step interpolation (non-continuous transitions). * @@ -155,25 +191,20 @@ private void interpolateStep(@NotNull FloatSortedSet floats, @NotNull List children; private final BlueprintAnimator.AnimatorData data; - private int searchCache = 0; - private final Float2ObjectMap valueCache = new Float2ObjectOpenHashMap<>(); - AnimationTree(@NotNull BlueprintElement.Group group, @Nullable BlueprintAnimator.AnimatorData data) { - this(null, group, data); - } AnimationTree( @Nullable AnimationTree parent, @NotNull BlueprintElement.Group group, - @Nullable BlueprintAnimator.AnimatorData data + @NotNull Function function ) { this.parent = parent; - this.data = data; + this.data = function.apply(group); children = filterIsInstance(group.children(), BlueprintElement.Group.class) - .map(g -> new AnimationTree(this, g, pointMap.get(g.name()))) + .map(g -> new AnimationTree(this, g, function)) .toList(); } @@ -184,40 +215,5 @@ Stream flatten() { children.stream().flatMap(AnimationTree::flatten) ); } - - private float tree(float first, float second, @NotNull Function> mapper) { - var value = data != null ? mapper.apply(data) : Collections.emptyList(); - return findTree(first, second, value).length(); - } - - private @NotNull Vector3f findTree(float first, float second, @NotNull List target) { - var get = find(first, second, target); - return parent != null ? parent.findTree(first, second, target).add(get) : get; - } - private @NotNull Vector3f find(float first, float second, @NotNull List target) { - return find(second, target).sub(find(first, target), new Vector3f()); - } - private @NotNull Vector3f find(float time, @NotNull List target) { - return valueCache.computeIfAbsent(time, _ -> { - if (target.size() <= 1) return EMPTY; - var i = searchCache; - for (; i < target.size(); i++) { - if (target.get(i).time() >= time) break; - } - searchCache = i; - if (i == 0) return EMPTY; - if (i == target.size()) return EMPTY; - var first = target.get(i - 1); - var second = target.get(i); - var t1 = first.time(); - var t2 = second.time(); - var a = InterpolationUtil.alpha(t1, t2, time); - return second.time() == time ? second.vector() : InterpolationUtil.lerp( - first.vector(InterpolationUtil.lerp(t1, t2, a)), - second.vector(), - a - ); - }); - } } } diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java index 3f5357feb..6a291d299 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelAnimation.java @@ -64,7 +64,7 @@ public record ModelAnimation( @NotNull ModelLoadContext context, @NotNull List children ) { - var animators = AnimationGenerator.createMovements(length(), children, associate( + var animators = AnimationGenerator.generate(length(), children, associate( animators().entrySet().stream() .filter(e -> context.availableUUIDs.contains(e.getKey())) .map(Map.Entry::getValue) diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java index b4d2e5fe8..458952eec 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelData.java @@ -105,7 +105,12 @@ public record ModelData( resolution(), mapToList(textures(), texture -> texture.toBlueprint(context)), group, - associate(animations().stream().map(raw -> raw.toBlueprint(context, group)), BlueprintAnimation::name) + associate( + animations().stream() + .parallel() + .map(raw -> raw.toBlueprint(context, group)), + BlueprintAnimation::name + ) ), context.errors ); diff --git a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java index 3115c9a30..bcfca85ba 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java +++ b/api/src/main/java/kr/toxicity/model/api/data/raw/ModelDatapoint.java @@ -97,7 +97,7 @@ && zb instanceof Float2FloatConstantFunction(float zc) if (string.isEmpty()) return Float2FloatFunction.ZERO; try { return Float2FloatFunction.of(Float.parseFloat(string)); - } catch (NumberFormatException ignored) { + } catch (NumberFormatException _) { return context.trySupply( () -> BetterModel.platform().evaluator().compile(context.placeholder.parseVariable(string)), error -> new ModelLoadContext.Fallback<>( diff --git a/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java b/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java index 1693bcdb9..ed597ea14 100644 --- a/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java +++ b/api/src/main/java/kr/toxicity/model/api/pack/PackPath.java @@ -47,6 +47,17 @@ public record PackPath(@NotNull String path) implements Comparable { return new PackPath(path.isEmpty() ? join(DELIMITER, subPaths) : path + DELIMITER + join(DELIMITER, subPaths)); } + /** + * Returns the name of the file or directory represented by this path. + * + * @return the name + * @since 3.1.0 + */ + public @NotNull String name() { + var name = path(); + return name.substring(name.lastIndexOf(DELIMITER) + 1); + } + @Override public @NotNull String toString() { return path; diff --git a/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java b/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java index 219d03285..cdc72fbf7 100644 --- a/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java +++ b/api/src/main/java/kr/toxicity/model/api/util/CollectionUtil.java @@ -12,8 +12,6 @@ import it.unimi.dsi.fastutil.floats.FloatCollection; import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import kr.toxicity.model.api.BetterModel; -import net.kyori.adventure.text.format.NamedTextColor; import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Unmodifiable; @@ -21,7 +19,6 @@ import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; -import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -322,38 +319,6 @@ public static T mapFloat(@NotNull Stream strea return collect; } - /** - * Map some map's value. - * @param original original map - * @param mapper value mapper - * @return unmodifiable map - * @param key - * @param value - * @param new value - */ - @NotNull - @Unmodifiable - public static Map mapValue(@NotNull Map original, @NotNull Function mapper) { - return associate(original.entrySet(), Map.Entry::getKey, e -> mapper.apply(e.getValue())); - } - - /** - * Gets filter with warning if not matched - * @param predicate delegated predicate - * @param lazyLogFunction log function - * @return predicate - * @param type - */ - @NotNull - public static Predicate filterWithWarning(@NotNull Predicate predicate, @NotNull Function lazyLogFunction) { - var logger = BetterModel.platform().logger(); - return t -> { - var testedValue = predicate.test(t); - if (!testedValue) logger.warn(LogUtil.toLog(lazyLogFunction.apply(t), NamedTextColor.YELLOW)); - return testedValue; - }; - } - /** * Associates collection to map * @param collection collection diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt index 991026383..45ace053a 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ModelManagerImpl.kt @@ -56,7 +56,7 @@ object ModelManagerImpl : ModelManager, GlobalManager { status = "Importing $typeName models..." goal = targetAssets.size }.forEachParallel(targetAssets, ModelAsset::sizeAssume) { - val index = pipeline.progress() + val index = pipeline.progress(it.name) val load = it.toTexturedModel() ?: return@forEachParallel modelFileMap.compute(load.name) { _, v -> if (v != null) { diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt b/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt index 52946a214..580f70e63 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/ReloadPipeline.kt @@ -18,6 +18,7 @@ class ReloadPipeline( ) : AutoCloseable { var status = "Starting..." + private var target = "Unknown" private val pool = parallelIOThreadPool() private val current = AtomicInteger() @@ -27,7 +28,10 @@ class ReloadPipeline( current.set(0) } - fun progress() = current.incrementAndGet() + fun progress(target: String): Int { + this.target = target + return current.incrementAndGet() + } fun forEachParallel(list: List, sizeAssume: (T) -> Long, block: (T) -> Unit) { pool.forEachParallel(list, sizeAssume, block) @@ -47,7 +51,8 @@ class ReloadPipeline( if (goal > 0) toFloat() / goal.toFloat() else 0F, this, goal, - status + status, + target ) }.run { indicators.forEach { @@ -60,7 +65,8 @@ class ReloadPipeline( val progress: Float, val current: Int, val goal: Int, - val status: String + val status: String, + val target: String ) override fun close() { diff --git a/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt b/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt index 16ab4b9f1..84e796e5c 100644 --- a/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt +++ b/core/src/main/kotlin/kr/toxicity/model/manager/debug/BossBarIndicator.kt @@ -36,6 +36,7 @@ class BossBarIndicator( override fun status(status: ReloadPipeline.Status) { bossBar.run { name(componentOf(status.status) { + append(" [${status.target}]".toComponent(NamedTextColor.AQUA)) append(" (${status.current.withComma()} / ${status.goal.withComma()})".toComponent(NamedTextColor.YELLOW)) }) progress(status.progress) diff --git a/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt b/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt index 90d029881..656de1733 100644 --- a/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt +++ b/core/src/main/kotlin/kr/toxicity/model/util/Packs.kt @@ -74,7 +74,7 @@ class FolderGenerator : PackGenerator { val bytes = it.get() pack[it.overlay()] = PackByte(it.path(), bytes) val file = it.path().toFile() - val index = pipeline.progress() + val index = pipeline.progress(it.path().name()) if (file.length() != bytes.size.toLong()) { file.writeBytes(bytes) changed.set(true) @@ -137,7 +137,7 @@ fun PackZipper.writeToResult(pipeline: ReloadPipeline, dir: File? = null): PackR return PackResult(build.meta(), dir).apply { pipeline.forEachParallel(build.resources(), PackResource::estimatedSize) { set(it.overlay(), PackByte(it.path(), it.get())) - val index = pipeline.progress() + val index = pipeline.progress(it.path().name()) debugPack { componentOf( "This file was successfully zipped: ".toComponent(), From 292f37334b470223ed0edfaede70c2580c35f1ee Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 10 May 2026 18:45:09 +0900 Subject: [PATCH 81/91] fix: initial tick of animation --- .../api/animation/AnimationStateHandler.java | 2 +- .../data/blueprint/AnimationGenerator.java | 40 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index c8cbe7296..27c909683 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -34,7 +34,7 @@ public final class AnimationStateHandler { private final PriorityMap animators = new PriorityMap<>(); @Getter - private int delay; + private int delay = 1; private volatile TreeIterator currentIterator = null; private volatile T beforeKeyframe = null, afterKeyframe = null; diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index dbc06b737..4e4ac0a7a 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -19,7 +19,6 @@ import java.util.*; import java.util.function.Function; -import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -61,10 +60,10 @@ public final class AnimationGenerator { .flatMap(BlueprintAnimator.AnimatorData::allPoints), VectorPoint::time, () -> new FloatAVLTreeSet(MathUtil.FRAME_COMPARATOR)); floatSet.add(0F); floatSet.add(length); - InterpolationUtil.insertLerpFrame(floatSet); var generator = new AnimationGenerator(g -> pointMap.get(g.name()), children); generator.interpolateRotation(floatSet); generator.interpolateStep(floatSet); + InterpolationUtil.insertLerpFrame(floatSet); return associate( pointMap.values() .stream() @@ -104,23 +103,26 @@ private AnimationGenerator( */ public void interpolateRotation(@NotNull FloatSortedSet floats) { var list = new FloatArrayList(floats); - var map = trees.stream() - .parallel() - .map(t -> { - var d = t.data; - if (d == null) return null; - var rot = d.rotation(); - if (rot.size() < 2) return null; - var interpolator = InterpolationUtil.interpolatorFor(rot); - return new RotationVector( - t, - list.doubleStream() - .mapToObj(value -> interpolator.build((float) value).vector()) - .toList() - ); - }) - .filter(Objects::nonNull) - .collect(Collectors.toUnmodifiableMap(v -> v.tree, v -> v.vectors)); + var map = associate( + trees.stream() + .parallel() + .map(t -> { + var d = t.data; + if (d == null) return null; + var rot = d.rotation(); + if (rot.size() < 2) return null; + var interpolator = InterpolationUtil.interpolatorFor(rot); + return new RotationVector( + t, + list.doubleStream() + .mapToObj(value -> interpolator.build((float) value).vector()) + .toList() + ); + }) + .filter(Objects::nonNull), + v -> v.tree, + v -> v.vectors + ); if (map.isEmpty()) return; var next = 0F; for (MaxRotation maxRotation : IntStream.range(0, list.size()) From dfc1627072926900c96371456d0f2a68739e620a Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 10 May 2026 21:28:18 +0900 Subject: [PATCH 82/91] fix: skip first frame on generating animation --- .../model/api/data/blueprint/AnimationGenerator.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index 4e4ac0a7a..f727d47b2 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -125,7 +125,7 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { ); if (map.isEmpty()) return; var next = 0F; - for (MaxRotation maxRotation : IntStream.range(0, list.size()) + for (MaxRotation maxRotation : IntStream.range(1, list.size()) .parallel() .mapToObj(i -> { var cache = new IdentityHashMap(trees.size()); @@ -138,7 +138,7 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { return new MaxRotation(list.getFloat(i), (float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0)); }) .sorted() - .toList() + .toArray(MaxRotation[]::new) ) { var previous = next; next = maxRotation.time; @@ -150,7 +150,7 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { ); for (float f = 1; f < length; f++) { var addTime = MathUtil.fma(f, interpolateTime, previous); - if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) continue; + if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) break; floats.add(addTime); } } From ce7b5055d32cff9e50e076324ce6e34752d9a61c Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sun, 10 May 2026 21:59:57 +0900 Subject: [PATCH 83/91] fix: calculation delta rotation --- .../model/api/data/blueprint/AnimationGenerator.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index f727d47b2..d0b026809 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -130,10 +130,10 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { .mapToObj(i -> { var cache = new IdentityHashMap(trees.size()); for (AnimationTree t : trees) { - Vector3f current, parent; + Vector3f delta, parent; var getVec = map.get(t); - current = getVec != null ? getVec.get(i) : VectorPoint.EMPTY.vector(); - cache.put(t, t.parent != null && (parent = cache.get(t.parent)) != null ? parent.add(current, new Vector3f()) : current); + delta = getVec != null ? getVec.get(i).sub(getVec.get(i - 1), new Vector3f()) : new Vector3f(); + cache.put(t, t.parent != null && (parent = cache.get(t.parent)) != null ? delta.add(parent) : delta); } return new MaxRotation(list.getFloat(i), (float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0)); }) @@ -143,9 +143,9 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { var previous = next; next = maxRotation.time; var length = (float) Math.ceil(maxRotation.maxRotation / 90F); - if (length < 2) continue; + if (length < 2F) continue; var interpolateTime = Math.max( - InterpolationUtil.lerp(0, next - previous, 1F / length), + (next - previous) / length, 0.05F ); for (float f = 1; f < length; f++) { From f60ec42800e12d6d4a9252276e069d2cd7d786ee Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Mon, 11 May 2026 22:41:17 +0900 Subject: [PATCH 84/91] refactor: simplify AnimationGenerator --- .../data/blueprint/AnimationGenerator.java | 47 +++++++------------ 1 file changed, 18 insertions(+), 29 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index d0b026809..32c52ee61 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -124,10 +124,9 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { v -> v.vectors ); if (map.isEmpty()) return; - var next = 0F; - for (MaxRotation maxRotation : IntStream.range(1, list.size()) + IntStream.range(1, list.size()) .parallel() - .mapToObj(i -> { + .forEach(i -> { var cache = new IdentityHashMap(trees.size()); for (AnimationTree t : trees) { Vector3f delta, parent; @@ -135,36 +134,26 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { delta = getVec != null ? getVec.get(i).sub(getVec.get(i - 1), new Vector3f()) : new Vector3f(); cache.put(t, t.parent != null && (parent = cache.get(t.parent)) != null ? delta.add(parent) : delta); } - return new MaxRotation(list.getFloat(i), (float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0)); - }) - .sorted() - .toArray(MaxRotation[]::new) - ) { - var previous = next; - next = maxRotation.time; - var length = (float) Math.ceil(maxRotation.maxRotation / 90F); - if (length < 2F) continue; - var interpolateTime = Math.max( - (next - previous) / length, - 0.05F - ); - for (float f = 1; f < length; f++) { - var addTime = MathUtil.fma(f, interpolateTime, previous); - if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) break; - floats.add(addTime); - } - } + var length = (float) Math.ceil((float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0) / 90F); + if (length < 2F) return; + var previous = list.getFloat(i - 1); + var next = list.getFloat(i); + var interpolateTime = Math.max( + (next - previous) / length, + 0.05F + ); + synchronized (floats) { + for (float f = 1; f < length; f++) { + var addTime = MathUtil.fma(f, interpolateTime, previous); + if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) break; + floats.add(addTime); + } + } + }); } private record RotationVector(@NotNull AnimationTree tree, @NotNull List vectors) {} - private record MaxRotation(float time, float maxRotation) implements Comparable { - @Override - public int compareTo(@NotNull AnimationGenerator.MaxRotation o) { - return Float.compare(time, o.time); - } - } - /** * Inserts keyframes for step interpolation (non-continuous transitions). * From b4fb743aebb509d4a1e05ce54323099d6d427581 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Tue, 12 May 2026 06:49:17 +0900 Subject: [PATCH 85/91] chore: update fabric-api to v0.148.2+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 00e5bb525..af9215371 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.148.0+26.1.2" +fabric-api = "0.148.2+26.1.2" fabric-language-kotlin = "1.13.11+kotlin.2.3.21" cloud-bukkit = "2.0.0-beta.15" From 377a115ff5545f9d8b2be491e63ecff77182c106 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 14 May 2026 13:46:26 +0900 Subject: [PATCH 86/91] refactor: simplify AnimationGenerator --- .../toxicity/model/api/data/blueprint/AnimationGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index 32c52ee61..2aadb8fe3 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -134,7 +134,7 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { delta = getVec != null ? getVec.get(i).sub(getVec.get(i - 1), new Vector3f()) : new Vector3f(); cache.put(t, t.parent != null && (parent = cache.get(t.parent)) != null ? delta.add(parent) : delta); } - var length = (float) Math.ceil((float) cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0) / 90F); + var length = (float) Math.ceil(cache.values().stream().mapToDouble(Vector3f::length).max().orElse(0.0) / 90.0); if (length < 2F) return; var previous = list.getFloat(i - 1); var next = list.getFloat(i); From 521eac9442ed8ecf5b35f7b9036b724e9de70c88 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Thu, 14 May 2026 13:46:57 +0900 Subject: [PATCH 87/91] chore: update gradle to v9.5.1 --- gradle/wrapper/gradle-wrapper.jar | Bin 48966 -> 48462 bytes gradle/wrapper/gradle-wrapper.properties | 4 ++- gradlew | 2 +- gradlew.bat | 31 ++++++++--------------- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index d997cfc60f4cff0e7451d19d49a82fa986695d07..b1b8ef56b44f16b14dc800fa8103a6d89abb526f 100644 GIT binary patch delta 39760 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 e(*aw}>J`&Ep$5$o2mVP)i30-M3~u@DBh0 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 delta 40115 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 e{Sg5G5zENPNVU~b5#<2@M#Os+0czL&{q{eZe&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :findJavaFromJavaHome set JAVA_HOME=%JAVA_HOME:"=% @@ -65,7 +65,7 @@ echo. 1>&2 echo Please set the JAVA_HOME variable in your environment to match the 1>&2 echo location of your Java installation. 1>&2 -goto fail +"%COMSPEC%" /c exit 1 :execute @rem Setup the command line @@ -73,21 +73,10 @@ goto fail @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* +@rem endlocal doesn't take effect until after the line is parsed and variables are expanded +@rem which allows us to clear the local environment before executing the java command +endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +:exitWithErrorLevel +@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts +"%COMSPEC%" /c exit %ERRORLEVEL% From 3b5d1df47f2733a9f601fd292ffbd225faa4da59 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 14 May 2026 18:45:01 +0000 Subject: [PATCH 88/91] fix(deps): update dependency org.ow2.asm:asm-tree to v9.10 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index af9215371..afe12ad9d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -30,7 +30,7 @@ adventure-option = "net.kyori:option:1.1.0" adventure-platform-bukkit = "net.kyori:adventure-platform-bukkit:4.4.1" adventure-platform-fabric = "net.kyori:adventure-platform-fabric:6.9.0" -asm-tree = "org.ow2.asm:asm-tree:9.9.1" +asm-tree = "org.ow2.asm:asm-tree:9.10" fabric-loader = "net.fabricmc:fabric-loader:0.19.2" fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric-language-kotlin" } From e77a8b0de3838600604306c990a8473c56733c3f Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Fri, 15 May 2026 20:51:40 +0900 Subject: [PATCH 89/91] chore: update fabric-api to v0.149.0+26.1.2 --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index afe12ad9d..13c4cae76 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -7,7 +7,7 @@ shadow = "9.4.1" minotaur = "2.9.0" hangarPublish = "0.1.4" -fabric-api = "0.148.2+26.1.2" +fabric-api = "0.149.0+26.1.2" fabric-language-kotlin = "1.13.11+kotlin.2.3.21" cloud-bukkit = "2.0.0-beta.15" From 917a95f48a3db038aeda1b577ed683ee015c74c4 Mon Sep 17 00:00:00 2001 From: toxicity188 Date: Sat, 16 May 2026 20:43:49 +0900 Subject: [PATCH 90/91] refactor: minecraft tick constant field --- .../model/api/animation/AnimationStateHandler.java | 6 +++--- .../model/api/data/blueprint/AnimationGenerator.java | 6 +++--- .../toxicity/model/api/util/InterpolationUtil.java | 2 +- .../java/kr/toxicity/model/api/util/MathUtil.java | 12 +++++++++++- 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java index 27c909683..a5f011700 100644 --- a/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java +++ b/api/src/main/java/kr/toxicity/model/api/animation/AnimationStateHandler.java @@ -223,7 +223,7 @@ public boolean stopAnimation(@NotNull String name) { * @return ticking frame */ public float frame() { - return afterKeyframe != null ? 20 * Tracker.MINECRAFT_TICK_MULTIPLIER * (currentIterator.time + MathUtil.FRAME_EPSILON) : 0F; + return afterKeyframe != null ? MathUtil.MINECRAFT_TICKS_PER_SECOND * Tracker.MINECRAFT_TICK_MULTIPLIER * (currentIterator.time + MathUtil.FRAME_EPSILON) : 0F; } private class TreeIterator implements BooleanSupplier { @@ -260,12 +260,12 @@ public boolean hasNext() { public @NotNull T next() { if (!started) { started = true; - time = (float) modifier.start() / 20; + time = (float) modifier.start() / MathUtil.MINECRAFT_TICKS_PER_SECOND; return iterator.next(); } if (!iterator.hasNext()) { ended = true; - time = (float) modifier.end() / 20; + time = (float) modifier.end() / MathUtil.MINECRAFT_TICKS_PER_SECOND; return previous; } var nxt = iterator.next(); diff --git a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java index 2aadb8fe3..e483e1e7c 100644 --- a/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java +++ b/api/src/main/java/kr/toxicity/model/api/data/blueprint/AnimationGenerator.java @@ -140,12 +140,12 @@ public void interpolateRotation(@NotNull FloatSortedSet floats) { var next = list.getFloat(i); var interpolateTime = Math.max( (next - previous) / length, - 0.05F + MathUtil.MINECRAFT_TICK_SECONDS ); synchronized (floats) { for (float f = 1; f < length; f++) { var addTime = MathUtil.fma(f, interpolateTime, previous); - if (next - addTime < 0.05F + MathUtil.FRAME_EPSILON) break; + if (next - addTime < MathUtil.MINECRAFT_TICK_SECONDS + MathUtil.FRAME_EPSILON) break; floats.add(addTime); } } @@ -176,7 +176,7 @@ private void interpolateStep(@NotNull FloatSortedSet floats, @NotNull List Date: Sat, 16 May 2026 20:44:25 +0900 Subject: [PATCH 91/91] chore: update workflows --- .github/workflows/pr-test.yml | 5 +---- .github/workflows/publish.yml | 1 + build.gradle.kts | 2 +- buildSrc/src/main/kotlin/Extensions.kt | 14 ++++++++++++++ .../main/kotlin/modrinth-conventions.gradle.kts | 2 +- 5 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.github/workflows/pr-test.yml b/.github/workflows/pr-test.yml index 7286f48a0..1634b7650 100644 --- a/.github/workflows/pr-test.yml +++ b/.github/workflows/pr-test.yml @@ -22,8 +22,5 @@ jobs: - name: Grant execute permission for gradlew run: chmod +x gradlew - - name: Build with Gradle + - name: Test build run: ./gradlew build --stacktrace - - - name: Run Tests - run: ./gradlew test --stacktrace diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b3771c9a5..eaa798167 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -16,6 +16,7 @@ jobs: MODRINTH_API_TOKEN: ${{ secrets.MODRINTH_API_TOKEN }} BUILD_NUMBER: ${{ github.run_number }} COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + COMMIT_HASH: ${{ github.sha }} steps: - uses: actions/checkout@v6 - name: Set up JDK 25 diff --git a/build.gradle.kts b/build.gradle.kts index 61a85e826..a001d8916 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -51,7 +51,7 @@ hangarPublish { version = project.version as String id = "BetterModel" apiKey = System.getenv("HANGAR_API_TOKEN") - val log = System.getenv("COMMIT_MESSAGE") + val log = commitMessage() if (log != null) { changelog = log channel = "Snapshot" diff --git a/buildSrc/src/main/kotlin/Extensions.kt b/buildSrc/src/main/kotlin/Extensions.kt index 5f3b2d582..753517610 100644 --- a/buildSrc/src/main/kotlin/Extensions.kt +++ b/buildSrc/src/main/kotlin/Extensions.kt @@ -27,5 +27,19 @@ val SUPPORTED_VERSIONS = buildList { addAll(LATEST_VERSION) } +fun commitMessage() = System.getenv("COMMIT_MESSAGE")?.let { + """ + **Commit hash**: ${System.getenv("COMMIT_HASH")?.let { hash -> "[$hash](https://github.com/toxicity188/BetterModel/commit/$hash) "} ?: "Unknown"} + + --- + + $it + + --- + + **Notice**: This is a snapshot build provided strictly for **testing purposes**. As a development version, unexpected issues or bugs may occur during use. + """.trimIndent() +} + val BUKKIT_LOADERS = listOf("spigot") val PAPER_LOADERS = listOf("paper", "purpur", "folia") diff --git a/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts b/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts index 07f8a9761..f545ad694 100644 --- a/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts +++ b/buildSrc/src/main/kotlin/modrinth-conventions.gradle.kts @@ -11,7 +11,7 @@ modrinth { token = System.getenv("MODRINTH_API_TOKEN") projectId = "bettermodel" syncBodyFrom = rootProject.file("BANNER.md").readText() - val log = System.getenv("COMMIT_MESSAGE") + val log = commitMessage() if (log != null) { versionType = "beta" changelog = log