Add support for custom elytra (#7202)

This commit is contained in:
brandon3055 2020-08-04 08:55:10 +10:00 committed by GitHub
parent 20702456ac
commit 399bc6c9c3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 307 additions and 9 deletions

View file

@ -46,6 +46,15 @@
} }
if (flag1) { if (flag1) {
@@ -689,7 +697,7 @@
if (this.field_71158_b.field_78901_c && !flag7 && !flag && !this.field_71075_bZ.field_75100_b && !this.func_184218_aH() && !this.func_70617_f_()) {
ItemStack itemstack = this.func_184582_a(EquipmentSlotType.CHEST);
- if (itemstack.func_77973_b() == Items.field_185160_cR && ElytraItem.func_185069_d(itemstack) && this.func_226566_ei_()) {
+ if (itemstack.canElytraFly(this) && this.func_226566_ei_()) {
this.field_71174_a.func_147297_a(new CEntityActionPacket(this, CEntityActionPacket.Action.START_FALL_FLYING));
}
}
@@ -985,4 +993,16 @@ @@ -985,4 +993,16 @@
return this.field_204230_bP; return this.field_204230_bP;
} }

View file

@ -0,0 +1,54 @@
--- a/net/minecraft/client/renderer/entity/layers/ElytraLayer.java
+++ b/net/minecraft/client/renderer/entity/layers/ElytraLayer.java
@@ -29,7 +29,7 @@
public void func_225628_a_(MatrixStack p_225628_1_, IRenderTypeBuffer p_225628_2_, int p_225628_3_, T p_225628_4_, float p_225628_5_, float p_225628_6_, float p_225628_7_, float p_225628_8_, float p_225628_9_, float p_225628_10_) {
ItemStack itemstack = p_225628_4_.func_184582_a(EquipmentSlotType.CHEST);
- if (itemstack.func_77973_b() == Items.field_185160_cR) {
+ if (shouldRender(itemstack, p_225628_4_)) {
ResourceLocation resourcelocation;
if (p_225628_4_ instanceof AbstractClientPlayerEntity) {
AbstractClientPlayerEntity abstractclientplayerentity = (AbstractClientPlayerEntity)p_225628_4_;
@@ -38,10 +38,10 @@
} else if (abstractclientplayerentity.func_152122_n() && abstractclientplayerentity.func_110303_q() != null && abstractclientplayerentity.func_175148_a(PlayerModelPart.CAPE)) {
resourcelocation = abstractclientplayerentity.func_110303_q();
} else {
- resourcelocation = field_188355_a;
+ resourcelocation = getElytraTexture(itemstack, p_225628_4_);
}
} else {
- resourcelocation = field_188355_a;
+ resourcelocation = getElytraTexture(itemstack, p_225628_4_);
}
p_225628_1_.func_227860_a_();
@@ -53,4 +53,29 @@
p_225628_1_.func_227865_b_();
}
}
+
+ /**
+ * Determines if the ElytraLayer should render.
+ * ItemStack and Entity are provided for modder convenience,
+ * For example, using the same ElytraLayer for multiple custom Elytra.
+ *
+ * @param stack The Elytra ItemStack
+ * @param entity The entity being rendered.
+ * @return If the ElytraLayer should render.
+ */
+ public boolean shouldRender(ItemStack stack, T entity) {
+ return stack.func_77973_b() == Items.field_185160_cR;
+ }
+
+ /**
+ * Gets the texture to use with this ElytraLayer.
+ * This assumes the vanilla Elytra model.
+ *
+ * @param stack The Elytra ItemStack.
+ * @param entity The entity being rendered.
+ * @return The texture.
+ */
+ public ResourceLocation getElytraTexture(ItemStack stack, T entity) {
+ return field_188355_a;
+ }
}

View file

