zh_cn:tutorial:custom_model
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revision | |||
zh_cn:tutorial:custom_model [2024/01/02 10:31] – [UnbakedModel方法] solidblock | zh_cn:tutorial:custom_model [2024/08/27 04:34] (current) – 更新翻译 solidblock | ||
---|---|---|---|
Line 1: | Line 1: | ||
====== 使用自定义模型动态渲染方块和物品 ====== | ====== 使用自定义模型动态渲染方块和物品 ====== | ||
- | 可以通过方块模型 JSON 文件将模型添加到游戏,但也可以通过 Java 代码来渲染。本教程中,我们将会将一个四面熔炉模型添加到游戏。 | + | 可以通过方块模型 JSON 文件将模型添加到游戏,但也可以通过 Java 代码来渲染。本教程中,我们将会把一个四面熔炉模型添加到游戏。 |
注意模型会在区块被重建时渲染。如果需要更加动态的渲染,可以使用 '' | 注意模型会在区块被重建时渲染。如果需要更加动态的渲染,可以使用 '' | ||
Line 13: | Line 13: | ||
==== Sprites ==== | ==== Sprites ==== | ||
- | 渲染纹理离不开'' | + | 渲染纹理离不开'' |
- | 这里,我们会使用两个熔炉纹理。它们是方块纹理,所以要从方块atlas'' | + | |
<code java> | <code java> | ||
+ | // 对于 1.21 之前的版本,将 `Identifier.ofVanilla` 替换为 `new Identifier`。 | ||
private static final SpriteIdentifier[] SPRITE_IDS = new SpriteIdentifier[]{ | private static final SpriteIdentifier[] SPRITE_IDS = new SpriteIdentifier[]{ | ||
- | new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, |
- | new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | new SpriteIdentifier(PlayerScreenHandler.BLOCK_ATLAS_TEXTURE, |
}; | }; | ||
- | private Sprite[] SPRITES = new Sprite[2]; | + | private Sprite[] SPRITES = new Sprite[SPRITE_IDS.length]; |
- | // Some constants to avoid magic numbers, these need to match the SPRITE_IDS | + | // 一些常量,以避免魔法数据,需要匹配 |
private static final int SPRITE_SIDE = 0; | private static final int SPRITE_SIDE = 0; | ||
private static final int SPRITE_TOP = 1; | private static final int SPRITE_TOP = 1; | ||
</ | </ | ||
- | ==== Meshes | + | ==== Mesh ==== |
'' | '' | ||
<code java> | <code java> | ||
Line 33: | Line 33: | ||
</ | </ | ||
- | ==== UnbakedModel方法 ==== | + | ==== UnbakedModel 方法 ==== |
<code java> | <code java> | ||
@Override | @Override | ||
Line 41: | Line 41: | ||
@Override | @Override | ||
- | public | + | public |
- | | + | // 与模型继承有关,我们这里还不需要使用到 |
} | } | ||
@Override | @Override | ||
- | public BakedModel bake(ModelLoader loader, Function< | + | public BakedModel bake(Baker baker, Function< |
- | // 获得sprites | + | // 获得 sprites |
for(int i = 0; i < 2; ++i) { | for(int i = 0; i < 2; ++i) { | ||
SPRITES[i] = textureGetter.apply(SPRITE_IDS[i]); | SPRITES[i] = textureGetter.apply(SPRITE_IDS[i]); | ||
} | } | ||
- | // 用Renderer API构建mesh | + | // 用 Renderer API 构建 mesh |
Renderer renderer = RendererAccess.INSTANCE.getRenderer(); | Renderer renderer = RendererAccess.INSTANCE.getRenderer(); | ||
MeshBuilder builder = renderer.meshBuilder(); | MeshBuilder builder = renderer.meshBuilder(); | ||
Line 59: | Line 59: | ||
for(Direction direction : Direction.values()) { | for(Direction direction : Direction.values()) { | ||
int spriteIdx = direction == Direction.UP || direction == Direction.DOWN ? SPRITE_TOP : SPRITE_SIDE; | int spriteIdx = direction == Direction.UP || direction == Direction.DOWN ? SPRITE_TOP : SPRITE_SIDE; | ||
- | // 将新的面(face)添加到mesh | + | // 将新的面(face)添加到 mesh |
emitter.square(direction, | emitter.square(direction, | ||
- | // 设置面的sprite,必须在.square()之后调用 | + | // 设置面的 sprite,必须在 .square() 之后调用 |
- | // 我们还没有指定任何uv坐标,所以我们使用整个纹理,BAKE_LOCK_UV恰好就这么做。 | + | // 我们还没有指定任何 uv 坐标,所以我们使用整个纹理,BAKE_LOCK_UV 恰好就这么做。 |
emitter.spriteBake(0, | emitter.spriteBake(0, | ||
// 启用纹理使用 | // 启用纹理使用 | ||
emitter.spriteColor(0, | emitter.spriteColor(0, | ||
- | // 将quad添加到mesh | + | // 将 quad 添加到 mesh |
emitter.emit(); | emitter.emit(); | ||
} | } | ||
Line 80: | Line 80: | ||
@Override | @Override | ||
public List< | public List< | ||
- | return Collections.emptyList(); | + | return Collections.emptyList(); |
} | } | ||
Line 105: | Line 105: | ||
@Override | @Override | ||
public Sprite getParticleSprite() { | public Sprite getParticleSprite() { | ||
- | return SPRITES[1]; // 方块被破坏时产生的颗粒,使用furnace_top | + | return SPRITES[1]; // 方块被破坏时产生的颗粒,使用 furnace_top |
} | } | ||
Line 140: | Line 140: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | 注意:确保覆盖了 '' | ||
===== 注册模型 ===== | ===== 注册模型 ===== | ||
- | 我们先写一个 '' | ||
- | 我们用 '' | + | 要让模型在游戏内被渲染需要注册,为注册我们需要创建 |
<code java> | <code java> | ||
@Environment(EnvType.CLIENT) | @Environment(EnvType.CLIENT) | ||
- | public class TutorialModelProvider | + | public class TutorialModelLoadingPlugin |
- | public static final Identifier | + | public static final ModelIdentifier |
@Override | @Override | ||
- | public | + | public |
- | if(identifier.equals(FOUR_SIDED_FURNACE_MODEL)) { | + | |
- | return new FourSidedFurnaceModel(); | + | pluginContext.modifyModelOnLoad().register((original, |
- | } else { | + | // 这个每次加载模型时都会调用,所以确保我们只针对我们的 |
- | return | + | final ModelIdentifier id = context.topLevelId(); |
- | } | + | |
+ | return new FourSidedFurnaceModel(); | ||
+ | } else { | ||
+ | // 如果不修改模型,就照样返回原来的 | ||
+ | | ||
+ | } | ||
+ | }); | ||
} | } | ||
} | } | ||
Line 166: | Line 175: | ||
@Override | @Override | ||
public void onInitializeClient() { | public void onInitializeClient() { | ||
- | | + | |
| | ||
- | /* 其他客户端指定的初始化 */ | + | /* 其他客户端特定的初始化 */ |
} | } | ||
} | } | ||
Line 174: | Line 183: | ||
不要忘记在 '' | 不要忘记在 '' | ||
- | < | + | < |
- | /* ... */ | + | { |
+ | [...] | ||
" | " | ||
- | | + | |
" | " | ||
" | " | ||
] | ] | ||
}, | }, | ||
+ | [...] | ||
+ | } | ||
</ | </ | ||
===== 使用模型 ===== | ===== 使用模型 ===== | ||
- | 你现在可以注册你的方块以使用新模型。比如,如果你的方块只有一个状态,把这个放在'' | + | 你可以[[blocks|注册方块]]以使用你的新模型。我们假设方块的 id 是 '' |
- | <code json> | + | |
+ | < | ||
+ | public final class TutorialBlocks { | ||
+ | [...] | ||
+ | public static final Block FOUR_SIDED_FURNACE = register(" | ||
+ | [...] | ||
+ | } | ||
+ | </ | ||
+ | <code javascript src/ | ||
{ | { | ||
" | " | ||
Line 203: | Line 223: | ||
==== 更新模型 ==== | ==== 更新模型 ==== | ||
我们复用相同的模型类,但是有一点点小改变: | 我们复用相同的模型类,但是有一点点小改变: | ||
- | * 我们会使用 '' | + | * 我们会使用 '' |
现在对 '' | 现在对 '' | ||
<code java> | <code java> | ||
- | // Minecraft 默认方块模型 | ||
- | private static final Identifier DEFAULT_BLOCK_MODEL = new Identifier(" | ||
- | |||
- | private ModelTransformation transformation; | ||
- | | ||
- | // 将默认模型添加到依赖中 | ||
- | public Collection< | ||
- | return Arrays.asList(DEFAULT_BLOCK_MODEL); | ||
- | } | ||
- | | ||
- | // 我们给 bake 函数添加一点逻辑 | ||
- | @Override | ||
- | public BakedModel bake(ModelLoader loader, Function< | ||
- | // 加载默认方块模型 | ||
- | JsonUnbakedModel defaultBlockModel = (JsonUnbakedModel) loader.getOrLoadModel(DEFAULT_BLOCK_MODEL); | ||
- | // 获取 ModelTransformation | ||
- | transformation = defaultBlockModel.getTransformations(); | ||
- | | ||
- | /* 先前的代码 */ | ||
- | } | ||
| | ||
// 我们需要实现 getTransformation() 和 getOverrides() | // 我们需要实现 getTransformation() 和 getOverrides() | ||
@Override | @Override | ||
public ModelTransformation getTransformation() { | public ModelTransformation getTransformation() { | ||
- | return | + | return |
} | } | ||
Line 248: | Line 248: | ||
@Override | @Override | ||
public void emitItemQuads(ItemStack itemStack, Supplier< | public void emitItemQuads(ItemStack itemStack, Supplier< | ||
- | | + | |
} | } | ||
</ | </ | ||
==== 加载模型 ==== | ==== 加载模型 ==== | ||
- | 更新我们先前创建的 '' | + | 更新我们先前创建的 '' |
<code java> | <code java> | ||
@Environment(EnvType.CLIENT) | @Environment(EnvType.CLIENT) | ||
- | public class TutorialModelProvider | + | public class TutorialModelLoadingPlugin |
- | public static final FourSidedFurnaceModel | + | public static final ModelIdentifier |
- | public static final Identifier FOUR_SIDED_FURNACE_MODEL_BLOCK = new Identifier(" | + | public static final ModelIdentifier |
- | public static final Identifier | + | |
@Override | @Override | ||
- | public | + | public |
- | if(identifier.equals(FOUR_SIDED_FURNACE_MODEL_BLOCK) || identifier.equals(FOUR_SIDED_FURNACE_MODEL_ITEM)) { | + | |
- | return | + | pluginContext.modifyModelOnLoad().register((original, |
- | } else { | + | // 这个每次加载模型时都会调用,所以确保我们只针对我们的 |
- | return | + | final ModelIdentifier id = context.topLevelId(); |
- | } | + | |
+ | return | ||
+ | } else { | ||
+ | // 如果不修改模型,就照样返回原来的 | ||
+ | | ||
+ | } | ||
+ | }); | ||
} | } | ||
} | } | ||
Line 278: | Line 283: | ||
===== 更加动态的渲染 ===== | ===== 更加动态的渲染 ===== | ||
- | '' | + | '' |
<code java> | <code java> | ||
@Override | @Override |
zh_cn/tutorial/custom_model.1704191509.txt.gz · Last modified: 2024/01/02 10:31 by solidblock