Advertisement
jayhillx

Red Panda 0.2

Jan 6th, 2024
991
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 15.16 KB | None | 0 0
  1. package com.mysticsbiomes.common.entity.animal;
  2.  
  3. import com.mysticsbiomes.init.MysticEntities;
  4. import net.minecraft.nbt.CompoundTag;
  5. import net.minecraft.network.syncher.EntityDataAccessor;
  6. import net.minecraft.network.syncher.EntityDataSerializers;
  7. import net.minecraft.network.syncher.SynchedEntityData;
  8. import net.minecraft.server.level.ServerLevel;
  9. import net.minecraft.util.ByIdMap;
  10. import net.minecraft.util.RandomSource;
  11. import net.minecraft.util.StringRepresentable;
  12. import net.minecraft.world.InteractionHand;
  13. import net.minecraft.world.InteractionResult;
  14. import net.minecraft.world.entity.*;
  15. import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
  16. import net.minecraft.world.entity.ai.attributes.Attributes;
  17. import net.minecraft.world.entity.ai.control.LookControl;
  18. import net.minecraft.world.entity.ai.control.MoveControl;
  19. import net.minecraft.world.entity.ai.goal.*;
  20. import net.minecraft.world.entity.animal.*;
  21. import net.minecraft.world.entity.monster.Monster;
  22. import net.minecraft.world.entity.player.Player;
  23. import net.minecraft.world.item.Items;
  24. import net.minecraft.world.item.crafting.Ingredient;
  25. import net.minecraft.world.level.Level;
  26. import net.minecraft.world.level.block.Blocks;
  27.  
  28. import javax.annotation.Nullable;
  29. import java.util.EnumSet;
  30. import java.util.function.IntFunction;
  31.  
  32. /**
  33.  * Red Pandas spawn in the Bamboo Blossom Forest, scouting out bamboo, and stealing items.
  34.  */
  35. public class RedPanda extends Animal {
  36.     private static final EntityDataAccessor<Byte> MAIN_GENE_ID = SynchedEntityData.defineId(RedPanda.class, EntityDataSerializers.BYTE);
  37.     private static final EntityDataAccessor<Byte> HIDDEN_GENE_ID = SynchedEntityData.defineId(RedPanda.class, EntityDataSerializers.BYTE);
  38.     private static final EntityDataAccessor<Byte> DATA_FLAGS_ID = SynchedEntityData.defineId(RedPanda.class, EntityDataSerializers.BYTE);
  39.     private int ticksSinceLastTimeStanding;
  40.  
  41.     public final AnimationState sleepingAnimationState = new AnimationState();
  42.     public final AnimationState standingPoseAnimationState = new AnimationState();
  43.  
  44.     public RedPanda(EntityType<? extends RedPanda> type, Level level) {
  45.         super(type, level);
  46.         this.moveControl = new MoveControl(this);
  47.         this.lookControl = new LookControl(this);
  48.     }
  49.  
  50.     protected void defineSynchedData() {
  51.         super.defineSynchedData();
  52.         this.entityData.define(MAIN_GENE_ID, (byte)0);
  53.         this.entityData.define(HIDDEN_GENE_ID, (byte)0);
  54.         this.entityData.define(DATA_FLAGS_ID, (byte)0);
  55.     }
  56.  
  57.     protected void registerGoals() {
  58.         this.goalSelector.addGoal(0, new FloatGoal(this));
  59.         this.goalSelector.addGoal(0, new RedPanda.StandUpGoal());
  60.         this.goalSelector.addGoal(1, new PanicGoal(this, 2.0));
  61.         this.goalSelector.addGoal(1, new BreedGoal(this, 1.0));
  62.         this.goalSelector.addGoal(2, new RedPanda.AttackGoal(this, 1.2F, true));
  63.         this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, Ingredient.of(Blocks.BAMBOO.asItem()), false));
  64.         this.goalSelector.addGoal(4, new AvoidEntityGoal<>(this, Monster.class, 4.0F, 2.0, 2.0));
  65.         this.goalSelector.addGoal(5, new LookAtPlayerGoal(this, Player.class, 6.0F));
  66.         this.goalSelector.addGoal(6, new RandomLookAroundGoal(this));
  67.         this.goalSelector.addGoal(7, new RedPanda.SleepGoal());
  68.         this.goalSelector.addGoal(8, new FollowParentGoal(this, 1.25));
  69.         this.goalSelector.addGoal(9, new WaterAvoidingRandomStrollGoal(this, 1.0));
  70.     }
  71.  
  72.     public static AttributeSupplier.Builder createAttributes() {
  73.         return Mob.createMobAttributes().add(Attributes.MOVEMENT_SPEED, 1.0F).add(Attributes.MAX_HEALTH, 10.0D).add(Attributes.FOLLOW_RANGE, 32.0D).add(Attributes.ATTACK_DAMAGE, 8.0D);
  74.     }
  75.  
  76.     public void setAttributes() {
  77.         if (this.isEnergetic()) {
  78.             this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(1.1F);
  79.         }
  80.  
  81.         if (this.isLazy()) {
  82.             this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.1F);
  83.         }
  84.     }
  85.  
  86.     public RedPanda getBreedOffspring(ServerLevel level, AgeableMob mob) {
  87.         RedPanda redPanda = MysticEntities.RED_PANDA.get().create(level);
  88.         if (redPanda != null) {
  89.             if (mob instanceof RedPanda parent) {
  90.                 redPanda.setGeneFromParents(this, parent);
  91.             }
  92.  
  93.             redPanda.setAttributes();
  94.         }
  95.         return redPanda;
  96.     }
  97.  
  98.     public EntityDimensions getDimensions(Pose pose) {
  99.         return pose == Pose.STANDING ? EntityDimensions.scalable(0.5F, 1.125F) : super.getDimensions(pose);
  100.     }
  101.  
  102.     protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) {
  103.         return pose == Pose.STANDING ? 1.0F : super.getStandingEyeHeight(pose, dimensions);
  104.     }
  105.  
  106.     /////////////////////////////////////////////////////////////////////////////////
  107.  
  108.     public void addAdditionalSaveData(CompoundTag tag) {
  109.         super.addAdditionalSaveData(tag);
  110.         tag.putBoolean("IsSleeping", this.isSleeping());
  111.  
  112.         tag.putString("MainGene", this.getMainGene().getSerializedName());
  113.         tag.putString("HiddenGene", this.getHiddenGene().getSerializedName());
  114.     }
  115.  
  116.     public void readAdditionalSaveData(CompoundTag tag) {
  117.         super.readAdditionalSaveData(tag);
  118.         this.setSleeping(tag.getBoolean("IsSleeping"));
  119.  
  120.         this.setMainGene(Gene.byName(tag.getString("MainGene")));
  121.         this.setHiddenGene(Gene.byName(tag.getString("HiddenGene")));
  122.     }
  123.  
  124.     /////////////////////////////////////////////////////////////////////////////////
  125.  
  126.     public Gene getMainGene() {
  127.         return Gene.byId(this.entityData.get(MAIN_GENE_ID));
  128.     }
  129.  
  130.     public void setMainGene(Gene gene) {
  131.         if (gene.getId() > 6) {
  132.             gene = Gene.getRandom(this.random);
  133.         }
  134.  
  135.         this.entityData.set(MAIN_GENE_ID, (byte)gene.getId());
  136.     }
  137.  
  138.     public Gene getHiddenGene() {
  139.         return Gene.byId(this.entityData.get(HIDDEN_GENE_ID));
  140.     }
  141.  
  142.     public void setHiddenGene(Gene gene) {
  143.         if (gene.getId() > 6) {
  144.             gene = Gene.getRandom(this.random);
  145.         }
  146.  
  147.         this.entityData.set(HIDDEN_GENE_ID, (byte)gene.getId());
  148.     }
  149.  
  150.     public void setGeneFromParents(RedPanda parent, @Nullable RedPanda parent2) {
  151.         if (parent2 == null) {
  152.             if (this.random.nextBoolean()) {
  153.                 this.setMainGene(parent.getOneOfGenesRandomly());
  154.                 this.setHiddenGene(Gene.getRandom(this.random));
  155.             } else {
  156.                 this.setMainGene(Gene.getRandom(this.random));
  157.                 this.setHiddenGene(parent.getOneOfGenesRandomly());
  158.             }
  159.         } else if (this.random.nextBoolean()) {
  160.             this.setMainGene(parent.getOneOfGenesRandomly());
  161.             this.setHiddenGene(parent2.getOneOfGenesRandomly());
  162.         } else {
  163.             this.setMainGene(parent2.getOneOfGenesRandomly());
  164.             this.setHiddenGene(parent.getOneOfGenesRandomly());
  165.         }
  166.  
  167.         if (this.random.nextInt(32) == 0) {
  168.             this.setMainGene(Gene.getRandom(this.random));
  169.         }
  170.  
  171.         if (this.random.nextInt(32) == 0) {
  172.             this.setHiddenGene(Gene.getRandom(this.random));
  173.         }
  174.     }
  175.  
  176.     private Gene getOneOfGenesRandomly() {
  177.         return this.random.nextBoolean() ? this.getMainGene() : this.getHiddenGene();
  178.     }
  179.  
  180.     public Gene getVariant() {
  181.         return Gene.getVariantFromGenes(this.getMainGene(), this.getHiddenGene());
  182.     }
  183.  
  184.     public boolean isEnergetic() {
  185.         return this.getVariant() == Gene.ENERGETIC;
  186.     }
  187.  
  188.     public boolean isLazy() {
  189.         return this.getVariant() == Gene.LAZY;
  190.     }
  191.  
  192.     public boolean isCurious() {
  193.         return this.getVariant() == Gene.CURIOUS;
  194.     }
  195.  
  196.     public boolean isClingy() {
  197.         return this.getVariant() == Gene.CLINGY;
  198.     }
  199.  
  200.     public boolean isShy() {
  201.         return this.getVariant() == Gene.SHY;
  202.     }
  203.  
  204.     public boolean isMischievous() {
  205.         return this.getVariant() == Gene.MISCHIEVOUS;
  206.     }
  207.  
  208.     public boolean isVelvet() {
  209.         return this.getVariant() == Gene.VELVET;
  210.     }
  211.  
  212.     /////////////////////////////////////////////////////////////////////////////////
  213.  
  214.     private boolean getFlag(int value) {
  215.         return (this.entityData.get(DATA_FLAGS_ID) & value) != 0;
  216.     }
  217.  
  218.     private void setFlag(int value, boolean b) {
  219.         if (b) {
  220.             this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) | value));
  221.         } else {
  222.             this.entityData.set(DATA_FLAGS_ID, (byte)(this.entityData.get(DATA_FLAGS_ID) & ~value));
  223.         }
  224.     }
  225.  
  226.     public boolean isSleeping() {
  227.         return this.getFlag(4);
  228.     }
  229.  
  230.     public void setSleeping(boolean sleeping) {
  231.         this.setPose(sleeping ? Pose.SLEEPING : Pose.SITTING);
  232.         this.setFlag(4, sleeping);
  233.     }
  234.  
  235.     public boolean isStanding() {
  236.         return this.getFlag(8);
  237.     }
  238.  
  239.     public void setStanding(boolean standing) {
  240.         this.setPose(standing ? Pose.STANDING : Pose.SITTING);
  241.         this.setFlag(8, standing);
  242.     }
  243.  
  244.     /////////////////////////////////////////////////////////////////////////////////
  245.  
  246.     public void tick() {
  247.         super.tick();
  248.         if (this.isStanding()) {
  249.             this.setPose(this.walkAnimation.isMoving() ? Pose.STANDING : Pose.SITTING);
  250.         }
  251.  
  252.         if (this.level().isClientSide()) {
  253.             this.sleepingAnimationState.animateWhen(this.isSleeping(), this.tickCount);
  254.         }
  255.     }
  256.  
  257.     public void aiStep() {
  258.         super.aiStep();
  259.         if (this.isSleeping() || this.isImmobile()) {
  260.             this.xxa = 0.0F;
  261.             this.zza = 0.0F;
  262.         }
  263.     }
  264.  
  265.     protected void customServerAiStep() {
  266.         super.customServerAiStep();
  267.         if (!this.isStanding()) {
  268.             ++this.ticksSinceLastTimeStanding;
  269.         }
  270.     }
  271.  
  272.     /////////////////////////////////////////////////////////////////////////////////
  273.  
  274.     public InteractionResult mobInteract(Player player, InteractionHand hand) {
  275.         this.setSleeping(player.getMainHandItem().is(Items.STICK));
  276.         this.setStanding(player.getMainHandItem().is(Items.PINK_PETALS));
  277.         return super.mobInteract(player, hand);
  278.     }
  279.  
  280.     /////////////////////////////////////////////////////////////////////////////////
  281.  
  282.     /**
  283.      * Those with clingy trait will search for other red pandas nearby before falling asleep.
  284.      * Those with lazy trait will sleep longer than others.
  285.      * Those with energetic trait will rarely sleep.
  286.      */
  287.     class SleepGoal extends Goal {
  288.  
  289.         public SleepGoal() {
  290.             this.setFlags(EnumSet.of(Flag.MOVE, Flag.LOOK, Flag.JUMP));
  291.         }
  292.  
  293.         public boolean canUse() {
  294.             return this.canSleep();
  295.         }
  296.  
  297.         public void start() {
  298.             RedPanda.this.setSleeping(true);
  299.         }
  300.  
  301.         public void stop() {
  302.             RedPanda.this.setSleeping(false);
  303.         }
  304.  
  305.         private boolean canSleep() {
  306.             return RedPanda.this.level().isNight();
  307.         }
  308.     }
  309.  
  310.     /**
  311.      * Those with lazy trait will never stand up.
  312.      * Those with energetic trait tend to stand up more often.
  313.      */
  314.     class StandUpGoal extends Goal {
  315.         private int remainingTicksStanding;
  316.  
  317.         public boolean canUse() {
  318.             return RedPanda.this.ticksSinceLastTimeStanding > 200 && !RedPanda.this.isStanding();
  319.         }
  320.  
  321.         public boolean canContinueToUse() {
  322.             return this.remainingTicksStanding > 0;
  323.         }
  324.  
  325.         public void start() {
  326.             RedPanda.this.setStanding(true);
  327.             this.remainingTicksStanding = RedPanda.this.random.nextInt(100) + 200;
  328.         }
  329.  
  330.         public void stop() {
  331.             RedPanda.this.setStanding(false);
  332.             RedPanda.this.ticksSinceLastTimeStanding = 0;
  333.         }
  334.  
  335.         public void tick() {
  336.             --this.remainingTicksStanding;
  337.         }
  338.     }
  339.  
  340.     class AttackGoal extends MeleeAttackGoal {
  341.  
  342.         public AttackGoal(PathfinderMob mob, double speed, boolean followIfNotSeen) {
  343.             super(mob, speed, followIfNotSeen);
  344.         }
  345.  
  346.         public boolean canUse() {
  347.             return super.canUse() && !RedPanda.this.isLazy() && !RedPanda.this.isShy();
  348.         }
  349.     }
  350.  
  351.     /**
  352.      * normal      - base for all red pandas, sleeps at night, likes to be alone, etc.
  353.      * curious     - looks at everything, interacts with others, picks up items.
  354.      * clingy      - will sleep next to other red pandas, does not leave others alone, will sleep in bed with trusted players.
  355.      * energetic   - sleeps less, runs more often, wakes other red pandas up.
  356.      * lazy        - sleeps more, slower, is less territorial.
  357.      * shy         - avoids untrusted players, sleeps directly under leaves, light sleeper.
  358.      * mischievous - steals items off players, wakes other red pandas from sleeping, scares shy traits.
  359.      * velvet      - normal, just dark red like a red velvet cupcake.
  360.      *
  361.      * territorial - attacks untrusted players who approach too fast.
  362.      * loyal       - picks up and gives player items they have dropped.
  363.      */
  364.     public enum Gene implements StringRepresentable {
  365.         NORMAL(0, "normal", false),
  366.         ENERGETIC(1, "energetic", false),
  367.         LAZY(2, "lazy", false),
  368.         CURIOUS(3, "curious", false),
  369.         CLINGY(4, "clingy", false),
  370.         SHY(5, "shy", false),
  371.         MISCHIEVOUS(6, "mischievous", false),
  372.         VELVET(7, "velvet", true);
  373.  
  374.         private static final IntFunction<Gene> BY_ID = ByIdMap.continuous(Gene::getId, values(), ByIdMap.OutOfBoundsStrategy.ZERO);
  375.         private final int id;
  376.         private final String name;
  377.         private final boolean isRecessive;
  378.  
  379.         Gene(int id, String type, boolean recessive) {
  380.             this.id = id;
  381.             this.name = type;
  382.             this.isRecessive = recessive;
  383.         }
  384.  
  385.         public int getId() {
  386.             return this.id;
  387.         }
  388.  
  389.         public String getSerializedName() {
  390.             return this.name;
  391.         }
  392.  
  393.         public boolean isRecessive() {
  394.             return this.isRecessive;
  395.         }
  396.  
  397.         static Gene getVariantFromGenes(Gene gene1, Gene gene2) {
  398.             if (gene1.isRecessive()) {
  399.                 return gene1 == gene2 ? gene1 : NORMAL;
  400.             } else {
  401.                 return gene1;
  402.             }
  403.         }
  404.  
  405.         public static Gene byId(int id) {
  406.             return BY_ID.apply(id);
  407.         }
  408.  
  409.         public static Gene byName(String name) {
  410.             return StringRepresentable.fromEnum(Gene::values).byName(name, NORMAL);
  411.         }
  412.  
  413.         public static Gene getRandom(RandomSource source) {
  414.             int i = source.nextInt(13);
  415.             if (i == 0) {
  416.                 return ENERGETIC;
  417.             } else if (i == 1) {
  418.                 return LAZY;
  419.             } else if (i == 2) {
  420.                 return CURIOUS;
  421.             } else if (i == 4) {
  422.                 return CLINGY;
  423.             } else if (i == 6) {
  424.                 return SHY;
  425.             } else if (i == 7) {
  426.                 return MISCHIEVOUS;
  427.             } else {
  428.                 return i < 9 ? VELVET : NORMAL;
  429.             }
  430.         }
  431.     }
  432.  
  433. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement