mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 13:37:58 +01:00
Fix various hot air balloon animations and quirks
It will no longer void the balloon and equipped fuel when broken
This commit is contained in:
parent
06e4a1c8be
commit
75aceac066
3 changed files with 110 additions and 35 deletions
|
@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.entity.mob.AirBalloonEntity;
|
|||
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.model.*;
|
||||
import net.minecraft.client.render.OverlayTexture;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.entity.model.EntityModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
|
@ -24,6 +25,7 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
private boolean isSandbags;
|
||||
|
||||
private final List<ModelPart> ropes;
|
||||
private final List<ModelPart> struts;
|
||||
private final List<ModelPart> sandbags;
|
||||
|
||||
public AirBalloonEntityModel(ModelPart root) {
|
||||
|
@ -41,6 +43,11 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
} else {
|
||||
ropes = List.of();
|
||||
}
|
||||
if (isBurner) {
|
||||
struts = List.of(root.getChild("strut_a"), root.getChild("strut_b"));
|
||||
} else {
|
||||
struts = List.of();
|
||||
}
|
||||
|
||||
sandbags = isSandbags ? List.of(
|
||||
root.getChild("sandbag_nw"), root.getChild("sandbag_sw"),
|
||||
|
@ -162,6 +169,9 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
ropes.forEach(rope -> {
|
||||
rope.visible = lifted;
|
||||
});
|
||||
struts.forEach(strut -> {
|
||||
strut.visible = lifted;
|
||||
});
|
||||
|
||||
root.pivotX += burnerWiggleProgress * MathHelper.sin((entity.age + tickDelta)) * 2.5F;
|
||||
root.pivotX += burnerWiggleProgress * MathHelper.cos((entity.age + tickDelta)) * 2.5F;
|
||||
|
@ -235,10 +245,10 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
matrices.push();
|
||||
matrices.translate(0, 1 * (1 - inflation), 0);
|
||||
matrices.scale(1, MathHelper.lerp(inflation, -0.05F, 1), 1);
|
||||
root.render(matrices, vertexConsumer, light, overlay, color);
|
||||
root.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, color);
|
||||
matrices.pop();
|
||||
} else {
|
||||
root.render(matrices, vertexConsumer, light, overlay, color);
|
||||
root.render(matrices, vertexConsumer, light, OverlayTexture.DEFAULT_UV, color);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,8 @@ import net.minecraft.item.Items;
|
|||
import net.minecraft.util.Colors;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
|
||||
public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
||||
public AirBalloonEntityRenderer(EntityRendererFactory.Context context) {
|
||||
|
@ -40,13 +42,19 @@ public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity
|
|||
|
||||
@Override
|
||||
public void render(AirBalloonEntity entity, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
|
||||
matrices.push();
|
||||
if (entity.hurtTime > 0) {
|
||||
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(MathHelper.sin(entity.age + tickDelta) * 3));
|
||||
}
|
||||
super.render(entity, yaw, tickDelta, matrices, vertices, light);
|
||||
matrices.pop();
|
||||
|
||||
if (MinecraftClient.getInstance().getEntityRenderDispatcher().shouldRenderHitboxes() && !entity.isInvisible() && !MinecraftClient.getInstance().hasReducedDebugInfo()) {
|
||||
MultiBox.forEach(entity.getBoundingBox(), box -> {
|
||||
WorldRenderer.drawBox(matrices, vertices.getBuffer(RenderLayer.getLines()), box.offset(entity.getPos().multiply(-1)), 1, 1, 1, 1);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -5,6 +5,7 @@ import net.minecraft.block.BlockState;
|
|||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.block.entity.FurnaceBlockEntity;
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.damage.DamageSource;
|
||||
import net.minecraft.entity.data.*;
|
||||
import net.minecraft.entity.data.DataTracker.Builder;
|
||||
import net.minecraft.entity.mob.MobEntity;
|
||||
|
@ -14,11 +15,14 @@ import net.minecraft.item.Item;
|
|||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.Items;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.nbt.NbtElement;
|
||||
import net.minecraft.nbt.NbtList;
|
||||
import net.minecraft.network.codec.PacketCodec;
|
||||
import net.minecraft.particle.ParticleTypes;
|
||||
import net.minecraft.predicate.entity.EntityPredicates;
|
||||
import net.minecraft.registry.RegistryKey;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.sound.SoundEvents;
|
||||
import net.minecraft.util.ActionResult;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
@ -26,6 +30,7 @@ import net.minecraft.util.StringIdentifiable;
|
|||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.math.random.Random;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.world.GameRules;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.event.GameEvent;
|
||||
|
||||
|
@ -57,6 +62,7 @@ import com.minelittlepony.unicopia.item.UItems;
|
|||
import com.minelittlepony.unicopia.item.component.BalloonDesignComponent;
|
||||
import com.minelittlepony.unicopia.item.component.UDataComponentTypes;
|
||||
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
||||
import com.minelittlepony.unicopia.util.serialization.NbtSerialisable;
|
||||
import com.minelittlepony.unicopia.util.serialization.PacketCodecUtils;
|
||||
import com.terraformersmc.terraform.boat.api.TerraformBoatType;
|
||||
|
||||
|
@ -80,7 +86,8 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
private Vec3d manualVelocity = Vec3d.ZERO;
|
||||
|
||||
private int maxFuel = 10000;
|
||||
private int fuel;
|
||||
private int activeFuel;
|
||||
private List<ItemStack> fuelItems = new ArrayList<>();
|
||||
|
||||
private final Animatable[] sandbags = IntStream.range(0, 5).mapToObj(Animatable::new).toArray(Animatable[]::new);
|
||||
private final Animatable burner = new Animatable(5);
|
||||
|
@ -182,6 +189,18 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
return (float)MathHelper.lerp(tickDelta, prevZDelta, zDelta);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected SoundEvent getHurtSound(DamageSource source) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvents.BLOCK_BAMBOO_WOOD_BREAK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
setAir(getMaxAir());
|
||||
|
@ -209,9 +228,13 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
setInflation(inflation);
|
||||
}
|
||||
|
||||
if (fuel > -6 && age % 2 == 0) {
|
||||
fuel -= boosting ? 50 : 1;
|
||||
if (fuel <= -6) {
|
||||
if (activeFuel <= 0 && !fuelItems.isEmpty()) {
|
||||
activeFuel = FurnaceBlockEntity.createFuelTimeMap().getOrDefault(fuelItems.remove(0).getItem(), 0);
|
||||
}
|
||||
|
||||
if (activeFuel > -6 && age % 2 == 0) {
|
||||
activeFuel -= boosting ? 50 : 1;
|
||||
if (activeFuel <= -6) {
|
||||
setBoostTicks(0);
|
||||
setAscending(false);
|
||||
}
|
||||
|
@ -238,7 +261,7 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
if (hasBurner() && isAscending()) {
|
||||
Vec3d burnerPos = getPos().add(0, 3, 0);
|
||||
for (int i = 0; i < (boosting ? 6 : 1); i++) {
|
||||
getWorld().addParticle(fuel <= 0
|
||||
getWorld().addParticle(activeFuel <= 0
|
||||
? ParticleTypes.SMOKE
|
||||
: getStackInHand(Hand.MAIN_HAND).isOf(Items.SOUL_LANTERN)
|
||||
? ParticleTypes.SOUL_FIRE_FLAME
|
||||
|
@ -305,6 +328,28 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
zDelta = getZ() - prevZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean damage(DamageSource source, float amount) {
|
||||
if (source.getAttacker() instanceof PlayerEntity player && player.getAbilities().creativeMode) {
|
||||
dropInventory();
|
||||
remove(RemovalReason.KILLED);
|
||||
return true;
|
||||
}
|
||||
if (super.damage(source, amount)) {
|
||||
hurtTime = 0;
|
||||
maxHurtTime = 0;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updatePostDeath() {
|
||||
if (!getWorld().isClient() && !isRemoved()) {
|
||||
remove(Entity.RemovalReason.KILLED);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult interactAt(PlayerEntity player, Vec3d hitPos, Hand hand) {
|
||||
ItemStack stack = player.getStackInHand(hand);
|
||||
|
@ -387,8 +432,8 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
|
||||
if (stack.isIn(ConventionalItemTags.SHEAR_TOOLS) && hasBalloon()) {
|
||||
stack.damage(1, player, getSlotForHand(hand));
|
||||
dropStack(BalloonDesignComponent.set(UItems.GIANT_BALLOON.getDefaultStack(), new BalloonDesignComponent(getDesign(), true)));
|
||||
setDesign(BalloonDesign.NONE);
|
||||
dropItem(UItems.GIANT_BALLOON);
|
||||
playSound(USounds.ENTITY_HOT_AIR_BALLOON_EQUIP_CANOPY.value(), 1, 1);
|
||||
if (!player.isSneaky()) {
|
||||
getWorld().emitGameEvent(player, GameEvent.EQUIP, getBlockPos());
|
||||
|
@ -414,15 +459,8 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
if (hasBurner()) {
|
||||
int fuel = FurnaceBlockEntity.createFuelTimeMap().getOrDefault(stack.getItem(), 0);
|
||||
if (fuel > 0) {
|
||||
if (this.fuel < maxFuel) {
|
||||
if (this.fuel < 0) {
|
||||
this.fuel = fuel;
|
||||
} else {
|
||||
this.fuel += fuel;
|
||||
}
|
||||
if (!player.getAbilities().creativeMode) {
|
||||
stack.decrement(1);
|
||||
}
|
||||
if (fuelItems.size() < 64) {
|
||||
fuelItems.add(stack.splitUnlessCreative(1, player));
|
||||
burner.setPulling();
|
||||
playSound(USounds.Vanilla.ENTITY_VILLAGER_YES, 1, 1);
|
||||
return ActionResult.SUCCESS;
|
||||
|
@ -436,10 +474,18 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
|
||||
@Override
|
||||
protected void dropInventory() {
|
||||
ItemStack lantern = getStackInHand(Hand.MAIN_HAND);
|
||||
setStackInHand(Hand.MAIN_HAND, ItemStack.EMPTY);
|
||||
dropStack(lantern);
|
||||
dropStack(getPickBlockStack());
|
||||
if (getWorld().getGameRules().getBoolean(GameRules.DO_ENTITY_DROPS)) {
|
||||
ItemStack lantern = getStackInHand(Hand.MAIN_HAND);
|
||||
setStackInHand(Hand.MAIN_HAND, ItemStack.EMPTY);
|
||||
dropStack(lantern);
|
||||
if (hasBalloon()) {
|
||||
dropStack(BalloonDesignComponent.set(UItems.GIANT_BALLOON.getDefaultStack(), new BalloonDesignComponent(getDesign(), true)));
|
||||
setDesign(BalloonDesign.NONE);
|
||||
}
|
||||
fuelItems.forEach(this::dropStack);
|
||||
fuelItems.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -518,21 +564,23 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
move(MovementType.SELF, getVelocity());
|
||||
setVelocity(getVelocity().multiply(slipperyness));
|
||||
}
|
||||
} else {
|
||||
Map<Box, List<Entity>> collidingEntities = getCollidingEntities(getBoundingBoxes().stream());
|
||||
|
||||
for (Map.Entry<Box, List<Entity>> passengers : collidingEntities.entrySet()) {
|
||||
for (Entity passenger : passengers.getValue()) {
|
||||
Living<?> living = Living.living(passenger);
|
||||
if (living != null) {
|
||||
living.getTransportation().setVehicle(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
updateLimbs(false);
|
||||
}
|
||||
|
||||
if (isAirworthy()) {
|
||||
Map<Box, List<Entity>> collidingEntities = getCollidingEntities(getBoundingBoxes().stream());
|
||||
|
||||
for (Map.Entry<Box, List<Entity>> passengers : collidingEntities.entrySet()) {
|
||||
for (Entity passenger : passengers.getValue()) {
|
||||
Living<?> living = Living.living(passenger);
|
||||
if (living != null) {
|
||||
living.getTransportation().setVehicle(this);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -714,7 +762,6 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
protected void fall(double heightDifference, boolean onGround, BlockState state, BlockPos landedPosition) {
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void readCustomDataFromNbt(NbtCompound compound) {
|
||||
super.readCustomDataFromNbt(compound);
|
||||
|
@ -724,7 +771,12 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
setBoostTicks(compound.getInt("boostTicks"));
|
||||
prevInflation = compound.getInt("inflationAmount");
|
||||
setInflation(prevInflation);
|
||||
fuel = MathHelper.clamp(compound.getInt("fuel"), 0, maxFuel);
|
||||
activeFuel = MathHelper.clamp(compound.getInt("fuel"), 0, maxFuel);
|
||||
fuelItems = compound.contains("fuelItems", NbtElement.LIST_TYPE) ? compound
|
||||
.getList("fuelItems", NbtElement.COMPOUND_TYPE).stream()
|
||||
.map(item -> ItemStack.fromNbtOrEmpty(getRegistryManager(), (NbtCompound)item))
|
||||
.limit(64)
|
||||
.collect(Collectors.toList()) : new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -735,7 +787,12 @@ public class AirBalloonEntity extends MobEntity implements EntityCollisions.Comp
|
|||
compound.putBoolean("burnerActive", isAscending());
|
||||
compound.putInt("boostTicks", getBoostTicks());
|
||||
compound.putInt("inflationAmount", getInflation());
|
||||
compound.putInt("fuel", fuel);
|
||||
compound.putInt("fuel", activeFuel);
|
||||
NbtList fuelItemsNbt = new NbtList();
|
||||
fuelItems.forEach(item -> {
|
||||
fuelItemsNbt.add(NbtSerialisable.encode(ItemStack.OPTIONAL_CODEC, item, getRegistryManager()));
|
||||
});
|
||||
compound.put("fuelItems", fuelItemsNbt);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
Loading…
Reference in a new issue