@ -360,7 +360,16 @@
if (map == null) { if (map == null) {
map = Maps.newEnumMap(EquipmentSlotType.class); map = Maps.newEnumMap(EquipmentSlotType.class);
} }
@@ -2658,8 +2693,16 @@ @@ -2434,6 +2469,8 @@
boolean flag = this.func_70083_f(7);
if (flag && !this.field_70122_E && !this.func_184218_aH() && !this.func_70644_a(Effects.field_188424_y)) {
ItemStack itemstack = this.func_184582_a(EquipmentSlotType.CHEST);
+ flag = itemstack.canElytraFly(this) && itemstack.elytraFlightTick(this, this.field_184629_bo);
+ if (false) //Forge: Moved to ElytraItem
if (itemstack.func_77973_b() == Items.field_185160_cR && ElytraItem.func_185069_d(itemstack)) {
flag = true;
if (!this.field_70170_p.field_72995_K && (this.field_184629_bo + 1) % 20 == 0) {
@@ -2658,8 +2695,16 @@
private void func_184608_ct() { private void func_184608_ct() {
if (this.func_184587_cr()) { if (this.func_184587_cr()) {
@ -379,7 +388,7 @@
this.field_184627_bm.func_222121_b(this.field_70170_p, this, this.func_184605_cv()); this.field_184627_bm.func_222121_b(this.field_70170_p, this, this.func_184605_cv());
if (this.func_226299_p_()) { if (this.func_226299_p_()) {
this.func_226293_b_(this.field_184627_bm, 5); this.func_226293_b_(this.field_184627_bm, 5);
@@ -2707,8 +2750,10 @@ @@ -2707,8 +2752,10 @@
public void func_184598_c(Hand p_184598_1_) { public void func_184598_c(Hand p_184598_1_) {
ItemStack itemstack = this.func_184586_b(p_184598_1_); ItemStack itemstack = this.func_184586_b(p_184598_1_);
if (!itemstack.func_190926_b() && !this.func_184587_cr()) { if (!itemstack.func_190926_b() && !this.func_184587_cr()) {
@ -391,7 +400,7 @@
if (!this.field_70170_p.field_72995_K) { if (!this.field_70170_p.field_72995_K) {
this.func_204802_c(1, true); this.func_204802_c(1, true);
this.func_204802_c(2, p_184598_1_ == Hand.OFF_HAND); this.func_204802_c(2, p_184598_1_ == Hand.OFF_HAND);
@@ -2768,6 +2813,9 @@ @@ -2768,6 +2815,9 @@
vector3d1 = vector3d1.func_178789_a(-this.field_70125_A * ((float)Math.PI / 180F)); vector3d1 = vector3d1.func_178789_a(-this.field_70125_A * ((float)Math.PI / 180F));
vector3d1 = vector3d1.func_178785_b(-this.field_70177_z * ((float)Math.PI / 180F)); vector3d1 = vector3d1.func_178785_b(-this.field_70177_z * ((float)Math.PI / 180F));
vector3d1 = vector3d1.func_72441_c(this.func_226277_ct_(), this.func_226280_cw_(), this.func_226281_cx_()); vector3d1 = vector3d1.func_72441_c(this.func_226277_ct_(), this.func_226280_cw_(), this.func_226281_cx_());
@ -401,7 +410,7 @@
this.field_70170_p.func_195594_a(new ItemParticleData(ParticleTypes.field_197591_B, p_195062_1_), vector3d1.field_72450_a, vector3d1.field_72448_b, vector3d1.field_72449_c, vector3d.field_72450_a, vector3d.field_72448_b + 0.05D, vector3d.field_72449_c); this.field_70170_p.func_195594_a(new ItemParticleData(ParticleTypes.field_197591_B, p_195062_1_), vector3d1.field_72450_a, vector3d1.field_72448_b, vector3d1.field_72449_c, vector3d.field_72450_a, vector3d.field_72448_b + 0.05D, vector3d.field_72449_c);
} }
@@ -2779,7 +2827,9 @@ @@ -2779,7 +2829,9 @@
} else { } else {
if (!this.field_184627_bm.func_190926_b() && this.func_184587_cr()) { if (!this.field_184627_bm.func_190926_b() && this.func_184587_cr()) {
this.func_226293_b_(this.field_184627_bm, 16); this.func_226293_b_(this.field_184627_bm, 16);
@ -412,7 +421,7 @@
this.func_184602_cy(); this.func_184602_cy();
} }
@@ -2800,7 +2850,11 @@ @@ -2800,7 +2852,11 @@
public void func_184597_cx() { public void func_184597_cx() {
if (!this.field_184627_bm.func_190926_b()) { if (!this.field_184627_bm.func_190926_b()) {
@ -424,7 +433,7 @@
if (this.field_184627_bm.func_222122_m()) { if (this.field_184627_bm.func_222122_m()) {
this.func_184608_ct(); this.func_184608_ct();
} }
@@ -2949,8 +3003,8 @@ @@ -2949,8 +3005,8 @@
} }
BlockState blockstate = this.field_70170_p.func_180495_p(p_213342_1_); BlockState blockstate = this.field_70170_p.func_180495_p(p_213342_1_);
@ -435,7 +444,7 @@
} }
this.func_213301_b(Pose.SLEEPING); this.func_213301_b(Pose.SLEEPING);
@@ -2966,15 +3020,15 @@ @@ -2966,15 +3022,15 @@
private boolean func_213359_p() { private boolean func_213359_p() {
return this.func_213374_dv().map((p_241350_1_) -> { return this.func_213374_dv().map((p_241350_1_) -> {
@ -454,7 +463,7 @@
Vector3d vector3d1 = BedBlock.func_220172_a(this.func_200600_R(), this.field_70170_p, p_241348_1_, 0).orElseGet(() -> { Vector3d vector3d1 = BedBlock.func_220172_a(this.func_200600_R(), this.field_70170_p, p_241348_1_, 0).orElseGet(() -> {
BlockPos blockpos = p_241348_1_.func_177984_a(); BlockPos blockpos = p_241348_1_.func_177984_a();
return new Vector3d((double)blockpos.func_177958_n() + 0.5D, (double)blockpos.func_177956_o() + 0.1D, (double)blockpos.func_177952_p() + 0.5D); return new Vector3d((double)blockpos.func_177958_n() + 0.5D, (double)blockpos.func_177956_o() + 0.1D, (double)blockpos.func_177952_p() + 0.5D);
@@ -2993,7 +3047,9 @@ @@ -2993,7 +3049,9 @@
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public Direction func_213376_dz() { public Direction func_213376_dz() {
BlockPos blockpos = this.func_213374_dv().orElse((BlockPos)null); BlockPos blockpos = this.func_213374_dv().orElse((BlockPos)null);
@ -465,7 +474,7 @@
} }
public boolean func_70094_T() { public boolean func_70094_T() {
@@ -3062,4 +3118,58 @@ @@ -3062,4 +3120,58 @@
public void func_213334_d(Hand p_213334_1_) { public void func_213334_d(Hand p_213334_1_) {
this.func_213361_c(p_213334_1_ == Hand.MAIN_HAND ? EquipmentSlotType.MAINHAND : EquipmentSlotType.OFFHAND); this.func_213361_c(p_213334_1_ == Hand.MAIN_HAND ? EquipmentSlotType.MAINHAND : EquipmentSlotType.OFFHAND);
} }

View file

@ -257,6 +257,15 @@
return false; return false;
} else { } else {
if (p_225503_1_ >= 2.0F) { if (p_225503_1_ >= 2.0F) {
@@ -1434,7 +1467,7 @@
public boolean func_226566_ei_() {
if (!this.field_70122_E && !this.func_184613_cA() && !this.func_70090_H() && !this.func_70644_a(Effects.field_188424_y)) {
ItemStack itemstack = this.func_184582_a(EquipmentSlotType.CHEST);
- if (itemstack.func_77973_b() == Items.field_185160_cR && ElytraItem.func_185069_d(itemstack)) {
+ if (itemstack.canElytraFly(this)) {
this.func_226567_ej_();
return true;
}
@@ -1475,6 +1508,10 @@ @@ -1475,6 +1508,10 @@
} }

View file

@ -0,0 +1,20 @@
--- a/net/minecraft/item/ElytraItem.java
+++ b/net/minecraft/item/ElytraItem.java
@@ -35,4 +35,17 @@
return ActionResult.func_226251_d_(itemstack);
}
}
+
+ @Override
+ public boolean canElytraFly(ItemStack stack, net.minecraft.entity.LivingEntity entity) {
+ return ElytraItem.func_185069_d(stack);
+ }
+
+ @Override
+ public boolean elytraFlightTick(ItemStack stack, net.minecraft.entity.LivingEntity entity, int flightTicks) {
+ if (!entity.field_70170_p.field_72995_K && (flightTicks + 1) % 20 == 0) {
+ stack.func_222118_a(1, entity, e -> e.func_213361_c(net.minecraft.inventory.EquipmentSlotType.CHEST));
+ }
+ return true;
+ }
}

View file

@ -819,4 +819,33 @@ public interface IForgeItem
return stack.getItem() == Blocks.CARVED_PUMPKIN.asItem(); return stack.getItem() == Blocks.CARVED_PUMPKIN.asItem();
} }
/**
* Used to determine if the player can use Elytra flight.
* This is called Client and Server side.
*
* @param stack The ItemStack in the Chest slot of the entity.
* @param entity The entity trying to fly.
* @return True if the entity can use Elytra flight.
*/
default boolean canElytraFly(ItemStack stack, LivingEntity entity)
{
return false;
}
/**
* Used to determine if the player can continue Elytra flight,
* this is called each tick, and can be used to apply ItemStack damage,
* consume Energy, or what have you.
* For example the Vanilla implementation of this, applies damage to the
* ItemStack every 20 ticks.
*
* @param stack ItemStack in the Chest slot of the entity.
* @param entity The entity currently in Elytra flight.
* @param flightTicks The number of ticks the entity has been Elytra flying for.
* @return True if the entity should continue Elytra flight or False to stop.
*/
default boolean elytraFlightTick(ItemStack stack, LivingEntity entity, int flightTicks)
{
return false;
}
} }

View file

@ -476,4 +476,32 @@ public interface IForgeItemStack extends ICapabilitySerializable<CompoundNBT>
{ {
return getStack().getItem().isEnderMask(getStack(), player, endermanEntity); return getStack().getItem().isEnderMask(getStack(), player, endermanEntity);
} }
/**
* Used to determine if the player can use Elytra flight.
* This is called Client and Server side.
*
* @param entity The entity trying to fly.
* @return True if the entity can use Elytra flight.
*/
default boolean canElytraFly(LivingEntity entity)
{
return getStack().getItem().canElytraFly(getStack(), entity);
}
/**
* Used to determine if the player can continue Elytra flight,
* this is called each tick, and can be used to apply ItemStack damage,
* consume Energy, or what have you.
* For example the Vanilla implementation of this, applies damage to the
* ItemStack every 20 ticks.
*
* @param entity The entity currently in Elytra flight.
* @param flightTicks The number of ticks the entity has been Elytra flying for.
* @return True if the entity should continue Elytra flight or False to stop.
*/
default boolean elytraFlightTick(LivingEntity entity, int flightTicks)
{
return getStack().getItem().elytraFlightTick(getStack(), entity, flightTicks);
}
} }

View file

@ -0,0 +1,132 @@
/*
* Minecraft Forge
* Copyright (c) 2016-2019.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package net.minecraftforge.debug.item;
import net.minecraft.block.DispenserBlock;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
import net.minecraft.client.renderer.entity.IEntityRenderer;
import net.minecraft.client.renderer.entity.PlayerRenderer;
import net.minecraft.client.renderer.entity.layers.ElytraLayer;
import net.minecraft.client.renderer.entity.model.ElytraModel;
import net.minecraft.client.renderer.entity.model.PlayerModel;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.EquipmentSlotType;
import net.minecraft.item.*;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.RegistryObject;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nullable;
@Mod(CustomElytraTest.MOD_ID)
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD, modid = CustomElytraTest.MOD_ID)
public class CustomElytraTest
{
public static final String MOD_ID = "custom_elytra_test";
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MOD_ID);
private static final RegistryObject<Item> TEST_ELYTRA = ITEMS.register("test_elytra",() -> new CustomElytra(new Item.Properties().maxDamage(100).group(ItemGroup.MISC)));
public CustomElytraTest()
{
final IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
ITEMS.register(modBus);
modBus.addListener(this::onClientSetup);
}
private void onClientSetup(FMLClientSetupEvent event)
{
registerElytraLayer();
}
@OnlyIn(Dist.CLIENT)
private void registerElytraLayer()
{
Minecraft.getInstance().getRenderManager().getSkinMap().values().forEach(player -> player.addLayer(new CustomElytraLayer(player)));
}
public static class CustomElytra extends Item
{
public CustomElytra(Properties properties)
{
super(properties);
DispenserBlock.registerDispenseBehavior(this, ArmorItem.DISPENSER_BEHAVIOR);
}
@Nullable
@Override
public EquipmentSlotType getEquipmentSlot(ItemStack stack)
{
return EquipmentSlotType.CHEST; //Or you could just extend ItemArmor
}
@Override
public boolean canElytraFly(ItemStack stack, LivingEntity entity)
{
return true;
}
@Override
public boolean elytraFlightTick(ItemStack stack, LivingEntity entity, int flightTicks)
{
//Adding 1 to ticksElytraFlying prevents damage on the very first tick.
if (!entity.world.isRemote && (flightTicks + 1) % 20 == 0)
{
stack.damageItem(1, entity, e -> e.sendBreakAnimation(EquipmentSlotType.CHEST));
}
return true;
}
}
@OnlyIn(Dist.CLIENT)
public static class CustomElytraLayer extends ElytraLayer<AbstractClientPlayerEntity, PlayerModel<AbstractClientPlayerEntity>>
{
private static final ResourceLocation TEXTURE_ELYTRA = new ResourceLocation(MOD_ID, "textures/entity/custom_elytra.png");
public CustomElytraLayer(IEntityRenderer<AbstractClientPlayerEntity, PlayerModel<AbstractClientPlayerEntity>> rendererIn)
{
super(rendererIn);
}
@Override
public boolean shouldRender(ItemStack stack, AbstractClientPlayerEntity entity)
{
return stack.getItem() == TEST_ELYTRA.get();
}
@Override
public ResourceLocation getElytraTexture(ItemStack stack, AbstractClientPlayerEntity entity)
{
return TEXTURE_ELYTRA;
}
}
}

View file

@ -76,3 +76,5 @@ license="LGPL v2.1"
modId="player_name_event_test" modId="player_name_event_test"
[[mods]] [[mods]]
modId="modded_overworld_biomes_test" modId="modded_overworld_biomes_test"
[[mods]]
modId="custom_elytra_test"

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "custom_elytra_test:item/custom_elytra"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2 KiB