Advertisement
jayhillx

Sea Otter 3

Apr 27th, 2024
859
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 11.70 KB | None | 0 0
  1. package com.mysticsbiomes.common.entity.animal;
  2.  
  3. import com.mysticsbiomes.init.MysticEntities;
  4. import net.minecraft.core.BlockPos;
  5. import net.minecraft.nbt.CompoundTag;
  6. import net.minecraft.network.syncher.EntityDataAccessor;
  7. import net.minecraft.network.syncher.EntityDataSerializers;
  8. import net.minecraft.network.syncher.SynchedEntityData;
  9. import net.minecraft.server.level.ServerLevel;
  10. import net.minecraft.world.InteractionHand;
  11. import net.minecraft.world.InteractionResult;
  12. import net.minecraft.world.entity.*;
  13. import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
  14. import net.minecraft.world.entity.ai.attributes.Attributes;
  15. import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
  16. import net.minecraft.world.entity.ai.control.BodyRotationControl;
  17. import net.minecraft.world.entity.ai.control.SmoothSwimmingLookControl;
  18. import net.minecraft.world.entity.ai.control.SmoothSwimmingMoveControl;
  19. import net.minecraft.world.entity.ai.goal.*;
  20. import net.minecraft.world.entity.ai.navigation.PathNavigation;
  21. import net.minecraft.world.entity.ai.navigation.WaterBoundPathNavigation;
  22. import net.minecraft.world.entity.animal.Animal;
  23. import net.minecraft.world.entity.player.Player;
  24. import net.minecraft.world.item.Items;
  25. import net.minecraft.world.level.Level;
  26. import net.minecraft.world.level.LevelReader;
  27. import net.minecraft.world.level.block.Blocks;
  28. import net.minecraft.world.level.pathfinder.BlockPathTypes;
  29. import net.minecraft.world.phys.Vec3;
  30.  
  31. import java.util.EnumSet;
  32.  
  33. public class SeaOtter extends Animal {
  34.     private static final EntityDataAccessor<Boolean> DATA_FLOATING_ID = SynchedEntityData.defineId(SeaOtter.class, EntityDataSerializers.BOOLEAN);
  35.     private static final EntityDataAccessor<Boolean> DATA_SWIMMING_ID = SynchedEntityData.defineId(SeaOtter.class, EntityDataSerializers.BOOLEAN);
  36.     private boolean needsToSurface;
  37.     private int ticksSinceLastSwamAround;
  38.     private int ticksSpentSwimmingAround;
  39.  
  40.     public final AnimationState floatingAnimationState = new AnimationState();
  41.  
  42.     public SeaOtter(EntityType<? extends SeaOtter> type, Level level) {
  43.         super(type, level);
  44.         this.moveControl = new SmoothSwimmingMoveControl(this, 85, 10, 0.02F, 0.1F, true);
  45.         this.lookControl = new SmoothSwimmingLookControl(this, 10);
  46.         this.setPathfindingMalus(BlockPathTypes.WATER, 0.0F);
  47.         this.setMaxUpStep(1.0F);
  48.     }
  49.  
  50.     @Override
  51.     protected void defineSynchedData() {
  52.         super.defineSynchedData();
  53.         this.entityData.define(DATA_FLOATING_ID, false);
  54.         this.entityData.define(DATA_SWIMMING_ID, false);
  55.     }
  56.  
  57.     @Override
  58.     protected void registerGoals() {
  59.         this.goalSelector.addGoal(0, new SeaOtter.SwimToSurface(this, 1.0D, 16));
  60.         this.goalSelector.addGoal(1, new SeaOtter.SwimAroundGoal(this, 1.0D, 10));
  61.         this.goalSelector.addGoal(2, new LookAtPlayerGoal(this, Player.class, 6.0F));
  62.         this.goalSelector.addGoal(3, new SeaOtter.FloatGoal());
  63.         this.goalSelector.addGoal(3, new RandomLookAroundGoal(this));
  64.     }
  65.  
  66.     public static AttributeSupplier.Builder createAttributes() {
  67.         return Mob.createMobAttributes().add(Attributes.MAX_HEALTH, 16.0F).add(Attributes.MOVEMENT_SPEED, 1.0D);
  68.     }
  69.  
  70.     @Override
  71.     public void addAdditionalSaveData(CompoundTag tag) {
  72.         super.addAdditionalSaveData(tag);
  73.         tag.putBoolean("Floating", this.isFloating());
  74.         tag.putBoolean("Swimming", this.isSwimming());
  75.         tag.putBoolean("NeedsToSurface", this.needsToSurface());
  76.         tag.putInt("TicksSinceSwam", this.ticksSinceLastSwamAround);
  77.         tag.putInt("TicksSwimming", this.ticksSpentSwimmingAround);
  78.     }
  79.  
  80.     @Override
  81.     public void readAdditionalSaveData(CompoundTag tag) {
  82.         super.readAdditionalSaveData(tag);
  83.         this.setFloating(tag.getBoolean("Floating"));
  84.         this.setSwimming(tag.getBoolean("Swimming"));
  85.         this.setNeedsToSurface(tag.getBoolean("NeedsToSurface"));
  86.         this.ticksSinceLastSwamAround = tag.getInt("TicksSinceSwam");
  87.         this.ticksSpentSwimmingAround = tag.getInt("TicksSwimming");
  88.     }
  89.  
  90.     @Override
  91.     public AgeableMob getBreedOffspring(ServerLevel level, AgeableMob mob) {
  92.         return MysticEntities.SEA_OTTER.get().create(level);
  93.     }
  94.  
  95.     @Override
  96.     public MobType getMobType() {
  97.         return MobType.WATER;
  98.     }
  99.  
  100.     @Override
  101.     public int getMaxAirSupply() {
  102.         return 600;
  103.     }
  104.  
  105.     ///////////////////////////////////////////////////////////////////////////////
  106.  
  107.     @Override
  108.     public void tick() {
  109.         super.tick();
  110.         if (this.isFloating()) {
  111.             this.wasTouchingWater = true;
  112.             this.setAirSupply(this.getMaxAirSupply());
  113.             this.setDeltaMovement(this.getDeltaMovement().multiply(1.0, 0.0, 1.0));
  114.         }
  115.  
  116.         if (this.level().isClientSide) {
  117.             this.floatingAnimationState.animateWhen(this.isFloating() && !this.isSwimming(), this.tickCount);
  118.         }
  119.  
  120.         if (!this.level().isClientSide) {
  121.             if (!this.isSwimming()) {
  122.                 ++this.ticksSinceLastSwamAround;
  123.             } else {
  124.                 ++this.ticksSpentSwimmingAround;
  125.             }
  126.         }
  127.     }
  128.  
  129.     @Override
  130.     public void aiStep() {
  131.         super.aiStep();
  132.         if (this.isEffectiveAi() && this.isAlive()) {
  133.             if (this.wantsToFloat() || (this.isUnderWater() && this.getAirSupply() < 200)) {
  134.                 this.setNeedsToSurface(true);
  135.             }
  136.  
  137.             if (this.wantsToSwim() && (!this.needsToSurface() || !this.wantsToFloat())) {
  138.                 this.setSwimming(true);
  139.             }
  140.         }
  141.     }
  142.  
  143.     ///////////////////////////////////////////////////////////////////////////////
  144.  
  145.     @Override
  146.     protected BodyRotationControl createBodyControl() {
  147.         return new SeaOtter.SeaOtterBodyRotationControl(this);
  148.     }
  149.  
  150.     public int getMaxHeadXRot() {
  151.         return 30;
  152.     }
  153.  
  154.     public int getMaxHeadYRot() {
  155.         return 60;
  156.     }
  157.  
  158.     public int getHeadRotSpeed() {
  159.         return 7;
  160.     }
  161.  
  162.     ///////////////////////////////////////////////////////////////////////////////
  163.  
  164.     @Override
  165.     protected PathNavigation createNavigation(Level level) {
  166.         return new WaterBoundPathNavigation(this, level);
  167.     }
  168.  
  169.     @Override
  170.     public void travel(Vec3 vec3) {
  171.         if (this.isEffectiveAi() && this.isInWater()) {
  172.             this.moveRelative(this.getSpeed(), vec3);
  173.             this.move(MoverType.SELF, this.getDeltaMovement());
  174.             this.setDeltaMovement(this.getDeltaMovement().scale(0.9));
  175.         } else {
  176.             super.travel(vec3);
  177.         }
  178.     }
  179.  
  180.     ///////////////////////////////////////////////////////////////////////////////
  181.  
  182.     public boolean isFloating() {
  183.         return this.entityData.get(DATA_FLOATING_ID);
  184.     }
  185.  
  186.     public void setFloating(boolean value) {
  187.         this.entityData.set(DATA_FLOATING_ID, value);
  188.     }
  189.  
  190.     public boolean wantsToFloat() {
  191.         return this.hasSwamLongEnough();
  192.     }
  193.  
  194.     ///////////////////////////////////////////////////////////////////////////////
  195.  
  196.     public boolean isSwimming() {
  197.         return this.entityData.get(DATA_SWIMMING_ID);
  198.     }
  199.  
  200.     public void setSwimming(boolean value) {
  201.         this.entityData.set(DATA_SWIMMING_ID, value);
  202.     }
  203.  
  204.     public boolean wantsToSwim() {
  205.         return this.ticksSinceLastSwamAround > 800;
  206.     }
  207.  
  208.     public boolean hasSwamLongEnough() {
  209.         return this.ticksSpentSwimmingAround > 600;
  210.     }
  211.  
  212.     public void resetTicksSinceLastSwimAround() {
  213.         this.ticksSinceLastSwamAround = 0;
  214.     }
  215.  
  216.     public void resetTicksSpentSwimmingAround() {
  217.         this.ticksSpentSwimmingAround = 0;
  218.     }
  219.  
  220.     ///////////////////////////////////////////////////////////////////////////////
  221.  
  222.     public boolean needsToSurface() {
  223.         return this.needsToSurface;
  224.     }
  225.  
  226.     public void setNeedsToSurface(boolean value) {
  227.         this.needsToSurface = value;
  228.     }
  229.  
  230.     ///////////////////////////////////////////////////////////////////////////////
  231.  
  232.     public InteractionResult mobInteract(Player player, InteractionHand hand) {
  233.         this.setFloating(player.getItemInHand(hand).is(Items.STICK));
  234.         this.setSwimming(!player.getItemInHand(hand).is(Items.STICK));
  235.         return super.mobInteract(player, hand);
  236.     }
  237.  
  238.     ///////////////////////////////////////////////////////////////////////////////
  239.  
  240.     // TODO: GOALS
  241.  
  242.     class SwimAroundGoal extends RandomSwimmingGoal {
  243.  
  244.         public SwimAroundGoal(PathfinderMob mob, double speed, int interval) {
  245.             super(mob, speed, interval);
  246.         }
  247.  
  248.         public boolean canUse() {
  249.             if (SeaOtter.this.isFloating()) {
  250.                 return false;
  251.             } else if (SeaOtter.this.needsToSurface()) {
  252.                 return false;
  253.             } else if (SeaOtter.this.wantsToFloat()) {
  254.                 return false;
  255.             } else {
  256.                 return super.canUse();
  257.             }
  258.         }
  259.  
  260.         public boolean canContinueToUse() {
  261.             return !SeaOtter.this.hasSwamLongEnough() && super.canContinueToUse();
  262.         }
  263.  
  264.         public void start() {
  265.             SeaOtter.this.setSwimming(true);
  266.             super.start();
  267.         }
  268.  
  269.         public void stop() {
  270.             super.stop();
  271.         }
  272.  
  273.         protected Vec3 getPosition() {
  274.             return BehaviorUtils.getRandomSwimmablePos(this.mob, 10, 7);
  275.         }
  276.     }
  277.  
  278.     class SwimToSurface extends MoveToBlockGoal {
  279.  
  280.         public SwimToSurface(PathfinderMob mob, double speed, int range) {
  281.             super(mob, speed, range);
  282.             this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK));
  283.         }
  284.  
  285.         public boolean canUse() {
  286.             return SeaOtter.this.needsToSurface() && super.canUse();
  287.         }
  288.  
  289.         public void start() {
  290.             System.out.println("swimming to surface");
  291.             super.start();
  292.         }
  293.  
  294.         public void stop() {
  295.             SeaOtter.this.setNeedsToSurface(false);
  296.             SeaOtter.this.resetTicksSinceLastSwimAround();
  297.             SeaOtter.this.resetTicksSpentSwimmingAround();
  298.             SeaOtter.this.getNavigation().stop();
  299.         }
  300.  
  301.         protected boolean isValidTarget(LevelReader level, BlockPos pos) {
  302.             return level.getBlockState(pos).is(Blocks.WATER) && level.getBlockState(pos.above()).isAir();
  303.         }
  304.  
  305.         public void tick() {
  306.             super.tick();
  307.  
  308.             if (this.isReachedTarget()) {
  309.                 this.stop();
  310.             }
  311.         }
  312.     }
  313.  
  314.     class FloatGoal extends Goal {
  315.  
  316.         public FloatGoal() {
  317.             this.setFlags(EnumSet.of(Flag.MOVE));
  318.         }
  319.  
  320.         public boolean canUse() {
  321.             return SeaOtter.this.wantsToFloat();
  322.         }
  323.  
  324.         public boolean canContinueToUse() {
  325.             return !SeaOtter.this.wantsToSwim(); // or is hungry/wants to search for food.
  326.         }
  327.  
  328.         public void start() {
  329.             SeaOtter.this.setFloating(true);
  330.             SeaOtter.this.setSwimming(false);
  331.         }
  332.  
  333.         public void stop() {
  334.             SeaOtter.this.setFloating(false);
  335.             SeaOtter.this.setSwimming(true);
  336.         }
  337.     }
  338.  
  339.     ///////////////////////////////////////////////////////////////////////////////
  340.  
  341.     // TODO: CONTROLS
  342.  
  343.     private class SeaOtterBodyRotationControl extends BodyRotationControl {
  344.  
  345.         public SeaOtterBodyRotationControl(Mob mob) {
  346.             super(mob);
  347.         }
  348.  
  349.         public void clientTick() {
  350.             if (!SeaOtter.this.isFloating()) {
  351.                 super.clientTick();
  352.             }
  353.         }
  354.     }
  355.  
  356.     ///////////////////////////////////////////////////////////////////////////////
  357.  
  358.     // TODO: TYPES
  359.  
  360. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement