diff --git a/src/main/java/biomesoplenty/client/renderer/BoatRendererBOP.java b/src/main/java/biomesoplenty/client/renderer/BoatRendererBOP.java new file mode 100644 index 000000000..ecfc4d11a --- /dev/null +++ b/src/main/java/biomesoplenty/client/renderer/BoatRendererBOP.java @@ -0,0 +1,78 @@ +package biomesoplenty.client.renderer; + +import biomesoplenty.common.entity.item.BoatEntityBOP; +import com.mojang.blaze3d.matrix.MatrixStack; +import com.mojang.blaze3d.vertex.IVertexBuilder; +import net.minecraft.client.renderer.IRenderTypeBuffer; +import net.minecraft.client.renderer.RenderType; +import net.minecraft.client.renderer.entity.EntityRenderer; +import net.minecraft.client.renderer.entity.EntityRendererManager; +import net.minecraft.client.renderer.entity.model.BoatModel; +import net.minecraft.client.renderer.texture.OverlayTexture; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.vector.Quaternion; +import net.minecraft.util.math.vector.Vector3f; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import static biomesoplenty.core.BiomesOPlenty.MOD_ID; + +@OnlyIn(Dist.CLIENT) +public class BoatRendererBOP extends EntityRenderer { + protected final BoatModel model = new BoatModel(); + + public BoatRendererBOP(EntityRendererManager renderer) { + super(renderer); + this.shadowRadius = 0.8f; + } + + @Override + public void render(BoatEntityBOP entity, float entityYaw, float partialTicks, MatrixStack matrixStack, IRenderTypeBuffer renderTypeBuffer, int light) { + matrixStack.pushPose(); + matrixStack.translate(0d, 0.375d, 0d); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(180f - entityYaw)); + float f = (float) entity.getHurtTime() - partialTicks; + float f1 = entity.getDamage() - partialTicks; + if (f1 < 0f) { + f1 = 0f; + } + if (f > 0f) { + matrixStack.mulPose(Vector3f.XP.rotationDegrees(MathHelper.sin(f) * f * f1 / 10f * (float) entity.getHurtDir())); + } + float f2 = entity.getBubbleAngle(partialTicks); + if (!MathHelper.equal(f2, 0f)) { + matrixStack.mulPose(new Quaternion(new Vector3f(1f, 0f, 1f), entity.getBubbleAngle(partialTicks), true)); + } + matrixStack.scale(-1f, -1f, 1f); + matrixStack.mulPose(Vector3f.YP.rotationDegrees(90.0F)); + this.model.setupAnim(entity, partialTicks, 0f, -0.1f, 0f, 0f); + IVertexBuilder ivertexbuilder = renderTypeBuffer.getBuffer(this.model.renderType(this.getTextureLocation(entity))); + this.model.renderToBuffer(matrixStack, ivertexbuilder, light, OverlayTexture.NO_OVERLAY, 1f, 1f, 1f, 1f); + if (!entity.isUnderWater()) { + IVertexBuilder ivertexbuilder1 = renderTypeBuffer.getBuffer(RenderType.waterMask()); + this.model.waterPatch().render(matrixStack, ivertexbuilder1, light, OverlayTexture.NO_OVERLAY); + } + matrixStack.popPose(); + super.render(entity, entityYaw, partialTicks, matrixStack, renderTypeBuffer, light); + } + + @Override + public ResourceLocation getTextureLocation(BoatEntityBOP entity) { + return BOAT_TEXTURE_LOCATIONS[entity.getModel().ordinal()]; + } + + private static final ResourceLocation[] BOAT_TEXTURE_LOCATIONS = new ResourceLocation[] { + new ResourceLocation(MOD_ID, "textures/entity/boat/fir.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/redwood.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/cherry.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/mahogany.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/jacaranda.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/palm.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/willow.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/dead.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/magic.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/umbran.png"), + new ResourceLocation(MOD_ID, "textures/entity/boat/hellbark.png") + }; +} diff --git a/src/main/java/biomesoplenty/common/entity/item/BoatEntityBOP.java b/src/main/java/biomesoplenty/common/entity/item/BoatEntityBOP.java new file mode 100644 index 000000000..213c71337 --- /dev/null +++ b/src/main/java/biomesoplenty/common/entity/item/BoatEntityBOP.java @@ -0,0 +1,183 @@ +package biomesoplenty.common.entity.item; + +import biomesoplenty.api.block.BOPBlocks; +import biomesoplenty.api.item.BOPItems; +import biomesoplenty.init.ModEntities; +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.item.BoatEntity; +import net.minecraft.item.Item; +import net.minecraft.item.Items; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.network.IPacket; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.GameRules; +import net.minecraft.world.World; +import net.minecraftforge.common.util.Constants; +import net.minecraftforge.fml.network.FMLPlayMessages; +import net.minecraftforge.fml.network.NetworkHooks; + +import java.util.Arrays; +import java.util.function.Supplier; + +public class BoatEntityBOP extends BoatEntity { + public BoatEntityBOP(EntityType type, World world) { + super(type, world); + } + + public BoatEntityBOP(World world, double x, double y, double z) { + super(ModEntities.boat, world); + setPos(x, y, z); + setDeltaMovement(Vector3d.ZERO); + this.xo = x; + this.yo = y; + this.zo = z; + } + + public BoatEntityBOP(FMLPlayMessages.SpawnEntity spawnEntity, World world) { + this(world, spawnEntity.getPosX(), spawnEntity.getPosY(), spawnEntity.getPosZ()); + } + + @Override + public IPacket getAddEntityPacket() { + return NetworkHooks.getEntitySpawningPacket(this); + } + + @Override + protected void addAdditionalSaveData(CompoundNBT nbt) { + nbt.putString("model", getModel().getName()); + } + + @Override + protected void readAdditionalSaveData(CompoundNBT nbt) { + if (nbt.contains("model", Constants.NBT.TAG_STRING)) { + this.entityData.set(DATA_ID_TYPE, BoatModel.byName(nbt.getString("model")).ordinal()); + } + } + + @Override + protected void checkFallDamage(double y, boolean onGround, BlockState state, BlockPos pos) { + this.lastYd = getDeltaMovement().y; + if (!isPassenger()) { + if (onGround) { + if (this.fallDistance > 3f) { + if (this.status != Status.ON_LAND) { + this.fallDistance = 0f; + return; + } + causeFallDamage(this.fallDistance, 1f); + if (!this.level.isClientSide && !this.removed) { + this.remove(); + if (this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) { + for (int i = 0; i < 3; ++i) { + spawnAtLocation(getModel().getPlanks()); + } + for (int j = 0; j < 2; ++j) { + spawnAtLocation(Items.STICK); + } + } + } + } + this.fallDistance = 0f; + } else if (!this.level.getFluidState(this.blockPosition().below()).is(FluidTags.WATER) && y < 0d) { + this.fallDistance = (float) ((double) this.fallDistance - y); + } + } + } + + @Override + public Item getDropItem() { + switch (BoatModel.byId(this.entityData.get(DATA_ID_TYPE))) { + case FIR: + return BOPItems.fir_boat; + case REDWOOD: + return BOPItems.redwood_boat; + case CHERRY: + return BOPItems.cherry_boat; + case MAHOGANY: + return BOPItems.mahogany_boat; + case JACARANDA: + return BOPItems.jacaranda_boat; + case PALM: + return BOPItems.palm_boat; + case WILLOW: + return BOPItems.willow_boat; + case DEAD: + return BOPItems.dead_boat; + case MAGIC: + return BOPItems.magic_boat; + case UMBRAN: + return BOPItems.umbran_boat; + case HELLBARK: + return BOPItems.hellbark_boat; + } + return Items.OAK_BOAT; + } + + public BoatEntityBOP withModel(BoatModel type) { + this.entityData.set(DATA_ID_TYPE, type.ordinal()); + return this; + } + + public BoatModel getModel() { + return BoatModel.byId(this.entityData.get(DATA_ID_TYPE)); + } + + @Deprecated + @Override + public void setType(Type vanillaType) { + } + + @Deprecated + @Override + public Type getBoatType() { + return Type.OAK; + } + + public enum BoatModel { + FIR("fir", () -> BOPBlocks.fir_planks), + REDWOOD("redwood", () -> BOPBlocks.redwood_planks), + CHERRY("cherry", () -> BOPBlocks.cherry_planks), + MAHOGANY("mahogany", () -> BOPBlocks.mahogany_planks), + JACARANDA("jacaranda", () -> BOPBlocks.jacaranda_planks), + PALM("palm", () -> BOPBlocks.palm_planks), + WILLOW("willow", () -> BOPBlocks.willow_planks), + DEAD("dead", () -> BOPBlocks.dead_planks), + MAGIC("magic", () -> BOPBlocks.magic_planks), + UMBRAN("umbran", () -> BOPBlocks.umbran_planks), + HELLBARK("hellbark", () -> BOPBlocks.hellbark_planks); + + private final String name; + private final Supplier supplierPlanks; + + BoatModel(String name, Supplier supplierPlanks) { + this.name = name; + this.supplierPlanks = supplierPlanks; + } + + public String getName() { + return this.name; + } + + public Block getPlanks() { + return this.supplierPlanks.get(); + } + + public String toString() { + return this.name; + } + + public static BoatModel byId(int id) { + BoatModel[] type = values(); + return type[id < 0 || id >= type.length ? 0 : id]; + } + + public static BoatModel byName(String aName) { + BoatModel[] type = values(); + return Arrays.stream(type).filter(t -> t.getName().equals(aName)).findFirst().orElse(type[0]); + } + } +} diff --git a/src/main/java/biomesoplenty/common/item/BoatItemBOP.java b/src/main/java/biomesoplenty/common/item/BoatItemBOP.java new file mode 100644 index 000000000..c4ddd8137 --- /dev/null +++ b/src/main/java/biomesoplenty/common/item/BoatItemBOP.java @@ -0,0 +1,72 @@ +package biomesoplenty.common.item; + +import biomesoplenty.common.entity.item.BoatEntityBOP; +import biomesoplenty.common.entity.item.BoatEntityBOP.BoatModel; +import biomesoplenty.common.util.inventory.ItemGroupBOP; +import net.minecraft.block.DispenserBlock; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.stats.Stats; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EntityPredicates; +import net.minecraft.util.Hand; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.RayTraceContext; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.vector.Vector3d; +import net.minecraft.world.World; + +import java.util.List; +import java.util.function.Predicate; + +public class BoatItemBOP extends Item { + private static final Predicate ENTITY_PREDICATE = EntityPredicates.NO_SPECTATORS.and(Entity::isPickable); + private final BoatModel model; + + public BoatItemBOP(BoatModel model) { + super(new Item.Properties().stacksTo(1).tab(ItemGroupBOP.instance)); + this.model = model; + DispenserBlock.registerBehavior(this, new DispenserBoatBehaviorBOP(model)); + } + + @Override + public ActionResult use(World world, PlayerEntity player, Hand hand) { + ItemStack heldItem = player.getItemInHand(hand); + RayTraceResult result = getPlayerPOVHitResult(world, player, RayTraceContext.FluidMode.ANY); + if (result.getType() == RayTraceResult.Type.MISS) { + return ActionResult.pass(heldItem); + } else { + Vector3d vector3d = player.getViewVector(1f); + List entities = world.getEntities(player, player.getBoundingBox().expandTowards(vector3d.scale(5d)).inflate(1d), ENTITY_PREDICATE); + if (!entities.isEmpty()) { + Vector3d vector3d1 = player.getEyePosition(1f); + for (Entity entity : entities) { + AxisAlignedBB bounds = entity.getBoundingBox().inflate((double) entity.getPickRadius()); + if (bounds.contains(vector3d1)) { + return ActionResult.pass(heldItem); + } + } + } + if (result.getType() == RayTraceResult.Type.BLOCK) { + BoatEntityBOP boat = new BoatEntityBOP(world, result.getLocation().x, result.getLocation().y, result.getLocation().z).withModel(this.model); + boat.yRot = player.yRot; + if (!world.noCollision(boat, boat.getBoundingBox().inflate(-0.1d))) { + return ActionResult.fail(heldItem); + } else { + if (!world.isClientSide()) { + world.addFreshEntity(boat); + if (!player.abilities.instabuild) { + heldItem.shrink(1); + } + } + player.awardStat(Stats.ITEM_USED.get(this)); + return ActionResult.sidedSuccess(heldItem, world.isClientSide()); + } + } else { + return ActionResult.pass(heldItem); + } + } + } +} diff --git a/src/main/java/biomesoplenty/common/item/DispenserBoatBehaviorBOP.java b/src/main/java/biomesoplenty/common/item/DispenserBoatBehaviorBOP.java new file mode 100644 index 000000000..0a1d583c2 --- /dev/null +++ b/src/main/java/biomesoplenty/common/item/DispenserBoatBehaviorBOP.java @@ -0,0 +1,45 @@ +package biomesoplenty.common.item; + +import biomesoplenty.common.entity.item.BoatEntityBOP; +import biomesoplenty.common.entity.item.BoatEntityBOP.BoatModel; +import net.minecraft.block.DispenserBlock; +import net.minecraft.dispenser.DefaultDispenseItemBehavior; +import net.minecraft.dispenser.IBlockSource; +import net.minecraft.item.ItemStack; +import net.minecraft.tags.FluidTags; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class DispenserBoatBehaviorBOP extends DefaultDispenseItemBehavior { + private final DefaultDispenseItemBehavior defaultDispenseItemBehavior = new DefaultDispenseItemBehavior(); + private final BoatModel model; + + public DispenserBoatBehaviorBOP(BoatModel model) { + this.model = model; + } + + @Override + public ItemStack execute(IBlockSource source, ItemStack stack) { + Direction direction = source.getBlockState().getValue(DispenserBlock.FACING); + World world = source.getLevel(); + double d0 = source.x() + (double) ((float) direction.getStepX() * 1.125f); + double d1 = source.y() + (double) ((float) direction.getStepY() * 1.125f); + double d2 = source.z() + (double) ((float) direction.getStepZ() * 1.125f); + BlockPos blockpos = source.getPos().relative(direction); + double d3; + if (world.getFluidState(blockpos).is(FluidTags.WATER)) { + d3 = 1d; + } else { + if (!world.getBlockState(blockpos).isAir() || !world.getFluidState(blockpos.below()).is(FluidTags.WATER)) { + return this.defaultDispenseItemBehavior.dispense(source, stack); + } + d3 = 0d; + } + BoatEntityBOP boat = new BoatEntityBOP(world, d0, d1 + d3, d2).withModel(this.model); + boat.yRot = direction.toYRot(); + world.addFreshEntity(boat); + stack.shrink(1); + return stack; + } +} diff --git a/src/main/java/biomesoplenty/core/BiomesOPlenty.java b/src/main/java/biomesoplenty/core/BiomesOPlenty.java index bcefb9aa8..a1fc920cf 100644 --- a/src/main/java/biomesoplenty/core/BiomesOPlenty.java +++ b/src/main/java/biomesoplenty/core/BiomesOPlenty.java @@ -8,8 +8,10 @@ package biomesoplenty.core; +import biomesoplenty.client.renderer.BoatRendererBOP; import biomesoplenty.init.*; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.fml.client.registry.RenderingRegistry; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; @@ -50,6 +52,7 @@ public class BiomesOPlenty private void clientSetup(final FMLClientSetupEvent event) { + RenderingRegistry.registerEntityRenderingHandler(ModEntities.boat, BoatRendererBOP::new); } private void loadComplete(final FMLLoadCompleteEvent event) // PostRegistrationEven diff --git a/src/main/java/biomesoplenty/init/ModEntities.java b/src/main/java/biomesoplenty/init/ModEntities.java index 9f7bc1327..337f8edd5 100644 --- a/src/main/java/biomesoplenty/init/ModEntities.java +++ b/src/main/java/biomesoplenty/init/ModEntities.java @@ -7,5 +7,20 @@ ******************************************************************************/ package biomesoplenty.init; +import biomesoplenty.common.entity.item.BoatEntityBOP; +import biomesoplenty.core.BiomesOPlenty; +import net.minecraft.entity.EntityClassification; +import net.minecraft.entity.EntityType; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; + +@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class ModEntities { + public static final EntityType boat = EntityType.Builder.of(BoatEntityBOP::new, EntityClassification.MISC).sized(1.375f, 0.5625f).setCustomClientFactory(BoatEntityBOP::new).clientTrackingRange(10).build(BiomesOPlenty.MOD_ID + ":boat"); + + @SubscribeEvent + public static void registerEntities(final RegistryEvent.Register> event) { + event.getRegistry().register(boat.setRegistryName("boat")); + } } diff --git a/src/main/java/biomesoplenty/init/ModItems.java b/src/main/java/biomesoplenty/init/ModItems.java index fb15549ad..8e877c993 100644 --- a/src/main/java/biomesoplenty/init/ModItems.java +++ b/src/main/java/biomesoplenty/init/ModItems.java @@ -7,14 +7,11 @@ ******************************************************************************/ package biomesoplenty.init; +import biomesoplenty.common.entity.item.BoatEntityBOP; +import biomesoplenty.common.item.BoatItemBOP; import biomesoplenty.common.item.MusicDiscItemBOP; import biomesoplenty.common.util.inventory.ItemGroupBOP; -import net.minecraft.entity.item.BoatEntity; -import net.minecraft.item.BoatItem; -import net.minecraft.item.Food; import net.minecraft.item.Item; -import net.minecraft.potion.EffectInstance; -import net.minecraft.potion.Effects; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -34,17 +31,17 @@ public class ModItems music_disc_wanderer = registerItem(new MusicDiscItemBOP("music_disc.wanderer"), "music_disc_wanderer"); - fir_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "fir_boat"); - redwood_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "redwood_boat"); - cherry_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "cherry_boat"); - mahogany_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "mahogany_boat"); - jacaranda_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "jacaranda_boat"); - palm_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "palm_boat"); - willow_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "willow_boat"); - dead_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "dead_boat"); - magic_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "magic_boat"); - umbran_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "umbran_boat"); - hellbark_boat = registerItem(new BoatItem(BoatEntity.Type.OAK, (new Item.Properties()).stacksTo(1).tab(ItemGroupBOP.instance)), "hellbark_boat"); + fir_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.FIR), "fir_boat"); + redwood_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.REDWOOD), "redwood_boat"); + cherry_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.CHERRY), "cherry_boat"); + mahogany_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.MAHOGANY), "mahogany_boat"); + jacaranda_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.JACARANDA), "jacaranda_boat"); + palm_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.PALM), "palm_boat"); + willow_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.WILLOW), "willow_boat"); + dead_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.DEAD), "dead_boat"); + magic_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.MAGIC), "magic_boat"); + umbran_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.UMBRAN), "umbran_boat"); + hellbark_boat = registerItem(new BoatItemBOP(BoatEntityBOP.BoatModel.HELLBARK), "hellbark_boat"); bop_icon = registerItem(new Item(new Item.Properties()), "bop_icon"); } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index 3769316e9..09e168833 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -36,7 +36,9 @@ public-f net.minecraft.item.AxeItem field_203176_a # BLOCK_STRIPPING_MAP public-f net.minecraft.item.HoeItem field_195973_b # TILLABLES public-f net.minecraft.item.ShovelItem field_195955_e # FLATTENABLES -protected net.minecraft.entity.item.BoatEntity func_184447_s()V #tickLerp +public net.minecraft.entity.item.BoatEntity field_184466_d #DATA_ID_TYPE +public net.minecraft.entity.item.BoatEntity field_184469_aF #status +public net.minecraft.entity.item.BoatEntity field_184473_aH #lastYd public net.minecraft.world.gen.feature.WorldDecoratingHelper *