Skip to content

Instantly share code, notes, and snippets.

@aksource
Last active October 22, 2023 04:40
Show Gist options
  • Save aksource/9be70a0bef9a46eec468 to your computer and use it in GitHub Desktop.
Save aksource/9be70a0bef9a46eec468 to your computer and use it in GitHub Desktop.
TextureStitchEvent利用。これで大体の需要は満たせてるかな?
package com.example.examplemod;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockColored;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemCameraTransforms;
import net.minecraft.client.renderer.block.statemap.StateMapperBase;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.resources.model.IBakedModel;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.EnumDyeColor;
import net.minecraft.item.Item;
import net.minecraft.item.ItemCloth;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.ModelBakeEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.*;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
@Mod(modid = SampleBlockTexChgMod.MOD_ID, name = "HogeHoge", version = "1.0", dependencies = "required-after:Forge@[1.8.9-11.15.1.1764,)", useMetadata = true)
public class SampleBlockTexChgMod {
/**
* ModId文字列
*/
public static final String MOD_ID = "sampleblocktexchgmod";
/**
* サンプルブロックのインスタンス
*/
private static Block sampleBlock;
/**
* ブロック描画用
*/
private static ModelResourceLocation normalMRL;
/**
* インベントリ描画用
*/
private static ModelResourceLocation inventoryMRL;
/**
* 羊毛テクスチャのリソロケ用
*/
private static List<ResourceLocation> coloredTexList = new ArrayList<>();
/**
* MODで追加したテクスチャのRLインスタンス
* ファイルの場所は、assets/</modid>/textures/blocks/sample.png
*/
private static ResourceLocation modTexRL = new ResourceLocation(MOD_ID.toLowerCase() + ":blocks/sample");
@EventHandler
public void preInit(FMLPreInitializationEvent event) {
sampleBlock = new SampleTexChgBlock();
if (event.getSide().isClient()) {
normalMRL = new ModelResourceLocation(sampleBlock.getRegistryName(), "normal");
inventoryMRL = new ModelResourceLocation(sampleBlock.getRegistryName(), "inventory");
/* リソロケ生成が面倒だからサボった */
for (EnumDyeColor enumDyeColor : EnumDyeColor.values()) {
coloredTexList.add(new ResourceLocation("blocks/wool_colored_" + enumDyeColor.name().toLowerCase()));
/* ここで、インベントリ描画用のModelResourceLocationの登録が必要 */
ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(sampleBlock), enumDyeColor.getMetadata(), inventoryMRL);
}
/* ここで、ブロック描画用のModelResourceLocationの登録が必要 */
ModelLoader.setCustomStateMapper(sampleBlock, new StateMapperBase() {
@Override
protected ModelResourceLocation getModelResourceLocation(IBlockState state) {
/* すべてのstateに対して同じModelResourceLocationを指定。あとのEventで利用 */
return normalMRL;
}
});
}
}
@EventHandler
public void init(FMLInitializationEvent event) {
if (event.getSide().isClient()) {
/* ModelBakeEvent登録 */
MinecraftForge.EVENT_BUS.register(this);
}
}
@EventHandler
public void postInit(FMLPostInitializationEvent event) {
/* すまんな、テンプレートなんだ。 */
}
@SubscribeEvent
public void onBakingModelEvent(ModelBakeEvent event) {
/* 形状のパクリ元 */
ResourceLocation rl = new ResourceLocation("block/cactus");
try {
/* パクリ元のIModelを取得。注意:ModelResourceLocationでも取れるが、IRetexturableModelではない。 */
IModel model = event.modelLoader.getModel(rl);
if (model instanceof IRetexturableModel) {
IBakedModel bakedModel = new SampleRetexturedBakedModel((IRetexturableModel) model);
/* ブロック描画用モデルのセット。ISmartBlockModel継承のものが良い。 */
event.modelRegistry.putObject(normalMRL, bakedModel);
/* インベントリ描画用のモデルのセット。ISmartItemModel継承のものが良い */
event.modelRegistry.putObject(inventoryMRL, bakedModel);
}
} catch (IOException e) {
/* モデル指定がミスるとここに飛ぶ */
e.printStackTrace();
}
}
@SubscribeEvent
public void textureStitch(TextureStitchEvent.Pre event) {
TextureMap textureMap = event.map;
/* JSONで指定していないテクスチャはこのタイミングで登録する。 */
textureMap.registerSprite(modTexRL);
}
/**
* サンプルブロッククラス。色付きブロック継承
*/
private static class SampleTexChgBlock extends BlockColored {
public SampleTexChgBlock() {
super(Material.ground);
/* ここらへんは、いいよね? */
this.setRegistryName("sample_tex_chg_block");
GameRegistry.registerBlock(this, ItemCloth.class);
this.setCreativeTab(CreativeTabs.tabBlock);
this.setUnlocalizedName("sample_tex_chg_block");
}
}
@SideOnly(Side.CLIENT)
private static class SampleRetexturedBakedModel implements ISmartBlockModel, ISmartItemModel {
private final IRetexturableModel retexturableModel;
/* bakeメソッドで必要。staticなクラスに置いても良いと思う。 */
private Function<ResourceLocation, TextureAtlasSprite> textureGetter = new Function<ResourceLocation, TextureAtlasSprite>() {
public TextureAtlasSprite apply(ResourceLocation location) {
return Minecraft.getMinecraft().getTextureMapBlocks().getAtlasSprite(location.toString());
}
};
public SampleRetexturedBakedModel(IRetexturableModel model) {
retexturableModel = model;
}
@Override
public IBakedModel handleItemState(ItemStack stack) {
/* retextureメソッドで、JSONで指定したテクスチャを入れ替えてモデルを生成できる。
* 今回はsideに指定したテクスチャを羊毛テクスチャに入れ替え */
return retexturableModel.retexture(ImmutableMap.of("side", coloredTexList.get(stack.getItemDamage() % 16).toString(),
"top", modTexRL.toString()))
.bake(retexturableModel.getDefaultState(), Attributes.DEFAULT_BAKED_FORMAT, textureGetter);
}
@Override
public IBakedModel handleBlockState(IBlockState state) {
/* retextureメソッドで、JSONで指定したテクスチャを入れ替えてモデルを生成できる。
* 今回はsideに指定したテクスチャを羊毛テクスチャに入れ替え */
return retexturableModel.retexture(ImmutableMap.of("side", coloredTexList.get(sampleBlock.getMetaFromState(state)).toString(),
"top", modTexRL.toString())).bake(retexturableModel.getDefaultState(), Attributes.DEFAULT_BAKED_FORMAT, textureGetter);
}
/* 以下、IBakedModelのメソッドだけど、handle~メソッドで違うモデルを返しているので、以下の状態で問題ない。 */
@Override
public List<BakedQuad> getFaceQuads(EnumFacing facing) {
return null;
}
@Override
public List<BakedQuad> getGeneralQuads() {
return null;
}
@Override
public boolean isAmbientOcclusion() {
return false;
}
@Override
public boolean isGui3d() {
return false;
}
@Override
public boolean isBuiltInRenderer() {
return false;
}
@Override
public TextureAtlasSprite getParticleTexture() {
return null;
}
@Override
public ItemCameraTransforms getItemCameraTransforms() {
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment