Added curing joke and ignimeous bulbs

This commit is contained in:
Sollace 2024-01-03 21:51:24 +01:00
parent 80225bf1e7
commit 6eea0944d2
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
27 changed files with 604 additions and 22 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
assets/models/bulb_idle.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,69 @@
// Made with Blockbench 4.8.3
// Exported for Minecraft version 1.17+ for Yarn
// Paste this class into your mod and generate all required imports
public class ignimious_bulb extends EntityModel<Entity> {
private final ModelPart head;
private final ModelPart cube_r1;
private final ModelPart head_r1;
private final ModelPart leaves;
private final ModelPart cube_r2;
private final ModelPart cube_r3;
private final ModelPart cube_r4;
private final ModelPart cube_r5;
private final ModelPart cube_r6;
private final ModelPart cube_r7;
private final ModelPart cube_r8;
private final ModelPart cube_r9;
private final ModelPart cube_r10;
private final ModelPart cube_r11;
private final ModelPart cube_r12;
private final ModelPart cube_r13;
public ignimious_bulb(ModelPart root) {
this.head = root.getChild("head");
this.leaves = root.getChild("leaves");
}
public static TexturedModelData getTexturedModelData() {
ModelData modelData = new ModelData();
ModelPartData modelPartData = modelData.getRoot();
ModelPartData head = modelPartData.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-24.0432F, -0.9905F, -48.1305F, 48.0F, 23.0F, 48.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 7.0F, 24.0F, -0.1308F, 0.0057F, 0.0433F));
ModelPartData cube_r1 = head.addChild("cube_r1", ModelPartBuilder.create().uv(112, 0).cuboid(-16.0F, -27.0F, 5.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(1.3731F, -21.6152F, -11.61F, -1.9802F, 0.1003F, 0.0006F));
ModelPartData head_r1 = head.addChild("head_r1", ModelPartBuilder.create().uv(0, 71).cuboid(-23.0F, -16.0F, -46.0F, 46.0F, 23.0F, 46.0F, new Dilation(0.0F)), ModelTransform.of(-0.0432F, -0.9905F, -0.1305F, -0.1309F, 0.0F, 0.0F));
ModelPartData leaves = modelPartData.addChild("leaves", ModelPartBuilder.create(), ModelTransform.pivot(0.0F, 27.0F, -1.0F));
ModelPartData cube_r2 = leaves.addChild("cube_r2", ModelPartBuilder.create().uv(112, 0).cuboid(-16.0F, 3.0F, -55.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 2.8316F, -1.0127F, -3.0858F));
ModelPartData cube_r3 = leaves.addChild("cube_r3", ModelPartBuilder.create().uv(112, 0).cuboid(-14.0F, 12.0F, -60.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 2.6063F, -0.075F, -3.1196F));
ModelPartData cube_r4 = leaves.addChild("cube_r4", ModelPartBuilder.create().uv(112, 0).cuboid(-20.0F, 1.0F, -51.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -0.7079F, -1.4622F, 0.4842F));
ModelPartData cube_r5 = leaves.addChild("cube_r5", ModelPartBuilder.create().uv(112, 0).cuboid(-16.0F, 6.0F, -58.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -0.4967F, 0.1003F, 0.0006F));
ModelPartData cube_r6 = leaves.addChild("cube_r6", ModelPartBuilder.create().uv(-64, 140).cuboid(-30.0F, 7.0F, -83.0F, 64.0F, 0.0F, 64.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 2.8708F, -0.1388F, -3.0651F));
ModelPartData cube_r7 = leaves.addChild("cube_r7", ModelPartBuilder.create().uv(-64, 140).cuboid(-30.0F, 7.0F, -83.0F, 64.0F, 0.0F, 64.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -1.084F, -1.4961F, 0.807F));
ModelPartData cube_r8 = leaves.addChild("cube_r8", ModelPartBuilder.create().uv(-64, 140).cuboid(-30.0F, 3.0F, -83.0F, 64.0F, 0.0F, 64.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -0.2651F, -0.035F, -0.0332F));
ModelPartData cube_r9 = leaves.addChild("cube_r9", ModelPartBuilder.create().uv(-64, 140).cuboid(-30.0F, 7.0F, -83.0F, 64.0F, 0.0F, 64.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -1.95F, 1.4932F, -1.6857F));
ModelPartData cube_r10 = leaves.addChild("cube_r10", ModelPartBuilder.create().uv(112, 0).cuboid(-16.0F, 10.0F, -57.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -2.5197F, 1.466F, -2.0202F));
ModelPartData cube_r11 = leaves.addChild("cube_r11", ModelPartBuilder.create().uv(112, 0).cuboid(-8.0F, 3.0F, -61.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, 2.9628F, 0.6133F, -2.978F));
ModelPartData cube_r12 = leaves.addChild("cube_r12", ModelPartBuilder.create().uv(112, 0).cuboid(-13.0F, 6.0F, -60.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -0.4768F, 0.8786F, -0.1186F));
ModelPartData cube_r13 = leaves.addChild("cube_r13", ModelPartBuilder.create().uv(112, 0).cuboid(-16.0F, 0.0F, -59.0F, 32.0F, 0.0F, 32.0F, new Dilation(0.0F)), ModelTransform.of(0.0F, 0.0F, 0.0F, -0.2911F, -0.5857F, 0.0605F));
return TexturedModelData.of(modelData, 256, 256);
}
@Override
public void setAngles(Entity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
}
@Override
public void render(MatrixStack matrices, VertexConsumer vertexConsumer, int light, int overlay, float red, float green, float blue, float alpha) {
head.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
leaves.render(matrices, vertexConsumer, light, overlay, red, green, blue, alpha);
}
}

View file

@ -62,11 +62,18 @@ public interface USounds {
SoundEvent ENTITY_SOMBRA_AMBIENT = register("entity.sombra.ambient");
SoundEvent ENTITY_SOMBRA_LAUGH = register("entity.sombra.laugh");
SoundEvent ENTITY_SOMBRA_SNICKER = register("entity.sombra.snicker");
SoundEvent ENTITY_SOMBRA_SCARY = USounds.Vanilla.ENTITY_GHAST_AMBIENT;
SoundEvent ENTITY_SOMBRA_SCARY = ENTITY_GHAST_AMBIENT;
SoundEvent ENTITY_CRYSTAL_SHARDS_AMBIENT = BLOCK_AMETHYST_BLOCK_HIT;
SoundEvent ENTITY_CRYSTAL_SHARDS_JOSTLE = BLOCK_AMETHYST_BLOCK_BREAK;
SoundEvent ENTITY_IGNIMEOUS_BULB_HURT = ENTITY_WARDEN_HURT;
SoundEvent ENTITY_IGNIMEOUS_BULB_DEATH = ENTITY_WARDEN_DEATH;
SoundEvent ENTITY_TENTACLE_ROAR = ENTITY_RAVAGER_ROAR;
SoundEvent ENTITY_TENTACLE_AMBIENT = BLOCK_CONDUIT_AMBIENT_SHORT;
SoundEvent ENTITY_TENTACLE_DIG = ENTITY_WARDEN_DIG;
SoundEvent ITEM_AMULET_CHARGING = register("item.amulet.charging");
SoundEvent ITEM_AMULET_RECHARGE = register("item.amulet.recharge");
@ -90,6 +97,8 @@ public interface USounds {
SoundEvent ITEM_STAFF_STRIKE = ENTITY_PLAYER_ATTACK_CRIT;
SoundEvent ITEM_MAGIC_STAFF_CHARGE = ENTITY_GUARDIAN_ATTACK;
SoundEvent ITEM_CURING_JOKE_CURE = BLOCK_AMETHYST_BLOCK_BREAK;
SoundEvent ITEM_ROCK_LAND = BLOCK_STONE_HIT;
RegistryEntry.Reference<SoundEvent> ITEM_MUFFIN_BOUNCE = BLOCK_NOTE_BLOCK_BANJO;

View file

@ -12,6 +12,7 @@ import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.util.TraceHelper;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FarmlandBlock;
import net.minecraft.item.BoneMealItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
@ -84,11 +85,11 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
w.setBlockState(pos.down(), Blocks.DIRT.getDefaultState());
}
w.setBlockState(pos, UBlocks.PLUNDER_VINE_BUD.getDefaultState());
} else if (w.random.nextInt(5000) == 0) {
} else if (w.random.nextInt(5000) == 0 || w.getBlockState(pos).isOf(UBlocks.CURING_JOKE)) {
if (w.getBlockState(pos.down()).isOf(Blocks.FARMLAND)) {
w.setBlockState(pos.down(), Blocks.DIRT.getDefaultState());
FarmlandBlock.setToDirt(null, state, w, pos.down());
}
w.breakBlock(pos, true);
w.breakBlock(pos, false);
TentacleEntity tentacle = new TentacleEntity(w, pos);
tentacle.updatePositionAndAngles(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0);
w.spawnEntity(tentacle);

View file

@ -0,0 +1,24 @@
package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import net.minecraft.block.BlockState;
import net.minecraft.block.FlowerBlock;
import net.minecraft.client.util.ParticleUtil;
import net.minecraft.entity.effect.StatusEffect;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.World;
class CuringJokeBlock extends FlowerBlock {
public CuringJokeBlock(StatusEffect suspiciousStewEffect, int effectDuration, Settings settings) {
super(suspiciousStewEffect, effectDuration, settings);
}
@Override
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
for (int i = 0; i < 3; i++) {
ParticleUtil.spawnParticle(world, pos, random, new MagicParticleEffect(0x3388EE));
}
}
}

View file

