Reorganized Imports/Packages
This commit is contained in:
parent
a8beba9196
commit
770a5b4046
854 changed files with 42775 additions and 41811 deletions
155
src/main/java/org/betterx/betterend/entity/CubozoaEntity.java
Normal file
155
src/main/java/org/betterx/betterend/entity/CubozoaEntity.java
Normal file
|
@ -0,0 +1,155 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundGameEventPacket;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.*;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.AbstractSchoolingFish;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.betterend.registry.EndBiomes;
|
||||
import org.betterx.betterend.registry.EndItems;
|
||||
|
||||
public class CubozoaEntity extends AbstractSchoolingFish {
|
||||
public static final int VARIANTS = 2;
|
||||
private static final EntityDataAccessor<Byte> VARIANT = SynchedEntityData.defineId(
|
||||
CubozoaEntity.class,
|
||||
EntityDataSerializers.BYTE
|
||||
);
|
||||
private static final EntityDataAccessor<Byte> SCALE = SynchedEntityData.defineId(
|
||||
CubozoaEntity.class,
|
||||
EntityDataSerializers.BYTE
|
||||
);
|
||||
|
||||
public CubozoaEntity(EntityType<CubozoaEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world,
|
||||
DifficultyInstance difficulty,
|
||||
MobSpawnType spawnReason,
|
||||
SpawnGroupData entityData,
|
||||
CompoundTag entityTag) {
|
||||
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
|
||||
|
||||
if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) {
|
||||
this.entityData.set(VARIANT, (byte) 1);
|
||||
}
|
||||
|
||||
if (entityTag != null) {
|
||||
if (entityTag.contains("Variant")) {
|
||||
this.entityData.set(VARIANT, entityTag.getByte("Variant"));
|
||||
}
|
||||
if (entityTag.contains("Scale")) {
|
||||
this.entityData.set(SCALE, entityTag.getByte("Scale"));
|
||||
}
|
||||
}
|
||||
|
||||
this.refreshDimensions();
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
this.entityData.define(VARIANT, (byte) 0);
|
||||
this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
tag.putByte("Variant", (byte) getVariant());
|
||||
tag.putByte("Scale", getByteScale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag tag) {
|
||||
super.readAdditionalSaveData(tag);
|
||||
if (tag.contains("Variant")) {
|
||||
this.entityData.set(VARIANT, tag.getByte("Variant"));
|
||||
}
|
||||
if (tag.contains("Scale")) {
|
||||
this.entityData.set(SCALE, tag.getByte("Scale"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getBucketItemStack() {
|
||||
ItemStack bucket = EndItems.BUCKET_CUBOZOA.getDefaultInstance();
|
||||
CompoundTag tag = bucket.getOrCreateTag();
|
||||
tag.putByte("Variant", entityData.get(VARIANT));
|
||||
tag.putByte("Scale", entityData.get(SCALE));
|
||||
return bucket;
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return LivingEntity
|
||||
.createLivingAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 2.0)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.5);
|
||||
}
|
||||
|
||||
public int getVariant() {
|
||||
return (int) this.entityData.get(VARIANT);
|
||||
}
|
||||
|
||||
public byte getByteScale() {
|
||||
return this.entityData.get(SCALE);
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return getByteScale() / 32F + 0.75F;
|
||||
}
|
||||
|
||||
protected float getStandingEyeHeight(Pose pose, EntityDimensions dimensions) {
|
||||
return dimensions.height * 0.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) {
|
||||
int count = random.nextInt(3);
|
||||
if (count > 0) {
|
||||
ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.GELATINE, count));
|
||||
this.level.addFreshEntity(drop);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getFlopSound() {
|
||||
return SoundEvents.SALMON_FLOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playerTouch(Player player) {
|
||||
if (player instanceof ServerPlayer && player.hurt(DamageSource.mobAttack(this), 0.5F)) {
|
||||
if (!this.isSilent()) {
|
||||
((ServerPlayer) player).connection.send(new ClientboundGameEventPacket(
|
||||
ClientboundGameEventPacket.PUFFER_FISH_STING,
|
||||
0.0F
|
||||
));
|
||||
}
|
||||
if (random.nextBoolean()) {
|
||||
player.addEffect(new MobEffectInstance(MobEffects.POISON, 20, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
214
src/main/java/org/betterx/betterend/entity/DragonflyEntity.java
Normal file
214
src/main/java/org/betterx/betterend/entity/DragonflyEntity.java
Normal file
|
@ -0,0 +1,214 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.*;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.control.FlyingMoveControl;
|
||||
import net.minecraft.world.entity.ai.control.LookControl;
|
||||
import net.minecraft.world.entity.ai.goal.BreedGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FollowParentGoal;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos;
|
||||
import net.minecraft.world.entity.ai.util.HoverRandomPos;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
import net.minecraft.world.level.pathfinder.Path;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import org.betterx.bclib.entity.DespawnableAnimal;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.registry.EndEntities;
|
||||
import org.betterx.betterend.registry.EndSounds;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class DragonflyEntity extends DespawnableAnimal implements FlyingAnimal {
|
||||
public DragonflyEntity(EntityType<DragonflyEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
this.moveControl = new FlyingMoveControl(this, 20, true);
|
||||
this.lookControl = new DragonflyLookControl(this);
|
||||
this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);
|
||||
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
|
||||
this.xpReward = 1;
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return LivingEntity
|
||||
.createLivingAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 8.0D)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0D)
|
||||
.add(Attributes.FLYING_SPEED, 1.0D)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.1D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeLeashed(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PathNavigation createNavigation(Level world) {
|
||||
FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) {
|
||||
public boolean isStableDestination(BlockPos pos) {
|
||||
BlockState state = this.level.getBlockState(pos);
|
||||
return state.isAir() || !state.getMaterial().blocksMotion();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
}
|
||||
};
|
||||
birdNavigation.setCanOpenDoors(false);
|
||||
birdNavigation.setCanFloat(false);
|
||||
birdNavigation.setCanPassDoors(true);
|
||||
return birdNavigation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWalkTargetValue(BlockPos pos, LevelReader world) {
|
||||
return world.getBlockState(pos).isAir() ? 10.0F : 0.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new FloatGoal(this));
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
||||
this.goalSelector.addGoal(3, new FollowParentGoal(this, 1.0D));
|
||||
this.goalSelector.addGoal(4, new WanderAroundGoal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPushable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entity.MovementEmission getMovementEmission() {
|
||||
return Entity.MovementEmission.EVENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlying() {
|
||||
return !this.onGround;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoGravity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SoundEvent getAmbientSound() {
|
||||
return EndSounds.ENTITY_DRAGONFLY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getSoundVolume() {
|
||||
return MHelper.randRange(0.25F, 0.5F, random);
|
||||
}
|
||||
|
||||
class DragonflyLookControl extends LookControl {
|
||||
DragonflyLookControl(Mob entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
protected boolean resetXRotOnTick() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class WanderAroundGoal extends Goal {
|
||||
WanderAroundGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
|
||||
public boolean canUse() {
|
||||
return DragonflyEntity.this.navigation.isDone() && DragonflyEntity.this.random.nextInt(10) == 0;
|
||||
}
|
||||
|
||||
public boolean canContinueToUse() {
|
||||
return DragonflyEntity.this.navigation.isInProgress();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
Vec3 vec3d = this.getRandomLocation();
|
||||
if (vec3d != null) {
|
||||
BlockPos pos = new BlockPos(vec3d);
|
||||
try {
|
||||
Path path = DragonflyEntity.this.navigation.createPath(pos, 1);
|
||||
if (path != null) {
|
||||
DragonflyEntity.this.navigation.moveTo(path, 1.0D);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
super.start();
|
||||
}
|
||||
|
||||
private Vec3 getRandomLocation() {
|
||||
int h = BlocksHelper.downRay(DragonflyEntity.this.level, DragonflyEntity.this.blockPosition(), 16);
|
||||
Vec3 rotation = DragonflyEntity.this.getViewVector(0.0F);
|
||||
Vec3 airPos = HoverRandomPos.getPos(DragonflyEntity.this, 8, 7, rotation.x, rotation.z, 1.5707964F, 3, 1);
|
||||
if (airPos != null) {
|
||||
if (isInVoid(airPos)) {
|
||||
for (int i = 0; i < 8; i++) {
|
||||
airPos = HoverRandomPos.getPos(
|
||||
DragonflyEntity.this,
|
||||
16,
|
||||
7,
|
||||
rotation.x,
|
||||
rotation.z,
|
||||
MHelper.PI2,
|
||||
3,
|
||||
1
|
||||
);
|
||||
if (airPos != null && !isInVoid(airPos)) {
|
||||
return airPos;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (h > 5 && airPos.y() >= DragonflyEntity.this.blockPosition().getY()) {
|
||||
airPos = new Vec3(airPos.x, airPos.y - h * 0.5, airPos.z);
|
||||
}
|
||||
return airPos;
|
||||
}
|
||||
return AirAndWaterRandomPos.getPos(
|
||||
DragonflyEntity.this,
|
||||
8,
|
||||
4,
|
||||
-2,
|
||||
rotation.x,
|
||||
rotation.z,
|
||||
1.5707963705062866D
|
||||
);
|
||||
}
|
||||
|
||||
private boolean isInVoid(Vec3 pos) {
|
||||
int h = BlocksHelper.downRay(DragonflyEntity.this.level, new BlockPos(pos), 128);
|
||||
return h > 100;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) {
|
||||
return EndEntities.DRAGONFLY.create(world);
|
||||
}
|
||||
}
|
175
src/main/java/org/betterx/betterend/entity/EndFishEntity.java
Normal file
175
src/main/java/org/betterx/betterend/entity/EndFishEntity.java
Normal file
|
@ -0,0 +1,175 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.damagesource.EntityDamageSource;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.SpawnGroupData;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.animal.AbstractSchoolingFish;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.betterend.registry.EndBiomes;
|
||||
import org.betterx.betterend.registry.EndItems;
|
||||
|
||||
public class EndFishEntity extends AbstractSchoolingFish {
|
||||
public static final int VARIANTS_NORMAL = 5;
|
||||
public static final int VARIANTS_SULPHUR = 3;
|
||||
public static final int VARIANTS = VARIANTS_NORMAL + VARIANTS_SULPHUR;
|
||||
private static final EntityDataAccessor<Byte> VARIANT = SynchedEntityData.defineId(
|
||||
EndFishEntity.class,
|
||||
EntityDataSerializers.BYTE
|
||||
);
|
||||
private static final EntityDataAccessor<Byte> SCALE = SynchedEntityData.defineId(
|
||||
EndFishEntity.class,
|
||||
EntityDataSerializers.BYTE
|
||||
);
|
||||
|
||||
public EndFishEntity(EntityType<EndFishEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world,
|
||||
DifficultyInstance difficulty,
|
||||
MobSpawnType spawnReason,
|
||||
SpawnGroupData entityData,
|
||||
CompoundTag entityTag) {
|
||||
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
|
||||
|
||||
if (BiomeAPI.getFromBiome(world.getBiome(blockPosition())) == EndBiomes.SULPHUR_SPRINGS) {
|
||||
this.entityData.set(VARIANT, (byte) (random.nextInt(VARIANTS_SULPHUR) + VARIANTS_NORMAL));
|
||||
}
|
||||
|
||||
if (entityTag != null) {
|
||||
if (entityTag.contains("Variant")) {
|
||||
this.entityData.set(VARIANT, entityTag.getByte("variant"));
|
||||
}
|
||||
if (entityTag.contains("Scale")) {
|
||||
this.entityData.set(SCALE, entityTag.getByte("scale"));
|
||||
}
|
||||
}
|
||||
|
||||
this.refreshDimensions();
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
this.entityData.define(VARIANT, (byte) this.getRandom().nextInt(VARIANTS_NORMAL));
|
||||
this.entityData.define(SCALE, (byte) this.getRandom().nextInt(16));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
tag.putByte("Variant", (byte) getVariant());
|
||||
tag.putByte("Scale", getByteScale());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag tag) {
|
||||
super.readAdditionalSaveData(tag);
|
||||
if (tag.contains("Variant")) {
|
||||
this.entityData.set(VARIANT, tag.getByte("Variant"));
|
||||
}
|
||||
if (tag.contains("Scale")) {
|
||||
this.entityData.set(SCALE, tag.getByte("Scale"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getBucketItemStack() {
|
||||
ItemStack bucket = EndItems.BUCKET_END_FISH.getDefaultInstance();
|
||||
CompoundTag tag = bucket.getOrCreateTag();
|
||||
tag.putByte("variant", entityData.get(VARIANT));
|
||||
tag.putByte("scale", entityData.get(SCALE));
|
||||
return bucket;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getFlopSound() {
|
||||
return SoundEvents.TROPICAL_FISH_FLOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return SoundEvents.SALMON_AMBIENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvents.SALMON_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(DamageSource source) {
|
||||
return SoundEvents.SALMON_HURT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (random.nextInt(8) == 0 && getFeetBlockState().is(Blocks.WATER)) {
|
||||
double x = getX() + random.nextGaussian() * 0.2;
|
||||
double y = getY() + random.nextGaussian() * 0.2;
|
||||
double z = getZ() + random.nextGaussian() * 0.2;
|
||||
level.addParticle(ParticleTypes.BUBBLE, x, y, z, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return LivingEntity
|
||||
.createLivingAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 2.0)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.75);
|
||||
}
|
||||
|
||||
public int getVariant() {
|
||||
return (int) this.entityData.get(VARIANT);
|
||||
}
|
||||
|
||||
public byte getByteScale() {
|
||||
return this.entityData.get(SCALE);
|
||||
}
|
||||
|
||||
public float getScale() {
|
||||
return getByteScale() / 32F + 0.75F;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) {
|
||||
Item item = source.isFire() ? EndItems.END_FISH_COOKED : EndItems.END_FISH_RAW;
|
||||
if (causedByPlayer && source instanceof EntityDamageSource) {
|
||||
EntityDamageSource damageSource = (EntityDamageSource) source;
|
||||
ItemStack handItem = ((Player) damageSource.getEntity()).getItemInHand(InteractionHand.MAIN_HAND);
|
||||
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FIRE_ASPECT, handItem) > 0) {
|
||||
item = EndItems.END_FISH_COOKED;
|
||||
}
|
||||
}
|
||||
ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(item));
|
||||
this.level.addFreshEntity(drop);
|
||||
}
|
||||
}
|
431
src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java
Normal file
431
src/main/java/org/betterx/betterend/entity/EndSlimeEntity.java
Normal file
|
@ -0,0 +1,431 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.BlockPos.MutableBlockPos;
|
||||
import net.minecraft.core.particles.ParticleOptions;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.syncher.EntityDataAccessor;
|
||||
import net.minecraft.network.syncher.EntityDataSerializers;
|
||||
import net.minecraft.network.syncher.SynchedEntityData;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.MobSpawnType;
|
||||
import net.minecraft.world.entity.SpawnGroupData;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.control.MoveControl;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
||||
import net.minecraft.world.entity.animal.IronGolem;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.monster.Slime;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.ServerLevelAccessor;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
|
||||
import org.betterx.bclib.api.biomes.BiomeAPI;
|
||||
import org.betterx.bclib.api.tag.CommonBlockTags;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.bclib.world.biomes.BCLBiome;
|
||||
import org.betterx.betterend.interfaces.ISlime;
|
||||
import org.betterx.betterend.registry.EndBiomes;
|
||||
import org.betterx.betterend.util.GlobalState;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public class EndSlimeEntity extends Slime {
|
||||
private static final EntityDataAccessor<Byte> VARIANT = SynchedEntityData.defineId(
|
||||
EndSlimeEntity.class,
|
||||
EntityDataSerializers.BYTE
|
||||
);
|
||||
|
||||
public EndSlimeEntity(EntityType<EndSlimeEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
this.moveControl = new EndSlimeMoveControl(this);
|
||||
}
|
||||
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new SwimmingGoal());
|
||||
this.goalSelector.addGoal(2, new FaceTowardTargetGoal());
|
||||
this.goalSelector.addGoal(3, new RandomLookGoal());
|
||||
this.goalSelector.addGoal(5, new MoveGoal());
|
||||
this.targetSelector.addGoal(
|
||||
1,
|
||||
new NearestAttackableTargetGoal<Player>(this, Player.class, 10, true, false, (livingEntity) -> {
|
||||
return Math.abs(livingEntity.getY() - this.getY()) <= 4.0D;
|
||||
})
|
||||
);
|
||||
this.targetSelector.addGoal(3, new NearestAttackableTargetGoal<IronGolem>(this, IronGolem.class, true));
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return LivingEntity
|
||||
.createLivingAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 1.0D)
|
||||
.add(Attributes.ATTACK_DAMAGE, 1.0D)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0D)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.15D);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SpawnGroupData finalizeSpawn(ServerLevelAccessor world,
|
||||
DifficultyInstance difficulty,
|
||||
MobSpawnType spawnReason,
|
||||
SpawnGroupData entityData,
|
||||
CompoundTag entityTag) {
|
||||
SpawnGroupData data = super.finalizeSpawn(world, difficulty, spawnReason, entityData, entityTag);
|
||||
BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(blockPosition()));
|
||||
if (biome == EndBiomes.FOGGY_MUSHROOMLAND) {
|
||||
this.setMossy();
|
||||
} else if (biome == EndBiomes.MEGALAKE || biome == EndBiomes.MEGALAKE_GROVE) {
|
||||
this.setLake();
|
||||
} else if (biome == EndBiomes.AMBER_LAND) {
|
||||
this.setAmber(true);
|
||||
}
|
||||
this.refreshDimensions();
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void defineSynchedData() {
|
||||
super.defineSynchedData();
|
||||
this.entityData.define(VARIANT, (byte) 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
super.addAdditionalSaveData(tag);
|
||||
tag.putByte("Variant", (byte) getSlimeType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag tag) {
|
||||
super.readAdditionalSaveData(tag);
|
||||
if (tag.contains("Variant")) {
|
||||
this.entityData.set(VARIANT, tag.getByte("Variant"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ParticleOptions getParticleType() {
|
||||
return ParticleTypes.PORTAL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(RemovalReason reason) {
|
||||
int i = this.getSize();
|
||||
if (!this.level.isClientSide && i > 1 && this.isDeadOrDying()) {
|
||||
Component text = this.getCustomName();
|
||||
boolean bl = this.isNoAi();
|
||||
float f = (float) i / 4.0F;
|
||||
int j = i / 2;
|
||||
int k = 2 + this.random.nextInt(3);
|
||||
int type = this.getSlimeType();
|
||||
|
||||
for (int l = 0; l < k; ++l) {
|
||||
float g = ((float) (l % 2) - 0.5F) * f;
|
||||
float h = ((float) (l / 2) - 0.5F) * f;
|
||||
EndSlimeEntity slimeEntity = (EndSlimeEntity) this.getType().create(this.level);
|
||||
if (this.isPersistenceRequired()) {
|
||||
slimeEntity.setPersistenceRequired();
|
||||
}
|
||||
|
||||
slimeEntity.setSlimeType(type);
|
||||
slimeEntity.setCustomName(text);
|
||||
slimeEntity.setNoAi(bl);
|
||||
slimeEntity.setInvulnerable(this.isInvulnerable());
|
||||
((ISlime) slimeEntity).be_setSlimeSize(j, true);
|
||||
slimeEntity.refreshDimensions();
|
||||
slimeEntity.moveTo(
|
||||
this.getX() + (double) g,
|
||||
this.getY() + 0.5D,
|
||||
this.getZ() + (double) h,
|
||||
this.random.nextFloat() * 360.0F,
|
||||
0.0F
|
||||
);
|
||||
this.level.addFreshEntity(slimeEntity);
|
||||
}
|
||||
}
|
||||
|
||||
((ISlime) this).entityRemove(reason);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) {
|
||||
int maxCount = this.getSize();
|
||||
int minCount = maxCount >> 1;
|
||||
if (minCount < 1) {
|
||||
minCount = 1;
|
||||
}
|
||||
if (causedByPlayer && this.lastHurtByPlayer != null) {
|
||||
int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer);
|
||||
minCount += looting;
|
||||
}
|
||||
int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount;
|
||||
ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(Items.SLIME_BALL, count));
|
||||
this.level.addFreshEntity(drop);
|
||||
}
|
||||
|
||||
public int getSlimeType() {
|
||||
return this.entityData.get(VARIANT).intValue();
|
||||
}
|
||||
|
||||
public void setSlimeType(int value) {
|
||||
this.entityData.set(VARIANT, (byte) value);
|
||||
}
|
||||
|
||||
protected void setMossy() {
|
||||
setSlimeType(1);
|
||||
}
|
||||
|
||||
public boolean isMossy() {
|
||||
return getSlimeType() == 1;
|
||||
}
|
||||
|
||||
protected void setLake() {
|
||||
setSlimeType(2);
|
||||
}
|
||||
|
||||
public boolean isLake() {
|
||||
return getSlimeType() == 2;
|
||||
}
|
||||
|
||||
protected void setAmber(boolean mossy) {
|
||||
this.entityData.set(VARIANT, (byte) 3);
|
||||
}
|
||||
|
||||
public boolean isAmber() {
|
||||
return this.entityData.get(VARIANT) == 3;
|
||||
}
|
||||
|
||||
public boolean isChorus() {
|
||||
return this.entityData.get(VARIANT) == 0;
|
||||
}
|
||||
|
||||
public static boolean canSpawn(EntityType entityType,
|
||||
LevelAccessor world,
|
||||
MobSpawnType spawnType,
|
||||
BlockPos pos,
|
||||
RandomSource random) {
|
||||
if (!world.getBlockState(pos.below()).is(CommonBlockTags.END_STONES)) {
|
||||
return false;
|
||||
}
|
||||
BCLBiome biome = BiomeAPI.getFromBiome(world.getBiome(pos));
|
||||
if (biome == EndBiomes.CHORUS_FOREST || biome == EndBiomes.MEGALAKE) {
|
||||
return true;
|
||||
}
|
||||
if (biome == EndBiomes.MEGALAKE_GROVE && random.nextBoolean()) {
|
||||
return true;
|
||||
}
|
||||
return random.nextInt(4) == 0 && isWaterNear(world, pos);
|
||||
}
|
||||
|
||||
private static boolean isWaterNear(LevelAccessor world, BlockPos pos) {
|
||||
final MutableBlockPos POS = GlobalState.stateForThread().POS;
|
||||
|
||||
for (int x = pos.getX() - 32; x <= pos.getX() + 32; x++) {
|
||||
POS.setX(x);
|
||||
for (int z = pos.getZ() - 32; z <= pos.getZ() + 32; z++) {
|
||||
POS.setZ(z);
|
||||
for (int y = pos.getY() - 8; y <= pos.getY() + 8; y++) {
|
||||
POS.setY(y);
|
||||
if (world.getBlockState(POS).getBlock() == Blocks.WATER) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class MoveGoal extends Goal {
|
||||
public MoveGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE));
|
||||
}
|
||||
|
||||
public boolean canUse() {
|
||||
if (EndSlimeEntity.this.isPassenger()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
float yaw = EndSlimeEntity.this.getYHeadRot();
|
||||
float speed = EndSlimeEntity.this.getSpeed();
|
||||
if (speed > 0.1) {
|
||||
float dx = Mth.sin(-yaw * 0.017453292F);
|
||||
float dz = Mth.cos(-yaw * 0.017453292F);
|
||||
BlockPos pos = EndSlimeEntity.this.blockPosition().offset(dx * speed * 4, 0, dz * speed * 4);
|
||||
int down = BlocksHelper.downRay(EndSlimeEntity.this.level, pos, 16);
|
||||
return down < 5;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.0D);
|
||||
}
|
||||
}
|
||||
|
||||
class SwimmingGoal extends Goal {
|
||||
public SwimmingGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.JUMP, Goal.Flag.MOVE));
|
||||
EndSlimeEntity.this.getNavigation().setCanFloat(true);
|
||||
}
|
||||
|
||||
public boolean canUse() {
|
||||
return (EndSlimeEntity.this.isInWater() || EndSlimeEntity.this.isInLava()) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (EndSlimeEntity.this.getRandom().nextFloat() < 0.8F) {
|
||||
EndSlimeEntity.this.getJumpControl().jump();
|
||||
}
|
||||
|
||||
((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).move(1.2D);
|
||||
}
|
||||
}
|
||||
|
||||
class RandomLookGoal extends Goal {
|
||||
private float targetYaw;
|
||||
private int timer;
|
||||
|
||||
public RandomLookGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.LOOK));
|
||||
}
|
||||
|
||||
public boolean canUse() {
|
||||
return EndSlimeEntity.this.getTarget() == null && (EndSlimeEntity.this.onGround || EndSlimeEntity.this.isInWater() || EndSlimeEntity.this
|
||||
.isInLava() || EndSlimeEntity.this.hasEffect(MobEffects.LEVITATION)) && EndSlimeEntity.this.getMoveControl() instanceof EndSlimeMoveControl;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
if (--this.timer <= 0) {
|
||||
this.timer = 40 + EndSlimeEntity.this.getRandom().nextInt(60);
|
||||
this.targetYaw = (float) EndSlimeEntity.this.getRandom().nextInt(360);
|
||||
}
|
||||
|
||||
((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look(this.targetYaw, false);
|
||||
}
|
||||
}
|
||||
|
||||
class FaceTowardTargetGoal extends Goal {
|
||||
private int ticksLeft;
|
||||
|
||||
public FaceTowardTargetGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.LOOK));
|
||||
}
|
||||
|
||||
public boolean canUse() {
|
||||
LivingEntity livingEntity = EndSlimeEntity.this.getTarget();
|
||||
if (livingEntity == null) {
|
||||
return false;
|
||||
} else if (!livingEntity.isAlive()) {
|
||||
return false;
|
||||
} else {
|
||||
return (!(livingEntity instanceof Player) || !((Player) livingEntity).getAbilities().invulnerable) && EndSlimeEntity.this
|
||||
.getMoveControl() instanceof EndSlimeMoveControl;
|
||||
}
|
||||
}
|
||||
|
||||
public void start() {
|
||||
this.ticksLeft = 300;
|
||||
super.start();
|
||||
}
|
||||
|
||||
public boolean canContinueToUse() {
|
||||
LivingEntity livingEntity = EndSlimeEntity.this.getTarget();
|
||||
if (livingEntity == null) {
|
||||
return false;
|
||||
} else if (!livingEntity.isAlive()) {
|
||||
return false;
|
||||
} else if (livingEntity instanceof Player && ((Player) livingEntity).getAbilities().invulnerable) {
|
||||
return false;
|
||||
} else {
|
||||
return --this.ticksLeft > 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
EndSlimeEntity.this.lookAt(EndSlimeEntity.this.getTarget(), 10.0F, 10.0F);
|
||||
((EndSlimeMoveControl) EndSlimeEntity.this.getMoveControl()).look(
|
||||
EndSlimeEntity.this.getYRot(),
|
||||
EndSlimeEntity.this.isDealsDamage()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class EndSlimeMoveControl extends MoveControl {
|
||||
private float targetYaw;
|
||||
private int ticksUntilJump;
|
||||
private boolean jumpOften;
|
||||
|
||||
public EndSlimeMoveControl(EndSlimeEntity slime) {
|
||||
super(slime);
|
||||
this.targetYaw = 180.0F * slime.getYRot() / 3.1415927F;
|
||||
}
|
||||
|
||||
public void look(float targetYaw, boolean jumpOften) {
|
||||
this.targetYaw = targetYaw;
|
||||
this.jumpOften = jumpOften;
|
||||
}
|
||||
|
||||
public void move(double speed) {
|
||||
this.speedModifier = speed;
|
||||
this.operation = MoveControl.Operation.MOVE_TO;
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
this.mob.setYRot(this.rotlerp(this.mob.getYRot(), this.targetYaw, 90.0F));
|
||||
this.mob.yHeadRot = this.mob.getYRot();
|
||||
this.mob.yBodyRot = this.mob.getYRot();
|
||||
if (this.operation != MoveControl.Operation.MOVE_TO) {
|
||||
this.mob.setZza(0.0F);
|
||||
} else {
|
||||
this.operation = MoveControl.Operation.WAIT;
|
||||
if (this.mob.isOnGround()) {
|
||||
this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
||||
if (this.ticksUntilJump-- <= 0) {
|
||||
this.ticksUntilJump = EndSlimeEntity.this.getJumpDelay();
|
||||
if (this.jumpOften) {
|
||||
this.ticksUntilJump /= 3;
|
||||
}
|
||||
|
||||
EndSlimeEntity.this.getJumpControl().jump();
|
||||
if (EndSlimeEntity.this.doPlayJumpSound()) {
|
||||
EndSlimeEntity.this.playSound(
|
||||
EndSlimeEntity.this.getJumpSound(),
|
||||
EndSlimeEntity.this.getSoundVolume(),
|
||||
getJumpSoundPitch()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
EndSlimeEntity.this.xxa = 0.0F;
|
||||
EndSlimeEntity.this.zza = 0.0F;
|
||||
this.mob.setSpeed(0.0F);
|
||||
}
|
||||
} else {
|
||||
this.mob.setSpeed((float) (this.speedModifier * this.mob.getAttributeValue(Attributes.MOVEMENT_SPEED)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private float getJumpSoundPitch() {
|
||||
float f = EndSlimeEntity.this.isTiny() ? 1.4F : 0.8F;
|
||||
return ((EndSlimeEntity.this.random.nextFloat() - EndSlimeEntity.this.random.nextFloat()) * 0.2F + 1.0F) * f;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.particles.ParticleTypes;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.effect.MobEffectInstance;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
|
||||
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
|
||||
import net.minecraft.world.entity.ai.goal.RandomLookAroundGoal;
|
||||
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
|
||||
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
||||
import net.minecraft.world.entity.monster.Monster;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.registry.EndSounds;
|
||||
|
||||
public class ShadowWalkerEntity extends Monster {
|
||||
public ShadowWalkerEntity(EntityType<ShadowWalkerEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(2, new AttackGoal(this, 1.0D, false));
|
||||
this.goalSelector.addGoal(7, new WaterAvoidingRandomStrollGoal(this, 1.0D));
|
||||
this.goalSelector.addGoal(8, new LookAtPlayerGoal(this, Player.class, 8.0F));
|
||||
this.goalSelector.addGoal(8, new RandomLookAroundGoal(this));
|
||||
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<Player>(this, Player.class, true));
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return Monster
|
||||
.createMonsterAttributes()
|
||||
.add(Attributes.FOLLOW_RANGE, 35.0)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.15)
|
||||
.add(Attributes.ATTACK_DAMAGE, 4.5)
|
||||
.add(Attributes.ARMOR, 2.0)
|
||||
.add(Attributes.SPAWN_REINFORCEMENTS_CHANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
level.addParticle(
|
||||
ParticleTypes.ASH,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
level.addParticle(
|
||||
ParticleTypes.SMOKE,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
level.addParticle(
|
||||
ParticleTypes.ENTITY_EFFECT,
|
||||
getX() + random.nextGaussian() * 0.2,
|
||||
getY() + random.nextGaussian() * 0.5 + 1,
|
||||
getZ() + random.nextGaussian() * 0.2,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getAmbientSound() {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getHurtSound(DamageSource source) {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER_DAMAGE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SoundEvent getDeathSound() {
|
||||
return EndSounds.ENTITY_SHADOW_WALKER_DEATH;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void playStepSound(BlockPos pos, BlockState state) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getSoundVolume() {
|
||||
return MHelper.randRange(0.25F, 0.5F, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getVoicePitch() {
|
||||
return MHelper.randRange(0.75F, 1.25F, random);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doHurtTarget(Entity target) {
|
||||
boolean attack = super.doHurtTarget(target);
|
||||
if (attack && target instanceof LivingEntity) {
|
||||
LivingEntity living = (LivingEntity) target;
|
||||
if (!(living.hasEffect(MobEffects.BLINDNESS))) {
|
||||
living.addEffect(new MobEffectInstance(MobEffects.BLINDNESS, 60));
|
||||
}
|
||||
}
|
||||
return attack;
|
||||
}
|
||||
|
||||
private final class AttackGoal extends MeleeAttackGoal {
|
||||
private final ShadowWalkerEntity walker;
|
||||
private int ticks;
|
||||
|
||||
public AttackGoal(ShadowWalkerEntity walker, double speed, boolean pauseWhenMobIdle) {
|
||||
super(walker, speed, pauseWhenMobIdle);
|
||||
this.walker = walker;
|
||||
}
|
||||
|
||||
public void start() {
|
||||
super.start();
|
||||
this.ticks = 0;
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
super.stop();
|
||||
this.walker.setAggressive(false);
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
++this.ticks;
|
||||
this.walker.setAggressive(this.ticks >= 5 && this.getTicksUntilNextAttack() < this.getAttackInterval() / 2);
|
||||
}
|
||||
}
|
||||
}
|
321
src/main/java/org/betterx/betterend/entity/SilkMothEntity.java
Normal file
321
src/main/java/org/betterx/betterend/entity/SilkMothEntity.java
Normal file
|
@ -0,0 +1,321 @@
|
|||
package org.betterx.betterend.entity;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtUtils;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.*;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.ai.control.FlyingMoveControl;
|
||||
import net.minecraft.world.entity.ai.control.LookControl;
|
||||
import net.minecraft.world.entity.ai.goal.BreedGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
||||
import net.minecraft.world.entity.ai.goal.FollowParentGoal;
|
||||
import net.minecraft.world.entity.ai.goal.Goal;
|
||||
import net.minecraft.world.entity.ai.navigation.FlyingPathNavigation;
|
||||
import net.minecraft.world.entity.ai.navigation.PathNavigation;
|
||||
import net.minecraft.world.entity.ai.util.AirAndWaterRandomPos;
|
||||
import net.minecraft.world.entity.ai.util.HoverRandomPos;
|
||||
import net.minecraft.world.entity.animal.FlyingAnimal;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import org.betterx.bclib.entity.DespawnableAnimal;
|
||||
import org.betterx.bclib.util.BlocksHelper;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.blocks.EndBlockProperties;
|
||||
import org.betterx.betterend.registry.EndBlocks;
|
||||
import org.betterx.betterend.registry.EndEntities;
|
||||
import org.betterx.betterend.registry.EndItems;
|
||||
|
||||
import java.util.EnumSet;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SilkMothEntity extends DespawnableAnimal implements FlyingAnimal {
|
||||
private BlockPos hivePos;
|
||||
private BlockPos entrance;
|
||||
private Level hiveWorld;
|
||||
|
||||
public SilkMothEntity(EntityType<? extends SilkMothEntity> entityType, Level world) {
|
||||
super(entityType, world);
|
||||
this.moveControl = new FlyingMoveControl(this, 20, true);
|
||||
this.lookControl = new MothLookControl(this);
|
||||
this.setPathfindingMalus(BlockPathTypes.WATER, -1.0F);
|
||||
this.setPathfindingMalus(BlockPathTypes.DANGER_FIRE, -1.0F);
|
||||
this.xpReward = 1;
|
||||
}
|
||||
|
||||
public static AttributeSupplier.Builder createMobAttributes() {
|
||||
return LivingEntity
|
||||
.createLivingAttributes()
|
||||
.add(Attributes.MAX_HEALTH, 2.0D)
|
||||
.add(Attributes.FOLLOW_RANGE, 16.0D)
|
||||
.add(Attributes.FLYING_SPEED, 0.4D)
|
||||
.add(Attributes.MOVEMENT_SPEED, 0.1D);
|
||||
}
|
||||
|
||||
public void setHive(Level world, BlockPos hive) {
|
||||
this.hivePos = hive;
|
||||
this.hiveWorld = world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canBeLeashed(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addAdditionalSaveData(CompoundTag tag) {
|
||||
if (hivePos != null) {
|
||||
tag.put("HivePos", NbtUtils.writeBlockPos(hivePos));
|
||||
tag.putString("HiveWorld", hiveWorld.dimension().location().toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readAdditionalSaveData(CompoundTag tag) {
|
||||
if (tag.contains("HivePos")) {
|
||||
hivePos = NbtUtils.readBlockPos(tag.getCompound("HivePos"));
|
||||
ResourceLocation worldID = new ResourceLocation(tag.getString("HiveWorld"));
|
||||
try {
|
||||
hiveWorld = level.getServer().getLevel(ResourceKey.create(Registry.DIMENSION_REGISTRY, worldID));
|
||||
} catch (Exception e) {
|
||||
BetterEnd.LOGGER.warning("Silk Moth Hive World {} is missing!", worldID);
|
||||
hivePos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerGoals() {
|
||||
this.goalSelector.addGoal(1, new ReturnToHiveGoal());
|
||||
this.goalSelector.addGoal(2, new BreedGoal(this, 1.0D));
|
||||
this.goalSelector.addGoal(5, new FollowParentGoal(this, 1.25D));
|
||||
this.goalSelector.addGoal(8, new WanderAroundGoal());
|
||||
this.goalSelector.addGoal(9, new FloatGoal(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PathNavigation createNavigation(Level world) {
|
||||
FlyingPathNavigation birdNavigation = new FlyingPathNavigation(this, world) {
|
||||
public boolean isStableDestination(BlockPos pos) {
|
||||
BlockState state = this.level.getBlockState(pos);
|
||||
return state.isAir() || !state.getMaterial().blocksMotion();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
super.tick();
|
||||
}
|
||||
};
|
||||
birdNavigation.setCanOpenDoors(false);
|
||||
birdNavigation.setCanFloat(false);
|
||||
birdNavigation.setCanPassDoors(true);
|
||||
return birdNavigation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPushable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean causeFallDamage(float fallDistance, float damageMultiplier, DamageSource damageSource) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entity.MovementEmission getMovementEmission() {
|
||||
return Entity.MovementEmission.EVENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlying() {
|
||||
return !this.onGround;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNoGravity() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AgeableMob getBreedOffspring(ServerLevel world, AgeableMob entity) {
|
||||
return EndEntities.SILK_MOTH.create(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void dropFromLootTable(DamageSource source, boolean causedByPlayer) {
|
||||
int minCount = 0;
|
||||
int maxCount = 1;
|
||||
if (causedByPlayer && this.lastHurtByPlayer != null) {
|
||||
int looting = EnchantmentHelper.getMobLooting(this.lastHurtByPlayer);
|
||||
minCount += looting;
|
||||
maxCount += looting;
|
||||
if (maxCount > 2) {
|
||||
maxCount = 2;
|
||||
}
|
||||
}
|
||||
int count = minCount < maxCount ? MHelper.randRange(minCount, maxCount, random) : maxCount;
|
||||
ItemEntity drop = new ItemEntity(level, getX(), getY(), getZ(), new ItemStack(EndItems.SILK_FIBER, count));
|
||||
this.level.addFreshEntity(drop);
|
||||
}
|
||||
|
||||
class MothLookControl extends LookControl {
|
||||
MothLookControl(Mob entity) {
|
||||
super(entity);
|
||||
}
|
||||
|
||||
protected boolean resetXRotOnTick() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class WanderAroundGoal extends Goal {
|
||||
WanderAroundGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return SilkMothEntity.this.navigation.isDone() && SilkMothEntity.this.random.nextInt(10) == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return SilkMothEntity.this.navigation.isInProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
Vec3 vec3d = null;
|
||||
if (SilkMothEntity.this.hivePos != null && SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level) {
|
||||
if (SilkMothEntity.this.position()
|
||||
.distanceToSqr(SilkMothEntity.this.hivePos.getX(),
|
||||
SilkMothEntity.this.hivePos.getY(),
|
||||
SilkMothEntity.this.hivePos.getZ()) > 16) {
|
||||
vec3d = SilkMothEntity.this.position().add(random.nextGaussian() * 2, 0, random.nextGaussian() * 2);
|
||||
}
|
||||
}
|
||||
vec3d = vec3d == null ? this.getRandomLocation() : vec3d;
|
||||
if (vec3d != null) {
|
||||
try {
|
||||
SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(new BlockPos(vec3d),
|
||||
1), 1.0D);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Vec3 getRandomLocation() {
|
||||
Vec3 vec3d3 = SilkMothEntity.this.getViewVector(0.0F);
|
||||
Vec3 vec3d4 = HoverRandomPos.getPos(SilkMothEntity.this, 8, 7, vec3d3.x, vec3d3.z, 1.5707964F, 3, 1);
|
||||
return vec3d4 != null ? vec3d4 : AirAndWaterRandomPos.getPos(
|
||||
SilkMothEntity.this,
|
||||
8,
|
||||
4,
|
||||
-2,
|
||||
vec3d3.x,
|
||||
vec3d3.z,
|
||||
1.5707963705062866D
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ReturnToHiveGoal extends Goal {
|
||||
ReturnToHiveGoal() {
|
||||
this.setFlags(EnumSet.of(Goal.Flag.MOVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse() {
|
||||
return SilkMothEntity.this.hivePos != null &&
|
||||
SilkMothEntity.this.hiveWorld == SilkMothEntity.this.level &&
|
||||
SilkMothEntity.this.navigation.isDone() &&
|
||||
SilkMothEntity.this.random.nextInt(8) == 0 &&
|
||||
SilkMothEntity.this.position().distanceToSqr(
|
||||
SilkMothEntity.this.hivePos.getX(),
|
||||
SilkMothEntity.this.hivePos.getY(),
|
||||
SilkMothEntity.this.hivePos.getZ()
|
||||
) < 16384;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canContinueToUse() {
|
||||
return SilkMothEntity.this.navigation.isInProgress() && level.getBlockState(entrance)
|
||||
.isAir() && (level.getBlockState(hivePos)
|
||||
.is(EndBlocks.SILK_MOTH_NEST) || level
|
||||
.getBlockState(hivePos)
|
||||
.is(EndBlocks.SILK_MOTH_HIVE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
BlockState state = SilkMothEntity.this.level.getBlockState(SilkMothEntity.this.hivePos);
|
||||
if (!state.is(EndBlocks.SILK_MOTH_NEST) && !state.is(EndBlocks.SILK_MOTH_HIVE)) {
|
||||
SilkMothEntity.this.hivePos = null;
|
||||
return;
|
||||
}
|
||||
try {
|
||||
SilkMothEntity.this.entrance = SilkMothEntity.this.hivePos.relative(state.getValue(BlockStateProperties.HORIZONTAL_FACING));
|
||||
SilkMothEntity.this.navigation.moveTo(SilkMothEntity.this.navigation.createPath(entrance, 1), 1.0D);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
super.tick();
|
||||
if (SilkMothEntity.this.entrance == null) {
|
||||
return;
|
||||
}
|
||||
double dx = Math.abs(SilkMothEntity.this.entrance.getX() - SilkMothEntity.this.getX());
|
||||
double dy = Math.abs(SilkMothEntity.this.entrance.getY() - SilkMothEntity.this.getY());
|
||||
double dz = Math.abs(SilkMothEntity.this.entrance.getZ() - SilkMothEntity.this.getZ());
|
||||
if (dx + dy + dz < 1) {
|
||||
BlockState state = SilkMothEntity.this.level.getBlockState(hivePos);
|
||||
if (state.is(EndBlocks.SILK_MOTH_NEST) || state.is(EndBlocks.SILK_MOTH_HIVE)) {
|
||||
int fullness = state.getValue(EndBlockProperties.FULLNESS);
|
||||
boolean isHive = state.is(EndBlocks.SILK_MOTH_HIVE);
|
||||
if (fullness < 3 && (isHive || SilkMothEntity.this.random.nextBoolean())) {
|
||||
fullness += isHive ? MHelper.randRange(1, 2, random) : 1;
|
||||
if (fullness > 3) {
|
||||
fullness = 3;
|
||||
}
|
||||
BlocksHelper.setWithUpdate(
|
||||
SilkMothEntity.this.hiveWorld,
|
||||
SilkMothEntity.this.hivePos,
|
||||
state.setValue(EndBlockProperties.FULLNESS, fullness)
|
||||
);
|
||||
}
|
||||
SilkMothEntity.this.level.playSound(
|
||||
null,
|
||||
SilkMothEntity.this.entrance,
|
||||
SoundEvents.BEEHIVE_ENTER,
|
||||
SoundSource.BLOCKS,
|
||||
1,
|
||||
1
|
||||
);
|
||||
SilkMothEntity.this.discard();
|
||||
} else {
|
||||
SilkMothEntity.this.hivePos = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package org.betterx.betterend.entity.model;
|
||||
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartNames;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||||
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.entity.CubozoaEntity;
|
||||
|
||||
public class CubozoaEntityModel extends EntityModel<CubozoaEntity> {
|
||||
private final static int TENTACLE_COUNT = 4;
|
||||
|
||||
private final ModelPart model;
|
||||
private final ModelPart[] tentacle_center;
|
||||
private final ModelPart[] tentacle;
|
||||
private float scaleY;
|
||||
private float scaleXZ;
|
||||
|
||||
public static LayerDefinition getTexturedModelData() {
|
||||
MeshDefinition modelData = new MeshDefinition();
|
||||
PartDefinition modelPartData = modelData.getRoot();
|
||||
|
||||
PartDefinition bodyPart = modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(0, 17).addBox(-2.0F, -12.5F, -2.0F, 4.0F, 4.0F, 4.0F),
|
||||
PartPose.offset(0.0F, 24.0F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
"main_cube_r1",
|
||||
CubeListBuilder.create().texOffs(0, 0).addBox(-5.0F, -7.0F, -5.0F, 10.0F, 7.0F, 10.0F),
|
||||
PartPose.offsetAndRotation(0.0F, -14.0F, 0.0F, 0.0F, 0.0F, -3.1416F)
|
||||
);
|
||||
|
||||
for (int i = 1; i <= TENTACLE_COUNT; i++) {
|
||||
PartDefinition tentaclePart = bodyPart.addOrReplaceChild(
|
||||
"tentacle_center_" + i,
|
||||
CubeListBuilder.create(),
|
||||
PartPose.offsetAndRotation(0.0F, 0.0F, 0.0F, 0.0F, i * 1.5708F, 0.0F)
|
||||
);
|
||||
|
||||
tentaclePart.addOrReplaceChild(
|
||||
"tentacle_" + i,
|
||||
CubeListBuilder.create().texOffs(16, 17).addBox(-4.0F, 0.0F, 0.0F, 8.0F, 7.0F, 0.0F),
|
||||
PartPose.offset(0.0F, -7.0F, 4.5F)
|
||||
);
|
||||
}
|
||||
|
||||
return LayerDefinition.create(modelData, 48, 48);
|
||||
}
|
||||
|
||||
public CubozoaEntityModel(ModelPart modelPart) {
|
||||
super(RenderType::entityTranslucent);
|
||||
tentacle = new ModelPart[TENTACLE_COUNT];
|
||||
tentacle_center = new ModelPart[TENTACLE_COUNT];
|
||||
|
||||
model = modelPart.getChild(PartNames.BODY);
|
||||
for (int i = 1; i <= TENTACLE_COUNT; i++) {
|
||||
tentacle_center[i - 1] = model.getChild("tentacle_center_" + i);
|
||||
tentacle[i - 1] = tentacle_center[i - 1].getChild("tentacle_" + i);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(CubozoaEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
float sin = Mth.sin(animationProgress * 0.13F);
|
||||
scaleY = sin * 0.1F + 0.9F;
|
||||
scaleXZ = Mth.sin(animationProgress * 0.13F + 3.14F) * 0.1F + 0.9F;
|
||||
|
||||
for (int i = 0; i < TENTACLE_COUNT; i++) {
|
||||
tentacle[i].xRot = sin * 0.15f;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack matrices,
|
||||
VertexConsumer vertices,
|
||||
int light,
|
||||
int overlay,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha) {
|
||||
matrices.pushPose();
|
||||
matrices.scale(scaleXZ, scaleY, scaleXZ);
|
||||
model.render(matrices, vertices, light, overlay);
|
||||
matrices.popPose();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
package org.betterx.betterend.entity.model;
|
||||
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartNames;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||||
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.entity.DragonflyEntity;
|
||||
|
||||
public class DragonflyEntityModel extends EntityModel<DragonflyEntity> {
|
||||
private final ModelPart model;
|
||||
private final ModelPart head;
|
||||
private final ModelPart tail;
|
||||
private final ModelPart tail_2;
|
||||
private final ModelPart wing_1;
|
||||
private final ModelPart wing_2;
|
||||
private final ModelPart wing_3;
|
||||
private final ModelPart wing_4;
|
||||
private final ModelPart legs_1;
|
||||
private final ModelPart legs_2;
|
||||
|
||||
public static LayerDefinition getTexturedModelData() {
|
||||
MeshDefinition modelData = new MeshDefinition();
|
||||
PartDefinition modelPartData = modelData.getRoot();
|
||||
|
||||
PartDefinition bodyPart = modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, -4.0F, 0.0F, 4.0F, 4.0F, 9.0F),
|
||||
PartPose.offset(2.0F, 21.5F, -4.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.HEAD,
|
||||
CubeListBuilder.create().texOffs(17, 0).addBox(-1.5F, -1.5F, -2.5F, 3.0F, 3.0F, 3.0F),
|
||||
PartPose.offsetAndRotation(-2.0F, -2.0F, 0.0F, 0.3491F, 0.0F, 0.0F)
|
||||
);
|
||||
|
||||
PartDefinition tailPart = bodyPart.addOrReplaceChild(
|
||||
PartNames.TAIL,
|
||||
CubeListBuilder.create().texOffs(26, 0).addBox(-1.5F, -1.5F, 0.0F, 3.0F, 3.0F, 7.0F),
|
||||
PartPose.offset(-2.0F, -2.0F, 9.0F)
|
||||
);
|
||||
|
||||
tailPart.addOrReplaceChild(
|
||||
PartNames.TAIL_FIN,
|
||||
CubeListBuilder.create().texOffs(36, 0).addBox(-1.0F, -1.0F, 0.0F, 2.0F, 2.0F, 10.0F),
|
||||
PartPose.offset(0.0F, 0.0F, 7.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.LEFT_WING,
|
||||
CubeListBuilder.create().texOffs(0, 13).addBox(-15.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F),
|
||||
PartPose.offset(-2.0F, -4.0F, 4.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.RIGHT_WING,
|
||||
CubeListBuilder.create().mirror().texOffs(0, 13).addBox(0.0F, 0.0F, -3.0F, 15.0F, 0.0F, 4.0F),
|
||||
PartPose.offset(-2.0F, -4.0F, 4.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.LEFT_WING_BASE,
|
||||
CubeListBuilder.create().texOffs(4, 17).addBox(-12.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F),
|
||||
PartPose.offset(-2.0F, -4.0F, 8.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.RIGHT_WING_BASE,
|
||||
CubeListBuilder.create().mirror().texOffs(4, 17).addBox(0.0F, 0.0F, -2.5F, 12.0F, 0.0F, 3.0F),
|
||||
PartPose.offset(-2.0F, -4.0F, 8.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.LEFT_LEG,
|
||||
CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F),
|
||||
PartPose.offsetAndRotation(-1.0F, 0.0F, 1.0F, 0.0F, 0.0F, -0.5236F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.RIGHT_LEG,
|
||||
CubeListBuilder.create().texOffs(50, 1).addBox(0.0F, 0.0F, 0.0F, 0.0F, 3.0F, 6.0F),
|
||||
PartPose.offsetAndRotation(-3.0F, 0.0F, 1.0F, 0.0F, 0.0F, 0.5236F)
|
||||
);
|
||||
|
||||
return LayerDefinition.create(modelData, 64, 64);
|
||||
}
|
||||
|
||||
public DragonflyEntityModel(ModelPart modelPart) {
|
||||
super(RenderType::entityCutout);
|
||||
|
||||
model = modelPart.getChild(PartNames.BODY);
|
||||
head = model.getChild(PartNames.HEAD);
|
||||
tail = model.getChild(PartNames.TAIL);
|
||||
tail_2 = tail.getChild(PartNames.TAIL_FIN);
|
||||
wing_1 = model.getChild(PartNames.LEFT_WING);
|
||||
wing_2 = model.getChild(PartNames.RIGHT_WING);
|
||||
wing_3 = model.getChild(PartNames.LEFT_WING_BASE);
|
||||
wing_4 = model.getChild(PartNames.RIGHT_WING_BASE);
|
||||
legs_1 = model.getChild(PartNames.LEFT_LEG);
|
||||
legs_2 = model.getChild(PartNames.RIGHT_LEG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(DragonflyEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
float progress = animationProgress * 2F;
|
||||
|
||||
wing_1.zRot = 0.3491F + (float) Math.sin(progress) * 0.3491F;
|
||||
wing_2.zRot = -wing_1.zRot;
|
||||
|
||||
wing_3.zRot = 0.3491F + (float) Math.cos(progress) * 0.3491F;
|
||||
wing_4.zRot = -wing_3.zRot;
|
||||
|
||||
progress = animationProgress * 0.05F;
|
||||
|
||||
head.xRot = 0.3491F + (float) Math.sin(progress * 0.7F) * 0.1F;
|
||||
tail.xRot = (float) Math.cos(progress) * 0.05F - 0.05F;
|
||||
tail_2.xRot = -tail.xRot * 1.5F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack matrices,
|
||||
VertexConsumer vertices,
|
||||
int light,
|
||||
int overlay,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha) {
|
||||
model.render(matrices, vertices, light, overlay);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package org.betterx.betterend.entity.model;
|
||||
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartNames;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||||
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.entity.EndFishEntity;
|
||||
|
||||
public class EndFishEntityModel extends EntityModel<EndFishEntity> {
|
||||
private final ModelPart model;
|
||||
private final ModelPart fin_top;
|
||||
private final ModelPart fin_bottom;
|
||||
private final ModelPart flipper;
|
||||
private final ModelPart fin_right;
|
||||
private final ModelPart fin_left;
|
||||
|
||||
public static LayerDefinition getTexturedModelData() {
|
||||
MeshDefinition modelData = new MeshDefinition();
|
||||
PartDefinition modelPartData = modelData.getRoot();
|
||||
|
||||
PartDefinition bodyPart = modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(0, 0).addBox(-1.0F, -2.0F, -4.0F, 2.0F, 4.0F, 8.0F),
|
||||
PartPose.offset(0.0F, 20.0F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.TOP_FIN,
|
||||
CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, -8.0F, 0.0F, 0.0F, 8.0F, 6.0F),
|
||||
PartPose.offsetAndRotation(0.0F, -2.0F, -4.0F, -0.6981F, 0.0F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.BOTTOM_FIN,
|
||||
CubeListBuilder.create().texOffs(0, 6).addBox(0.0F, 0.0F, 0.0F, 0.0F, 8.0F, 6.0F),
|
||||
PartPose.offsetAndRotation(0.0F, 2.0F, -4.0F, 0.6981F, 0.0F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.TAIL_FIN,
|
||||
CubeListBuilder.create().texOffs(0, 15).addBox(0.0F, -5.0F, 0.0F, 0.0F, 5.0F, 5.0F),
|
||||
PartPose.offsetAndRotation(0.0F, 0.0F, 2.0F, -0.7854F, 0.0F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.RIGHT_FIN,
|
||||
CubeListBuilder.create().texOffs(0, 25).addBox(-3.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F),
|
||||
PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, 0.7854F, 0.0F)
|
||||
);
|
||||
|
||||
bodyPart.addOrReplaceChild(
|
||||
PartNames.LEFT_FIN,
|
||||
CubeListBuilder.create().mirror().texOffs(0, 25).addBox(0.7071F, 0.7071F, -1.5F, 3.0F, 0.0F, 3.0F),
|
||||
PartPose.offsetAndRotation(-1.0F, 0.0F, -1.0F, 1.5708F, -0.7854F, 0.0F)
|
||||
);
|
||||
|
||||
return LayerDefinition.create(modelData, 32, 32);
|
||||
}
|
||||
|
||||
public EndFishEntityModel(ModelPart modelPart) {
|
||||
super(RenderType::entityCutout);
|
||||
|
||||
model = modelPart.getChild(PartNames.BODY);
|
||||
fin_top = model.getChild(PartNames.TOP_FIN);
|
||||
fin_bottom = model.getChild(PartNames.BOTTOM_FIN);
|
||||
flipper = model.getChild(PartNames.TAIL_FIN);
|
||||
fin_right = model.getChild(PartNames.RIGHT_FIN);
|
||||
fin_left = model.getChild(PartNames.LEFT_FIN);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(EndFishEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
float s1 = (float) Math.sin(animationProgress * 0.1);
|
||||
float s2 = (float) Math.sin(animationProgress * 0.05);
|
||||
flipper.yRot = s1 * 0.3F;
|
||||
fin_top.xRot = s2 * 0.02F - 0.6981F;
|
||||
fin_bottom.xRot = 0.6981F - s2 * 0.02F;
|
||||
fin_left.yRot = s1 * 0.3F - 0.7854F;
|
||||
fin_right.yRot = 0.7854F - s1 * 0.3F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack matrices,
|
||||
VertexConsumer vertices,
|
||||
int light,
|
||||
int overlay,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha) {
|
||||
model.render(matrices, vertices, light, overlay);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,153 @@
|
|||
package org.betterx.betterend.entity.model;
|
||||
|
||||
import net.minecraft.client.model.ListModel;
|
||||
import net.minecraft.client.model.geom.EntityModelSet;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartNames;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||||
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.bclib.util.MHelper;
|
||||
import org.betterx.betterend.entity.EndSlimeEntity;
|
||||
import org.betterx.betterend.registry.EndEntitiesRenders;
|
||||
|
||||
public class EndSlimeEntityModel<T extends EndSlimeEntity> extends ListModel<T> {
|
||||
private final ModelPart innerCube;
|
||||
private final ModelPart rightEye;
|
||||
private final ModelPart leftEye;
|
||||
private final ModelPart mouth;
|
||||
private final ModelPart flower;
|
||||
private final ModelPart crop;
|
||||
|
||||
public static LayerDefinition getShellOnlyTexturedModelData() {
|
||||
return getTexturedModelData(true);
|
||||
}
|
||||
|
||||
public static LayerDefinition getCompleteTexturedModelData() {
|
||||
return getTexturedModelData(false);
|
||||
}
|
||||
|
||||
private static LayerDefinition getTexturedModelData(boolean onlyShell) {
|
||||
MeshDefinition modelData = new MeshDefinition();
|
||||
PartDefinition modelPartData = modelData.getRoot();
|
||||
|
||||
if (onlyShell) {
|
||||
modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(0, 0).addBox(-4.0F, 16.0F, -4.0F, 8.0F, 8.0F, 8.0F),
|
||||
PartPose.ZERO
|
||||
);
|
||||
} else {
|
||||
modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(0, 16).addBox(-3.0F, 17.0F, -3.0F, 6.0F, 6.0F, 6.0F),
|
||||
PartPose.ZERO
|
||||
);
|
||||
|
||||
modelPartData.addOrReplaceChild(
|
||||
PartNames.RIGHT_EYE,
|
||||
CubeListBuilder.create().texOffs(32, 0).addBox(-3.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F),
|
||||
PartPose.ZERO
|
||||
);
|
||||
|
||||
modelPartData.addOrReplaceChild(
|
||||
PartNames.LEFT_EYE,
|
||||
CubeListBuilder.create().texOffs(32, 4).addBox(1.25F, 18.0F, -3.5F, 2.0F, 2.0F, 2.0F),
|
||||
PartPose.ZERO
|
||||
);
|
||||
|
||||
modelPartData.addOrReplaceChild(
|
||||
PartNames.MOUTH,
|
||||
CubeListBuilder.create().texOffs(32, 8).addBox(0.0F, 21.0F, -3.5F, 1.0F, 1.0F, 1.0F),
|
||||
PartPose.ZERO
|
||||
);
|
||||
|
||||
PartDefinition flowerPart = modelPartData.addOrReplaceChild(
|
||||
"flower",
|
||||
CubeListBuilder.create(),
|
||||
PartPose.ZERO
|
||||
);
|
||||
PartDefinition cropPart = modelPartData.addOrReplaceChild("crop", CubeListBuilder.create(), PartPose.ZERO);
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
final PartDefinition parent = i < 4 ? flowerPart : cropPart;
|
||||
final float rot = MHelper.degreesToRadians(i < 4 ? (i * 45F) : ((i - 4) * 90F + 45F));
|
||||
|
||||
PartDefinition petalRotPart = parent.addOrReplaceChild(
|
||||
"petalRot_" + i,
|
||||
CubeListBuilder.create(),
|
||||
PartPose.offsetAndRotation(0, 0, 0, 0, rot, 0)
|
||||
);
|
||||
|
||||
|
||||
petalRotPart.addOrReplaceChild(
|
||||
"petal_" + i,
|
||||
CubeListBuilder.create().texOffs(40, 0).addBox(0.0F, 0.0F, 0.0F, 8.0F, 8.0F, 0.0F),
|
||||
PartPose.offset(-4, 8, 0)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return LayerDefinition.create(modelData, 64, 32);
|
||||
}
|
||||
|
||||
public EndSlimeEntityModel(EntityModelSet modelSet, boolean onlyShell) {
|
||||
super(RenderType::entityCutout);
|
||||
|
||||
ModelPart modelPart = modelSet.bakeLayer(onlyShell
|
||||
? EndEntitiesRenders.END_SLIME_SHELL_MODEL
|
||||
: EndEntitiesRenders.END_SLIME_MODEL);
|
||||
|
||||
innerCube = modelPart.getChild(PartNames.BODY);
|
||||
if (!onlyShell) {
|
||||
rightEye = modelPart.getChild(PartNames.RIGHT_EYE);
|
||||
leftEye = modelPart.getChild(PartNames.LEFT_EYE);
|
||||
mouth = modelPart.getChild(PartNames.MOUTH);
|
||||
flower = modelPart.getChild("flower");
|
||||
crop = modelPart.getChild("crop");
|
||||
} else {
|
||||
rightEye = null;
|
||||
leftEye = null;
|
||||
mouth = null;
|
||||
flower = null;
|
||||
crop = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(T entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
}
|
||||
|
||||
public void renderFlower(PoseStack matrices, VertexConsumer vertices, int light, int overlay) {
|
||||
flower.render(matrices, vertices, light, overlay);
|
||||
}
|
||||
|
||||
public void renderCrop(PoseStack matrices, VertexConsumer vertices, int light, int overlay) {
|
||||
crop.render(matrices, vertices, light, overlay);
|
||||
}
|
||||
|
||||
private boolean isOnlyShell() {
|
||||
return rightEye == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterable<ModelPart> parts() {
|
||||
if (isOnlyShell()) {
|
||||
return ImmutableList.of(this.innerCube);
|
||||
} else {
|
||||
return ImmutableList.of(this.innerCube, this.rightEye, this.leftEye, this.mouth);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package org.betterx.betterend.entity.model;
|
||||
|
||||
import net.minecraft.client.model.EntityModel;
|
||||
import net.minecraft.client.model.geom.ModelPart;
|
||||
import net.minecraft.client.model.geom.PartNames;
|
||||
import net.minecraft.client.model.geom.PartPose;
|
||||
import net.minecraft.client.model.geom.builders.CubeListBuilder;
|
||||
import net.minecraft.client.model.geom.builders.LayerDefinition;
|
||||
import net.minecraft.client.model.geom.builders.MeshDefinition;
|
||||
import net.minecraft.client.model.geom.builders.PartDefinition;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.entity.SilkMothEntity;
|
||||
|
||||
public class SilkMothEntityModel extends EntityModel<SilkMothEntity> {
|
||||
private final ModelPart legsL;
|
||||
private final ModelPart cube_r1;
|
||||
private final ModelPart cube_r2;
|
||||
private final ModelPart cube_r3;
|
||||
private final ModelPart legsR;
|
||||
private final ModelPart cube_r4;
|
||||
private final ModelPart cube_r5;
|
||||
private final ModelPart cube_r6;
|
||||
private final ModelPart head_pivot;
|
||||
private final ModelPart tendril_r_r1;
|
||||
private final ModelPart tendril_r_r2;
|
||||
private final ModelPart bb_main;
|
||||
private final ModelPart wingR_r1;
|
||||
private final ModelPart wingL_r1;
|
||||
private final ModelPart abdomen_r1;
|
||||
|
||||
public static LayerDefinition getTexturedModelData() {
|
||||
MeshDefinition modelData = new MeshDefinition();
|
||||
PartDefinition modelPartData = modelData.getRoot();
|
||||
|
||||
PartDefinition legsL = modelPartData.addOrReplaceChild(
|
||||
PartNames.LEFT_LEG,
|
||||
CubeListBuilder.create().texOffs(0, 0),
|
||||
PartPose.offsetAndRotation(1.5f, 19.9f, -0.45f, 0.0f, 0.0f, 0.6981f)
|
||||
);
|
||||
|
||||
legsL.addOrReplaceChild(
|
||||
"cube_r1",
|
||||
CubeListBuilder.create().texOffs(0, 13).addBox(0.0216f, 0.0f, -0.5976f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f)
|
||||
);
|
||||
|
||||
legsL.addOrReplaceChild(
|
||||
"cube_r2",
|
||||
CubeListBuilder.create().texOffs(0, 15).addBox(0.0f, 0.0f, -0.6f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f)
|
||||
);
|
||||
|
||||
legsL.addOrReplaceChild(
|
||||
"cube_r3",
|
||||
CubeListBuilder.create().texOffs(0, 14).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f)
|
||||
);
|
||||
|
||||
PartDefinition legsR = modelPartData.addOrReplaceChild(
|
||||
PartNames.RIGHT_LEG,
|
||||
CubeListBuilder.create().texOffs(0, 0),
|
||||
PartPose.offsetAndRotation(-1.5f, 19.9f, -0.55f, 0.0f, 3.1416f, -0.6545f)
|
||||
);
|
||||
|
||||
legsR.addOrReplaceChild(
|
||||
"cube_r4",
|
||||
CubeListBuilder.create().texOffs(0, 10).addBox(0.0f, 0.0f, -0.5f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.0f, 0.0f, -1.0f, 0.0f, 0.2182f, 0.3927f)
|
||||
);
|
||||
|
||||
legsR.addOrReplaceChild(
|
||||
"cube_r5",
|
||||
CubeListBuilder.create().texOffs(0, 11).addBox(0.0f, 0.0f, -0.4f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.5f, 0.1f, -0.05f, 0.0f, 0.0f, 0.3927f)
|
||||
);
|
||||
|
||||
legsR.addOrReplaceChild(
|
||||
"cube_r6",
|
||||
CubeListBuilder.create().texOffs(0, 12).addBox(0.0216f, 0.0f, -0.4024f, 3.0f, 0.0f, 1.0f),
|
||||
PartPose.offsetAndRotation(0.0f, 0.0f, 0.9f, 0.0f, -0.2182f, 0.3927f)
|
||||
);
|
||||
|
||||
PartDefinition head_pivot = modelPartData.addOrReplaceChild(
|
||||
PartNames.HEAD,
|
||||
CubeListBuilder.create().texOffs(15, 10).addBox(-1.5f, -1.5f, -2.0f, 3.0f, 3.0f, 3.0f),
|
||||
PartPose.offset(0.0f, 18.0f, -3.0f)
|
||||
);
|
||||
|
||||
head_pivot.addOrReplaceChild(
|
||||
"tendril_r_r1",
|
||||
CubeListBuilder.create().mirror().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f),
|
||||
PartPose.offsetAndRotation(1.0f, -1.15f, -1.0f, 0.0f, 0.0f, 0.3927f)
|
||||
);
|
||||
|
||||
head_pivot.addOrReplaceChild(
|
||||
"tendril_r_r2",
|
||||
CubeListBuilder.create().texOffs(23, 0).addBox(-1.5f, -5.0f, 0.0f, 3.0f, 5.0f, 0.0f),
|
||||
PartPose.offsetAndRotation(-1.0f, -1.15f, -1.0f, 0.0f, 0.0f, -0.3927f)
|
||||
);
|
||||
|
||||
PartDefinition bb_main = modelPartData.addOrReplaceChild(
|
||||
PartNames.BODY,
|
||||
CubeListBuilder.create().texOffs(19, 19).addBox(-2.5f, -8.5f, -3.0f, 5.0f, 5.0f, 3.0f),
|
||||
PartPose.offset(0.0f, 24.0f, 0.0f)
|
||||
);
|
||||
|
||||
bb_main.addOrReplaceChild(
|
||||
PartNames.RIGHT_WING,
|
||||
CubeListBuilder.create().mirror().texOffs(0, 5).addBox(-7.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f),
|
||||
PartPose.offsetAndRotation(-1.5f, -6.5f, 0.5f, 0.0f, 0.0f, 0.3927f)
|
||||
);
|
||||
|
||||
bb_main.addOrReplaceChild(
|
||||
PartNames.LEFT_WING,
|
||||
CubeListBuilder.create().texOffs(0, 5).addBox(-2.0f, 0.0f, -3.0f, 9.0f, 0.0f, 5.0f),
|
||||
PartPose.offsetAndRotation(1.5f, -6.5f, 0.5f, 0.0f, 0.0f, -0.3927f)
|
||||
);
|
||||
|
||||
bb_main.addOrReplaceChild(
|
||||
"abdomen_r1",
|
||||
CubeListBuilder.create().texOffs(0, 10).addBox(-3.0f, -4.0f, -1.0f, 4.0f, 4.0f, 7.0f),
|
||||
PartPose.offsetAndRotation(1.0f, -3.9f, 0.0f, -0.3927f, 0.0f, 0.0f)
|
||||
);
|
||||
|
||||
return LayerDefinition.create(modelData, 64, 64);
|
||||
}
|
||||
|
||||
public SilkMothEntityModel(ModelPart modelPart) {
|
||||
super(RenderType::entityCutout);
|
||||
|
||||
legsL = modelPart.getChild(PartNames.LEFT_LEG);
|
||||
cube_r1 = legsL.getChild("cube_r1");
|
||||
cube_r2 = legsL.getChild("cube_r2");
|
||||
cube_r3 = legsL.getChild("cube_r3");
|
||||
legsR = modelPart.getChild(PartNames.RIGHT_LEG);
|
||||
cube_r4 = legsR.getChild("cube_r4");
|
||||
cube_r5 = legsR.getChild("cube_r5");
|
||||
cube_r6 = legsR.getChild("cube_r6");
|
||||
head_pivot = modelPart.getChild(PartNames.HEAD);
|
||||
tendril_r_r1 = head_pivot.getChild("tendril_r_r1");
|
||||
tendril_r_r2 = head_pivot.getChild("tendril_r_r2");
|
||||
bb_main = modelPart.getChild(PartNames.BODY);
|
||||
wingR_r1 = bb_main.getChild(PartNames.RIGHT_WING);
|
||||
wingL_r1 = bb_main.getChild(PartNames.LEFT_WING);
|
||||
abdomen_r1 = bb_main.getChild("abdomen_r1");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupAnim(SilkMothEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
wingR_r1.zRot = Mth.sin(animationProgress * 2F) * 0.4F + 0.3927F;
|
||||
wingL_r1.zRot = -wingR_r1.zRot;
|
||||
head_pivot.xRot = Mth.sin(animationProgress * 0.03F) * 0.1F;
|
||||
tendril_r_r1.zRot = Mth.sin(animationProgress * 0.07F) * 0.2F + 0.3927F;
|
||||
tendril_r_r2.zRot = -tendril_r_r1.zRot;
|
||||
abdomen_r1.xRot = Mth.sin(animationProgress * 0.05F) * 0.1F - 0.3927F;
|
||||
legsR.zRot = Mth.sin(animationProgress * 0.07F) * 0.1F - 0.6545F;
|
||||
legsL.zRot = -legsR.zRot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToBuffer(PoseStack matrices,
|
||||
VertexConsumer vertices,
|
||||
int light,
|
||||
int overlay,
|
||||
float red,
|
||||
float green,
|
||||
float blue,
|
||||
float alpha) {
|
||||
bb_main.render(matrices, vertices, light, overlay);
|
||||
head_pivot.render(matrices, vertices, light, overlay);
|
||||
legsL.render(matrices, vertices, light, overlay);
|
||||
legsR.render(matrices, vertices, light, overlay);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.client.renderer.entity.layers.EyesLayer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.CubozoaEntity;
|
||||
import org.betterx.betterend.entity.model.CubozoaEntityModel;
|
||||
import org.betterx.betterend.registry.EndEntitiesRenders;
|
||||
|
||||
public class RendererEntityCubozoa extends MobRenderer<CubozoaEntity, CubozoaEntityModel> {
|
||||
private static final ResourceLocation[] TEXTURE = new ResourceLocation[2];
|
||||
private static final RenderType[] GLOW = new RenderType[2];
|
||||
|
||||
public RendererEntityCubozoa(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new CubozoaEntityModel(ctx.bakeLayer(EndEntitiesRenders.CUBOZOA_MODEL)), 0.5f);
|
||||
this.addLayer(new EyesLayer<CubozoaEntity, CubozoaEntityModel>(this) {
|
||||
@Override
|
||||
public RenderType renderType() {
|
||||
return GLOW[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack matrices,
|
||||
MultiBufferSource vertexConsumers,
|
||||
int light,
|
||||
CubozoaEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float tickDelta,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]);
|
||||
this.getParentModel()
|
||||
.renderToBuffer(matrices,
|
||||
vertexConsumer,
|
||||
15728640,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scale(CubozoaEntity entity, PoseStack matrixStack, float f) {
|
||||
float scale = entity.getScale();
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(CubozoaEntity entity) {
|
||||
return TEXTURE[entity.getVariant()];
|
||||
}
|
||||
|
||||
static {
|
||||
TEXTURE[0] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa.png");
|
||||
TEXTURE[1] = BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur.png");
|
||||
|
||||
GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_glow.png"));
|
||||
GLOW[1] = RenderType.eyes(BetterEnd.makeID("textures/entity/cubozoa/cubozoa_sulphur_glow.png"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.client.renderer.entity.layers.EyesLayer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.DragonflyEntity;
|
||||
import org.betterx.betterend.entity.model.DragonflyEntityModel;
|
||||
import org.betterx.betterend.registry.EndEntitiesRenders;
|
||||
|
||||
public class RendererEntityDragonfly extends MobRenderer<DragonflyEntity, DragonflyEntityModel> {
|
||||
private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/dragonfly.png");
|
||||
private static final RenderType GLOW = RenderType.eyes(BetterEnd.makeID("textures/entity/dragonfly_glow.png"));
|
||||
|
||||
public RendererEntityDragonfly(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new DragonflyEntityModel(ctx.bakeLayer(EndEntitiesRenders.DRAGONFLY_MODEL)), 0.5f);
|
||||
this.addLayer(new EyesLayer<DragonflyEntity, DragonflyEntityModel>(this) {
|
||||
@Override
|
||||
public RenderType renderType() {
|
||||
return GLOW;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(DragonflyEntity entity) {
|
||||
return TEXTURE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.client.renderer.entity.layers.EyesLayer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.EndFishEntity;
|
||||
import org.betterx.betterend.entity.model.EndFishEntityModel;
|
||||
import org.betterx.betterend.registry.EndEntitiesRenders;
|
||||
|
||||
public class RendererEntityEndFish extends MobRenderer<EndFishEntity, EndFishEntityModel> {
|
||||
private static final ResourceLocation[] TEXTURE = new ResourceLocation[EndFishEntity.VARIANTS];
|
||||
private static final RenderType[] GLOW = new RenderType[EndFishEntity.VARIANTS];
|
||||
|
||||
public RendererEntityEndFish(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new EndFishEntityModel(ctx.bakeLayer(EndEntitiesRenders.END_FISH_MODEL)), 0.5f);
|
||||
this.addLayer(new EyesLayer<EndFishEntity, EndFishEntityModel>(this) {
|
||||
@Override
|
||||
public RenderType renderType() {
|
||||
return GLOW[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack matrices,
|
||||
MultiBufferSource vertexConsumers,
|
||||
int light,
|
||||
EndFishEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float tickDelta,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getVariant()]);
|
||||
this.getParentModel()
|
||||
.renderToBuffer(matrices,
|
||||
vertexConsumer,
|
||||
15728640,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scale(EndFishEntity entity, PoseStack matrixStack, float f) {
|
||||
float scale = entity.getScale();
|
||||
matrixStack.scale(scale, scale, scale);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(EndFishEntity entity) {
|
||||
return TEXTURE[entity.getVariant()];
|
||||
}
|
||||
|
||||
static {
|
||||
for (int i = 0; i < EndFishEntity.VARIANTS; i++) {
|
||||
TEXTURE[i] = BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + ".png");
|
||||
GLOW[i] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_fish/end_fish_" + i + "_glow.png"));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.LivingEntityRenderer;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.client.renderer.entity.RenderLayerParent;
|
||||
import net.minecraft.client.renderer.entity.layers.EyesLayer;
|
||||
import net.minecraft.client.renderer.entity.layers.RenderLayer;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.EndSlimeEntity;
|
||||
import org.betterx.betterend.entity.model.EndSlimeEntityModel;
|
||||
|
||||
public class RendererEntityEndSlime extends MobRenderer<EndSlimeEntity, EndSlimeEntityModel<EndSlimeEntity>> {
|
||||
private static final ResourceLocation[] TEXTURE = new ResourceLocation[4];
|
||||
private static final RenderType[] GLOW = new RenderType[4];
|
||||
|
||||
public RendererEntityEndSlime(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new EndSlimeEntityModel<>(ctx.getModelSet(), false), 0.25f);
|
||||
this.addLayer(new OverlayFeatureRenderer<EndSlimeEntity>(this, ctx));
|
||||
this.addLayer(new EyesLayer<EndSlimeEntity, EndSlimeEntityModel<EndSlimeEntity>>(this) {
|
||||
@Override
|
||||
public RenderType renderType() {
|
||||
return GLOW[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(PoseStack matrices,
|
||||
MultiBufferSource vertexConsumers,
|
||||
int light,
|
||||
EndSlimeEntity entity,
|
||||
float limbAngle,
|
||||
float limbDistance,
|
||||
float tickDelta,
|
||||
float animationProgress,
|
||||
float headYaw,
|
||||
float headPitch) {
|
||||
VertexConsumer vertexConsumer = vertexConsumers.getBuffer(GLOW[entity.getSlimeType()]);
|
||||
this.getParentModel()
|
||||
.renderToBuffer(matrices,
|
||||
vertexConsumer,
|
||||
15728640,
|
||||
OverlayTexture.NO_OVERLAY,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
if (entity.isLake()) {
|
||||
this.getParentModel().renderFlower(matrices, vertexConsumer, 15728640, OverlayTexture.NO_OVERLAY);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(EndSlimeEntity entity) {
|
||||
return TEXTURE[entity.getSlimeType()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render(EndSlimeEntity slimeEntity,
|
||||
float f,
|
||||
float g,
|
||||
PoseStack matrixStack,
|
||||
MultiBufferSource vertexConsumerProvider,
|
||||
int i) {
|
||||
this.shadowRadius = 0.25F * (float) slimeEntity.getSize();
|
||||
super.render(slimeEntity, f, g, matrixStack, vertexConsumerProvider, i);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void scale(EndSlimeEntity slimeEntity, PoseStack matrixStack, float f) {
|
||||
matrixStack.scale(0.999F, 0.999F, 0.999F);
|
||||
matrixStack.translate(0.0D, 0.0010000000474974513D, 0.0D);
|
||||
float h = (float) slimeEntity.getSize();
|
||||
float i = Mth.lerp(f, slimeEntity.oSquish, slimeEntity.squish) / (h * 0.5F + 1.0F);
|
||||
float j = 1.0F / (i + 1.0F);
|
||||
matrixStack.scale(j * h, 1.0F / j * h, j * h);
|
||||
}
|
||||
|
||||
private final class OverlayFeatureRenderer<T extends EndSlimeEntity> extends RenderLayer<T, EndSlimeEntityModel<T>> {
|
||||
private final EndSlimeEntityModel<T> modelOrdinal;
|
||||
private final EndSlimeEntityModel<T> modelLake;
|
||||
|
||||
public OverlayFeatureRenderer(RenderLayerParent<T, EndSlimeEntityModel<T>> featureRendererContext,
|
||||
EntityRendererProvider.Context ctx) {
|
||||
super(featureRendererContext);
|
||||
modelOrdinal = new EndSlimeEntityModel<>(ctx.getModelSet(), true);
|
||||
modelLake = new EndSlimeEntityModel<>(ctx.getModelSet(), true);
|
||||
}
|
||||
|
||||
public void render(PoseStack matrixStack,
|
||||
MultiBufferSource vertexConsumerProvider,
|
||||
int i,
|
||||
T livingEntity,
|
||||
float f,
|
||||
float g,
|
||||
float h,
|
||||
float j,
|
||||
float k,
|
||||
float l) {
|
||||
if (!livingEntity.isInvisible()) {
|
||||
if (livingEntity.isLake()) {
|
||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation(
|
||||
livingEntity)));
|
||||
this.getParentModel()
|
||||
.renderFlower(matrixStack,
|
||||
vertexConsumer,
|
||||
i,
|
||||
LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F)
|
||||
);
|
||||
} else if (livingEntity.isAmber() || livingEntity.isChorus()) {
|
||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityCutout(this.getTextureLocation(
|
||||
livingEntity)));
|
||||
this.getParentModel()
|
||||
.renderCrop(matrixStack,
|
||||
vertexConsumer,
|
||||
i,
|
||||
LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F)
|
||||
);
|
||||
}
|
||||
|
||||
EndSlimeEntityModel<T> model = livingEntity.getSlimeType() == 1 ? modelLake : modelOrdinal;
|
||||
this.getParentModel().copyPropertiesTo(model);
|
||||
model.prepareMobModel(livingEntity, f, g, h);
|
||||
model.setupAnim(livingEntity, f, g, j, k, l);
|
||||
VertexConsumer vertexConsumer = vertexConsumerProvider.getBuffer(RenderType.entityTranslucent(this.getTextureLocation(
|
||||
livingEntity)));
|
||||
model.renderToBuffer(
|
||||
matrixStack,
|
||||
vertexConsumer,
|
||||
i,
|
||||
LivingEntityRenderer.getOverlayCoords(livingEntity, 0.0F),
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F,
|
||||
1.0F
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
TEXTURE[0] = BetterEnd.makeID("textures/entity/end_slime/end_slime.png");
|
||||
TEXTURE[1] = BetterEnd.makeID("textures/entity/end_slime/end_slime_mossy.png");
|
||||
TEXTURE[2] = BetterEnd.makeID("textures/entity/end_slime/end_slime_lake.png");
|
||||
TEXTURE[3] = BetterEnd.makeID("textures/entity/end_slime/end_slime_amber.png");
|
||||
GLOW[0] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_glow.png"));
|
||||
GLOW[1] = GLOW[0];
|
||||
GLOW[2] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_lake_glow.png"));
|
||||
GLOW[3] = RenderType.eyes(BetterEnd.makeID("textures/entity/end_slime/end_slime_amber_glow.png"));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.model.PlayerModel;
|
||||
import net.minecraft.client.model.geom.ModelLayers;
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.ShadowWalkerEntity;
|
||||
|
||||
public class RendererEntityShadowWalker extends HumanoidMobRenderer<ShadowWalkerEntity, PlayerModel<ShadowWalkerEntity>> {
|
||||
private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/shadow_walker.png");
|
||||
|
||||
public RendererEntityShadowWalker(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new PlayerModel<ShadowWalkerEntity>(ctx.bakeLayer(ModelLayers.PLAYER), false), 0.5F);
|
||||
//super(entityRenderDispatcher, new PlayerModel<ShadowWalkerEntity>(0.0F, false), 0.5F);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(ShadowWalkerEntity zombieEntity) {
|
||||
return TEXTURE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package org.betterx.betterend.entity.render;
|
||||
|
||||
import net.minecraft.client.renderer.entity.EntityRendererProvider;
|
||||
import net.minecraft.client.renderer.entity.MobRenderer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import org.betterx.betterend.BetterEnd;
|
||||
import org.betterx.betterend.entity.SilkMothEntity;
|
||||
import org.betterx.betterend.entity.model.SilkMothEntityModel;
|
||||
import org.betterx.betterend.registry.EndEntitiesRenders;
|
||||
|
||||
public class SilkMothEntityRenderer extends MobRenderer<SilkMothEntity, SilkMothEntityModel> {
|
||||
private static final ResourceLocation TEXTURE = BetterEnd.makeID("textures/entity/silk_moth.png");
|
||||
|
||||
public SilkMothEntityRenderer(EntityRendererProvider.Context ctx) {
|
||||
super(ctx, new SilkMothEntityModel(ctx.bakeLayer(EndEntitiesRenders.SILK_MOTH_MODEL)), 0.5f);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResourceLocation getTextureLocation(SilkMothEntity entity) {
|
||||
return TEXTURE;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue