Minecraft 1.12.2模组开发(四十五) 水火两用船
生活随笔
收集整理的這篇文章主要介紹了
Minecraft 1.12.2模组开发(四十五) 水火两用船
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
今天我們在MC中實現一艘可以在水中和巖漿中滑行的船
本期教程之前可以先復習一下生物實體教程,會比較好理解一些。
1.船是一種生物實體,所以我們首先要制作船的模型,這里直接使用了原版的船模型,當然你也可以用Blockbench制作模型。
ModelObBoat.java
package com.joy187.rejoymod.entity.model;import com.joy187.rejoymod.entity.EntityObBoat; import net.minecraft.client.model.IMultipassModel; import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelRenderer; import net.minecraft.client.renderer.GLAllocation; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.Entity; import net.minecraft.util.math.MathHelper;public class ModelObBoat extends ModelBase implements IMultipassModel {public ModelRenderer[] boatSides = new ModelRenderer[5];public ModelRenderer[] paddles = new ModelRenderer[2];public ModelRenderer noWater;private final int patchList = GLAllocation.generateDisplayLists(1);public ModelObBoat(){this.boatSides[0] = (new ModelRenderer(this, 0, 0)).setTextureSize(128, 64);this.boatSides[1] = (new ModelRenderer(this, 0, 19)).setTextureSize(128, 64);this.boatSides[2] = (new ModelRenderer(this, 0, 27)).setTextureSize(128, 64);this.boatSides[3] = (new ModelRenderer(this, 0, 35)).setTextureSize(128, 64);this.boatSides[4] = (new ModelRenderer(this, 0, 43)).setTextureSize(128, 64);int i = 32;int j = 6;int k = 20;int l = 4;int i1 = 28;this.boatSides[0].addBox(-14.0F, -9.0F, -3.0F, 28, 16, 3, 0.0F);this.boatSides[0].setRotationPoint(0.0F, 3.0F, 1.0F);this.boatSides[1].addBox(-13.0F, -7.0F, -1.0F, 18, 6, 2, 0.0F);this.boatSides[1].setRotationPoint(-15.0F, 4.0F, 4.0F);this.boatSides[2].addBox(-8.0F, -7.0F, -1.0F, 16, 6, 2, 0.0F);this.boatSides[2].setRotationPoint(15.0F, 4.0F, 0.0F);this.boatSides[3].addBox(-14.0F, -7.0F, -1.0F, 28, 6, 2, 0.0F);this.boatSides[3].setRotationPoint(0.0F, 4.0F, -9.0F);this.boatSides[4].addBox(-14.0F, -7.0F, -1.0F, 28, 6, 2, 0.0F);this.boatSides[4].setRotationPoint(0.0F, 4.0F, 9.0F);this.boatSides[0].rotateAngleX = ((float)Math.PI / 2F);this.boatSides[1].rotateAngleY = ((float)Math.PI * 3F / 2F);this.boatSides[2].rotateAngleY = ((float)Math.PI / 2F);this.boatSides[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(128, 64);this.noWater.addBox(-14.0F, -9.0F, -3.0F, 28, 16, 3, 0.0F);this.noWater.setRotationPoint(0.0F, -3.0F, 1.0F);this.noWater.rotateAngleX = ((float)Math.PI / 2F);}/*** Sets the models various rotation angles then renders the model.*/public void render(Entity entityIn, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch, float scale){GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F);EntityObBoat entityboat = (EntityObBoat)entityIn;this.setRotationAngles(limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch, scale, entityIn);for (int i = 0; i < 5; ++i){this.boatSides[i].render(scale);}this.renderPaddle(entityboat, 0, scale, limbSwing);this.renderPaddle(entityboat, 1, scale, limbSwing);}public void renderMultipass(Entity p_187054_1_, float p_187054_2_, float p_187054_3_, float p_187054_4_, float p_187054_5_, float p_187054_6_, float scale){GlStateManager.rotate(90.0F, 0.0F, 1.0F, 0.0F);GlStateManager.colorMask(false, false, false, false);this.noWater.render(scale);GlStateManager.colorMask(true, true, true, true);}protected ModelRenderer makePaddle(boolean p_187056_1_){ModelRenderer modelrenderer = (new ModelRenderer(this, 62, p_187056_1_ ? 0 : 20)).setTextureSize(128, 64);int i = 20;int j = 7;int k = 6;float f = -5.0F;modelrenderer.addBox(-1.0F, 0.0F, -5.0F, 2, 2, 18);modelrenderer.addBox(p_187056_1_ ? -1.001F : 0.001F, -3.0F, 8.0F, 1, 6, 7);return modelrenderer;}protected void renderPaddle(EntityObBoat boat, int paddle, float scale, float limbSwing){float f = boat.getRowingTime(paddle, limbSwing);ModelRenderer modelrenderer = this.paddles[paddle];modelrenderer.rotateAngleX = (float) MathHelper.clampedLerp(-1.0471975803375244D, -0.2617993950843811D, (double)((MathHelper.sin(-f) + 1.0F) / 2.0F));modelrenderer.rotateAngleY = (float)MathHelper.clampedLerp(-(Math.PI / 4D), (Math.PI / 4D), (double)((MathHelper.sin(-f + 1.0F) + 1.0F) / 2.0F));if (paddle == 1){modelrenderer.rotateAngleY = (float)Math.PI - modelrenderer.rotateAngleY;}modelrenderer.render(scale);} }2.我們要讓船在巖漿和水上行走,所以我們的EntityObBoat類要繼承船實體類,同時讓船對巖漿產生免疫:
EntityObBoat.java
package com.joy187.rejoymod.entity;import com.joy187.rejoymod.item.ModItems; import net.minecraft.block.BlockLiquid; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.MoverType; import net.minecraft.entity.item.EntityBoat; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityWaterMob; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.MobEffects; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.network.play.client.CPacketSteerBoat; import net.minecraft.potion.PotionEffect; import net.minecraft.util.*; import net.minecraft.util.math.*; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly;import java.util.ArrayList; import java.util.List;public class EntityObBoat extends EntityBoat {private static final DataParameter<Integer> TIME_SINCE_HIT = EntityDataManager.createKey(EntityObBoat.class, DataSerializers.VARINT);private static final DataParameter<Integer> FORWARD_DIRECTION = EntityDataManager.createKey(EntityObBoat.class, DataSerializers.VARINT);private static final DataParameter<Float> DAMAGE_TAKEN = EntityDataManager.createKey(EntityObBoat.class, DataSerializers.FLOAT);private static final DataParameter<Boolean>[] DATA_ID_PADDLE = new DataParameter[]{EntityDataManager.createKey(EntityObBoat.class, DataSerializers.BOOLEAN), EntityDataManager.createKey(EntityObBoat.class, DataSerializers.BOOLEAN)};private final float[] paddlePositions;private float outOfControlCounter;private float deltaRotation;private int lerpSteps;private double boatPitch;private double lerpY;private double lerpZ;private double boatYaw;private double lerpXRot;private boolean leftInputDown;private boolean rightInputDown;private boolean forwardInputDown;private boolean backInputDown;private double lavaLevel;private float boatGlide;private Status status;private Status previousStatus;private double lastYd;public EntityObBoat(World world){super(world);//我們的船對巖漿、火免疫,不然會燒掉this.isImmuneToFire = true;this.paddlePositions = new float[2];this.preventEntitySpawning = true;this.setSize(1.375F, 0.5625F);}public EntityObBoat(World world, double x, double y, double z){this(world);this.motionX = 0.0D;this.motionY = 0.0D;this.motionZ = 0.0D;this.prevPosX = x;this.prevPosY = y;this.prevPosZ = z;this.setPosition(x, y, z);}@Overrideprotected boolean canTriggerWalking(){return false;}@Overrideprotected void entityInit(){this.dataManager.register(TIME_SINCE_HIT, 0);this.dataManager.register(FORWARD_DIRECTION, 1);this.dataManager.register(DAMAGE_TAKEN, 0.0F);for(DataParameter<Boolean> parameter : DATA_ID_PADDLE){this.dataManager.register(parameter, false);}}@Overridepublic AxisAlignedBB getCollisionBox(Entity entity){return entity.canBePushed() ? entity.getEntityBoundingBox() : null;}@Overridepublic AxisAlignedBB getCollisionBoundingBox(){return this.getEntityBoundingBox();}@Overridepublic boolean canBePushed(){return true;}@Overridepublic double getMountedYOffset(){return -0.1D;}@Overridepublic boolean attackEntityFrom(DamageSource source, float amount){if(this.isEntityInvulnerable(source)){return false;}else if(!this.world.isRemote && !this.isDead){if(source instanceof EntityDamageSourceIndirect && 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 takeDamage = source.getTrueSource() instanceof EntityPlayer && ((EntityPlayer) source.getTrueSource()).capabilities.isCreativeMode;if(takeDamage || this.getDamageTaken() > 40.0F){ //判斷我們如果將船打破后會掉落什么物品if(!takeDamage && this.world.getGameRules().getBoolean("doEntityDrops")){this.dropItemWithOffset(ModItems.OBBOAT, 1, 0.0F);}this.setDead();}return true;}}else{return true;}}@Overridepublic void applyEntityCollision(Entity entity){if(entity instanceof EntityObBoat){if(entity.getEntityBoundingBox().minY < this.getEntityBoundingBox().maxY){super.applyEntityCollision(entity);}}else if(entity.getEntityBoundingBox().minY <= this.getEntityBoundingBox().minY){super.applyEntityCollision(entity);}}@Override@SideOnly(Side.CLIENT)public void performHurtAnimation(){this.setForwardDirection(-this.getForwardDirection());this.setTimeSinceHit(10);this.setDamageTaken(this.getDamageTaken() * 11.0F);}@Overridepublic boolean canBeCollidedWith(){return !this.isDead;}@Override@SideOnly(Side.CLIENT)public void setPositionAndRotationDirect(double x, double y, double z, float yaw, float pitch, int posRotationIncrements, boolean teleport){this.boatPitch = x;this.lerpY = y;this.lerpZ = z;this.boatYaw = yaw;this.lerpXRot = pitch;this.lerpSteps = 10;}@Overridepublic EnumFacing getAdjustedHorizontalFacing(){return this.getHorizontalFacing().rotateY();}@Overridepublic void onUpdate(){this.previousStatus = this.status;this.status = this.getBoatStatus();if(this.status != Status.UNDER_LAVA && this.status != Status.UNDER_FLOWING_LAVA){this.outOfControlCounter = 0.0F;}else{this.outOfControlCounter++;}if(!this.world.isRemote && this.outOfControlCounter >= 60.0F){this.removePassengers();}if(this.getTimeSinceHit() > 0){this.setTimeSinceHit(this.getTimeSinceHit() - 1);}if(this.getDamageTaken() > 0.0F){this.setDamageTaken(this.getDamageTaken() - 1.0F);}this.prevPosX = this.posX;this.prevPosY = this.posY;this.prevPosZ = this.posZ;if(!this.world.isRemote){this.setFlag(6, this.isGlowing());}this.onEntityUpdate();this.tickLerp();if(this.canPassengerSteer()){if(this.getPassengers().size() == 0 || !(this.getPassengers().get(0) instanceof EntityPlayer)){this.setPaddleState(false, false);}this.updateMotion();if(this.world.isRemote){this.controlBoat();this.world.sendPacketToServer(new CPacketSteerBoat(this.getPaddleState(0), this.getPaddleState(1)));}this.move(MoverType.SELF, this.motionX, this.motionY, this.motionZ);}else{this.motionX = 0.0D;this.motionY = 0.0D;this.motionZ = 0.0D;}for(int i = 0; i <= 1; i++){if(this.getPaddleState(i)){if(!this.isSilent() && (double) (this.paddlePositions[i] % ((float) Math.PI * 2F)) <= (Math.PI / 4D) && ((double) this.paddlePositions[i] + 0.39269909262657166D) % (Math.PI * 2D) >= (Math.PI / 4D)){SoundEvent event = this.getPaddleSound();if(event != null){Vec3d look = this.getLook(1.0F);double lookX = i == 1 ? -look.z : look.z;double lookZ = i == 1 ? look.x : -look.x;this.world.playSound(null, this.posX + lookX, this.posY, this.posZ + lookZ, event, this.getSoundCategory(), 1.0F, 0.8F + 0.4F * this.rand.nextFloat());}}this.paddlePositions[i] = (float) ((double) this.paddlePositions[i] + 0.39269909262657166D);}else{this.paddlePositions[i] = 0.0F;}}this.doBlockCollisions();List<Entity> entities = this.world.getEntitiesInAABBexcluding(this, this.getEntityBoundingBox().expand(0.20000000298023224D, -0.009999999776482582D, 0.20000000298023224D), EntitySelectors.getTeamCollisionPredicate(this));if(!entities.isEmpty()){boolean flag = !this.world.isRemote && !(this.getControllingPassenger() instanceof EntityPlayer);for(Entity entity : entities){if(!entity.isPassenger(this)){if(flag && this.getPassengers().size() < 2 && !entity.isRiding() && entity.width < this.width && entity instanceof EntityLivingBase && !(entity instanceof EntityWaterMob) && !(entity instanceof EntityPlayer)){entity.startRiding(this);}else{this.applyEntityCollision(entity);}}}}}//船被打破之后掉落的物品@Overridepublic ItemStack getPickedResult(RayTraceResult target){return new ItemStack(ModItems.OBBOAT, 1, 0);}private void tickLerp(){if(this.lerpSteps > 0 && !this.canPassengerSteer()){double posX = this.posX + (this.boatPitch - this.posX) / (double) this.lerpSteps;double posY = this.posY + (this.lerpY - this.posY) / (double) this.lerpSteps;double posZ = this.posZ + (this.lerpZ - this.posZ) / (double) this.lerpSteps;double yaw = MathHelper.wrapDegrees(this.boatYaw - (double) this.rotationYaw);this.rotationYaw = (float) ((double) this.rotationYaw + yaw / (double) this.lerpSteps);this.rotationPitch = (float) ((double) this.rotationPitch + (this.lerpXRot - (double) this.rotationPitch) / (double) this.lerpSteps);this.lerpSteps--;this.setPosition(posX, posY, posZ);this.setRotation(this.rotationYaw, this.rotationPitch);}}@Overridepublic void setPaddleState(boolean leftPaddle, boolean rightPaddle){this.dataManager.set(DATA_ID_PADDLE[0], leftPaddle);this.dataManager.set(DATA_ID_PADDLE[1], rightPaddle);}@Override@SideOnly(Side.CLIENT)public float getRowingTime(int side, float limbSwing){return this.getPaddleState(side) ? (float) MathHelper.clampedLerp((double) this.paddlePositions[side] - 0.39269909262657166D, this.paddlePositions[side], limbSwing) : 0.0F;}private Status getBoatStatus(){Status status = this.getUnderLavaStatus();if(status != null){this.lavaLevel = this.getEntityBoundingBox().maxY;return status;}else if(this.checkInLava()){return Status.IN_LAVA;}else{float f = this.getBoatGlide();if(f > 0.0F){this.boatGlide = f;return Status.ON_LAND;}else{return Status.IN_AIR;}}}private float getLavaLevelAbove(){AxisAlignedBB boundingBox = this.getEntityBoundingBox();int minX = MathHelper.floor(boundingBox.minX);int maxX = MathHelper.ceil(boundingBox.maxX);int minY = MathHelper.floor(boundingBox.maxY);int maxY = MathHelper.ceil(boundingBox.maxY - this.lastYd);int minZ = MathHelper.floor(boundingBox.minZ);int maxZ = MathHelper.ceil(boundingBox.maxZ);BlockPos.PooledMutableBlockPos mutableBlockPos = BlockPos.PooledMutableBlockPos.retain();try{label78:for(int y = minY; y < maxY; y++){float liquidHeight = 0.0F;int x = minX;while(true){if(x >= maxX){if(liquidHeight < 1.0F){return (float) mutableBlockPos.getY() + liquidHeight;}break;}for(int z = minZ; z < maxZ; z++){mutableBlockPos.setPos(x, y, z);IBlockState state = this.world.getBlockState(mutableBlockPos);//判斷船是否在巖漿或者水上if(state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER){liquidHeight = Math.max(liquidHeight, BlockLiquid.getBlockLiquidHeight(state, this.world, mutableBlockPos));}if(liquidHeight >= 1.0F){continue label78;}}x++;}}return (float) (maxY + 1);}finally{mutableBlockPos.release();}}@Overridepublic float getBoatGlide(){AxisAlignedBB entityBoundingBox = this.getEntityBoundingBox();AxisAlignedBB boundingBox = new AxisAlignedBB(entityBoundingBox.minX, entityBoundingBox.minY - 0.001D, entityBoundingBox.minZ, entityBoundingBox.maxX, entityBoundingBox.minY, entityBoundingBox.maxZ);int minX = MathHelper.floor(boundingBox.minX) - 1;int maxX = MathHelper.ceil(boundingBox.maxX) + 1;int minY = MathHelper.floor(boundingBox.minY) - 1;int maxY = MathHelper.ceil(boundingBox.maxY) + 1;int minZ = MathHelper.floor(boundingBox.minZ) - 1;int maxZ = MathHelper.ceil(boundingBox.maxZ) + 1;List<AxisAlignedBB> list = new ArrayList<>();float slipperiness = 0.0F;int friction = 0;BlockPos.PooledMutableBlockPos mutableBlockPos = BlockPos.PooledMutableBlockPos.retain();try{for(int x = minX; x < maxX; x++){for(int z = minZ; z < maxZ; z++){int offset = (x != minX && x != maxX - 1 ? 0 : 1) + (z != minZ && z != maxZ - 1 ? 0 : 1);if(offset != 2){for(int y = minY; y < maxY; y++){if(offset <= 0 || y != minY && y != maxY - 1){mutableBlockPos.setPos(x, y, z);IBlockState state = this.world.getBlockState(mutableBlockPos);state.addCollisionBoxToList(this.world, mutableBlockPos, boundingBox, list, this, false);if(!list.isEmpty()){slipperiness += state.getBlock().getSlipperiness(state, this.world, mutableBlockPos, this);friction++;}list.clear();}}}}}}finally{mutableBlockPos.release();}return slipperiness / (float) friction;}private boolean checkInLava(){AxisAlignedBB entityBoundingBox = this.getEntityBoundingBox();int minX = MathHelper.floor(entityBoundingBox.minX);int maxX = MathHelper.ceil(entityBoundingBox.maxX);int minY = MathHelper.floor(entityBoundingBox.minY);int maxY = MathHelper.ceil(entityBoundingBox.minY + 0.001D);int minZ = MathHelper.floor(entityBoundingBox.minZ);int maxZ = MathHelper.ceil(entityBoundingBox.maxZ);boolean flag = false;this.lavaLevel = Double.MIN_VALUE;BlockPos.PooledMutableBlockPos mutableBlockPos = BlockPos.PooledMutableBlockPos.retain();try{for(int x = minX; x < maxX; x++){for(int y = minY; y < maxY; y++){for(int z = minZ; z < maxZ; z++){mutableBlockPos.setPos(x, y, z);IBlockState state = this.world.getBlockState(mutableBlockPos);//判斷巖漿是否在巖漿或水中滑行if(state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER){float liquidHeight = BlockLiquid.getLiquidHeight(state, this.world, mutableBlockPos);this.lavaLevel = Math.max(liquidHeight, this.lavaLevel);flag |= entityBoundingBox.minY < (double) liquidHeight;}}}}}finally{mutableBlockPos.release();}return flag;}private Status getUnderLavaStatus(){AxisAlignedBB entityBoundingBox = this.getEntityBoundingBox();double entityHeight = entityBoundingBox.maxY + 0.001D;int minX = MathHelper.floor(entityBoundingBox.minX);int maxX = MathHelper.ceil(entityBoundingBox.maxX);int minY = MathHelper.floor(entityBoundingBox.maxY);int maxY = MathHelper.ceil(entityHeight);int minZ = MathHelper.floor(entityBoundingBox.minZ);int maxZ = MathHelper.ceil(entityBoundingBox.maxZ);boolean flag = false;BlockPos.PooledMutableBlockPos mutableBlockPos = BlockPos.PooledMutableBlockPos.retain();try{for(int x = minX; x < maxX; x++){for(int y = minY; y < maxY; y++){for(int z = minZ; z < maxZ; z++){mutableBlockPos.setPos(x, y, z);IBlockState state = this.world.getBlockState(mutableBlockPos);if((state.getMaterial() == Material.LAVA || state.getMaterial() == Material.WATER) && entityHeight < (double) BlockLiquid.getLiquidHeight(state, this.world, mutableBlockPos)){if(state.getValue(BlockLiquid.LEVEL) != 0){return Status.UNDER_FLOWING_LAVA;}flag = true;}}}}}finally{mutableBlockPos.release();}return flag ? Status.UNDER_LAVA : null;}private void updateMotion(){double gravity = this.hasNoGravity() ? 0.0D : -0.03999999910593033D;double position = 0.0D;float momentum = 0.05F;if(this.previousStatus == Status.IN_AIR && this.status != Status.IN_AIR && this.status != Status.ON_LAND){this.lavaLevel = this.getEntityBoundingBox().minY + (double) this.height;this.setPosition(this.posX, (double) (this.getLavaLevelAbove() - this.height) + 0.101D, this.posZ);this.motionY = 0.0D;this.lastYd = 0.0D;this.status = Status.IN_LAVA;}else{if(this.status == Status.IN_LAVA){position = (this.lavaLevel - this.getEntityBoundingBox().minY) / (double) this.height;momentum = 0.9F;}else if(this.status == Status.UNDER_FLOWING_LAVA){gravity = -7.0E-4D;momentum = 0.9F;}else if(this.status == Status.UNDER_LAVA){position = 0.009999999776482582D;momentum = 0.45F;}else if(this.status == Status.IN_AIR){momentum = 0.9F;}else if(this.status == Status.ON_LAND){momentum = this.boatGlide;if(this.getControllingPassenger() instanceof EntityPlayer){this.boatGlide /= 2.0F;}}this.motionX *= momentum;this.motionZ *= momentum;this.deltaRotation *= momentum;this.motionY += gravity;if(position > 0.0D){this.motionY += position * 0.06153846016296973D;this.motionY *= 0.75D;}}}private void controlBoat(){if(this.isBeingRidden()){float speed = 0.0F;if(this.leftInputDown){this.deltaRotation += -1.0F;}if(this.rightInputDown){this.deltaRotation++;}if(this.rightInputDown != this.leftInputDown && !this.forwardInputDown && !this.backInputDown){speed += 0.005F;}this.rotationYaw += this.deltaRotation;if(this.forwardInputDown){speed += 0.04F;}if(this.backInputDown){speed -= 0.005F;}this.motionX += (MathHelper.sin(-this.rotationYaw * 0.017453292F) * speed);this.motionZ += (MathHelper.cos(this.rotationYaw * 0.017453292F) * speed);this.setPaddleState(this.rightInputDown && !this.leftInputDown || this.forwardInputDown, this.leftInputDown && !this.rightInputDown || this.forwardInputDown);}}@Overridepublic void updatePassenger(Entity passenger){//當玩家進入船中,防止其著火,就賦予其防火效果((EntityLivingBase)passenger).addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, 100));if(this.isPassenger(passenger)){float x = 0.0F;float height = (float) ((this.isDead ? 0.009999999776482582D : this.getMountedYOffset()) + passenger.getYOffset());if(this.getPassengers().size() > 1){int index = this.getPassengers().indexOf(passenger);if(index == 0){x = 0.2F;}else{x = -0.6F;}if(passenger instanceof EntityAnimal){x = (float) ((double) x + 0.2D);}}Vec3d pos = (new Vec3d(x, 0.0D, 0.0D)).rotateYaw(-this.rotationYaw * 0.017453292F - ((float) Math.PI / 2F));passenger.setPosition(this.posX + pos.x, this.posY + (double) height, this.posZ + pos.z);passenger.rotationYaw += this.deltaRotation;passenger.setRotationYawHead(passenger.getRotationYawHead() + this.deltaRotation);this.applyYawToEntity(passenger);if(passenger instanceof EntityAnimal && this.getPassengers().size() > 1){int rotation = passenger.getEntityId() % 2 == 0 ? 90 : 270;passenger.setRenderYawOffset(((EntityAnimal) passenger).renderYawOffset + (float) rotation);passenger.setRotationYawHead(passenger.getRotationYawHead() + (float) rotation);}if(this.isInsideOfMaterial(Material.WATER)){passenger.dismountRidingEntity();}}}@Overrideprotected void applyYawToEntity(Entity entityToUpdate){entityToUpdate.setRenderYawOffset(this.rotationYaw);float yaw = MathHelper.wrapDegrees(entityToUpdate.rotationYaw - this.rotationYaw);float clampedYaw = MathHelper.clamp(yaw, -105.0F, 105.0F);entityToUpdate.prevRotationYaw += clampedYaw - yaw;entityToUpdate.rotationYaw += clampedYaw - yaw;entityToUpdate.setRotationYawHead(entityToUpdate.rotationYaw);}@Override@SideOnly(Side.CLIENT)public void applyOrientationToEntity(Entity entityToUpdate){this.applyYawToEntity(entityToUpdate);}@Overrideprotected void writeEntityToNBT(NBTTagCompound compound){}@Overrideprotected void readEntityFromNBT(NBTTagCompound compound){}@Overridepublic boolean processInitialInteract(EntityPlayer player, EnumHand hand){if(player.isSneaking()){return false;}else{if(!this.world.isRemote && this.outOfControlCounter < 60.0F && !this.isInsideOfMaterial(Material.WATER)){player.startRiding(this);}return true;}}@Overrideprotected void updateFallState(double y, boolean onGround, IBlockState state, BlockPos pos){this.lastYd = this.motionY;if(!this.isRiding()){if(onGround){if(this.fallDistance > 3.0F){if(this.status != Status.ON_LAND){this.fallDistance = 0.0F;return;}this.fall(this.fallDistance, 1.0F);if(!this.world.isRemote && !this.isDead){this.setDead();if(this.world.getGameRules().getBoolean("doEntityDrops")){for(int i = 0; i < 3; i++){this.entityDropItem(new ItemStack(Blocks.OBSIDIAN, 1, 0), 0.0F);}}}}this.fallDistance = 0.0F;}else if(this.world.getBlockState((new BlockPos(this)).down()).getMaterial() != Material.LAVA && y < 0.0D ||this.world.getBlockState((new BlockPos(this)).down()).getMaterial() != Material.WATER && y < 0.0D){this.fallDistance = (float) ((double) this.fallDistance - y);}}}@Overridepublic boolean getPaddleState(int state){return this.dataManager.get(DATA_ID_PADDLE[state]) && this.getControllingPassenger() != null;}@Overridepublic void setDamageTaken(float damageTaken){this.dataManager.set(DAMAGE_TAKEN, damageTaken);}@Overridepublic float getDamageTaken(){return this.dataManager.get(DAMAGE_TAKEN);}@Overridepublic void setTimeSinceHit(int timeSinceHit){this.dataManager.set(TIME_SINCE_HIT, timeSinceHit);}@Overridepublic int getTimeSinceHit(){return this.dataManager.get(TIME_SINCE_HIT);}@Overridepublic void setForwardDirection(int forwardDirection){this.dataManager.set(FORWARD_DIRECTION, forwardDirection);}@Overridepublic int getForwardDirection(){return this.dataManager.get(FORWARD_DIRECTION);}@Overrideprotected boolean canFitPassenger(Entity passenger){return this.getPassengers().size() < 2;}@Overridepublic Entity getControllingPassenger(){List<Entity> passengers = this.getPassengers();return passengers.isEmpty() ? null : passengers.get(0);}@Override@SideOnly(Side.CLIENT)public void updateInputs(boolean left, boolean right, boolean forward, boolean back){this.leftInputDown = left;this.rightInputDown = right;this.forwardInputDown = forward;this.backInputDown = back;}//枚舉船的幾種狀態public enum Status{IN_LAVA,UNDER_LAVA,UNDER_FLOWING_LAVA,ON_LAND,IN_AIR} }3.新建船的渲染類RenderObBoat.java,這里直接使用原版的船渲染類。
RenderObBoat.java
package com.joy187.rejoymod.entity.render;import com.joy187.rejoymod.entity.EntityObBoat; import com.joy187.rejoymod.entity.model.ModelObBoat; import com.joy187.rejoymod.util.Reference; import net.minecraft.client.model.IMultipassModel; import net.minecraft.client.model.ModelBase; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.entity.Render; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper;public class RenderObBoat extends Render<EntityObBoat> {//這個要對應我們的船的皮膚貼圖文件路徑public static final ResourceLocation TEXTURES = new ResourceLocation(Reference.Mod_ID + ":textures/entity/obboat.png");protected ModelBase modelBoat = new ModelObBoat();public RenderObBoat(RenderManager renderManagerIn){super(renderManagerIn);this.shadowSize = 0.5F;this.modelBoat = new ModelObBoat();}public void doRender(EntityObBoat entity, double x, double y, double z, float entityYaw, float partialTicks){GlStateManager.pushMatrix();this.setupTranslation(x, y, z);this.setupRotation(entity, entityYaw, partialTicks);this.bindEntityTexture(entity);if (this.renderOutlines){GlStateManager.enableColorMaterial();GlStateManager.enableOutlineMode(this.getTeamColor(entity));}this.modelBoat.render(entity, partialTicks, 0.0F, -0.1F, 0.0F, 0.0F, 0.0625F);if (this.renderOutlines){GlStateManager.disableOutlineMode();GlStateManager.disableColorMaterial();}GlStateManager.popMatrix();super.doRender(entity, x, y, z, entityYaw, partialTicks);}public void setupRotation(EntityObBoat p_188311_1_, float p_188311_2_, float p_188311_3_){GlStateManager.rotate(180.0F - p_188311_2_, 0.0F, 1.0F, 0.0F);float f = (float)p_188311_1_.getTimeSinceHit() - p_188311_3_;float f1 = p_188311_1_.getDamageTaken() - p_188311_3_;if (f1 < 0.0F){f1 = 0.0F;}if (f > 0.0F){GlStateManager.rotate(MathHelper.sin(f) * f * f1 / 10.0F * (float)p_188311_1_.getForwardDirection(), 1.0F, 0.0F, 0.0F);}GlStateManager.scale(-1.0F, -1.0F, 1.0F);}public void setupTranslation(double p_188309_1_, double p_188309_3_, double p_188309_5_){GlStateManager.translate((float)p_188309_1_, (float)p_188309_3_ + 0.375F, (float)p_188309_5_);}/*** Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.*/protected ResourceLocation getEntityTexture(EntityObBoat entity){return TEXTURES;}public boolean isMultipass(){return true;}public void renderMultipass(EntityObBoat p_188300_1_, double p_188300_2_, double p_188300_4_, double p_188300_6_, float p_188300_8_, float p_188300_9_){GlStateManager.pushMatrix();this.setupTranslation(p_188300_2_, p_188300_4_, p_188300_6_);this.setupRotation(p_188300_1_, p_188300_8_, p_188300_9_);this.bindEntityTexture(p_188300_1_);((IMultipassModel)this.modelBoat).renderMultipass(p_188300_1_, p_188300_9_, 0.0F, -0.1F, 0.0F, 0.0F, 0.0625F);GlStateManager.popMatrix();} }在RenderHandler.java中的registerEntityRenders()中添加船的渲染注冊:
RenderHandler.java
public class RenderHandler {public static void registerEntityRenders() {RenderingRegistry.registerEntityRenderingHandler(EntityObBoat.class, new IRenderFactory<EntityObBoat>(){@Overridepublic Render<? super EntityObBoat> createRenderFor(RenderManager manager){return new RenderObBoat(manager);}});} }4.在EntityInit.java中添加我們的船的注冊信息:
registerEntity("obboat", EntityObBoat.class, ENTITY_NEXT_ID, 20);5.生物實體部分完成,我們要制作一個專門生成船的物品,新建ItemObBoat類。
ItemObBoat.java
package com.joy187.rejoymod.item;import com.joy187.rejoymod.entity.EntityObBoat; import net.minecraft.block.Block; import net.minecraft.creativetab.CreativeTabs; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.item.ItemStack; import net.minecraft.stats.StatList; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World;import java.util.List;public class ItemObBoat extends ItemBase{public ItemObBoat(String name, CreativeTabs tab) {super(name,tab);this.maxStackSize=1;}private EntityObBoat.Type type= EntityObBoat.Type.OAK;public ItemObBoat(EntityObBoat.Type typeIn){this.type = typeIn;this.maxStackSize = 1;this.setCreativeTab(CreativeTabs.TRANSPORTATION);this.setUnlocalizedName("boat." + "ob");}/*** Called when the equipped item is right clicked.*/public ActionResult<ItemStack> onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn){ItemStack itemstack = playerIn.getHeldItem(handIn);float f = 1.0F;float f1 = playerIn.prevRotationPitch + (playerIn.rotationPitch - playerIn.prevRotationPitch) * 1.0F;float f2 = playerIn.prevRotationYaw + (playerIn.rotationYaw - playerIn.prevRotationYaw) * 1.0F;double d0 = playerIn.prevPosX + (playerIn.posX - playerIn.prevPosX) * 1.0D;double d1 = playerIn.prevPosY + (playerIn.posY - playerIn.prevPosY) * 1.0D + (double)playerIn.getEyeHeight();double d2 = playerIn.prevPosZ + (playerIn.posZ - playerIn.prevPosZ) * 1.0D;Vec3d vec3d = new Vec3d(d0, d1, d2);float f3 = MathHelper.cos(-f2 * 0.017453292F - (float)Math.PI);float f4 = MathHelper.sin(-f2 * 0.017453292F - (float)Math.PI);float f5 = -MathHelper.cos(-f1 * 0.017453292F);float f6 = MathHelper.sin(-f1 * 0.017453292F);float f7 = f4 * f5;float f8 = f3 * f5;double d3 = 5.0D;Vec3d vec3d1 = vec3d.addVector((double)f7 * 5.0D, (double)f6 * 5.0D, (double)f8 * 5.0D);RayTraceResult raytraceresult = worldIn.rayTraceBlocks(vec3d, vec3d1, true);if (raytraceresult == null){return new ActionResult<ItemStack>(EnumActionResult.PASS, itemstack);}else{Vec3d vec3d2 = playerIn.getLook(1.0F);boolean flag = false;List<Entity> list = worldIn.getEntitiesWithinAABBExcludingEntity(playerIn, playerIn.getEntityBoundingBox().expand(vec3d2.x * 5.0D, vec3d2.y * 5.0D, vec3d2.z * 5.0D).grow(1.0D));for (int i = 0; i < list.size(); ++i){Entity entity = list.get(i);if (entity.canBeCollidedWith()){AxisAlignedBB axisalignedbb = entity.getEntityBoundingBox().grow((double)entity.getCollisionBorderSize());if (axisalignedbb.contains(vec3d)){flag = true;}}}if (flag){return new ActionResult<ItemStack>(EnumActionResult.PASS, itemstack);}else if (raytraceresult.typeOfHit != RayTraceResult.Type.BLOCK){return new ActionResult<ItemStack>(EnumActionResult.PASS, itemstack);}else{Block block = worldIn.getBlockState(raytraceresult.getBlockPos()).getBlock();boolean flag1 = block == Blocks.WATER || block == Blocks.FLOWING_WATER || block == Blocks.LAVA || block == Blocks.FLOWING_LAVA;//這里聲明我們要召喚的船的實體類(第2步中的實體類)EntityObBoat entityboat = new EntityObBoat(worldIn, raytraceresult.hitVec.x, flag1 ? raytraceresult.hitVec.y - 0.12D : raytraceresult.hitVec.y, raytraceresult.hitVec.z);//entityboat.setBoatType(this.type);entityboat.rotationYaw = playerIn.rotationYaw;if (!worldIn.getCollisionBoxes(entityboat, entityboat.getEntityBoundingBox().grow(-0.1D)).isEmpty()){return new ActionResult<ItemStack>(EnumActionResult.FAIL, itemstack);}else{if (!worldIn.isRemote){worldIn.spawnEntity(entityboat);}if (!playerIn.capabilities.isCreativeMode){itemstack.shrink(1);}playerIn.addStat(StatList.getObjectUseStats(this));return new ActionResult<ItemStack>(EnumActionResult.SUCCESS, itemstack);}}}} }在ModItems.java中添加該物品的注冊信息:
//物品名稱 放入哪個物品欄public static final Item OBBOAT = new ItemObBoat("obboat",IdlFramework.ITEM_TAB);6.在resources包中的assets\rejoymod\models\item中新建物品模型文件:
obboat.json
{"parent": "item/generated","textures": {"layer0": "rejoymod:items/obboat"} }在en_us.lang中添加船物品和船實體的英文名稱:
item.obboat.name=Example Boat entity.obboat.name=Example Boat在textures\item中添加物品的貼圖:
在textures\entity中添加船實體的皮膚貼圖:
7.保存所有文件 -> 進入游戲測試:
巖漿中行船
水中行船
總結
以上是生活随笔為你收集整理的Minecraft 1.12.2模组开发(四十五) 水火两用船的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何在AI(Adobe illustra
- 下一篇: 妖怪与和尚过河问题