跳到主要内容

开始之前!

FreeMinecraftModels (FMM) 目前正在积极开发中!这意味着某些功能尚未完成,并且正在积极开发中。

然而,目前插件的核心功能已完全可用 - 转换 bbmodel 文件、生成资源包、在游戏中生成实体并管理它们的动画、放置持久化道具的能力,这些都基本可以正常工作。

请考虑在 https://www.patreon.com/magmaguy 支持开发!

导出的资源包内容在 FreeMinecraftModels 这边采用 CC0 许可证,不保留任何权利。您可以自由使用、分发、修改用于任何目的,无需任何限制或署名。

使用此插件

FreeMinecraftModels (FMM) 能为 Minecraft 服务器管理员做什么?

它可以:

  • 导入 .bbmodel 或 fmmodel(FFM 的自定义格式)模型
  • 生成超出普通 Minecraft 资源包模型限制的资源包(最大 112x112x112 单位或游戏内 7x7x7 方块,使用多个骨骼时功能上无限制)
  • 在游戏中显示这些模型,向基岩版客户端发送特定的基岩版兼容数据包,同时向 1.19.4+ Java 版客户端发送显示实体
  • 按照在 Blockbench 中配置的方式为这些模型设置动画
  • 处理默认状态动画,无需其他插件(行走、待机、死亡、攻击、生成)
  • 处理随底层实体旋转且 x 和 z 轴不同的碰撞箱
  • 管理三种类型的模型:静态、动态和道具
    • 道具是持久化的,可以放置在世界中,即使服务器重启也会保持,并且可以将带有道具的地图分发到其他服务器
    • 动态模型适用于需要底层生物实体才能运行的模型,理想情况下由自定义 Boss 插件或宠物插件使用
    • 静态模型适用于不应移动的非持久化模型,基本上是临时装饰或效果

如何添加现有模型?

要导入模型,只需将 .bbmodel 拖到 imports 文件夹中并执行 /fmm reload。这将在 models 文件夹中生成一个 .fmmodel 文件,并将模型添加到 outputs 文件夹中的资源包。

您需要使用该资源包才能正确查看模型! 这是一个普通的资源包,因此您只需将其放入资源包文件夹即可。Minecraft 服务器有办法托管资源包。我推荐使用我的插件 ResourcePackManager,它会自动获取文件并远程托管,甚至将它们与其他插件的文件合并。

如何在游戏中查看模型?

重要的是要注意,虽然 FreeMinecraftModels 可以作为独立插件用于查看道具(基本上是可以放置在世界中的自定义模型),但该插件通常在与诸如 EliteMobs 之类的插件配合使用时效果最佳,在那里模型被积极用于具体的事情,在这种情况下是 Boss 战。

有三种类型的模型:静态、动态和道具。

  • 道具是持久化的,可以放置在世界中,即使服务器重启也会保持,并且可以将带有道具的地图分发到其他服务器
  • 动态模型适用于需要底层生物实体才能运行的模型,理想情况下由自定义 Boss 插件或宠物插件使用
  • 静态模型适用于不应移动的非持久化模型,基本上是临时装饰或效果

在游戏中查看静态模型

要在游戏中查看静态模型,请使用命令 /fmm spawn static <id>,其中 id 是模型的文件名,小写且不带文件扩展名。

在游戏中查看动态模型

要在游戏中查看动态模型,请使用命令 /fmm spawn dynamic <id>,其中 id 是模型的文件名,小写且不带文件扩展名。

在游戏中查看道具

要在游戏中查看动态模型,请使用命令 /fmm spawn prop <id>,其中 id 是模型的文件名,小写且不带文件扩展名。

FreeMinecraftModels (FMM) 能为建模师做什么?

FMM 遵循标准资源包规则进行资源包生成。此外,它尽可能与 ModelEngine 兼容的模型保持兼容,以尝试标准化跨插件的模型创建。

模型生成功能/限制

如果您曾经为 ModelEngine 创建过模型,您会熟悉许多 Minecraft 资源包生成限制:

立方体:

这里的立方体与 Blockbench 中的相同,它们是构成模型的立方体。

  • 立方体最大可以达到 112x112x112 "像素"(Blockbench 单位)或游戏内 7x7x7 方块(使用显示大小绕过普通 Minecraft 限制,很快将通过显示实体进一步绕过 1.19.4+)
  • 立方体的合法旋转为 0、22.5、-22.5、45 和 -45。没有其他旋转有效。
  • 立方体只在一个轴上旋转,这意味着 [22.5, 0, 0] 的旋转是可以的,[22.5, 0, 45] 的旋转将无法完全工作,只会在一个轴上旋转。

骨骼:

