diff --git a/src/main/java/ru/betterend/entity/EntityJello.java b/src/main/java/ru/betterend/entity/EntityJello.java new file mode 100644 index 00000000..a58ba0f3 --- /dev/null +++ b/src/main/java/ru/betterend/entity/EntityJello.java @@ -0,0 +1,183 @@ +package ru.betterend.entity; + +import java.util.List; +import java.util.Random; +import net.minecraft.block.Blocks; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.SpawnReason; +import net.minecraft.entity.ai.control.MoveControl; +import net.minecraft.entity.ai.goal.EscapeDangerGoal; +import net.minecraft.entity.ai.goal.FleeEntityGoal; +import net.minecraft.entity.ai.goal.SwimAroundGoal; +import net.minecraft.entity.attribute.DefaultAttributeContainer; +import net.minecraft.entity.attribute.EntityAttributes; +import net.minecraft.entity.damage.DamageSource; +import net.minecraft.entity.data.DataTracker; +import net.minecraft.entity.data.TrackedData; +import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.entity.passive.SchoolingFishEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.particle.ParticleTypes; +import net.minecraft.predicate.entity.EntityPredicates; +import net.minecraft.sound.SoundEvent; +import net.minecraft.sound.SoundEvents; +import net.minecraft.tag.FluidTags; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; +import net.minecraft.world.ServerWorldAccess; +import net.minecraft.world.World; +import ru.betterend.registry.EndItems; + +public class EntityJello extends SchoolingFishEntity { + public static final int VARIANTS = 5; + private static final TrackedData VARIANT = DataTracker.registerData(EntityJello.class, TrackedDataHandlerRegistry.BYTE); + private static final TrackedData SCALE = DataTracker.registerData(EntityJello.class, TrackedDataHandlerRegistry.BYTE); + + public EntityJello(EntityType entityType, World world) { + super(entityType, world); + this.moveControl = new JelloMoveControl(this); + } + + @Override + protected void initGoals() { + this.goalSelector.add(0, new EscapeDangerGoal(this, 1.25D)); + this.goalSelector.add(2, new FleeEntityGoal(this, PlayerEntity.class, 8.0F, 0.4D, 0.6D, EntityPredicates.EXCEPT_SPECTATOR::test)); + this.goalSelector.add(4, new SwimToRandomPlaceGoal(this)); + } + + @Override + protected void initDataTracker() { + super.initDataTracker(); + this.dataTracker.startTracking(VARIANT, (byte) this.getRandom().nextInt(VARIANTS)); + this.dataTracker.startTracking(SCALE, (byte) this.getRandom().nextInt(16)); + } + + @Override + public void writeCustomDataToTag(CompoundTag tag) { + super.writeCustomDataToTag(tag); + tag.putByte("Variant", (byte) getVariant()); + tag.putByte("Scale", (byte) getScale()); + } + + @Override + public void readCustomDataFromTag(CompoundTag tag) { + super.readCustomDataFromTag(tag); + if (tag.contains("Variant")) { + this.dataTracker.set(VARIANT, tag.getByte("Variant")); + } + if (tag.contains("Scale")) { + this.dataTracker.set(SCALE, tag.getByte("Scale")); + } + } + + @Override + protected ItemStack getFishBucketItem() { + return new ItemStack(EndItems.BUCKET_END_FISH); + } + + @Override + protected SoundEvent getFlopSound() { + return SoundEvents.ENTITY_TROPICAL_FISH_FLOP; + } + + @Override + protected SoundEvent getAmbientSound() { + return SoundEvents.ENTITY_SALMON_AMBIENT; + } + + @Override + protected SoundEvent getDeathSound() { + return SoundEvents.ENTITY_SALMON_DEATH; + } + + @Override + protected SoundEvent getHurtSound(DamageSource source) { + return SoundEvents.ENTITY_SALMON_HURT; + } + + @Override + public void tick() { + super.tick(); + if (random.nextInt(8) == 0 && getBlockState().isOf(Blocks.WATER)) { + double x = getX() + random.nextGaussian() * 0.2; + double y = getY() + random.nextGaussian() * 0.2; + double z = getZ() + random.nextGaussian() * 0.2; + world.addParticle(ParticleTypes.BUBBLE, x, y, z, 0, 0, 0); + } + } + + public static DefaultAttributeContainer.Builder createMobAttributes() { + return LivingEntity.createLivingAttributes() + .add(EntityAttributes.GENERIC_MAX_HEALTH, 2.0) + .add(EntityAttributes.GENERIC_FOLLOW_RANGE, 16.0) + .add(EntityAttributes.GENERIC_MOVEMENT_SPEED, 0.05); + } + + public int getVariant() { + return (int) this.dataTracker.get(VARIANT); + } + + public float getScale() { + return this.dataTracker.get(SCALE) / 32F + 0.75F; + } + + public static boolean canSpawn(EntityType type, ServerWorldAccess world, SpawnReason spawnReason, BlockPos pos, Random random) { + Box box = new Box(pos).expand(16); + List list = world.getEntitiesByClass(EntityJello.class, box, (entity) -> { return true; }); + return list.size() < 9; + } + + static class JelloMoveControl extends MoveControl { + private final EntityJello jello; + + JelloMoveControl(EntityJello owner) { + super(owner); + this.jello = owner; + } + + public void tick() { + if (this.jello.isSubmergedIn(FluidTags.WATER)) { + this.jello.setVelocity(this.jello.getVelocity().add(0.0D, 0.005D, 0.0D)); + } + + if (this.state == MoveControl.State.MOVE_TO && !this.jello.getNavigation().isIdle()) { + float f = (float) (this.speed * this.jello.getAttributeValue(EntityAttributes.GENERIC_MOVEMENT_SPEED)); + this.jello.setMovementSpeed(MathHelper.lerp(0.025F, this.jello.getMovementSpeed(), f)); + double d = this.targetX - this.jello.getX(); + double e = this.targetY - this.jello.getY(); + double g = this.targetZ - this.jello.getZ(); + if (e != 0.0D) { + double h = (double) MathHelper.sqrt(d * d + e * e + g * g); + this.jello.setVelocity(this.jello.getVelocity().add(0.0D, (double) this.jello.getMovementSpeed() * (e / h) * 0.1D, 0.0D)); + } + + if (d != 0.0D || g != 0.0D) { + float i = (float) (MathHelper.atan2(g, d) * 57.2957763671875D) - 90.0F; + this.jello.yaw = this.changeAngle(this.jello.yaw, i, 5.0F); + this.jello.bodyYaw = this.jello.yaw; + } + + } + else { + this.jello.setMovementSpeed(0.0F); + } + } + } + + static class SwimToRandomPlaceGoal extends SwimAroundGoal { + private final EntityJello fish; + + public SwimToRandomPlaceGoal(EntityJello jello) { + super(jello, 1.0D, 40); + this.fish = jello; + } + + public boolean canStart() { + return this.fish.hasSelfControl() && super.canStart(); + } + } +} diff --git a/src/main/java/ru/betterend/entity/model/ModelEntityJello.java b/src/main/java/ru/betterend/entity/model/ModelEntityJello.java new file mode 100644 index 00000000..2bdee3d7 --- /dev/null +++ b/src/main/java/ru/betterend/entity/model/ModelEntityJello.java @@ -0,0 +1,51 @@ +package ru.betterend.entity.model; + +import net.minecraft.client.model.ModelPart; +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.VertexConsumer; +import net.minecraft.client.util.math.MatrixStack; +import ru.betterend.entity.BlockBenchModel; +import ru.betterend.entity.EntityJello; + +public class ModelEntityJello extends BlockBenchModel { + private final ModelPart model; + private final ModelPart tentacles; + private final ModelPart main_cube; + + public ModelEntityJello() { + super(RenderLayer::getEntityTranslucent); + + textureWidth = 48; + textureHeight = 48; + + model = new ModelPart(this); + model.setPivot(0.0F, 24.0F, 0.0F); + model.setTextureOffset(16, 17).addCuboid(-4.0F, -7.0F, 4.5F, 8.0F, 7.0F, 0.0F, 0.0F); + model.setTextureOffset(16, 17).addCuboid(-4.0F, -7.0F, -4.5F, 8.0F, 7.0F, 0.0F, 0.0F); + model.setTextureOffset(0, 17).addCuboid(-2.0F, -12.5F, -2.0F, 4.0F, 4.0F, 4.0F, 0.0F); + + tentacles = new ModelPart(this); + tentacles.setPivot(0.0F, -6.0F, 0.0F); + model.addChild(tentacles); + setRotationAngle(tentacles, 0.0F, -1.5708F, 0.0F); + tentacles.setTextureOffset(16, 17).addCuboid(-4.0F, -1.0F, 4.5F, 8.0F, 7.0F, 0.0F, 0.0F); + tentacles.setTextureOffset(16, 17).addCuboid(-4.0F, -1.0F, -4.5F, 8.0F, 7.0F, 0.0F, 0.0F); + + main_cube = new ModelPart(this); + main_cube.setPivot(0.0F, -14.0F, 0.0F); + model.addChild(main_cube); + setRotationAngle(main_cube, 0.0F, 0.0F, -3.1416F); + main_cube.setTextureOffset(0, 0).addCuboid(-5.0F, -7.0F, -5.0F, 10.0F, 7.0F, 10.0F, 0.0F); + } + + @Override + public void setAngles(EntityJello entity, float limbAngle, float limbDistance, float animationProgress, float headYaw, float headPitch) { + + } + + @Override + public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) { + model.render(matrices, vertices, light, overlay); + } + +} diff --git a/src/main/java/ru/betterend/entity/render/RendererEntityJello.java b/src/main/java/ru/betterend/entity/render/RendererEntityJello.java new file mode 100644 index 00000000..68e15ead --- /dev/null +++ b/src/main/java/ru/betterend/entity/render/RendererEntityJello.java @@ -0,0 +1,28 @@ +package ru.betterend.entity.render; + +import net.minecraft.client.render.entity.EntityRenderDispatcher; +import net.minecraft.client.render.entity.MobEntityRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.util.Identifier; +import ru.betterend.BetterEnd; +import ru.betterend.entity.EntityJello; +import ru.betterend.entity.model.ModelEntityJello; + +public class RendererEntityJello extends MobEntityRenderer { + private static final Identifier TEXTURE = BetterEnd.makeID("textures/entity/jello.png"); + + public RendererEntityJello(EntityRenderDispatcher entityRenderDispatcher) { + super(entityRenderDispatcher, new ModelEntityJello(), 0.5f); + } + + @Override + protected void scale(EntityJello entity, MatrixStack matrixStack, float f) { + float scale = entity.getScale(); + matrixStack.scale(scale, scale, scale); + } + + @Override + public Identifier getTexture(EntityJello entity) { + return TEXTURE; + } +} \ No newline at end of file diff --git a/src/main/java/ru/betterend/item/ItemSpawnEgg.java b/src/main/java/ru/betterend/item/ItemSpawnEgg.java index 0cb7fe14..d1b0583f 100644 --- a/src/main/java/ru/betterend/item/ItemSpawnEgg.java +++ b/src/main/java/ru/betterend/item/ItemSpawnEgg.java @@ -2,9 +2,16 @@ package ru.betterend.item; import net.minecraft.entity.EntityType; import net.minecraft.item.SpawnEggItem; +import ru.betterend.patterns.Patterned; +import ru.betterend.patterns.Patterns; -public abstract class ItemSpawnEgg extends SpawnEggItem { +public class ItemSpawnEgg extends SpawnEggItem implements Patterned { public ItemSpawnEgg(EntityType type, int primaryColor, int secondaryColor, Settings settings) { super(type, primaryColor, secondaryColor, settings); } + + @Override + public String getModelPattern(String name) { + return Patterns.createJson(Patterns.ITEM_SPAWN_EGG, name); + } } diff --git a/src/main/java/ru/betterend/patterns/Patterns.java b/src/main/java/ru/betterend/patterns/Patterns.java index d99c2c4e..49b530c6 100644 --- a/src/main/java/ru/betterend/patterns/Patterns.java +++ b/src/main/java/ru/betterend/patterns/Patterns.java @@ -90,6 +90,7 @@ public class Patterns { public final static Identifier ITEM_BLOCK = BetterEnd.makeID("patterns/item/pattern_block_item.json"); public final static Identifier ITEM_GENERATED = BetterEnd.makeID("patterns/item/pattern_item_generated.json"); public final static Identifier ITEM_HANDHELD = BetterEnd.makeID("patterns/item/pattern_item_handheld.json"); + public final static Identifier ITEM_SPAWN_EGG = BetterEnd.makeID("patterns/item/pattern_item_spawn_egg.json"); public static String createJson(Reader data, String parent, String block) { try (BufferedReader buffer = new BufferedReader(data)) { diff --git a/src/main/java/ru/betterend/registry/EndEntities.java b/src/main/java/ru/betterend/registry/EndEntities.java index 601d9fb5..a094be57 100644 --- a/src/main/java/ru/betterend/registry/EndEntities.java +++ b/src/main/java/ru/betterend/registry/EndEntities.java @@ -15,6 +15,7 @@ import ru.betterend.BetterEnd; import ru.betterend.entity.EntityDragonfly; import ru.betterend.entity.EntityEndFish; import ru.betterend.entity.EntityEndSlime; +import ru.betterend.entity.EntityJello; import ru.betterend.entity.EntityShadowWalker; import ru.betterend.util.MHelper; import ru.betterend.util.SpawnHelper; @@ -24,11 +25,13 @@ public class EndEntities { public static final EntityType END_SLIME = register("end_slime", SpawnGroup.MONSTER, 2F, 2F, EntityEndSlime::new, EntityEndSlime.createMobAttributes(), false, MHelper.color(28, 28, 28), MHelper.color(99, 11, 99)); public static final EntityType END_FISH = register("end_fish", SpawnGroup.WATER_AMBIENT, 0.5F, 0.5F, EntityEndFish::new, EntityEndFish.createMobAttributes(), true, MHelper.color(3, 50, 76), MHelper.color(120, 206, 255)); public static final EntityType SHADOW_WALKER = register("shadow_walker", SpawnGroup.MONSTER, 0.6F, 1.95F, EntityShadowWalker::new, EntityShadowWalker.createMobAttributes(), true, MHelper.color(30, 30, 30), MHelper.color(5, 5, 5)); + public static final EntityType JELLO = register("jello", SpawnGroup.WATER_AMBIENT, 0.6F, 1F, EntityJello::new, EntityJello.createMobAttributes(), true, MHelper.color(151, 77, 181), MHelper.color(93, 176, 238)); public static void register() { SpawnHelper.restrictionLand(END_SLIME, EntityEndSlime::canSpawn); SpawnHelper.restrictionWater(END_FISH, EntityEndFish::canSpawn); SpawnHelper.restrictionLand(SHADOW_WALKER, HostileEntity::canSpawnInDark); + SpawnHelper.restrictionWater(JELLO, EntityJello::canSpawn); } protected static EntityType register(String name, SpawnGroup group, float width, float height, EntityFactory entity) { diff --git a/src/main/java/ru/betterend/registry/EndEntitiesRenders.java b/src/main/java/ru/betterend/registry/EndEntitiesRenders.java index e72afbdf..0ae2f516 100644 --- a/src/main/java/ru/betterend/registry/EndEntitiesRenders.java +++ b/src/main/java/ru/betterend/registry/EndEntitiesRenders.java @@ -1,31 +1,30 @@ package ru.betterend.registry; +import java.util.function.Function; + import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry; +import net.minecraft.client.render.entity.EntityRenderDispatcher; import net.minecraft.client.render.entity.MobEntityRenderer; import net.minecraft.entity.EntityType; import ru.betterend.entity.render.RendererEntityDragonfly; import ru.betterend.entity.render.RendererEntityEndFish; import ru.betterend.entity.render.RendererEntityEndSlime; +import ru.betterend.entity.render.RendererEntityJello; import ru.betterend.entity.render.RendererEntityShadowWalker; public class EndEntitiesRenders { public static void register() { - register(EndEntities.DRAGONFLY, RendererEntityDragonfly.class); - register(EndEntities.END_SLIME, RendererEntityEndSlime.class); - register(EndEntities.END_FISH, RendererEntityEndFish.class); - register(EndEntities.SHADOW_WALKER, RendererEntityShadowWalker.class); + register(EndEntities.DRAGONFLY, RendererEntityDragonfly::new); + register(EndEntities.END_SLIME, RendererEntityEndSlime::new); + register(EndEntities.END_FISH, RendererEntityEndFish::new); + register(EndEntities.SHADOW_WALKER, RendererEntityShadowWalker::new); + register(EndEntities.JELLO, RendererEntityJello::new); } - private static void register(EntityType type, Class> renderer) { + private static void register(EntityType type, Function> render) { EntityRendererRegistry.INSTANCE.register(type, (entityRenderDispatcher, context) -> { - MobEntityRenderer render = null; - try { - render = renderer.getConstructor(entityRenderDispatcher.getClass()).newInstance(entityRenderDispatcher); - } catch (Exception e) { - e.printStackTrace(); - } - return render; + return render.apply(entityRenderDispatcher); }); } } diff --git a/src/main/java/ru/betterend/registry/EndItems.java b/src/main/java/ru/betterend/registry/EndItems.java index 8e096744..ff06cfb9 100644 --- a/src/main/java/ru/betterend/registry/EndItems.java +++ b/src/main/java/ru/betterend/registry/EndItems.java @@ -41,6 +41,7 @@ import ru.betterend.item.EndPickaxe; import ru.betterend.item.EndToolMaterial; import ru.betterend.item.EternalCrystal; import ru.betterend.item.GuideBook; +import ru.betterend.item.ItemSpawnEgg; import ru.betterend.item.PatternedItem; import ru.betterend.tab.CreativeTabs; import ru.betterend.util.TagHelper; @@ -157,7 +158,7 @@ public class EndItems { } public static Item registerEgg(String name, EntityType type, int background, int dots) { - SpawnEggItem item = new SpawnEggItem(type, background, dots, makeItemSettings()); + SpawnEggItem item = new ItemSpawnEgg(type, background, dots, makeItemSettings()); ItemDispenserBehavior behavior = new ItemDispenserBehavior() { public ItemStack dispenseSilently(BlockPointer pointer, ItemStack stack) { Direction direction = pointer.getBlockState().get(DispenserBlock.FACING); diff --git a/src/main/resources/assets/betterend/lang/en_us.json b/src/main/resources/assets/betterend/lang/en_us.json index b7654c59..c9d8254e 100644 --- a/src/main/resources/assets/betterend/lang/en_us.json +++ b/src/main/resources/assets/betterend/lang/en_us.json @@ -421,5 +421,8 @@ "block.betterend.charnia_light_blue": "Light Blue Charnia", "block.betterend.charnia_orange": "Orange Charnia", "block.betterend.charnia_purple": "Purple Charnia", - "block.betterend.charnia_red": "Red Charnia" + "block.betterend.charnia_red": "Red Charnia", + + "entity.betterend.jello": "Jello", + "item.betterend.spawn_egg_jello": "Jello Spawn Egg" } \ No newline at end of file diff --git a/src/main/resources/assets/betterend/lang/ru_ru.json b/src/main/resources/assets/betterend/lang/ru_ru.json index 4a01a735..5509f597 100644 --- a/src/main/resources/assets/betterend/lang/ru_ru.json +++ b/src/main/resources/assets/betterend/lang/ru_ru.json @@ -423,5 +423,8 @@ "block.betterend.charnia_light_blue": "Голубая чарния", "block.betterend.charnia_orange": "Оранжевая чарния", "block.betterend.charnia_purple": "Пурпурная чарния", - "block.betterend.charnia_red": "Красная чарния" + "block.betterend.charnia_red": "Красная чарния", + + "entity.betterend.jello": "Желе", + "item.betterend.spawn_egg_jello": "Яйцо призыва желе" } \ No newline at end of file diff --git a/src/main/resources/assets/betterend/models/item/spawn_egg_end_fish.json b/src/main/resources/assets/betterend/models/item/spawn_egg_end_fish.json deleted file mode 100644 index 796d20ab..00000000 --- a/src/main/resources/assets/betterend/models/item/spawn_egg_end_fish.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "item/template_spawn_egg" -} diff --git a/src/main/resources/assets/betterend/models/item/spawn_egg_end_slime.json b/src/main/resources/assets/betterend/models/item/spawn_egg_end_slime.json deleted file mode 100644 index 796d20ab..00000000 --- a/src/main/resources/assets/betterend/models/item/spawn_egg_end_slime.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "item/template_spawn_egg" -} diff --git a/src/main/resources/assets/betterend/models/item/spawn_egg_shadow_walker.json b/src/main/resources/assets/betterend/models/item/spawn_egg_shadow_walker.json deleted file mode 100644 index 796d20ab..00000000 --- a/src/main/resources/assets/betterend/models/item/spawn_egg_shadow_walker.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "parent": "item/template_spawn_egg" -} diff --git a/src/main/resources/assets/betterend/models/item/spawn_egg_dragonfly.json b/src/main/resources/assets/betterend/patterns/item/pattern_item_spawn_egg.json similarity index 100% rename from src/main/resources/assets/betterend/models/item/spawn_egg_dragonfly.json rename to src/main/resources/assets/betterend/patterns/item/pattern_item_spawn_egg.json diff --git a/src/main/resources/assets/betterend/textures/entity/jello.png b/src/main/resources/assets/betterend/textures/entity/jello.png new file mode 100644 index 00000000..f38db9da Binary files /dev/null and b/src/main/resources/assets/betterend/textures/entity/jello.png differ