I was creating a custom boat, already have it working but it doesn't load his texture, it loads the oak boat texture
Also, I want to make it go faster hen the normal but don't know what value I have to change.
Boat class:
package com.handreans.dancinglizards.entities;
import com.handreans.dancinglizards.init.BlockInit;
import com.handreans.dancinglizards.init.DLEntityTypes;
import com.handreans.dancinglizards.init.ItemInit;
import net.minecraft.block.BlockState;
import net.minecraft.block.LilyPadBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MoverType;
import net.minecraft.entity.item.BoatEntity;
import net.minecraft.entity.passive.AnimalEntity;
import net.minecraft.entity.passive.WaterMobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.fluid.IFluidState;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.network.IPacket;
import net.minecraft.network.datasync.DataParameter;
import net.minecraft.network.datasync.DataSerializers;
import net.minecraft.network.datasync.EntityDataManager;
import net.minecraft.network.play.client.CSteerBoatPacket;
import net.minecraft.network.play.server.SSpawnObjectPacket;
import net.minecraft.particles.ParticleTypes;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.*;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.IBooleanFunction;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import java.util.List;
public class DLBoatEntity extends BoatEntity
{
private static final DataParameter<Integer> TIME_SINCE_HIT = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.VARINT);
private static final DataParameter<Integer> FOWARD_DIRECTION = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.VARINT);
private static final DataParameter<Float> DAMAGE_TAKEN = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.FLOAT);
private static final DataParameter<Integer> BOAT_TYPE = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.VARINT);
private static final DataParameter<Boolean> field_1 = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Boolean> field_2 = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.BOOLEAN);
private static final DataParameter<Integer> ROCKING_TICKS = EntityDataManager.createKey(DLBoatEntity.class, DataSerializers.VARINT);
private final float[] paddlePositions = new float[2];
private float momentum;
private float outOfControlTicks;
private float deltaRotation;
private int lerpSteps;
private double lerpX;
private double lerpY;
private double lerpZ;
private double lerpYaw;
private double lerpPitch;
private boolean leftInputDown;
private boolean rightInputDown;
private boolean forwardInputDown;
private boolean backInputDown;
private double waterLevel;
private float boatGlide;
private DLBoatEntity.Status status;
private DLBoatEntity.Status previousStatus;
private double lastYd;
private boolean rocking;
private boolean field_203060_aN;
private float rockingIntensity;
private float rockingAngle;
private float prevRockingAngle;
public DLBoatEntity(EntityType<? extends DLBoatEntity> entity, World world)
{
super(entity, world);
this.preventEntitySpawning = true;
}
public DLBoatEntity(World worldIn, double x, double y, double z)
{
this((EntityType<? extends DLBoatEntity>) DLEntityTypes.BOAT.get(), worldIn);
this.setPosition(x, y, z);
this.setMotion(Vec3d.ZERO);
this.prevPosX = x;
this.prevPosY = y;
this.prevPosZ = z;
}
protected boolean canTriggerWalking()
{
return false;
}
protected void registerData()
{
this.dataManager.register(TIME_SINCE_HIT, 0);
this.dataManager.register(FOWARD_DIRECTION, 1);
this.dataManager.register(DAMAGE_TAKEN, 0.0F);
this.dataManager.register(field_1, false);
this.dataManager.register(field_2, false);
this.dataManager.register(ROCKING_TICKS, 0);
}
@Override
@Nullable
public AxisAlignedBB getCollisionBox(Entity entityIn)
{
return entityIn.canBePushed() ? entityIn.getBoundingBox() : null;
}
@Nullable
@Override
public AxisAlignedBB getCollisionBoundingBox() {
return this.getBoundingBox();
}
@Override
public boolean canBePushed() {
return true;
}
@Override
public double getMountedYOffset() {
return -0.1D;
}
@Override
public boolean attackEntityFrom(DamageSource source, float amount) {
if (this.isInvulnerableTo(source))
{
return false;
}
else if (!this.world.isRemote && !this.removed)
{
if (source instanceof IndirectEntityDamageSource && source.getTrueSource() != null && this.isPassenger(source.getTrueSource()))
{
return false;
}
else
{
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamageTaken(this.getDamageTaken() + amount * 10.0F);
this.markVelocityChanged();
boolean flag = source.getTrueSource() instanceof PlayerEntity && ((PlayerEntity)source.getTrueSource()).abilities.isCreativeMode;
if (flag || this.getDamageTaken() > 40.0F)
{
if (!flag && this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS))
{
this.entityDropItem(this.getItemBoat());
}
this.remove();
}
return true;
}
}
else
{
return true;
}
}
@Override
public void onEnterBubbleColumnWithAirAbove(boolean downwards) {
if (!this.world.isRemote)
{
this.rocking = true;
this.field_203060_aN = downwards;
if (this.getRockingTicks() == 0)
{
this.setRockingTicks(60);
}
}
this.world.addParticle(ParticleTypes.SPLASH, this.getPosX() + (double)this.rand.nextFloat(), this.getPosY() + 0.7D, this.getPosZ() + (double)this.rand.nextFloat(), 0.0D, 0.0D, 0.0D);
if (this.rand.nextInt(20) == 0)
{
this.world.playSound(this.getPosX(), this.getPosY(), this.getPosZ(), this.getSplashSound(), this.getSoundCategory(), 1.0F, 0.8F + 0.4F * this.rand.nextFloat(), false);
}
}
@Override
public void applyEntityCollision(Entity entityIn) {
if (entityIn instanceof DLBoatEntity)
{
if (entityIn.getBoundingBox().minY < this.getBoundingBox().maxY)
{
super.applyEntityCollision(entityIn);
}
}
else if (entityIn.getBoundingBox().minY <= this.getBoundingBox().minY)
{
super.applyEntityCollision(entityIn);
}
}
@Override
public Item getItemBoat()
{
return ItemInit.DL_BOAT.get();
}
@OnlyIn(Dist.CLIENT)
@Override
public void performHurtAnimation() {
this.setForwardDirection(-this.getForwardDirection());
this.setTimeSinceHit(10);
this.setDamageTaken(this.getDamageTaken() * 11.0F);
}
@Override
public boolean canBeCollidedWith() {
return !this.removed;
}
@OnlyIn(Dist.CLIENT)
@Override
public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport) {
this.lerpX = x;
this.lerpY = y;
this.lerpZ = z;
this.lerpYaw = (double)yaw;
this.lerpPitch = (double)pitch;
this.lerpSteps = 10;
}
@Override
public Direction getAdjustedHorizontalFacing() {
return this.getHorizontalFacing().rotateY();
}
@Override
public void tick() {
this.previousStatus = this.status;
this.status = this.getBoatStatus();
if (this.status != Status.UNDER_WATER && this.status != Status.UNDER_FLOWING_WATER)
{
this.outOfControlTicks = 0.0F;
}
else
{
++this.outOfControlTicks;
}
if (!this.world.isRemote && this.outOfControlTicks >= 60.0F)
{
this.removePassengers();
}
if (this.getTimeSinceHit() > 0)
{
this.setTimeSinceHit(this.getTimeSinceHit() -1);
}
if (this.getDamageTaken() > 0.0F)
{
this.setDamageTaken(this.getDamageTaken() - 1.0F);
}
super.tick();
this.tickLerp();
if (this.canPassengerSteer())
{
if (this.getPassengers().isEmpty() || !(this.getPassengers().get(0) instanceof PlayerEntity))
{
this.setPaddleState(false, false);
}
this.updateMotion();
if(this.world.isRemote)
{
this.controlBoat();
this.world.sendPacketToServer(new CSteerBoatPacket(this.getPaddleState(0), this.getPaddleState(1)));
}
this.move(MoverType.SELF, this.getMotion());
}
else
{
this.setMotion(Vec3d.ZERO);
}
this.updateRocking();
for(int i = 0; i <= 1; ++i)
{
if (this.getPaddleState(i))
{
if (!this.isSilent() && (double)(this.paddlePositions[i] % ((float)Math.PI * 2F)) <= (double)((float)Math.PI / 4F) && ((double)this.paddlePositions[i] + (double)((float)Math.PI / 8F)) % (double)((float)Math.PI * 2F) >= (double)((float)Math.PI / 4F))
{
SoundEvent soundEvent = this.getPaddleSound();
if (soundEvent != null)
{
Vec3d vec3d = this.getLook(1.0F);
double d0 = i == 1 ? -vec3d.z : vec3d.z;
double d1 = i == 1 ? vec3d.x : vec3d.x;
this.world.playSound((PlayerEntity)null, this.getPosX() + d0, this.getPosY(), this.getPosZ() + d1, soundEvent, this.getSoundCategory(), 1.0F, 0.8F + 0.4F * this.rand.nextFloat());
}
}
this.paddlePositions[i] = (float)((double)this.paddlePositions[i] + (double)((float)Math.PI / 8F));
}
else
{
this.paddlePositions[i] = 0.0F;
}
}
this.doBlockCollisions();
List<Entity> list = this.world.getEntitiesInAABBexcluding(this, this.getBoundingBox().grow((double)0.2F, (double)-0.01F, (double)0.2F), EntityPredicates.pushableBy(this));
if (!list.isEmpty())
{
boolean flag = !this.world.isRemote && !(this.getControllingPassenger() instanceof PlayerEntity);
for(int j = 0;j < list.size(); ++j)
{
Entity entity = list.get(j);
if (!entity.isPassenger(this))
{
if (flag && this.getPassengers().size() < 2 && !entity.isPassenger() && entity.getWidth() < this.getWidth() && entity instanceof LivingEntity && !(entity instanceof WaterMobEntity) && !(entity instanceof PlayerEntity))
{
entity.startRiding(this);
}
else
{
this.applyEntityCollision(entity);
}
}
}
}
}
private void updateRocking()
{
if (this.world.isRemote)
{
int i = this.getRockingTicks();
if (i > 0)
{
this.rockingIntensity += 0.05F;
}
else
{
this.rockingIntensity -= 0.1F;
}
this.rockingIntensity = MathHelper.clamp(this.rockingIntensity, 0.0F, 1.0F);
this.prevRockingAngle = this.rockingAngle;
this.rockingAngle = 10.0F * (float)Math.sin((double)(0.5F * (float)this.world.getGameTime())) * this.rockingIntensity;
}
else
{
if (!this.rocking)
{
this.setRockingTicks(0);
}
int k = this.getRockingTicks();
if (k > 0)
{
--k;
this.setRockingTicks(k);
int j = 60 - k - 1;
if (j > 0 && k == 0)
{
this.setRockingTicks(0);
Vec3d vec3d = this.getMotion();
if (this.field_203060_aN) {
this.setMotion(vec3d.add(0.0D, -0.7D, 0.0D));
this.removePassengers();
}
else
{
this.setMotion(vec3d.x, this.isPassenger(PlayerEntity.class) ? 2.7D : 0.6D, vec3d.z);
}
}
this.rocking = false;
}
}
}
@Nullable
@Override
protected SoundEvent getPaddleSound() {
switch(this.getBoatStatus())
{
case IN_WATER:
case UNDER_WATER:
case UNDER_FLOWING_WATER:
return SoundEvents.ENTITY_BOAT_PADDLE_WATER;
case ON_LAND:
return SoundEvents.ENTITY_BOAT_PADDLE_LAND;
case IN_AIR:
default:
return null;
}
}
private void tickLerp()
{
if (this.canPassengerSteer())
{
this.lerpSteps = 0;
this.setPacketCoordinates(this.getPosX(), this.getPosY(), this.getPosZ());
}
if (this.lerpSteps > 0)
{
double d0 = this.getPosX() + (this.lerpX - this.getPosX()) / (double)this.lerpSteps;
double d1 = this.getPosY() + (this.lerpY - this.getPosY()) / (double)this.lerpSteps;
double d2 = this.getPosZ() + (this.lerpZ - this.getPosZ()) / (double)this.lerpSteps;
double d3 = MathHelper.wrapDegrees(this.lerpYaw - (double)this.rotationYaw);
this.rotationYaw = (float)((double)this.rotationYaw + d3 / (double)this.rotationYaw);
this.rotationPitch = (float)((double)this.rotationPitch + (this.lerpPitch - (double)this.rotationPitch) / (double)this.lerpSteps);
--this.lerpSteps;
this.setPosition(d0, d1, d2);
this.setRotation(this.rotationYaw, this.rotationPitch);
}
}
@Override
public void setPaddleState(boolean left, boolean right) {
this.dataManager.set(field_1, left);
this.dataManager.set(field_2, right);
}
@OnlyIn(Dist.CLIENT)
@Override
public float getRowingTime(int side, float limbSwing) {
return this.getPaddleState(side) ? (float)MathHelper.clampedLerp((double)this.paddlePositions[side] - (double)((float)Math.PI / 8F), (double)this.paddlePositions[side], (double)limbSwing) : 0.0F;
}
private DLBoatEntity.Status getBoatStatus()
{
DLBoatEntity.Status dlboatentity$status = this.getUnderwaterStatus();
if (dlboatentity$status != null)
{
this.waterLevel = this.getBoundingBox().maxY;
return dlboatentity$status;
}
else if (this.checkInWater())
{
return DLBoatEntity.Status.IN_WATER;
}
else
{
float f = this.getBoatGlide();
if (f > 0.0F)
{
this.boatGlide = f;
return DLBoatEntity.Status.ON_LAND;
}
else
{
return DLBoatEntity.Status.IN_AIR;
}
}
}
@Override
public float getWaterLevelAbove() {
AxisAlignedBB axisalignedbb = this.getBoundingBox();
int i = MathHelper.floor(axisalignedbb.minX);
int j = MathHelper.ceil(axisalignedbb.maxX);
int k = MathHelper.floor(axisalignedbb.maxY);
int l = MathHelper.ceil(axisalignedbb.maxY - this.lastYd);
int i1 = MathHelper.floor(axisalignedbb.minZ);
int j1 = MathHelper.ceil(axisalignedbb.maxZ);
try (BlockPos.PooledMutable blockpos$pooledmutable = BlockPos.PooledMutable.retain()) {
label161:
for(int k1 = k; k1 < l; ++k1) {
float f = 0.0F;
for(int l1 = i; l1 < j; ++l1) {
for(int i2 = i1; i2 < j1; ++i2) {
blockpos$pooledmutable.setPos(l1, k1, i2);
IFluidState ifluidstate = this.world.getFluidState(blockpos$pooledmutable);
if (ifluidstate.isTagged(FluidTags.WATER)) {
f = Math.max(f, ifluidstate.getActualHeight(this.world, blockpos$pooledmutable));
}
if (f >= 1.0F) {
continue label161;
}
}
}
if (f < 1.0F) {
float f2 = (float)blockpos$pooledmutable.getY() + f;
return f2;
}
}
float f1 = (float)(l + 1);
return f1;
}
}
@Override
public float getBoatGlide() {
AxisAlignedBB axisalignedbb = this.getBoundingBox();
AxisAlignedBB axisalignedbb1 = new AxisAlignedBB(axisalignedbb.minX, axisalignedbb.minY - 0.001D, axisalignedbb.minZ, axisalignedbb.maxX, axisalignedbb.minY, axisalignedbb.maxZ);
int i = MathHelper.floor(axisalignedbb1.minX) - 1;
int j = MathHelper.ceil(axisalignedbb1.maxX) + 1;
int k = MathHelper.floor(axisalignedbb1.minY) - 1;
int l = MathHelper.ceil(axisalignedbb1.maxY) + 1;
int i1 = MathHelper.floor(axisalignedbb1.minZ) - 1;
int j1 = MathHelper.ceil(axisalignedbb1.maxZ) + 1;
VoxelShape voxelshape = VoxelShapes.create(axisalignedbb1);
float f = 0.0F;
int k1 = 0;
try (BlockPos.PooledMutable blockpos$pooledmutable = BlockPos.PooledMutable.retain()) {
for(int l1 = i; l1 < j; ++l1) {
for(int i2 = i1; i2 < j1; ++i2) {
int j2 = (l1 != i && l1 != j - 1 ? 0 : 1) + (i2 != i1 && i2 != j1 - 1 ? 0 : 1);
if (j2 != 2) {
for(int k2 = k; k2 < l; ++k2) {
if (j2 <= 0 || k2 != k && k2 != l - 1) {
blockpos$pooledmutable.setPos(l1, k2, i2);
BlockState blockstate = this.world.getBlockState(blockpos$pooledmutable);
if (!(blockstate.getBlock() instanceof LilyPadBlock) && VoxelShapes.compare(blockstate.getCollisionShape(this.world, blockpos$pooledmutable).withOffset((double)l1, (double)k2, (double)i2), voxelshape, IBooleanFunction.AND)) {
f += blockstate.getSlipperiness(this.world, blockpos$pooledmutable, this);
++k1;
}
}
}
}
}
}
}
return f / (float)k1;
}
private boolean checkInWater()
{
AxisAlignedBB axisalignedbb = this.getBoundingBox();
int i = MathHelper.floor(axisalignedbb.minX);
int j = MathHelper.ceil(axisalignedbb.maxX);
int k = MathHelper.floor(axisalignedbb.minY);
int l = MathHelper.ceil(axisalignedbb.minY + 0.001D);
int i1 = MathHelper.floor(axisalignedbb.minZ);
int j1 = MathHelper.ceil(axisalignedbb.maxZ);
boolean flag = false;
this.waterLevel = Double.MIN_VALUE;
try (BlockPos.PooledMutable blockpos$pooledmutable = BlockPos.PooledMutable.retain()) {
for(int k1 = i; k1 < j; ++k1) {
for(int l1 = k; l1 < l; ++l1) {
for(int i2 = i1; i2 < j1; ++i2) {
blockpos$pooledmutable.setPos(k1, l1, i2);
IFluidState ifluidstate = this.world.getFluidState(blockpos$pooledmutable);
if (ifluidstate.isTagged(FluidTags.WATER)) {
float f = (float)l1 + ifluidstate.getActualHeight(this.world, blockpos$pooledmutable);
this.waterLevel = Math.max((double)f, this.waterLevel);
flag |= axisalignedbb.minY < (double)f;
}
}
}
}
}
return flag;
}
@Nullable
private DLBoatEntity.Status getUnderwaterStatus()
{
AxisAlignedBB axisalignedbb = this.getBoundingBox();
double d0 = axisalignedbb.maxY + 0.001D;
int i = MathHelper.floor(axisalignedbb.minX);
int j = MathHelper.ceil(axisalignedbb.maxX);
int k = MathHelper.floor(axisalignedbb.maxY);
int l = MathHelper.ceil(d0);
int i1 = MathHelper.floor(axisalignedbb.minZ);
int j1 = MathHelper.ceil(axisalignedbb.maxZ);
boolean flag = false;
try (BlockPos.PooledMutable blockpos$pooledmutable = BlockPos.PooledMutable.retain()) {
for(int k1 = i; k1 < j; ++k1) {
for(int l1 = k; l1 < l; ++l1) {
for(int i2 = i1; i2 < j1; ++i2) {
blockpos$pooledmutable.setPos(k1, l1, i2);
IFluidState ifluidstate = this.world.getFluidState(blockpos$pooledmutable);
if (ifluidstate.isTagged(FluidTags.WATER) && d0 < (double)((float)blockpos$pooledmutable.getY() + ifluidstate.getActualHeight(this.world, blockpos$pooledmutable))) {
if (!ifluidstate.isSource()) {
DLBoatEntity.Status dlboatentity$status = DLBoatEntity.Status.UNDER_FLOWING_WATER;
return dlboatentity$status;
}
flag = true;
}
}
}
}
}
return flag ? DLBoatEntity.Status.UNDER_WATER : null;
}
private void updateMotion()
{
double d0 = (double)-0.04F;
double d1 = this.hasNoGravity() ? 0.0D : (double)-0.04F;
double d2 = 0.0D;
this.momentum = 0.05F;
if (this.previousStatus == DLBoatEntity.Status.IN_AIR && this.status != DLBoatEntity.Status.IN_AIR && this.status != DLBoatEntity.Status.ON_LAND) {
this.waterLevel = this.getPosYHeight(1.0D);
this.setPosition(this.getPosX(), (double)(this.getWaterLevelAbove() - this.getHeight()) + 0.101D, this.getPosZ());
this.setMotion(this.getMotion().mul(1.0D, 0.0D, 1.0D));
this.lastYd = 0.0D;
this.status = DLBoatEntity.Status.IN_WATER;
} else {
if (this.status == DLBoatEntity.Status.IN_WATER) {
d2 = (this.waterLevel - this.getPosY()) / (double) this.getHeight();
this.momentum = 0.9F;
} else if (this.status == DLBoatEntity.Status.UNDER_FLOWING_WATER) {
d1 = -7.0E-4D;
this.momentum = 0.9F;
} else if (this.status == DLBoatEntity.Status.UNDER_WATER) {
d2 = (double) 0.01F;
this.momentum = 0.45F;
} else if (this.status == DLBoatEntity.Status.IN_AIR) {
this.momentum = 0.9F;
} else if (this.status == DLBoatEntity.Status.ON_LAND) {
this.momentum = this.boatGlide;
if (this.getControllingPassenger() instanceof PlayerEntity) {
this.boatGlide /= 2.0F;
}
}
Vec3d vec3d = this.getMotion();
this.setMotion(vec3d.x * (double) this.momentum, vec3d.y + d1, vec3d.z * (double) this.momentum);
this.deltaRotation *= this.momentum;
if (d2 > 0.0D) {
Vec3d vec3d1 = this.getMotion();
this.setMotion(vec3d1.x, (vec3d1.y + d2 * 0.06153846016296973D) * 0.75D, vec3d1.z);
}
}
}
private void controlBoat()
{
if (this.isBeingRidden()) {
float f = 0.0F;
if (this.leftInputDown) {
--this.deltaRotation;
}
if (this.rightInputDown) {
++this.deltaRotation;
}
if (this.rightInputDown != this.leftInputDown && !this.forwardInputDown && !this.backInputDown) {
f += 0.005F;
}
this.rotationYaw += this.deltaRotation;
if (this.forwardInputDown) {
f += 0.04F;
}
if (this.backInputDown) {
f -= 0.005F;
}
this.setMotion(this.getMotion().add((double)(MathHelper.sin(-this.rotationYaw * ((float)Math.PI / 180F)) * f), 0.0D, (double)(MathHelper.cos(this.rotationYaw * ((float)Math.PI / 180F)) * f)));
this.setPaddleState(this.rightInputDown && !this.leftInputDown || this.forwardInputDown, this.leftInputDown && !this.rightInputDown || this.forwardInputDown);
}
}
@Override
public void updatePassenger(Entity passenger) {
if (this.isPassenger(passenger)) {
float f = 0.0F;
float f1 = (float)((this.removed ? (double)0.01F : this.getMountedYOffset()) + passenger.getYOffset());
if (this.getPassengers().size() > 1) {
int i = this.getPassengers().indexOf(passenger);
if (i == 0) {
f = 0.2F;
} else {
f = -0.6F;
}
if (passenger instanceof AnimalEntity) {
f = (float)((double)f + 0.2D);
}
}
Vec3d vec3d = (new Vec3d((double)f, 0.0D, 0.0D)).rotateYaw(-this.rotationYaw * ((float)Math.PI / 180F) - ((float)Math.PI / 2F));
passenger.setPosition(this.getPosX() + vec3d.x, this.getPosY() + (double)f1, this.getPosZ() + vec3d.z);
passenger.rotationYaw += this.deltaRotation;
passenger.setRotationYawHead(passenger.getRotationYawHead() + this.deltaRotation);
this.applyYawToEntity(passenger);
if (passenger instanceof AnimalEntity && this.getPassengers().size() > 1) {
int j = passenger.getEntityId() % 2 == 0 ? 90 : 270;
passenger.setRenderYawOffset(((AnimalEntity)passenger).renderYawOffset + (float)j);
passenger.setRotationYawHead(passenger.getRotationYawHead() + (float)j);
}
}
}
protected void applyYawToEntity(Entity entityToUpdate) {
entityToUpdate.setRenderYawOffset(this.rotationYaw);
float f = MathHelper.wrapDegrees(entityToUpdate.rotationYaw - this.rotationYaw);
float f1 = MathHelper.clamp(f, -105.0F, 105.0F);
entityToUpdate.prevRotationYaw += f1 - f;
entityToUpdate.rotationYaw += f1 - f;
entityToUpdate.setRotationYawHead(entityToUpdate.rotationYaw);
}
@OnlyIn(Dist.CLIENT)
@Override
public void applyOrientationToEntity(Entity entityToUpdate) {
this.applyYawToEntity(entityToUpdate);
}
@Override
public boolean processInitialInteract(PlayerEntity player, Hand hand) {
if (player.isSecondaryUseActive()) {
return false;
} else {
return !this.world.isRemote && this.outOfControlTicks < 60.0F ? player.startRiding(this) : false;
}
}
protected void updateFallState(double y, boolean onGroundIn, BlockState state, BlockPos pos) {
this.lastYd = this.getMotion().y;
if (!this.isPassenger()) {
if (onGroundIn) {
if (this.fallDistance > 3.0F) {
if (this.status != DLBoatEntity.Status.ON_LAND) {
this.fallDistance = 0.0F;
return;
}
this.onLivingFall(this.fallDistance, 1.0F);
if (!this.world.isRemote && !this.removed) {
this.remove();
if (this.world.getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
for(int i = 0; i < 3; ++i) {
this.entityDropItem(BlockInit.DL_PLANKS.get());
}
for(int j = 0; j < 2; ++j) {
this.entityDropItem(Items.STICK);
}
}
}
}
this.fallDistance = 0.0F;
} else if (!this.world.getFluidState((new BlockPos(this)).down()).isTagged(FluidTags.WATER) && y < 0.0D) {
this.fallDistance = (float)((double)this.fallDistance - y);
}
}
}
@Override
public boolean getPaddleState(int side) {
return this.dataManager.<Boolean>get(side == 0 ? field_1 : field_2) && this.getControllingPassenger() != null;
}
@Override
public void setDamageTaken(float damageTaken) {
this.dataManager.set(DAMAGE_TAKEN, damageTaken);
}
@Override
public float getDamageTaken() {
return this.dataManager.get(DAMAGE_TAKEN);
}
@Override
public void setTimeSinceHit(int timeSinceHit) {
this.dataManager.set(TIME_SINCE_HIT, timeSinceHit);
}
@Override
public int getTimeSinceHit() {
return this.dataManager.get(TIME_SINCE_HIT);
}
private void setRockingTicks(int p_203055_1_)
{
this.dataManager.set(ROCKING_TICKS, p_203055_1_);
}
private int getRockingTicks()
{
return this.dataManager.get(ROCKING_TICKS);
}
@OnlyIn(Dist.CLIENT)
@Override
public float getRockingAngle(float partialTicks) {
return MathHelper.lerp(partialTicks, this.prevRockingAngle, this.rockingAngle);
}
@Override
public void setForwardDirection(int forwardDirection) {
this.dataManager.set(FOWARD_DIRECTION, forwardDirection);
}
@Override
public int getForwardDirection() {
return this.dataManager.get(FOWARD_DIRECTION);
}
protected boolean canFitPassenger(Entity passenger) {
return this.getPassengers().size() < 2 && !this.areEyesInFluid(FluidTags.WATER);
}
@Nullable
@Override
public Entity getControllingPassenger() {
List<Entity> list = this.getPassengers();
return list.isEmpty() ? null : list.get(0);
}
@Override
public void updateInputs(boolean p_184442_1_, boolean p_184442_2_, boolean p_184442_3_, boolean p_184442_4_) {
this.leftInputDown = p_184442_1_;
this.rightInputDown = p_184442_2_;
this.forwardInputDown = p_184442_3_;
this.backInputDown = p_184442_4_;
}
@Override
public IPacket<?> createSpawnPacket() {
return new SSpawnObjectPacket(this);
}
@Override
protected void addPassenger(Entity passenger) {
super.addPassenger(passenger);
if (this.canPassengerSteer() && this.lerpSteps > 0) {
this.lerpSteps = 0;
this.setPositionAndRotation(this.lerpX, this.lerpY, this.lerpZ, (float)this.lerpYaw, (float)this.lerpPitch);
}
}
public static enum Status
{
IN_WATER,
UNDER_WATER,
UNDER_FLOWING_WATER,
ON_LAND,
IN_AIR;
}
}
Boat model class:
package com.handreans.dancinglizards.client.entity.model;
import com.google.common.collect.ImmutableList;
import com.handreans.dancinglizards.entities.DLBoatEntity;
import net.minecraft.client.renderer.entity.model.SegmentedModel;
import net.minecraft.client.renderer.model.ModelRenderer;
import net.minecraft.entity.item.BoatEntity;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import java.util.Arrays;
@OnlyIn(Dist.CLIENT)
public class DLBoatModel extends SegmentedModel<DLBoatEntity>
{
private final ModelRenderer[] paddles = new ModelRenderer[2];
private final ModelRenderer noWater;
private final ImmutableList<ModelRenderer> field_228243_f_;
public DLBoatModel()
{
ModelRenderer[] amodelrenderer = new ModelRenderer[]{(new ModelRenderer(this, 0, 0)).setTextureSize(1024, 512)};
int i = 32;
int j = 6;
int k = 20;
int l = 4;
int i1 = 28;
amodelrenderer[0].addBox(-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F, 0.0F);
amodelrenderer[0].setRotationPoint(0.0F, 3.0F, 1.0F);
amodelrenderer[1].addBox(-13.0F, -7.0F, -1.0F, 18.0F, 6.0F, 2.0F, 0.0F);
amodelrenderer[1].setRotationPoint(-15.0F, 4.0F, 4.0F);
amodelrenderer[2].addBox(-8.0F, -7.0F, -1.0F, 16.0F, 6.0F, 2.0F, 0.0F);
amodelrenderer[2].setRotationPoint(15.0F, 4.0F, 0.0F);
amodelrenderer[3].addBox(-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F, 0.0F);
amodelrenderer[3].setRotationPoint(0.0F, 4.0F, -9.0F);
amodelrenderer[4].addBox(-14.0F, -7.0F, -1.0F, 28.0F, 6.0F, 2.0F, 0.0F);
amodelrenderer[4].setRotationPoint(0.0F, 4.0F, 9.0F);
amodelrenderer[0].rotateAngleX = ((float)Math.PI / 2F);
amodelrenderer[1].rotateAngleY = ((float)Math.PI * 1.5F);
amodelrenderer[2].rotateAngleY = ((float)Math.PI / 2F);
amodelrenderer[3].rotateAngleY = (float)Math.PI;
this.paddles[0] = this.makePaddle(true);
this.paddles[0].setRotationPoint(3.0F, -5.0F, 9.0F);
this.paddles[1] = this.makePaddle(false);
this.paddles[1].setRotationPoint(3.0F, -5.0F, -9.0F);
this.paddles[1].rotateAngleY = (float)Math.PI;
this.paddles[0].rotateAngleZ = 0.19634955F;
this.paddles[1].rotateAngleZ = 0.19634955F;
this.noWater = (new ModelRenderer(this, 0, 0)).setTextureSize(1024, 512);
this.noWater.addBox(-14.0F, -9.0F, -3.0F, 28.0F, 16.0F, 3.0F, 0.0F);
this.noWater.setRotationPoint(0.0F, -3.0F, 1.0F);
this.noWater.rotateAngleX = ((float)Math.PI / 2F);
ImmutableList.Builder<ModelRenderer> builder = ImmutableList.builder();
builder.addAll(Arrays.asList(amodelrenderer));
builder.addAll(Arrays.asList(this.paddles));
this.field_228243_f_ = builder.build();
}
@Override
public ImmutableList<ModelRenderer> getParts() {
return this.field_228243_f_;
}
public ModelRenderer func_228245_c_() {
return this.noWater;
}
protected ModelRenderer makePaddle(boolean p_187056_1_) {
ModelRenderer modelrenderer = (new ModelRenderer(this, 62, p_187056_1_ ? 0 : 20)).setTextureSize(1024, 512);
int i = 20;
int j = 7;
int k = 6;
float f = -5.0F;
modelrenderer.addBox(-1.0F, 0.0F, -5.0F, 2.0F, 2.0F, 18.0F);
modelrenderer.addBox(p_187056_1_ ? -1.001F : 0.001F, -3.0F, 8.0F, 1.0F, 6.0F, 7.0F);
return modelrenderer;
}
@Override
public void setRotationAngles(DLBoatEntity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch)
{
this.func_228244_a_(entityIn, 0, limbSwing);
this.func_228244_a_(entityIn, 1, limbSwing);
}
protected void func_228244_a_(BoatEntity p_228244_1_, int p_228244_2_, float p_228244_3_) {
float f = p_228244_1_.getRowingTime(p_228244_2_, p_228244_3_);
ModelRenderer modelrenderer = this.paddles[p_228244_2_];
modelrenderer.rotateAngleX = (float) MathHelper.clampedLerp((double)(-(float)Math.PI / 3F), (double)-0.2617994F, (double)((MathHelper.sin(-f) + 1.0F) / 2.0F));
modelrenderer.rotateAngleY = (float)MathHelper.clampedLerp((double)(-(float)Math.PI / 4F), (double)((float)Math.PI / 4F), (double)((MathHelper.sin(-f + 1.0F) + 1.0F) / 2.0F));
if (p_228244_2_ == 1) {
modelrenderer.rotateAngleY = (float)Math.PI - modelrenderer.rotateAngleY;
}
}
}
Boat renderer class:
package com.handreans.dancinglizards.client.entity.render;
import com.handreans.dancinglizards.DancingLizards;
import com.handreans.dancinglizards.client.entity.model.DLBoatModel;
import com.handreans.dancinglizards.entities.DLBoatEntity;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.Quaternion;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.Vector3f;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererManager;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.MathHelper;
public class DLBoatRender extends EntityRenderer<DLBoatEntity>
{
protected static final ResourceLocation TEXTURE = new ResourceLocation(DancingLizards.MOD_ID, "textures/entity/dl_boat.png");
protected final DLBoatModel modelBoat = new DLBoatModel();
public DLBoatRender(EntityRendererManager renderManagerIn) {
super(renderManagerIn);
this.shadowSize = 0.8F;
}
@Override
public void render(DLBoatEntity entityIn, float entityYaw, float partialTicks, MatrixStack matrixStackIn, IRenderTypeBuffer bufferIn, int packedLightIn) {
matrixStackIn.push();
matrixStackIn.translate(0.0D, 0.375D, 0.0D);
matrixStackIn.rotate(Vector3f.YP.rotationDegrees(180.0F - entityYaw));
float f = (float)entityIn.getTimeSinceHit() - partialTicks;
float f1 = entityIn.getDamageTaken() - partialTicks;
if (f1 < 0.0F) {
f1 = 0.0F;
}
if (f > 0.0F) {
matrixStackIn.rotate(Vector3f.XP.rotationDegrees(MathHelper.sin(f) * f * f1 / 10.0F * (float)entityIn.getForwardDirection()));
}
float f2 = entityIn.getRockingAngle(partialTicks);
if (!MathHelper.epsilonEquals(f2, 0.0F)) {
matrixStackIn.rotate(new Quaternion(new Vector3f(1.0F, 0.0F, 1.0F), entityIn.getRockingAngle(partialTicks), true));
}
matrixStackIn.scale(-1.0F, -1.0F, 1.0F);
matrixStackIn.rotate(Vector3f.YP.rotationDegrees(90.0F));
this.modelBoat.setRotationAngles(entityIn, partialTicks, 0.0F, -0.1F, 0.0F, 0.0F);
IVertexBuilder ivertexbuilder = bufferIn.getBuffer(this.modelBoat.getRenderType(this.getEntityTexture(entityIn)));
this.modelBoat.render(matrixStackIn, ivertexbuilder, packedLightIn, OverlayTexture.NO_OVERLAY, 1.0F, 1.0F, 1.0F, 1.0F);
IVertexBuilder ivertexbuilder1 = bufferIn.getBuffer(RenderType.getWaterMask());
this.modelBoat.func_228245_c_().render(matrixStackIn, ivertexbuilder1, packedLightIn, OverlayTexture.NO_OVERLAY);
matrixStackIn.pop();
super.render(entityIn, entityYaw, partialTicks, matrixStackIn, bufferIn, packedLightIn);
}
@Override
public ResourceLocation getEntityTexture(DLBoatEntity entity) {
return TEXTURE;
}
}