骨骼是 Blockbench 所称的"组"。它们用于将立方体分组在一起,应该用于为动画蓝图将骨骼分组在一起。

  • 骨骼最大可以达到 112x112x112 "像素"(Blockbench 单位)或游戏内 7x7x7 方块。请注意,骨骼的大小由其包含的内容设置,因此如果您的立方体相距超过 7 个方块,您可能会超过此大小限制。绕过此限制很简单,只需将方块放在不包含在第一个骨骼蓝图中的不同骨骼蓝图中!
  • 可以有任何旋转!但是,建议避免使用 90、-90、180 和 -180 的默认旋转,因为这些通常会导致意外行为。请注意,这实际上不适用于动画,只是骨骼的默认静止位置。

骨骼比立方体灵活得多,但您应该使用尽可能少的骨骼!在 FMM 中,由于 Minecraft 的限制,每个骨骼都是一个不同的实体。在规模化时,这将很快影响性能!始终使用尽可能少的骨骼,并注意您计划生成该模型的数量 - 您计划拥有的越多,您应该拥有的骨骼就越少!

虚拟骨骼

虚拟骨骼是 model engine 术语,用于具有特定元数据的骨骼,通常以特定名称的形式,用于特定目的。

以下虚拟骨骼已在 FreeMinecraftModels 中实现:

  • 碰撞箱/眼睛高度:名为 "hitbox" 的骨骼,带有定义边界的立方体蓝图,并且具有相同的 x 和 z 值(如果它们不相同,将选择最大值)定义碰撞箱。眼睛高度设置在碰撞箱的骨骼蓝图的枢轴点。
  • 名称标签:名称以 "tag_" 开头的骨骼。老实说,我更希望在这里更具体一些,使用 "tag_name",以便将标签用于其他事情,但这将在以后认真考虑。
  • 头部:名称以 h_ 开头的骨骼。这是一个虚拟骨骼,用于定义模型的头部,它将根据底层实体头部的旋转而旋转。

更安全、更简单、不可编辑的文件分发

FMM 尝试解决的一件事是用户重新利用他们获得的模型,以模型创建者不希望他们编辑的方式编辑它们,特别是为了重新皮肤或以其他方式稍微改变模型,并可能试图作为原创作品转售。

为此,FMM 使用 .fmmodel 文件格式,旨在将 .bbmodel 文件精简到可以被插件使用但无法在 Blockbench 中编辑的程度。

作为建模师,您现在可以选择是否要发布不可编辑的 .fmmodel 文件、可编辑的 .bbmodel 文件,甚至对两者进行差异定价或分发服务条款。

生成 .fmmodel 就像将您的 .bbmodel 放入 ~/plugins/FreeMinecraftModels/imports 文件夹并使用 /fmm reload 重新加载插件或重启服务器一样简单。然后您的 .fmmodel 将位于 ~/plugins/FreeMinecraftModels/models 文件夹中。

FreeMinecraftModels (FMM) 能为想要将其集成到插件中的开发人员做什么?

FMM 有一个 maven 仓库! Maven:


<repository>
<id>magmaguy-repo-releases</id>
<name>MagmaGuy's Repository</name>
<url>https://repo.magmaguy.com/releases</url>
</repository>

<dependency>
<groupId>com.magmaguy</groupId>
<artifactId>FreeMinecraftModels</artifactId>
<version>LATEST.VERSION.HERE</version>
</dependency>

Gradle:

maven {
name = "magmaguyRepoReleases"
url = uri("https://repo.magmaguy.com/releases")
}

compileOnly group : 'com.magmaguy', name: 'FreeMinecraftModels', version: 'LATEST.VERSION.HERE'

注意 FreeMinecraftModels 旨在用作 API,需要在服务器上安装插件。不要将其打包到您的插件中!

API 使用

FMM 旨在尽可能易于用作 API。

现在,如果您希望使用 FreeMinecraftModels 作为 API 来访问使用自定义模型,您只需要了解四个类:

  • ModeledEntity - 所有实体的基类
  • StaticEntity - 当您想使用非永久性静态模型时
  • DynamicEntity - 当您想用模型伪装另一个生物实体时
  • PropEntity - 当您想在世界中放置一个即使服务器重启也会保持的模型时

以下是处理静态模型的代码片段:

import org.bukkit.Bukkit;

public class FreeMinecraftModelsModel {
private StaticEntity staticEntity = null;

//Create the model
public FreeMinecraftModelsModel(String id, Location location) {
//This spawns the entity!
staticEntity = StaticEntity.create(id, location);
//This checks if the entity spawned correctly
if (staticEntity == null) Bukkit.getLogger().warning(("FMM failed to find a model named " + id + " !"));
}

public void remove() {
//This removes the entity
staticEntity.remove();
}
}

请记住,静态模型旨在保持在原地并充当固定位置的装饰元素(这里的"移动"不包括动画)。虽然可以移动它们,但如果这是您的目的,请考虑是否可能想要使用动态模型。

以下是我的自定义 Boss 插件 EliteMobs 如何使用动态实体:

package com.magmaguy.elitemobs.thirdparty.custommodels.freeminecraftmodels;

