tutorial:shield
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision | ||
tutorial:shield [2021/10/18 04:24] – one word change cringestar_boi | tutorial:shield [2023/12/22 04:12] – almost done cringestar_boi | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Making a Custom Shield in Minecraft ====== | + | ====== Making a Custom Shield in Minecraft |
Congrats! You just learned how to create your custom sword in the last tutorial! Now imagine you want to shield yourself from that sword if your friend got it. If you made it too op, a regular shield won't do. So we will see how to make a custom shield.\\ | Congrats! You just learned how to create your custom sword in the last tutorial! Now imagine you want to shield yourself from that sword if your friend got it. If you made it too op, a regular shield won't do. So we will see how to make a custom shield.\\ | ||
Line 5: | Line 5: | ||
Library source is available at https:// | Library source is available at https:// | ||
+ | |||
+ | Library compiled as a jar is available at https:// | ||
===== Adding the library to your project ===== | ===== Adding the library to your project ===== | ||
Line 11: | Line 13: | ||
**gradle.properties**\\ | **gradle.properties**\\ | ||
<code java> | <code java> | ||
- | fabric_shield_lib_version=1.4.1 | + | fabric_shield_lib_version=1.7.2-1.20.4 |
+ | midnightlib_version=1.5.2-fabric | ||
+ | mod_menu_version=9.0.0-pre.1 | ||
+ | fabricasm_version=2.3 | ||
</ | </ | ||
**build.gradle** (under dependencies)\\ | **build.gradle** (under dependencies)\\ | ||
<code java> | <code java> | ||
- | modImplementation " | + | modImplementation " |
+ | |||
+ | modImplementation " | ||
+ | |||
+ | modImplementation " | ||
+ | |||
+ | modImplementation " | ||
</ | </ | ||
- | At the time of writing, latest project.fabric_shield_lib_version should be 1.4.1, and latest project.minecraft_version should be 1.17.1. This page will be updated whenever a new update comes out.\\ \\ | + | |
- | **build.gradle** (under repositories)\\ | + | At the time of writing, latest project.fabric_shield_lib_version should be 1.7.2-1.20.4. This page will be updated whenever a new update comes out.\\ \\ |
+ | **build.gradle** (inside | ||
<code java> | <code java> | ||
- | allprojects { repositories { maven { url ' | + | maven {url = ' |
+ | maven {url " | ||
+ | maven {url = " | ||
</ | </ | ||
+ | |||
+ | __// | ||
===== Adding a custom shield ===== | ===== Adding a custom shield ===== | ||
- | **If you want your shield to support banner decoration, | + | **If you want your shield to support banner decoration |
On to the non-boring steps! We will now make a custom shield!\\ \\ | On to the non-boring steps! We will now make a custom shield!\\ \\ | ||
If you have followed the above steps correctly and refreshed the project, then you will have the fabric shield api installed.\\ | If you have followed the above steps correctly and refreshed the project, then you will have the fabric shield api installed.\\ | ||
If so, the first step to do is create a new instance of an Item like: | If so, the first step to do is create a new instance of an Item like: | ||
<code java> | <code java> | ||
- | public static final Item NETHERITE_SHIELD = new FabricShieldItem(new FabricItemSettings().maxDamage(2500).group(ItemGroup.COMBAT), 10, 13, Items.NETHERITE_INGOT); | + | public static final Item NETHERITE_SHIELD = new FabricShieldItem(new FabricItemSettings().maxDamage(2500), |
- | </ | + | </ |
- | Then, we have to register it, like so:\\ | + | |
+ | Then, we have to register it, like so: | ||
+ | |||
<code java> | <code java> | ||
- | Registry.register(Registry.ITEM, new Identifier(" | + | Registry.register(Registries.ITEM, new Identifier(" |
- | </ | + | </ |
- | And our shield is done!\\ | + | |
+ | If you want to add your shield to a creative tab, add this into your '' | ||
+ | <code java> | ||
+ | ItemGroupEvents.modifyEntriesEvent(ItemGroups.COMBAT).register(entries -> { | ||
+ | entries.add(NETHERITE_SHIELD); | ||
+ | }); | ||
+ | </ | ||
+ | |||
+ | And our shield is (code-wise) | ||
Now, we have to create the textures and models of the shield.\\ | Now, we have to create the textures and models of the shield.\\ | ||
- | For the texture, you can use anything. A good place to start is looking | + | For the texture, you can use anything. A good place to start is to look at Mojang's shield |
Now, for the models, we have to write a few .json files.\\ | Now, for the models, we have to write a few .json files.\\ | ||
- | For the model file without blocking, we use: \\ | + | |
+ | |||
+ | Inside '' | ||
<code javascript> | <code javascript> | ||
{ | { | ||
- | " | + | " |
" | " | ||
" | " | ||
Line 56: | Line 85: | ||
} | } | ||
</ | </ | ||
- | Put it in resources/ | + | |
- | For the blocking model, use this: \\ | + | In the same folder, create another file, '' |
<code javascript> | <code javascript> | ||
{ | { | ||
- | " | + | " |
+ | " | ||
+ | " | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | Plop it in resources/models/item/netherite_shield_blocking.json\\ \\ | + | |
- | Don't forget to add it to **en_us.json**\\ | + | Lastly, create a '' |
<code javascript> | <code javascript> | ||
{ | { | ||
- | "item.examplemod.netherite_shield": "Netherite Shield" | + | "replace": |
+ | | ||
+ | " | ||
+ | ] | ||
} | } | ||
</ | </ | ||
- | And with that, your shield is done! | ||
- | + | Don't forget to add it to **en_us.json** in '' | |
- | ===== Adding a banner support | + | < |
- | + | { | |
- | This is where mixins get involved. | + | "item.examplemod.netherite_shield": |
- | + | } | |
- | First thing you will want to do is to change | + | |
- | + | ||
- | < | + | |
- | public static final Item NETHERITE_SHIELD = new FabricBannerShieldItem(new FabricItemSettings().maxDamage(2500).group(ItemGroup.COMBAT), | + | |
</ | </ | ||
+ | And with that, your non-decorateable shield is done! | ||
- | Next, we will need to create an '' | + | ===== Adding a custom shield with banner support ===== |
+ | If you want to make your shield accept banners and decorateable like a vanilla shield, the process is slightly different. | ||
+ | We still make the item in the same way, just make it a FabricBannerShieldItem: | ||
<code java> | <code java> | ||
- | public static final EntityModelLayer NETHERITE_SHIELD_MODEL_LAYER | + | public static final Item NETHERITE_BANNER_SHIELD |
</ | </ | ||
- | | ||
- | And now we get to the mixin. Don't worry, its an easy one. | ||
- | |||
- | If this is your first time, [[tutorial: | ||
- | We will make a class called '' | + | Then, we have to register it: |
+ | |||
<code java> | <code java> | ||
- | @Mixin | + | Registry.register(Registries.ITEM, new Identifier(" |
- | public class RendererMixin { | + | |
- | + | ||
- | { | + | |
</ | </ | ||
- | Then we will make the necessary '' | + | If you want to add your shield to a creative tab, add this into your '' |
<code java> | <code java> | ||
- | @Mixin | + | ItemGroupEvents.modifyEntriesEvent(ItemGroups.COMBAT).register(entries -> { |
- | public class RendererMixin | + | entries.addAfter(Items.SHIELD,NETHERITE_BANNER_SHIELD); |
- | | + | }); |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(" | + | |
- | | + | |
- | } | + | |
</ | </ | ||
- | Next, we need to @Shadow the '' | + | Now the item is created, we need to set up its rendering. For these steps, |
- | <code java> | + | |
- | @Mixin (BuiltinModelItemRenderer.class) | + | |
- | public class RendererMixin { | + | |
- | private ShieldEntityModel modelNetheriteShield; | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, new Identifier(" | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE_NO_PATTERN = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | |
- | @Final | ||
- | @Shadow | ||
- | private EntityModelLoader entityModelLoader; | ||
- | } | ||
- | </ | ||
- | Now we will inject into the '' | + | First, |
<code java> | <code java> | ||
- | @Mixin (BuiltinModelItemRenderer.class) | + | public class ExampleModClient implements ClientModInitializer |
- | public class RendererMixin | + | |
- | | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE_NO_PATTERN = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | |
- | | + | |
- | @Shadow | + | |
- | private EntityModelLoader entityModelLoader; | + | |
- | + | | |
- | | + | public void onInitializeClient() { |
- | | + | |
- | modelNetheriteShield = new ShieldEntityModel(this.entityModelLoader.getModelPart(ExampleMod.NETHERITE_SHIELD_MODEL_LAYER)); | + | |
- | } | + | |
- | } | + | |
- | </ | + | |
- | + | ||
- | Now we get to the most important part of the mixin. We will inject a method to render a banner on our shield. | + | |
- | + | ||
- | <code java> | + | |
- | @Mixin (BuiltinModelItemRenderer.class) | + | |
- | public | + | |
- | | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | |
- | private static final SpriteIdentifier NETHERITE_SHIELD_BASE_NO_PATTERN = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | + | |
- | + | ||
- | @Final | + | |
- | @Shadow | + | |
- | private EntityModelLoader entityModelLoader; | + | |
- | + | ||
- | + | ||
- | @Inject(method = " | + | |
- | private | + | |
- | this.modelNetheriteShield = new ShieldEntityModel(this.entityModelLoader.getModelPart(ExampleMod.NETHERITE_SHIELD_MODEL_LAYER)); | + | |
- | } | + | |
| | ||
- | @Inject(method = " | ||
- | private void mainRender(ItemStack stack, ModelTransformation.Mode mode, MatrixStack matrices, VertexConsumerProvider vertexConsumers, | ||
- | if (stack.isOf(ExampleMod.NETHERITE_SHIELD)) { | ||
- | FabricShieldItem.renderBanner(stack, | ||
- | //The first five parameters are taken from the method, while the last 3 you provide yourself. You will provide the model, and then your 2 sprite identifiers in the order of ''// | ||
- | '' | ||
- | } | ||
} | } | ||
- | |||
- | | ||
} | } | ||
- | </ | + | </ |
- | There is one more big thing and five little things | + | Next, we will register out '' |
- | We have to register our '' | + | <code java> |
+ | public class ExampleModClient implements ClientModInitializer { | ||
- | To create our '' | + | public static final EntityModelLayer NETHERITE_SHIELD_MODEL_LAYER = new EntityModelLayer(new Identifier(" |
- | <code java> | ||
- | public class ExampleModClient implements ClientModInitializer { | ||
@Override | @Override | ||
public void onInitializeClient() { | public void onInitializeClient() { | ||
- | | + | EntityModelLayerRegistry.registerModelLayer(netherite_banner_shield_model_layer, |
} | } | ||
} | } | ||
</ | </ | ||
- | Before | + | Then we will create |
- | < | + | < |
- | { | + | public class ExampleModClient implements ClientModInitializer |
- | [...] | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | ], | + | |
- | " | + | |
- | " | + | |
- | ] | + | |
- | } | + | |
- | [...] | + | |
- | } | + | |
- | </ | + | |
- | Ok, so now that is done, we can work in our client initializer. | + | public static final EntityModelLayer NETHERITE_SHIELD_MODEL_LAYER = new EntityModelLayer(new Identifier(" |
+ | |||
+ | public static ShieldEntityModel modelNetheriteShield; | ||
- | First, we will register out '' | ||
- | |||
- | <code java> | ||
- | public class ExampleModClient implements ClientModInitializer { | ||
@Override | @Override | ||
public void onInitializeClient() { | public void onInitializeClient() { | ||
- | EntityModelLayerRegistry.registerModelLayer(ExampleMod.NETHERITE_SHIELD_MODEL_LAYER, | + | EntityModelLayerRegistry.registerModelLayer(NETHERITE_SHIELD_MODEL_LAYER, |
} | } | ||
} | } | ||
</ | </ | ||
- | Next we will register | + | And then register |
<code java> | <code java> | ||
public class ExampleModClient implements ClientModInitializer { | public class ExampleModClient implements ClientModInitializer { | ||
+ | |||
+ | public static final EntityModelLayer NETHERITE_SHIELD_MODEL_LAYER = new EntityModelLayer(new Identifier(" | ||
+ | | ||
+ | public static ShieldEntityModel modelNetheriteShield; | ||
+ | |||
@Override | @Override | ||
public void onInitializeClient() { | public void onInitializeClient() { | ||
- | EntityModelLayerRegistry.registerModelLayer(ExampleMod.NETHERITE_SHIELD_MODEL_LAYER, | + | EntityModelLayerRegistry.registerModelLayer(NETHERITE_SHIELD_MODEL_LAYER, |
- | | + | |
- | | + | ShieldSetModelCallback.EVENT.register((loader) -> { |
- | | + | modelNetheriteShield = new ShieldEntityModel(loader.getModelPart(netherite_banner_shield_model_layer)); |
- | }); | + | return ActionResult.PASS; |
+ | }); | ||
} | } | ||
} | } | ||
</ | </ | ||
- | That is now all of the complicated things done! We now only need to change | + | Next, we have to create |
+ | <code java> | ||
+ | public class ExampleModClient implements ClientModInitializer { | ||
- | In your shield model, '' | + | public static final EntityModelLayer netherite_banner_shield_model_layer = new EntityModelLayer(new Identifier(" |
- | <code javascript> | + | |
- | { | + | public static ShieldEntityModel modelNetheriteShield; |
- | "parent":"fabricshieldlib: | + | |
- | "overrides": [ | + | public static final SpriteIdentifier NETHERITE_BANNER_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, |
- | { | + | public static final SpriteIdentifier NETHERITE_BANNER_SHIELD_BASE_NO_PATTERN = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, |
- | | + | |
- | " | + | @Override |
- | }, | + | public void onInitializeClient() { |
- | | + | |
- | } | + | |
- | ] | + | ShieldSetModelCallback.EVENT.register((loader) -> { |
+ | modelNetheriteShield = new ShieldEntityModel(loader.getModelPart(netherite_banner_shield_model_layer)); | ||
+ | return ActionResult.PASS; | ||
+ | | ||
+ | } | ||
} | } | ||
</ | </ | ||
- | You also have to change your blocking | + | Finally, we are going to register our shield with the '' |
+ | <code java> | ||
+ | public class ExampleModClient implements ClientModInitializer { | ||
+ | |||
+ | public static final EntityModelLayer netherite_banner_shield_model_layer = new EntityModelLayer(new Identifier(" | ||
+ | |||
+ | public static ShieldEntityModel modelNetheriteShield; | ||
+ | |||
+ | public static final SpriteIdentifier NETHERITE_BANNER_SHIELD_BASE = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | ||
+ | public static final SpriteIdentifier NETHERITE_BANNER_SHIELD_BASE_NO_PATTERN = new SpriteIdentifier(SpriteAtlasTexture.BLOCK_ATLAS_TEXTURE, | ||
+ | |||
+ | @Override | ||
+ | public void onInitializeClient() { | ||
+ | EntityModelLayerRegistry.registerModelLayer(NETHERITE_SHIELD_MODEL_LAYER, | ||
+ | |||
+ | ShieldSetModelCallback.EVENT.register((loader) -> { | ||
+ | modelNetheriteShield = new ShieldEntityModel(loader.getModelPart(netherite_banner_shield_model_layer)); | ||
+ | return ActionResult.PASS; | ||
+ | }); | ||
+ | |||
+ | BuiltinItemRendererRegistry.INSTANCE.register(ExampleMod.NETHERITE_BANNER_SHIELD, | ||
+ | renderBanner(stack, | ||
+ | //The first five parameters are taken from the method, while the last 3 you provide yourself. You will provide the model, and then your 2 sprite identifiers in the order of SHIELD_NAME_BASE and then SHIELD_NAME_BASE_NOPATTERN. | ||
+ | }); | ||
+ | } | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | That is all of our code done, we only have a few .json files to make. \\ | ||
+ | |||
+ | Firstly, inside | ||
<code javascript> | <code javascript> | ||
{ | { | ||
- | " | + | " |
+ | " | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | }, | ||
+ | " | ||
+ | } | ||
+ | ] | ||
} | } | ||
- | </ | + | </ |
- | For this next step, you will add '' | + | In the same folder, create another file, '' |
- | Then, you will need to make a '' | + | <code javascript> |
+ | { | ||
+ | " | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | For this next step, you will add a '' | ||
+ | Then, you will need to make a '' | ||
Then, you will move both of these textures into '' | Then, you will move both of these textures into '' | ||
- | For one last thing, you will need to add names for each of your shield color variants in '' | + | Lastly, create a '' |
<code javascript> | <code javascript> | ||
{ | { | ||
- | | + | |
- | "item.examplemod.netherite_shield.red": | + | "values": |
- | "item.examplemod.netherite_shield.orange" | + | " |
- | " | + | ] |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
- | " | + | |
} | } | ||
- | </ | + | </ |
- | Now your shield is done and has banner support! | + | Don't forget to add it to **en_us.json** in '' |
+ | <code javascript> | ||
+ | { | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | " | ||
+ | } |
tutorial/shield.txt · Last modified: 2024/01/14 18:05 by cringestar_boi