机缘
C++编程学习、我的世界模组开发
收获
- 掌握了1.12~1.19全部版本的forge模组开发流程,目前已经拥有4个个人模组:
1.生化危机8&4
2.生化危机枪械
3.MC鹅鸭杀
4.1.12.2掉落物光束
- 获得了1333名粉丝的关注
- 成功考研上岸:22东华大学计算机专硕854考研上岸实录
日常
- 平时有时间会选择创作,记录一路以来的模组开发经验。
- 劳逸结合地写代码,看文献,形成一种正向反馈和良性循环。
成就
- MC模组生化危机4重制版Boss门德斯代码:
该Boss可以拿起周围的方块对玩家发起攻击,也可以将玩家吸入空中进行攻击。
public class EntityChief3 extends Monster implements IAnimatable {
private AnimationFactory factory = new AnimationFactory(this);
private int timer;
private static final EntityDataAccessor<Integer> STATE = SynchedEntityData.defineId(EntityChief3.class, EntityDataSerializers.INT);
// private static final EntityDataAccessor<Integer> REGENERATION = SynchedEntityData.defineId(EntityChief3.class,
// EntityDataSerializers.INT);
private final ServerBossEvent bossInfo = (ServerBossEvent)(new ServerBossEvent(this.getDisplayName(), BossEvent.BossBarColor.PURPLE, BossEvent.BossBarOverlay.PROGRESS)).setDarkenScreen(true);
// public EntityChief3(PlayMessages.SpawnEntity packet, Level world) {
// this(EntityInit.CHIEF3.get(), world);
// }
public EntityChief3(EntityType<EntityChief3> type, Level world) {
super(type, world);
xpReward = 100;
setPersistenceRequired();
this.timer=0;
//this.setItemSlot(EquipmentSlot.MAINHAND,);
}
@Override protected void registerGoals() {
this.goalSelector.addGoal(4, new FloatGoal(this));
this.goalSelector.addGoal(5, new RandomLookAroundGoal(this));
this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 1.2));
super.registerGoals();
this.goalSelector.addGoal(2, new MeleeAttackGoal(this, 1.2, false) {
@Override
protected double getAttackReachSqr(@NotNull LivingEntity entity) {
return 0;
}
});
this.targetSelector.addGoal(1, new HurtByTargetGoal(this));
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, false, false));
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, IronGolem.class, false, false));
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<>(this, AbstractVillager.class, false, false));
}
@Override protected void defineSynchedData() {
super.defineSynchedData();
this.getEntityData().define(STATE, 0);
//this.getEntityData().define(REGENERATION, AquamiraeConfig.Common.corneliaRegenerationAbility.get());
}
@Override public void addAdditionalSaveData(@NotNull CompoundTag tag) {
super.addAdditionalSaveData(tag);
CompoundTag data = new CompoundTag();
data.putInt("Attack", this.getEntityData().get(STATE));
//data.putInt("Regeneration", this.getEntityData().get(REGENERATION));
tag.put("CorneliaData", data);
}
@Override
public void readAdditionalSaveData(@NotNull CompoundTag tag) {
super.readAdditionalSaveData(tag);
// CompoundTag data = (CompoundTag) tag.get("CorneliaData");
// if (data == null) return;
this.getEntityData().set(STATE, tag.getInt("Attack"));
//this.getEntityData().set(REGENERATION, data.getInt("Regeneration"));
}
@Override
public AnimationFactory getFactory() {
return this.factory;
}
public void setAttackingState(int time) {
this.entityData.set(STATE, time);
}
@Override
public void baseTick() {
//if (this.getHealth() < this.getMaxHealth() * 0.3 && this.getEntityData().get(REGENERATION) > 0 && !this.hasEffect(MobEffects.LEVITATION)) this.rage();
if (this.getHealth() <= this.getMaxHealth() * 0.1 && !this.hasEffect(MobEffects.WEAKNESS)) this.heal(0.5F*random.nextFloat());
if (this.getTarget() != null) {
this.timer=(this.timer+1)%120;
final LivingEntity target = this.getTarget();
final double distance = this.distanceToSqr(target);
this.lookControl.setLookAt(target);
this.yBodyRot = this.yHeadRot;
if (this.entityData.get(STATE) == 1) {
// if ((distance < 3 || this.hasEffect(MobEffects.LEVITATION))) ANIMATIONS.play("attack", Math.random() < 0.5 ? 40 : 20);
// else if (distance < 25 && random.nextInt(100) == 1) ANIMATIONS.play("attack", Math.random() < 0.5 ? 40 : 20);
// else
if (distance < 600 && random.nextInt(200) == 1) this.timer=-5;
}
if (this.entityData.get(STATE) == 1 && this.timer==25) {
target.setDeltaMovement(new Vec3(target.getX(), target.getY(), target.getZ())
.vectorTo(new Vec3(this.getX(), this.getY() + 0.5F, this.getZ())).scale(0.25F));
if (target instanceof Player player) player.hurtMarked = true;
}
if (this.entityData.get(STATE) == 1 && (this.timer == 8 || this.timer == 35))
this.setDeltaMovement(new Vec3(this.getX(), this.getY(), this.getZ())
.vectorTo(new Vec3(target.getX(), target.getY() + 0.1F, target.getZ())).scale(0.2F));
if (this.entityData.get(STATE) == 1 && distance < 12) this.doHurtTarget(target);
if( this.timer==45) this.setAttackingState(2);
if ((this.timer == 8+45 || this.timer==28+45))
{
this.addEffect(new MobEffectInstance(MobEffects.LEVITATION,40,1,false,false));
this.rage();
}
if(this.entityData.get(STATE) == 1 && this.timer == 108)
{
this.timer=-10;
}
// if(this.entityData.get(STATE) == 2 && this.timer == 30)
// {
// this.timer=-10;
// }
if (this.isUnderWater() && !this.hasEffect(MobEffects.LEVITATION)) this.setDeltaMovement(new Vec3(this.getX(), this.getY(), this.getZ())
.vectorTo(new Vec3(target.getX(), target.getY(), target.getZ())).scale(0.04F));
else if (this.isInWater() && !this.hasEffect(MobEffects.LEVITATION)) this.setDeltaMovement(new Vec3(this.getX(), this.getY(), this.getZ())
.vectorTo(new Vec3(target.getX(), target.getY(), target.getZ())).scale(0.04F).add(0F, 0.08F, 0F));
System.out.println(this.getEntityData().get(STATE) +" "+this.timer);
}
else{
this.timer--;
if(this.timer<0) this.timer=0;
}
// ANIMATIONS.playSound("attack", 40, "aquamirae:entity.captain_cornelia.attack_1", SoundSource.HOSTILE, 2F, 1F);
// ANIMATIONS.playSound("attack", 20, "aquamirae:entity.captain_cornelia.attack_2", SoundSource.HOSTILE, 2F, 1F);
if (this.timer>10)
this.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 5, 3, false, false));
if (this.hasEffect(MobEffects.LEVITATION) && !this.getLevel().isClientSide()) {
final Vec3 center = new Vec3(this.getX(), this.getY(), this.getZ());
List<LivingEntity> list = this.getLevel().getEntitiesOfClass(LivingEntity.class, new AABB(center, center).inflate(10), e -> true).stream()
.sorted(Comparator.comparingDouble(ent -> ent.distanceToSqr(center))).toList();
final MobEffectInstance LEVITATION = this.getEffect(MobEffects.LEVITATION);
final int DURATION = LEVITATION == null ? 0 : LEVITATION.getDuration();
list.forEach(entity -> {
if (entity instanceof Player player && (player.isCreative() || player.isSpectator())) return;
if (entity.getMaxHealth() <= 100) {
if (DURATION > 1) {
final double radius = 5;
final Vec3 orbit = new Vec3(center.x + Math.cos(entity.tickCount * -0.1F) * radius, center.y,
center.z + Math.sin(entity.tickCount * -0.1F) * radius);
entity.setDeltaMovement(new Vec3(entity.getX(), entity.getY(), entity.getZ()).vectorTo(orbit).scale(0.2F));
if (entity instanceof Player _player) _player.hurtMarked = true;
} else if (DURATION == 1) {
entity.setDeltaMovement(new Vec3(this.getX(), this.getY(), this.getZ())
.vectorTo(new Vec3(entity.getX(), entity.getY(), entity.getZ())).scale(0.2F));
if (entity instanceof Player _player) _player.hurtMarked = true;
}
}
});
this.getPersistentData().putDouble("Par1", this.getPersistentData().getDouble("Par1") + 1);
if (this.getLevel() instanceof ServerLevel server && this.getPersistentData().getDouble("Par1") > 1) {
this.getPersistentData().putDouble("Par1", 0);
server.sendParticles(ParticleInit.MUCUS_PARTICLE.get(), this.getX(), this.getY() - 0.2, this.getZ(), 1,
0.3, 0.1, 0.3, 0.1);
}
if (this.isInWater()) this.setDeltaMovement(new Vec3(0F, 0.4F, 0F));
}
this.getPersistentData().putDouble("Par2", this.getPersistentData().getDouble("Par2") + 1);
if (this.getLevel() instanceof ServerLevel server && this.getPersistentData().getDouble("Par2") > 9) {
this.getPersistentData().putDouble("Par2", 0);
server.sendParticles(ParticleInit.FLAME_PARTICLE.get(), this.getX(), this.getY() + 1.7, this.getZ(), 1,
0.15, 0.1, 0.15, 0.1);
}
//
final Vec3 center = this.position();
List<Player> players = this.getLevel().getEntitiesOfClass(Player.class, new AABB(center, center).inflate(32), e -> true).stream()
.sorted(Comparator.comparingDouble(ent -> ent.distanceToSqr(center))).toList();
//players.forEach(player -> { if (player.getLevel().isClientSide()) AquamiraeAmbient.playCorneliaMusic(player); });
super.baseTick();
}
public void rage() {
//this.getEntityData().set(REGENERATION, this.getEntityData().get(REGENERATION) - 1);
//this.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 200, 0, false, false));
this.addEffect(new MobEffectInstance(MobEffects.MOVEMENT_SLOWDOWN, 20, 3, false, false));
this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 20, 0, false, false));
this.getDeltaMovement().add(0,1+random.nextDouble(),0);
if (this.level instanceof ServerLevel serverLevel) {
final BlockPos pos = new BlockPos(this.getX(), this.getY(), this.getZ());
LightningBolt entityToSpawn = new LightningBolt(EntityType.LIGHTNING_BOLT, serverLevel);
entityToSpawn.moveTo(Vec3.atBottomCenterOf(pos));
entityToSpawn.setVisualOnly(true);
serverLevel.addFreshEntity(entityToSpawn);
serverLevel.playSound(null, pos, SoundEvents.FIREWORK_ROCKET_LARGE_BLAST, SoundSource.HOSTILE, 3, 1);
serverLevel.playSound(null, pos, SoundEvents.FIREWORK_ROCKET_LARGE_BLAST, SoundSource.HOSTILE, 4, 1);
// for(int i=0;i<3;i++)
// {
FireEntity enderBomb = new FireEntity(EntityInit.FIREENTITY.get(), this.level);
enderBomb.setPos(this.position());
int k=this.random.nextInt(3);
if(k==0)
enderBomb.setBlock(Blocks.BIRCH_PLANKS.defaultBlockState());
else if(k==1)
enderBomb.setBlock(Blocks.FIRE.defaultBlockState());
else
enderBomb.setBlock(Blocks.STONE_BRICK_SLAB.defaultBlockState());
enderBomb.setTarget(this.getTarget());
enderBomb.setAttackType(0);
this.level.addFreshEntity(enderBomb);
// }
// DynamicProjectile.create(AquamiraeEntities.POISONED_CHAKRA.get(), this, this.level, null, 5, 0F, 600, 1000);
// DynamicProjectile.create(AquamiraeEntities.POISONED_CHAKRA.get(), this, this.level, null, 5, 0.33F, 600, 1000);
// DynamicProjectile.create(AquamiraeEntities.POISONED_CHAKRA.get(), this, this.level, null, 5, 0.66F, 600, 1000);
}
}
// @Override protected void dropEquipment() {
// if (Math.random() <= 0.2F) {
// final ItemEntity item = new ItemEntity(EntityType.ITEM, this.level);
// item.setItem(this.getMainHandItem());
// item.moveTo(this.position());
// this.level.addFreshEntity(item);
// }
// }
@Override
public @NotNull MobType getMobType() {
return MobType.WATER;
}
@Override public boolean removeWhenFarAway(double distanceToClosestPlayer) {
return false;
}
@Override
protected SoundEvent getAmbientSound() {
Random ran = new Random();
int co = ran.nextInt(3);
if(co==0) return SoundInit.ENTITY_CHIEF_AMBIENT1.get();
if(co==1) return SoundInit.ENTITY_CHIEF_AMBIENT2.get();
return SoundEvents.RAVAGER_ROAR;
}
@Override
protected SoundEvent getHurtSound(DamageSource source) {
Random ran = new Random();
int co = ran.nextInt(2);
if(co==0) return SoundEvents.RAVAGER_HURT;
return SoundInit.ENTITY_HESEN_HURT2.get();
}
@Override
protected SoundEvent getDeathSound() {
return SoundInit.ENTITY_CHIEF_DEATH.get();
}
@Override public boolean hurt(DamageSource source, float amount) {
if (source.getDirectEntity() instanceof AbstractArrow) return false;
if (source == DamageSource.FALL) return false;
if (source == DamageSource.CACTUS) return false;
if (source == DamageSource.DROWN) return false;
if (source == DamageSource.LIGHTNING_BOLT) return false;
if (source.isExplosion()) return false;
if (source.getMsgId().equals("trident")) return false;
return super.hurt(source, amount);
}
// @Override public SpawnGroupData finalizeSpawn(@NotNull ServerLevelAccessor world, @NotNull DifficultyInstance difficulty, @NotNull MobSpawnType reason, @Nullable SpawnGroupData livingdata, @Nullable CompoundTag tag) {
// if (this.getLevel() instanceof ServerLevel serverLevel) serverLevel.playSound(null, new BlockPos(this.getX(), this.getY(), this.getZ()),
// AquamiraeSounds.ENTITY_CAPTAIN_CORNELIA_HORN.get(), SoundSource.HOSTILE, 3, 1);
// this.addEffect(new MobEffectInstance(MobEffects.LEVITATION, 120, 0, false, false));
// AquamiraeMod.loadFromConfig(this, Attributes.MOVEMENT_SPEED, AquamiraeConfig.Common.corneliaMovementSpeed.get());
// AquamiraeMod.loadFromConfig(this, Attributes.MAX_HEALTH, AquamiraeConfig.Common.corneliaMaxHealth.get());
// AquamiraeMod.loadFromConfig(this, Attributes.ARMOR, AquamiraeConfig.Common.corneliaArmor.get());
// AquamiraeMod.loadFromConfig(this, Attributes.STATE_DAMAGE, AquamiraeConfig.Common.corneliaAttackDamage.get());
// AquamiraeMod.loadFromConfig(this, Attributes.FOLLOW_RANGE, AquamiraeConfig.Common.corneliaFollowRange.get());
// AquamiraeMod.loadFromConfig(this, Attributes.STATE_KNOCKBACK, AquamiraeConfig.Common.corneliaAttackKnockback.get());
// AquamiraeMod.loadFromConfig(this, Attributes.KNOCKBACK_RESISTANCE, AquamiraeConfig.Common.corneliaKnockbackResistance.get());
// return super.finalizeSpawn(world, difficulty, reason, livingdata, tag);
// }
@Override public boolean canChangeDimensions() {
return false;
}
@Override public void startSeenByPlayer(@NotNull ServerPlayer player) {
super.startSeenByPlayer(player);
this.bossInfo.addPlayer(player);
}
@Override public void stopSeenByPlayer(@NotNull ServerPlayer player) {
super.stopSeenByPlayer(player);
this.bossInfo.removePlayer(player);
}
@Override public void customServerAiStep() {
super.customServerAiStep();
this.fallDistance=0;
if(this.timer<45)
this.setAttackingState(1);
else
this.setAttackingState(2);
this.bossInfo.setProgress(this.getHealth() / this.getMaxHealth());
}
public static AttributeSupplier.@NotNull Builder prepareAttributes() {
return Monster.createMobAttributes()
.add(Attributes.MOVEMENT_SPEED, 0.3D)
.add(Attributes.MAX_HEALTH, 150D)
.add(Attributes.ARMOR, 6D)
.add(Attributes.ATTACK_DAMAGE, 4)
.add(Attributes.FOLLOW_RANGE, 50)
.add(Attributes.KNOCKBACK_RESISTANCE, 1)
.add(Attributes.ATTACK_KNOCKBACK, 2);
}
private <E extends IAnimatable> PlayState predicate(AnimationEvent<E> event) {
if (event.isMoving()) {
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.walk", true));
return PlayState.CONTINUE;
}
// Random ran = new Random();
// int co = ran.nextInt(30);
// if(co==1) {
// event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.dimi.idle2", true));
// return PlayState.CONTINUE;
// }
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.idle", true));
return PlayState.CONTINUE;
}
private <E extends IAnimatable> PlayState predicate1(AnimationEvent<E> event) {
// if (this.timer>55 && !(this.dead || this.getHealth() < 0.01 || this.isDeadOrDying())) {
// event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.idle", true));
// return PlayState.CONTINUE;
// }
if (this.entityData.get(STATE)==1 && !(this.dead || this.getHealth() < 0.01 || this.isDeadOrDying())) {
int k=this.random.nextInt(10);
if(k<5)
{
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.attack", true));
return PlayState.CONTINUE;
}
// else if(k<7){
// event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.idle", true));
// return PlayState.CONTINUE;
// }
else{
if(this.getTarget()!=null)
{
LivingEntity livingentity = this.getTarget();
double d00 = livingentity.getX() - this.getX();
double d10 = livingentity.getZ() - this.getZ();
double d20 = Math.max(d00 * d00 + d10 * d10, 0.001D);
if(livingentity instanceof IronGolem) livingentity.hurt(DamageSource.CACTUS,(livingentity.getMaxHealth()+livingentity.getArmorValue())*0.25f);
livingentity.push(d00 / d20 * 4.0D, 0.4D, d10 / d20 * 4.0D);
}
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.attack2", false));
return PlayState.CONTINUE;
}
}
if (this.entityData.get(STATE) == 3 && !(this.dead || this.getHealth() < 0.01 || this.isDeadOrDying())) {
event.getController().setAnimation(new AnimationBuilder().addAnimation("animation.chief2.idle", false));
return PlayState.CONTINUE;
}
return PlayState.CONTINUE;
}
@Override
public void registerControllers(AnimationData data) {
data.addAnimationController(new AnimationController(this, "controller",
0, this::predicate));
data.addAnimationController(new AnimationController(this, "controller1",
0, this::predicate1));
}
}
憧憬
研究生顺利毕业、找到大厂工作。
文章评论