import com.magmaguy.elitemobs.thirdparty.custommodels.CustomModelInterface;
import api.com.magmaguy.freeminecraftmodels.ModeledEntityManager;
import customentity.com.magmaguy.freeminecraftmodels.DynamicEntity;
import lombok.Getter;
import org.bukkit.entity.LivingEntity;

public class CustomModelFMM implements CustomModelInterface {
@Getter
private DynamicEntity dynamicEntity;

public CustomModelFMM(LivingEntity livingEntity, String modelName, String nametagName) {
dynamicEntity = DynamicEntity.create(modelName, livingEntity);
if (dynamicEntity == null) return;
dynamicEntity.setName(nametagName);
}

public static void reloadModels() {
ModeledEntityManager.reload();
}

public static boolean modelExists(String modelName) {
return ModeledEntityManager.modelExists(modelName);
}

@Override
public void shoot() {
if (dynamicEntity.hasAnimation("attack_ranged")) dynamicEntity.playAnimation("attack_ranged", false);
else dynamicEntity.playAnimation("attack", false);
}

@Override
public void melee() {
if (dynamicEntity.hasAnimation("attack_melee")) dynamicEntity.playAnimation("attack_melee", false);
else dynamicEntity.playAnimation("attack", false);
}

@Override
public void playAnimationByName(String animationName) {
dynamicEntity.playAnimation(animationName, false);
}

@Override
public void setName(String nametagName, boolean visible) {
dynamicEntity.setName(nametagName);
dynamicEntity.setNameVisible(visible);
}

@Override
public void setNameVisible(boolean visible) {
dynamicEntity.setNameVisible(visible);
}

@Override
public void switchPhase() {
dynamicEntity.stopCurrentAnimations();
}
}

动态模型建立在生物实体之上,可以在使用 create 方法时提供(如上面的示例),或者在动态实体上运行 spawn 方法时提供。

作为开发人员为 FreeMinecraftModels (FMM) 项目做出贡献

FMM 在 GPLV3 许可证下分发,欢迎代码贡献。以下是基本贡献指南:

  • 遵循现有的命名约定,保持现有的详细程度,并添加足够的文档,使您的贡献易于理解
  • 保持贡献与插件的范围相关。如果您不知道它是否相关,请随时提前询问。
  • 注意代码的性能影响。如果贡献过于未优化或导致性能影响过大,可能会被拒绝。

插件总体概述

为了节省您的时间,以下是 FMM 的逻辑流程的快速分解:

  1. 读取 imports 文件夹
  2. 将文件从 imports 文件夹移动到 models 文件夹。如果文件是 .bbmodel,它会在 models 文件夹中转换为 .fmmodel
  3. 读取 models 文件夹中的文件。
  4. 解释所有模型结构,创建包含 Bone 组的 Skeleton,这些骨骼包含子 BoneCube 组。CubeBone 生成与它们各自相关的 JSON 资源包数据。这意味着 Cube 生成特定于立方体的 JSON,Bone 生成轮廓和单独的骨骼蓝图文件。请注意,一个骨骼蓝图会生成一个资源包文件。模型在生成时会添加到列表中。
  5. 仍然在 Skeleton 中,解释模型中的所有 Animations(如果有)
  6. 所有数据现在已初始化,资源包已在 outputs 文件夹中生成,插件已准备好使用。

此插件中使用的技巧:

这里使用的技巧已经相当成熟和标准化,但仍将列出,因为它们可能违反直觉。

请注意,这些技巧对用户和建模师完全不可见;列出限制和解决方法只是为了帮助您了解 FMM 如何绕过各种 Minecraft 限制。

  • 所有模型都放大 4 倍,然后在代码中重新调整大小和枢轴点,以扩展模型的理论最大尺寸
  • 因为资源包模型只能具有从 -16 到 +32 的大小,所以模型会在后台移动。这对玩家完全不可见。
  • 皮革马铠用于创建可以通过代码影响色调的模型(即用于伤害指示)。马铠必须设置为白色才能显示正确的颜色!
  • Blockbench 对纹理使用特定的 ID 系统,但实际上从配置中按顺序读取纹理。这里根据它们在纹理列表中的位置分配 ID,遵循 Blockbench 的做法。
  • 由于 Minecraft 的限制,每个骨骼都是一个不同的实体
  • 皮革马铠位于盔甲架的头部槽位
  • 盔甲架和显示实体都用于默认静态项目;基岩版客户端获得盔甲架,1.19.4+ 客户端获得显示实体(较旧的客户端将获得盔甲架)

为 FreeMinecraftModels (FMM) 项目做出一般贡献

FMM 实际上是由 https://www.patreon.com/magmaguy 的可爱人们众筹的!所有贡献的帮助都超出您的想象 ;)

当前计划的功能:

  • 基岩版客户端 RSP 生成
  • 带有 geyser 集成的 RSP 管理
  • tag_projectile 作为元骨骼,可以从中发射抛射物(每个模型可以有多个)

当前希望修复的奇怪限制:

  • TransformationMatrix 很混乱,但尚未开发出更好的解决方案。它们需要一些擅长矩阵的人来做一些工作。