@ -21,6 +21,7 @@ import com.minelittlepony.unicopia.block.cloud.SoggyCloudBlock;
import com.minelittlepony.unicopia.block.cloud.SoggyCloudSlabBlock;
import com.minelittlepony.unicopia.block.cloud.SoggyCloudStairsBlock;
import com.minelittlepony.unicopia.block.cloud.UnstableCloudBlock;
import com.minelittlepony.unicopia.entity.effect.UEffects;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.cloud.CloudBlockItem;
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
@ -138,6 +139,7 @@ public interface UBlocks {
Block PLUNDER_VINE = register("plunder_vine", new ThornBlock(Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).ticksRandomly().sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY), () -> UBlocks.PLUNDER_VINE_BUD));
Block PLUNDER_VINE_BUD = register("plunder_vine_bud", new ThornBudBlock(Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).nonOpaque().ticksRandomly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY), PLUNDER_VINE.getDefaultState()));
Block CURING_JOKE = register("curing_joke", new CuringJokeBlock(UEffects.BUTTER_FINGERS, 7, AbstractBlock.Settings.create().mapColor(MapColor.PALE_PURPLE).noCollision().breakInstantly().sounds(BlockSoundGroup.GRASS).offset(AbstractBlock.OffsetType.XZ).pistonBehavior(PistonBehavior.DESTROY)));
Block CHITIN = register("chitin", new SnowyBlock(Settings.create().mapColor(MapColor.PALE_PURPLE).hardness(5).requiresTool().ticksRandomly().sounds(BlockSoundGroup.CORAL)), ItemGroups.NATURAL);
Block SURFACE_CHITIN = register("surface_chitin", new GrowableBlock(Settings.copy(CHITIN), () -> CHITIN), ItemGroups.NATURAL);
@ -240,7 +242,7 @@ public interface UBlocks {
StrippableBlockRegistry.register(PALM_LOG, STRIPPED_PALM_LOG);
StrippableBlockRegistry.register(ZAP_WOOD, STRIPPED_ZAP_WOOD);
StrippableBlockRegistry.register(PALM_WOOD, STRIPPED_PALM_WOOD);
Collections.addAll(TRANSLUCENT_BLOCKS, WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL);
Collections.addAll(TRANSLUCENT_BLOCKS, WEATHER_VANE, CHITIN_SPIKES, PLUNDER_VINE, PLUNDER_VINE_BUD, CLAM_SHELL, SCALLOP_SHELL, TURRET_SHELL, CURING_JOKE);
TintedBlock.REGISTRY.add(PALM_LEAVES);
FlammableBlockRegistry.getDefaultInstance().add(GREEN_APPLE_LEAVES, 30, 60);

View file

@ -98,6 +98,7 @@ public interface URenderers {
EntityRendererRegistry.register(UEntities.FRIENDLY_CREEPER, FriendlyCreeperEntityRenderer::new);
EntityRendererRegistry.register(UEntities.LOOT_BUG, LootBugEntityRenderer::new);
EntityRendererRegistry.register(UEntities.TENTACLE, TentacleEntityRenderer::new);
EntityRendererRegistry.register(UEntities.IGNIMEOUS_BULB, IgnimeousBulbEntityRenderer::new);
BlockEntityRendererFactories.register(UBlockEntities.WEATHER_VANE, WeatherVaneBlockEntityRenderer::new);
BlockEntityRendererFactories.register(UBlockEntities.FANCY_BED, CloudBedBlockEntityRenderer::new);

View file

@ -0,0 +1,77 @@
package com.minelittlepony.unicopia.client.render.entity;
import com.minelittlepony.unicopia.entity.mob.IgnimeousBulbEntity;
import net.minecraft.client.model.Dilation;
import net.minecraft.client.model.ModelData;
import net.minecraft.client.model.ModelPart;
import net.minecraft.client.model.ModelPartBuilder;
import net.minecraft.client.model.ModelPartData;
import net.minecraft.client.model.ModelTransform;
import net.minecraft.client.model.TexturedModelData;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.entity.model.EntityModel;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.math.MathHelper;
public class IgnimeousBulbEntityModel extends EntityModel<IgnimeousBulbEntity> {
private final ModelPart part;
private final ModelPart head;
private final ModelPart leaves;
public IgnimeousBulbEntityModel(ModelPart root) {
super(RenderLayer::getEntityTranslucent);
this.part = root;
head = root.getChild("head");
leaves = root.getChild("leaves");
}
public static TexturedModelData getTexturedModelData() {
ModelData data = new ModelData();
ModelPartData root = data.getRoot();
ModelPartData head = root.addChild("head", ModelPartBuilder.create().uv(0, 0).cuboid(-24.0432F, -0.9905F, -48.1305F, 48, 23, 48, Dilation.NONE), ModelTransform.of(0, 7, 24, -0.1308F, 0.0057F, 0.0433F));
head.addChild("jaw", ModelPartBuilder.create().uv(112, 0).cuboid(-16, -27, 5, 32, 0, 32, Dilation.NONE), ModelTransform.of(1.3731F, -21.6152F, -11.61F, -1.9802F, 0.1003F, 0.0006F));
head.addChild("head", ModelPartBuilder.create().uv(0, 71).cuboid(-23, -16, -46, 46, 23, 46, Dilation.NONE), ModelTransform.of(-0.0432F, -0.9905F, -0.1305F, -0.1309F, 0, 0));
ModelPartData leaves = root.addChild("leaves", ModelPartBuilder.create(), ModelTransform.pivot(0, 27, -1));
leaves.addChild("leaf_1", ModelPartBuilder.create().uv(112, 0).cuboid(-16, 3, -55, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(2.8316F, -1.0127F, -3.0858F));
leaves.addChild("leaf_2", ModelPartBuilder.create().uv(112, 0).cuboid(-14, 12, -60, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(2.6063F, -0.075F, -3.1196F));
leaves.addChild("leaf_3", ModelPartBuilder.create().uv(112, 0).cuboid(-20, 1, -51, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(-0.7079F, -1.4622F, 0.4842F));
leaves.addChild("leaf_4", ModelPartBuilder.create().uv(112, 0).cuboid(-16, 6, -58, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(-0.4967F, 0.1003F, 0.0006F));
leaves.addChild("leaf_5", ModelPartBuilder.create().uv(-64, 140).cuboid(-30, 7, -83, 64, 0, 64, Dilation.NONE), ModelTransform.rotation(2.8708F, -0.1388F, -3.0651F));
leaves.addChild("leaf_6", ModelPartBuilder.create().uv(-64, 140).cuboid(-30, 7, -83, 64, 0, 64, Dilation.NONE), ModelTransform.rotation(-1.084F, -1.4961F, 0.807F));
leaves.addChild("leaf_7", ModelPartBuilder.create().uv(-64, 140).cuboid(-30, 3, -83, 64, 0, 64, Dilation.NONE), ModelTransform.rotation(-0.2651F, -0.035F, -0.0332F));
leaves.addChild("leaf_8", ModelPartBuilder.create().uv(-64, 140).cuboid(-30, 7, -83, 64, 0, 64, Dilation.NONE), ModelTransform.rotation(-1.95F, 1.4932F, -1.6857F));
leaves.addChild("leaf_9", ModelPartBuilder.create().uv(112, 0).cuboid(-16, 10, -57, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(-2.5197F, 1.466F, -2.0202F));
leaves.addChild("leaf_10", ModelPartBuilder.create().uv(112, 0).cuboid(-8, 3, -61, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(2.9628F, 0.6133F, -2.978F));
leaves.addChild("leaf_11", ModelPartBuilder.create().uv(112, 0).cuboid(-13, 6, -60, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(-0.4768F, 0.8786F, -0.1186F));
leaves.addChild("leaf_12", ModelPartBuilder.create().uv(112, 0).cuboid(-16, 0, -59, 32, 0, 32, Dilation.NONE), ModelTransform.rotation(-0.2911F, -0.5857F, 0.0605F));
return TexturedModelData.of(data, 256, 256);
}
@Override
public void setAngles(IgnimeousBulbEntity entity, float limbSwing, float limbSwingAmount, float tickDelta, float yaw, float pitch) {
float age = entity.age + tickDelta;
head.yScale = 1 - MathHelper.sin(age * 0.05F) * 0.02F;
float hScale = 1 + MathHelper.cos(age * 0.06F) * 0.02F;
head.xScale = hScale;
head.zScale = hScale;
head.pitch = MathHelper.sin(age * 0.02F) * 0.02F;
head.yaw = MathHelper.cos(age * 0.02F) * 0.02F;
leaves.yScale = 1 + MathHelper.sin(age * 0.05F) * 0.12F;
}
@Override
public void render(MatrixStack matrices, VertexConsumer vertices, int light, int overlay, float red, float green, float blue, float alpha) {
part.render(matrices, vertices, light, overlay);
}
}

View file

@ -0,0 +1,39 @@
package com.minelittlepony.unicopia.client.render.entity;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.entity.mob.IgnimeousBulbEntity;
import net.minecraft.client.render.OverlayTexture;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
public class IgnimeousBulbEntityRenderer extends EntityRenderer<IgnimeousBulbEntity> {
private static final Identifier IDLE_TEXTURE = Unicopia.id("textures/entity/poison_joke/bulb_idle.png");
private static final Identifier ANGRY_TEXTURE = Unicopia.id("textures/entity/poison_joke/bulb_angry.png");
private final IgnimeousBulbEntityModel model;
public IgnimeousBulbEntityRenderer(EntityRendererFactory.Context context) {
super(context);
model = new IgnimeousBulbEntityModel(IgnimeousBulbEntityModel.getTexturedModelData().createModel());
}
@Override
public void render(IgnimeousBulbEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
matrices.push();
matrices.scale(-1, -1, 1);
matrices.translate(0, -1.5F, 0);
model.setAngles(entity, 0, 0, tickDelta, entity.getYaw(tickDelta), entity.getPitch(tickDelta));
model.render(matrices, vertices.getBuffer(model.getLayer(getTexture(entity))), light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
matrices.pop();
super.render(entity, yaw, tickDelta, matrices, vertices, light);
}
@Override
public Identifier getTexture(IgnimeousBulbEntity entity) {
return entity.isAngry() ? ANGRY_TEXTURE : IDLE_TEXTURE;
}
}

View file

@ -97,6 +97,9 @@ public class TentacleEntityModel extends EntityModel<TentacleEntity> {
@Override
public void setAngles(TentacleEntity entity, float limbSwing, float limbSwingAmount, float tickDelta, float yaw, float pitch) {
boolean growing = entity.getGrowth(tickDelta) < 1;
float age = entity.age + tickDelta + (entity.getUuid().getMostSignificantBits() % 100);
float idleWaveTimer = entity.getAnimationTimer(tickDelta);
@ -116,9 +119,11 @@ public class TentacleEntityModel extends EntityModel<TentacleEntity> {
bendIntentisty += 3F;
bone.resetTransform();
bone.pitch = MathHelper.lerp(attackProgress, idlePitch, bone.pitch + attackCurve);
bone.yaw = MathHelper.lerp(attackProgress, idleYaw, bone.yaw + sweepDirection * attackCurve);
bone.roll = MathHelper.lerp(attackProgress, idleRoll, bone.roll);
if (!growing) {
bone.pitch = MathHelper.lerp(attackProgress, idlePitch, bone.pitch + attackCurve);
bone.yaw = MathHelper.lerp(attackProgress, idleYaw, bone.yaw + sweepDirection * attackCurve);
bone.roll = MathHelper.lerp(attackProgress, idleRoll, bone.roll);
}
attackCurve *= 1.04F;
}

View file

@ -9,6 +9,7 @@ import net.minecraft.client.render.entity.EntityRenderer;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
public class TentacleEntityRenderer extends EntityRenderer<TentacleEntity> {
private static final Identifier TEXTURE = Unicopia.id("textures/entity/poison_joke/tentacle.png");
@ -26,8 +27,9 @@ public class TentacleEntityRenderer extends EntityRenderer<TentacleEntity> {
matrices.scale(-1, -1, 1);
float scale = entity.getGrowth(tickDelta);
matrices.translate(0, -0.75F + 3F * (1 - scale), 0);
scale = MathHelper.clamp(scale, 0.5F, 1);
matrices.scale(scale, scale, scale);
matrices.translate(0, -0.9F, 0);
model.setAngles(entity, 0, 0, tickDelta, entity.getYaw(tickDelta), entity.getPitch(tickDelta));
model.render(matrices, vertices.getBuffer(model.getLayer(getTexture(entity))), light, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);

View file

@ -0,0 +1,167 @@
package com.minelittlepony.unicopia.entity.mob;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.MovementType;
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.mob.MobEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class IgnimeousBulbEntity extends MobEntity {
private static final TrackedData<Boolean> ANGRY = DataTracker.registerData(IgnimeousBulbEntity.class, TrackedDataHandlerRegistry.BOOLEAN);
private static final List<BlockPos> TENTACLE_OFFSETS = List.of(
new BlockPos(-3, 0, -3), new BlockPos(0, 0, -4), new BlockPos(3, 0, -3),
new BlockPos(-4, 0, 0), new BlockPos(4, 0, 0),
new BlockPos(-3, 0, 3), new BlockPos(0, 0, 4), new BlockPos(3, 0, 4)
);
@Nullable
private Map<BlockPos, TentacleEntity> tentacles;
public IgnimeousBulbEntity(EntityType<? extends IgnimeousBulbEntity> type, World world) {
super(type, world);
}
public IgnimeousBulbEntity(World world) {
super(UEntities.IGNIMEOUS_BULB, world);
}
@Override
protected void initDataTracker() {
super.initDataTracker();
dataTracker.startTracking(ANGRY, false);
}
public boolean isAngry() {
return dataTracker.get(ANGRY);
}
public void setAngry(boolean angry) {
dataTracker.set(ANGRY, angry);
}
@Override
public void tick() {
if (!getWorld().isClient && !isRemoved()) {
var center = new BlockPos.Mutable();
var tentacles = getTentacles();
TENTACLE_OFFSETS.forEach(offset -> {
tentacles.compute(adjustForTerrain(center, offset), this::updateTentacle);
});
if (getWorld().random.nextInt(isAngry() ? 12 : 1200) == 0) {
for (TentacleEntity tentacle : tentacles.values()) {
tentacle.addActiveTicks(120);
}
}
LivingEntity target = getAttacker();
setAngry(target != null);
if (isAngry() && getWorld().random.nextInt(30) == 0) {
if (target instanceof PlayerEntity player) {
Pony.of(player).getMagicalReserves().getEnergy().add(6);
}
tentacles.values()
.stream()
.sorted(Comparator.comparing(a -> a.distanceTo(target)))
.limit(2)
.forEach(tentacle -> {
tentacle.setTarget(target);
});
}
}
super.tick();
}
private Map<BlockPos, TentacleEntity> getTentacles() {
if (tentacles == null) {
tentacles = getWorld().getEntitiesByClass(TentacleEntity.class, this.getBoundingBox().expand(5, 0, 5), EntityPredicates.VALID_ENTITY)
.stream()
.collect(Collectors.toMap(TentacleEntity::getBlockPos, Function.identity()));
}
return tentacles;
}
private TentacleEntity updateTentacle(BlockPos pos, @Nullable TentacleEntity tentacle) {
if (tentacle == null || tentacle.isRemoved()) {
tentacle = new TentacleEntity(getWorld(), pos);
tentacle.updatePositionAndAngles(pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, getWorld().random.nextFloat() * 360, 0);
getWorld().spawnEntity(tentacle);
}
return tentacle;
}
private BlockPos adjustForTerrain(BlockPos.Mutable mutable, BlockPos offset) {
World w = getWorld();
mutable.set(getBlockPos());
mutable.move(offset);
while (w.isAir(mutable.down()) && w.isInBuildLimit(mutable)) {
mutable.move(Direction.DOWN);
}
while (!w.isAir(mutable) && w.isInBuildLimit(mutable)) {
mutable.move(Direction.UP);
}
return mutable.toImmutable();
}
@Override
public void remove(RemovalReason reason) {
super.remove(reason);
getTentacles().values().forEach(tentacle -> tentacle.remove(reason));
}
@Override
public void move(MovementType movementType, Vec3d movement) { }
@Override
public void addVelocity(double deltaX, double deltaY, double deltaZ) { }
@Override
@Nullable
protected SoundEvent getHurtSound(DamageSource source) {
return USounds.ENTITY_IGNIMEOUS_BULB_HURT;
}
@Override
@Nullable
protected SoundEvent getDeathSound() {
return USounds.ENTITY_IGNIMEOUS_BULB_DEATH;
}
@Override
public void writeCustomDataToNbt(NbtCompound nbt) {
super.writeCustomDataToNbt(nbt);
nbt.putBoolean("angry", isAngry());
}
@Override
public void readCustomDataFromNbt(NbtCompound nbt) {
super.readCustomDataFromNbt(nbt);
setAngry(nbt.getBoolean("angry"));
}
}

View file

@ -4,6 +4,8 @@ import java.util.Comparator;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.block.UBlocks;
import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.util.shape.Sphere;
@ -19,9 +21,10 @@ import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.decoration.AbstractDecorationEntity;
import net.minecraft.entity.mob.HostileEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.math.BlockPos;
@ -126,7 +129,7 @@ public class TentacleEntity extends AbstractDecorationEntity {
@Override
public boolean damage(DamageSource source, float amount) {
if (source.getAttacker() instanceof PlayerEntity player) {
if (player.getStackInHand(Hand.MAIN_HAND).isIn(ItemTags.SHOVELS)) {
if (player.getStackInHand(Hand.MAIN_HAND).isIn(ItemTags.AXES)) {
kill();
ParticleUtils.spawnParticles(ParticleTypes.EFFECT, this, 10);
}
@ -134,15 +137,20 @@ public class TentacleEntity extends AbstractDecorationEntity {
setTarget(player);
}
}
ticksActive += 20;
playSound(SoundEvents.ENTITY_RAVAGER_ROAR, 5, 1);
addActiveTicks(20 + getWorld().random.nextInt(30));
playSound(USounds.ENTITY_TENTACLE_ROAR, 5, 1);
return true;
}
public void addActiveTicks(int ticks) {
ticksActive += ticks;
}
@Override
public void tick() {
prevMotionOffset = getMotionOffset();
prevGrowth = getGrowth();
int growth = getGrowth();
prevGrowth = growth;
super.tick();
prevAttackingTicks = attackingTicks;
if (isAttacking()) {
@ -164,9 +172,6 @@ public class TentacleEntity extends AbstractDecorationEntity {
target = null;
}
playSound(SoundEvents.BLOCK_POINTED_DRIPSTONE_LAND, 1, 1);
}
}
@ -175,8 +180,6 @@ public class TentacleEntity extends AbstractDecorationEntity {
ParticleUtils.spawnParticles(getWorld(), sphere, ParticleTypes.ASH, 4);
if (!getWorld().isClient) {
int growth = getGrowth();
if (growth >= MAX_GROWTH / 2) {
if (age % 50 == 0) {
updateTarget();
@ -189,28 +192,40 @@ public class TentacleEntity extends AbstractDecorationEntity {
if (growth < MAX_GROWTH) {
setGrowth(growth + 1);
if (growth == 0) {
playSound(USounds.ENTITY_TENTACLE_DIG, 1, 1);
}
}
if (getWorld().random.nextInt(110) == 0) {
playSound(SoundEvents.BLOCK_CONDUIT_AMBIENT_SHORT, 1, 0.3F);
playSound(USounds.ENTITY_TENTACLE_AMBIENT, 1, 0.3F);
}
if (ticksActive > 0) {
ticksActive--;
setMotionOffset(getMotionOffset() + ticksActive);
}
} else {
if (growth < MAX_GROWTH && age % 15 == getWorld().random.nextInt(14)) {
getWorld().addBlockBreakParticles(getBlockPos().down(), getWorld().getBlockState(getBlockPos().down()));
}
}
}
public void setTarget(LivingEntity target) {
this.target = target;
playSound(SoundEvents.ENTITY_RAVAGER_ROAR, 5, 1);
playSound(USounds.ENTITY_TENTACLE_ROAR, 5, 1);
if (target instanceof PlayerEntity player) {
Pony.of(player).getMagicalReserves().getEnergy().add(6);
}
}
public LivingEntity getTarget() {
return target;
}
private void updateTarget() {
if (!canTarget(target)) {
target = null;
@ -260,6 +275,16 @@ public class TentacleEntity extends AbstractDecorationEntity {
}
@Override
public void remove(RemovalReason reason) {
super.remove(reason);
if (getWorld().isAir(getBlockPos()) && getWorld().getBlockState(getBlockPos().down()).isIn(BlockTags.DIRT)) {
getWorld().setBlockState(getBlockPos(), UBlocks.CURING_JOKE.getDefaultState());
}
}
@Override
public boolean canStayAttached() {
return getWorld().isTopSolid(getBlockPos().down(), this);
@ -286,4 +311,18 @@ public class TentacleEntity extends AbstractDecorationEntity {
@Override
public void addVelocity(double deltaX, double deltaY, double deltaZ) { }
@Override
public void writeCustomDataToNbt(NbtCompound nbt) {
super.writeCustomDataToNbt(nbt);
nbt.putInt("growth", getGrowth());
nbt.putInt("motion_offset", getMotionOffset());
}
@Override
public void readCustomDataFromNbt(NbtCompound nbt) {
super.readCustomDataFromNbt(nbt);
setGrowth(nbt.getInt("growth"));
setMotionOffset(nbt.getInt("motion_offset"));
}
}

View file

@ -67,9 +67,12 @@ public interface UEntities {
EntityType<LootBugEntity> LOOT_BUG = register("loot_bug", FabricEntityTypeBuilder.create(SpawnGroup.MONSTER, LootBugEntity::new)
.trackRangeChunks(8)
.dimensions(EntityDimensions.fixed(0.8F, 0.6F)));
EntityType<TentacleEntity> TENTACLE = register("tentacle", FabricEntityTypeBuilder.<TentacleEntity>create(SpawnGroup.MISC, TentacleEntity::new)
EntityType<TentacleEntity> TENTACLE = register("ignimeous_vine", FabricEntityTypeBuilder.<TentacleEntity>create(SpawnGroup.MISC, TentacleEntity::new)
.trackRangeChunks(8)
.dimensions(EntityDimensions.fixed(0.8F, 0.8F)));
EntityType<IgnimeousBulbEntity> IGNIMEOUS_BULB = register("ignimeous_bulb", FabricEntityTypeBuilder.<IgnimeousBulbEntity>create(SpawnGroup.MISC, IgnimeousBulbEntity::new)
.trackRangeChunks(8)
.dimensions(EntityDimensions.fixed(3, 2)));
static <T extends Entity> EntityType<T> register(String name, FabricEntityTypeBuilder<T> builder) {
EntityType<T> type = builder.build();
@ -84,6 +87,7 @@ public interface UEntities {
FabricDefaultAttributeRegistry.register(SOMBRA, SombraEntity.createMobAttributes());
FabricDefaultAttributeRegistry.register(FRIENDLY_CREEPER, FriendlyCreeperEntity.createCreeperAttributes());
FabricDefaultAttributeRegistry.register(LOOT_BUG, LootBugEntity.createSilverfishAttributes());
FabricDefaultAttributeRegistry.register(IGNIMEOUS_BULB, IgnimeousBulbEntity.createMobAttributes());
if (!Unicopia.getConfig().disableButterflySpawning.get()) {
final Predicate<BiomeSelectionContext> butterflySpawnable = BiomeSelectors.foundInOverworld()

View file

@ -0,0 +1,119 @@
package com.minelittlepony.unicopia.item;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.particle.MagicParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.util.InventoryUtil;
import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.entity.InventoryOwner;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
public class CuringJokeItem extends BlockItem {
static final List<Predicate<LivingEntity>> EFFECTS = List.of(
CuringJokeItem::restoreAir,
CuringJokeItem::restoreHunger,
CuringJokeItem::restoreHealth,
CuringJokeItem::removeEffect,
CuringJokeItem::uncurseItem,
CuringJokeItem::repairItem
);
public CuringJokeItem(Block block, Settings settings) {
super(block, settings);
}
@Override
public ItemStack finishUsing(ItemStack stack, World world, LivingEntity user) {
var items = new ArrayList<>(EFFECTS);
while (!items.isEmpty()) {
if (items.remove(world.random.nextInt(items.size())).test(user)) {
ParticleUtils.spawnParticles(new MagicParticleEffect(0x3388EE), user, 25);
world.playSound(null, user.getBlockPos(), USounds.ITEM_CURING_JOKE_CURE, user.getSoundCategory(), 1, 1);
break;
}
}
return super.finishUsing(stack, world, user);
}
static boolean restoreAir(LivingEntity user) {
if (user.getAir() < user.getMaxAir()) {
user.setAir(user.getMaxAir());
return true;
}
return false;
}
static boolean restoreHunger(LivingEntity user) {
if (user instanceof PlayerEntity player && player.getHungerManager().getFoodLevel() < 20) {
player.getHungerManager().add(20, 0);
return true;
}
return false;
}
static boolean restoreHealth(LivingEntity user) {
if (user.getHealth() < user.getMaxHealth()) {
user.setHealth(user.getMaxHealth());
return true;
}
return false;
}
static boolean removeEffect(LivingEntity user) {
return user.getStatusEffects().stream().filter(effect -> {
return !effect.getEffectType().isBeneficial();
}).findAny().filter(effect -> {
user.removeStatusEffect(effect.getEffectType());
return true;
}).isPresent();
}
static boolean uncurseItem(LivingEntity user) {
return getInventory(user)
.filter(s -> EnchantmentHelper.get(s).keySet().stream().anyMatch(Enchantment::isCursed))
.findAny()
.filter(s -> {
var enchantments = EnchantmentHelper.get(s);
return enchantments.keySet().stream().filter(Enchantment::isCursed).findAny().filter(e -> {
enchantments.remove(e);
EnchantmentHelper.set(enchantments, s);
return true;
}).isPresent();
}).isPresent();
}
static boolean repairItem(LivingEntity user) {
return getInventory(user)
.filter(s -> s.getDamage() < s.getMaxDamage())
.findAny().filter(s -> {
s.setDamage(0);
return true;
}).isPresent();
}
static Stream<ItemStack> getInventory(LivingEntity entity) {
if (entity instanceof PlayerEntity player) {
return InventoryUtil.stream(player.getInventory());
}
if (entity instanceof InventoryOwner owner) {
return InventoryUtil.stream(owner.getInventory());
}
return StreamSupport.stream(entity.getItemsEquipped().spliterator(), false);
}
}

View file

@ -53,6 +53,8 @@ public interface UFoodComponents {
FoodComponent CANDY = builder(7, 0.9F).alwaysEdible().build();
FoodComponent SALT_CUBE = builder(0, 2.9F).alwaysEdible().build();
FoodComponent POISON_JOKE = builder(0, 0F).alwaysEdible().snack().build();
@Deprecated
FoodComponent SHELL = builder(3, 5).build();
@Deprecated

View file

@ -88,6 +88,7 @@ public interface UItems {
Item ACORN = register("acorn", new Item(new Item.Settings().food(UFoodComponents.ACORN).maxCount(16)), ItemGroups.FOOD_AND_DRINK);
Item MANGO = register("mango", new Item(new Item.Settings().food(UFoodComponents.MANGO)), ItemGroups.FOOD_AND_DRINK);
Item BANANA = register("banana", new Item(new Item.Settings().food(UFoodComponents.BANANA)), ItemGroups.FOOD_AND_DRINK);
Item CURING_JOKE = register("curing_joke", new CuringJokeItem(UBlocks.CURING_JOKE, new Item.Settings().food(UFoodComponents.POISON_JOKE)), ItemGroups.NATURAL);
Item PINEAPPLE = register("pineapple", new PineappleItem(new Item.Settings().food(UFoodComponents.BANANA).maxDamage(3)), ItemGroups.FOOD_AND_DRINK);
Item PINEAPPLE_CROWN = register("pineapple_crown", new AliasedBlockItem(UBlocks.PINEAPPLE, new Item.Settings()), ItemGroups.NATURAL);

View file

@ -0,0 +1,5 @@
{
"variants": {
"": { "model": "unicopia:block/curing_joke" }
}
}

View file

@ -246,6 +246,7 @@
"block.unicopia.palm_hanging_sign": "Palm Hanging Sign",
"block.unicopia.apple_pie": "Apple Pie",
"block.unicopia.weather_vane": "Weather Vane",
"block.unicopia.curing_joke": "Curing Joke",
"block.unicopia.mango": "Mango",
"block.unicopia.mango_leaves": "Mango Leaves",
"block.unicopia.mango_sapling": "Mango Sapling",
@ -322,6 +323,8 @@
"entity.unicopia.sombra.taunt": "That's not going to work on me!",
"entity.unicopia.storm_cloud": "Storm Cloud",
"entity.unicopia.crystal_shards": "Crystal Shards",
"entity.unicopia.ignimeous_vine": "Ignimeous Vine",
"entity.unicopia.ignimeous_bulb": "Ignimeous Bulb",
"player.reachDistance": "Reach Distance",
"player.miningSpeed": "Mining Speed",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/cross",
"textures": {
"cross": "unicopia:block/curing_joke"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": {
"layer0": "unicopia:item/curing_joke"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB