mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 21:38:00 +01:00
More work on hot air balloons
This commit is contained in:
parent
2e472a7982
commit
5448db4bdd
8 changed files with 274 additions and 81 deletions
|
@ -6,6 +6,7 @@ import net.minecraft.client.model.*;
|
|||
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 AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
||||
|
||||
|
@ -13,13 +14,11 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
|
||||
private final ModelPart burner;
|
||||
private final ModelPart balloon;
|
||||
private final ModelPart basket;
|
||||
|
||||
public AirBalloonEntityModel(ModelPart root) {
|
||||
this.root = root;
|
||||
burner = root.getChild("burner");
|
||||
balloon = root.getChild("balloon");
|
||||
basket = root.getChild("basket");
|
||||
}
|
||||
|
||||
public static TexturedModelData getTexturedModelData() {
|
||||
|
@ -27,10 +26,10 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
ModelPartData root = modelData.getRoot();
|
||||
|
||||
ModelPartData burner = root.addChild("burner", ModelPartBuilder.create().uv(8, 107).cuboid(-6, -47, -6, 11, 15, 11, Dilation.NONE), ModelTransform.pivot(0, 24, 0));
|
||||
burner.addChild("rope_d_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(-5, -46, -6, 0.7854F, 0, -0.7854F));
|
||||
burner.addChild("rope_c_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(-4, -44, 3, -0.7854F, 0, -0.7854F));
|
||||
burner.addChild("rope_b_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(5, -46, 1, -0.7854F, 0, 0.7854F));
|
||||
burner.addChild("rope_a_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(5, -45, -6, 0.7854F, 0, 0.7854F));
|
||||
burner.addChild("rope_d_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(-5, -46, -6, 0.7854F, 0, -0.7854F));
|
||||
burner.addChild("rope_c_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(-4, -44, 3, -0.7854F, 0, -0.7854F));
|
||||
burner.addChild("rope_b_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of( 5, -46, 1, -0.7854F, 0, 0.7854F));
|
||||
burner.addChild("rope_a_r1", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of( 5, -45, -6, 0.7854F, 0, 0.7854F));
|
||||
|
||||
ModelPartData balloon = root.addChild("balloon", ModelPartBuilder.create().uv(64, 1).cuboid(-54, -178, -59, 112, 120, 112, Dilation.NONE), ModelTransform.pivot(0, 24, 0));
|
||||
balloon.addChild("rope_d_r2", ModelPartBuilder.create().uv(0, 107).cuboid(-2, -68, 0, 2, 68, 2, Dilation.NONE), ModelTransform.of(-14, -11, -16, 0.4363F, 0, -0.4363F));
|
||||
|
@ -43,16 +42,23 @@ public class AirBalloonEntityModel extends EntityModel<AirBalloonEntity> {
|
|||
.uv(64, 68).cuboid(15, -12, -16, 2, 11, 30, Dilation.NONE)
|
||||
.uv(80, 38).cuboid(-16, -12, -17, 32, 11, 2, Dilation.NONE)
|
||||
.uv(0, 32).cuboid(8, -12, 13, 8, 11, 2, Dilation.NONE)
|
||||
.uv(0, 6).cuboid(-16, -12, 13, 8, 11, 2, Dilation.NONE), ModelTransform.pivot(0, 0, 0));
|
||||
.uv(0, 6).cuboid(-16, -12, 13, 8, 11, 2, Dilation.NONE), ModelTransform.NONE);
|
||||
basket.addChild("rim", ModelPartBuilder.create().uv(40, 34).cuboid(-18, -13, -17, 4, 2, 32, Dilation.NONE)
|
||||
.uv(0, 32).cuboid(14, -13, -17, 4, 2, 32, Dilation.NONE)
|
||||
.uv(80, 32).cuboid(-17, -13, -18, 34, 2, 4, Dilation.NONE)
|
||||
.uv(0, 19).cuboid(7, -13, 12, 10, 2, 4, Dilation.NONE)
|
||||
.uv(0, 0).cuboid(-17, -13, 12, 10, 2, 4, Dilation.NONE), ModelTransform.pivot(0, 0, 0));
|
||||
.uv(0, 0).cuboid(-17, -13, 12, 10, 2, 4, Dilation.NONE), ModelTransform.NONE);
|
||||
return TexturedModelData.of(modelData, 512, 512);
|
||||
}
|
||||
@Override
|
||||
public void setAngles(AirBalloonEntity entity, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
|
||||
root.yaw = entity.bodyYaw;
|
||||
burner.visible = entity.hasBurner();
|
||||
balloon.visible = entity.hasBalloon();
|
||||
|
||||
float xSpeed = (float)(entity.getX() - entity.prevX);
|
||||
|
||||
root.pitch = MathHelper.sin(-xSpeed);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -2,12 +2,12 @@ package com.minelittlepony.unicopia.client.render.entity;
|
|||
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.entity.AirBalloonEntity;
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||
import net.minecraft.client.render.entity.LivingEntityRenderer;
|
||||
|
||||
import net.minecraft.client.render.entity.*;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
public class AirBalloonEntityRenderer extends LivingEntityRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
||||
private static final Identifier TEXTURE = Unicopia.id("textures/entity/spellbook/normal.png");
|
||||
public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
||||
private static final Identifier TEXTURE = Unicopia.id("textures/entity/air_balloon.png");
|
||||
|
||||
public AirBalloonEntityRenderer(EntityRendererFactory.Context context) {
|
||||
super(context, new AirBalloonEntityModel(AirBalloonEntityModel.getTexturedModelData().createModel()), 0);
|
||||
|
|
|
@ -1,13 +1,25 @@
|
|||
package com.minelittlepony.unicopia.entity;
|
||||
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.entity.*;
|
||||
import net.minecraft.entity.data.*;
|
||||
import net.minecraft.entity.mob.FlyingEntity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class AirBalloonEntity extends FlyingEntity {
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
|
||||
|
||||
public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.ComplexCollidable {
|
||||
private static final byte HAS_BALLOON = 1;
|
||||
private static final byte HAS_BURNER = 2;
|
||||
private static final byte BURNER_ACTIVE = 4;
|
||||
private static final TrackedData<Integer> FLAGS = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||
|
||||
public AirBalloonEntity(EntityType<? extends AirBalloonEntity> type, World world) {
|
||||
super(type, world);
|
||||
|
@ -16,50 +28,152 @@ public class AirBalloonEntity extends FlyingEntity {
|
|||
@Override
|
||||
protected void initDataTracker() {
|
||||
super.initDataTracker();
|
||||
dataTracker.startTracking(FLAGS, 0);
|
||||
}
|
||||
|
||||
public boolean hasBalloon() {
|
||||
return getFlag(HAS_BALLOON);
|
||||
}
|
||||
|
||||
public void setHasBalloon(boolean hasBalloon) {
|
||||
setFlag(HAS_BALLOON, hasBalloon);
|
||||
}
|
||||
|
||||
public boolean hasBurner() {
|
||||
return getFlag((byte)(HAS_BURNER | HAS_BALLOON));
|
||||
}
|
||||
|
||||
public void setHasBurner(boolean hasBurner) {
|
||||
setFlag(HAS_BURNER, hasBurner);
|
||||
}
|
||||
|
||||
public boolean isBurnerActive() {
|
||||
return getFlag((byte)(HAS_BURNER | BURNER_ACTIVE));
|
||||
}
|
||||
|
||||
public void setBurnerActive(boolean burnerActive) {
|
||||
setFlag(BURNER_ACTIVE, burnerActive);
|
||||
}
|
||||
|
||||
private boolean getFlag(byte flag) {
|
||||
return (dataTracker.get(FLAGS).intValue() & flag) == flag;
|
||||
}
|
||||
|
||||
private void setFlag(byte flag, boolean val) {
|
||||
int v = dataTracker.get(FLAGS);
|
||||
dataTracker.set(FLAGS, val ? (v | flag) : (v & ~flag));
|
||||
}
|
||||
|
||||
private boolean isAirworthy() {
|
||||
return hasBalloon() && (!onGround || isBurnerActive());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick() {
|
||||
this.setHasBalloon(true);
|
||||
this.setHasBurner(true);
|
||||
this.setBurnerActive(false);
|
||||
|
||||
if (!world.isClient) {
|
||||
setAir(getMaxAir());
|
||||
|
||||
float xSpeed = 0;//-0.015F * (this.age % 1000 < 500 ? -1 : 1);
|
||||
|
||||
addVelocity(xSpeed, 0, 0);
|
||||
if (isAirworthy()) {
|
||||
setVelocity(getVelocity()
|
||||
.add(getWind(world, getBlockPos()))
|
||||
.normalize()
|
||||
.multiply(0.2)
|
||||
.add(0, isBurnerActive() ? 0.09F : isTouchingWater() ? 0.02F : -0.06F, 0));
|
||||
} else {
|
||||
addVelocity(0, isTouchingWater() ? 0.02F : -0.02F, 0);
|
||||
}
|
||||
|
||||
if (isLeashed()) {
|
||||
Vec3d leashPost = getHoldingEntity().getPos();
|
||||
Vec3d pos = getPos();
|
||||
|
||||
for (var e : this.world.getOtherEntities(this, getBoundingBox().expand(0.2, 1.0E-7, 0.2))) {
|
||||
if (!(e instanceof PlayerEntity)) {
|
||||
e.setVelocity(e.getVelocity().multiply(0.3).add(getVelocity().multiply(0.84)));
|
||||
if (leashPost.distanceTo(pos) >= 5) {
|
||||
Vec3d newVel = leashPost.subtract(pos).multiply(0.01);
|
||||
setVelocity(newVel.lengthSquared() < 0.03 ? Vec3d.ZERO : newVel);
|
||||
}
|
||||
}
|
||||
|
||||
double diff = (getBoundingBox().maxY + getVelocity().y) - e.getBoundingBox().minY;
|
||||
if (age % 20 < 10) {
|
||||
if (getVelocity().y < 0.1) {
|
||||
addVelocity(0, 0.01, 0);
|
||||
}
|
||||
} else {
|
||||
if (getVelocity().y > -0.1) {
|
||||
addVelocity(0, -0.01, 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (diff > 0) {
|
||||
e.addVelocity(0, diff, 0);
|
||||
//setVelocity(Vec3d.ZERO);
|
||||
float weight = 0;
|
||||
|
||||
if (getVelocity().length() > 0) {
|
||||
Box box = getBoundingBox();
|
||||
for (var e : this.world.getOtherEntities(this, box.expand(1, 1.0E-7, 1))) {
|
||||
Vec3d vel = e.getVelocity();
|
||||
|
||||
if (getVelocity().y > 0 && box.maxY > e.getBoundingBox().minY) {
|
||||
e.setPosition(e.getX(), box.maxY + 0.1, e.getZ());
|
||||
}
|
||||
|
||||
if (!(e instanceof PlayerEntity)) {
|
||||
e.setVelocity(vel.multiply(0.3).add(getVelocity().multiply(0.786)));
|
||||
}
|
||||
|
||||
e.setOnGround(true);
|
||||
|
||||
if (horizontalSpeed != 0) {
|
||||
e.distanceTraveled = 0;
|
||||
e.horizontalSpeed = 0;
|
||||
if (e instanceof LivingEntity l) {
|
||||
l.limbAngle = 0;
|
||||
l.limbDistance = 0;
|
||||
}
|
||||
}
|
||||
|
||||
weight++;
|
||||
}
|
||||
|
||||
e.distanceTraveled = 0;
|
||||
e.horizontalSpeed = 0;
|
||||
if (e instanceof LivingEntity l) {
|
||||
l.limbAngle = 0;
|
||||
l.limbDistance = 0;
|
||||
Box balloonTopBox = getBoundingBox().offset(0.125, 11, 0).expand(2.25, 0, 2);
|
||||
|
||||
for (var e : this.world.getOtherEntities(this, balloonTopBox.expand(1.0E-7))) {
|
||||
Vec3d vel = e.getVelocity();
|
||||
|
||||
double yVel = vel.y + Math.max(balloonTopBox.maxY - e.getBoundingBox().minY, 0);
|
||||
yVel /= 8;
|
||||
yVel += 0.3;
|
||||
|
||||
e.setVelocity(vel.getX(), yVel, vel.getZ());
|
||||
e.setVelocity(e.getVelocity().multiply(0.3).add(getVelocity().multiply(0.786)));
|
||||
e.setOnGround(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (getVelocity().y > -0.6 && !isTouchingWater()) {
|
||||
if (isBurnerActive()) {
|
||||
weight -= 3;
|
||||
}
|
||||
addVelocity(0, MathHelper.clamp(-weight / 10F, -1, isLeashed() ? 0.2F : 1), 0);
|
||||
}
|
||||
|
||||
super.tick();
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerCollision(PlayerEntity player) {
|
||||
player.setVelocity(player.getVelocity().multiply(0.9).add(getVelocity().multiply(0.56)));
|
||||
if (getVelocity().lengthSquared() > 0) {
|
||||
// player.setVelocity(getVelocity().multiply(1.3));
|
||||
player.setVelocity(player.getVelocity().multiply(0.3).add(getVelocity().multiply(
|
||||
getVelocity().y < 0 ? 0.828 : 0.728
|
||||
)));
|
||||
|
||||
double diff = (getBoundingBox().maxY + getVelocity().y) - player.getBoundingBox().minY;
|
||||
double diff = (getBoundingBox().maxY + getVelocity().y) - player.getBoundingBox().minY;
|
||||
|
||||
if (diff > 0) {
|
||||
player.addVelocity(0, diff, 0);
|
||||
if (diff > 0) {
|
||||
player.addVelocity(0, diff, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -87,14 +201,53 @@ public class AirBalloonEntity extends FlyingEntity {
|
|||
return getBoundingBox().expand(30, 100, 30);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getCollissionShapes(ShapeContext context, Consumer<VoxelShape> output) {
|
||||
|
||||
Box box = getBoundingBox().expand(0.3, 0, 0.3);
|
||||
|
||||
double wallheight = box.maxY + 1;
|
||||
double wallThickness = 0.7;
|
||||
|
||||
output.accept(VoxelShapes.cuboid(new Box(box.minX, box.minY, box.minZ, box.minX + wallThickness + 0.2, wallheight, box.minZ + wallThickness)));
|
||||
output.accept(VoxelShapes.cuboid(new Box(box.maxX - wallThickness - 0.2, box.minY, box.minZ, box.maxX, wallheight, box.minZ + wallThickness)));
|
||||
output.accept(VoxelShapes.cuboid(new Box(box.minX, box.minY, box.maxZ - wallThickness, box.maxX, wallheight, box.maxZ)));
|
||||
|
||||
output.accept(VoxelShapes.cuboid(new Box(box.minX, box.minY, box.minZ, box.minX + wallThickness, wallheight, box.maxZ)));
|
||||
output.accept(VoxelShapes.cuboid(new Box(box.maxX - wallThickness, box.minY, box.minZ, box.maxX, wallheight, box.maxZ)));
|
||||
|
||||
// top of balloon
|
||||
if (hasBalloon()) {
|
||||
output.accept(VoxelShapes.cuboid(getBoundingBox().offset(0.125, 11, 0).expand(2.25, 0, 2)));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void readCustomDataFromNbt(NbtCompound compound) {
|
||||
super.readCustomDataFromNbt(compound);
|
||||
setHasBalloon(compound.getBoolean("hasBalloon"));
|
||||
setHasBurner(compound.getBoolean("hasBurner"));
|
||||
setBurnerActive(compound.getBoolean("burnerActive"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeCustomDataToNbt(NbtCompound compound) {
|
||||
super.writeCustomDataToNbt(compound);
|
||||
compound.putBoolean("hasBalloon", hasBalloon());
|
||||
compound.putBoolean("hasBurner", hasBurner());
|
||||
compound.putBoolean("burnerActive", isBurnerActive());
|
||||
}
|
||||
|
||||
static Vec3d getWind(World world, BlockPos pos) {
|
||||
return Vec3d.ofCenter(pos).normalize().multiply(1, 0, 1).multiply(0.2);//.multiply((world.getRandom().nextFloat() - 0.5) * 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public interface UEntities {
|
|||
.dimensions(EntityDimensions.fixed(0.9F, 0.5F)));
|
||||
EntityType<AirBalloonEntity> AIR_BALLOON = register("air_balloon", FabricEntityTypeBuilder.create(SpawnGroup.MISC, AirBalloonEntity::new)
|
||||
.trackRangeBlocks(1000)
|
||||
.dimensions(EntityDimensions.fixed(3, 0.1F)));
|
||||
.dimensions(EntityDimensions.fixed(2.5F, 0.1F)));
|
||||
|
||||
static <T extends Entity> EntityType<T> register(String name, FabricEntityTypeBuilder<T> builder) {
|
||||
EntityType<T> type = builder.build();
|
||||
|
|
|
@ -14,8 +14,8 @@ import com.minelittlepony.unicopia.FlightType;
|
|||
import com.minelittlepony.unicopia.InteractionManager;
|
||||
import com.minelittlepony.unicopia.Owned;
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||
import com.minelittlepony.unicopia.entity.UEntityAttributes;
|
||||
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
|
||||
import com.minelittlepony.unicopia.entity.player.PlayerDimensions;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||
|
@ -42,14 +42,9 @@ import net.minecraft.entity.mob.VexEntity;
|
|||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.entity.projectile.ShulkerBulletEntity;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
|
||||
public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider {
|
||||
public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider, EntityCollisions.ComplexCollidable {
|
||||
private static final Optional<Float> BLOCK_HEIGHT = Optional.of(0.5F);
|
||||
|
||||
@NotNull
|
||||
|
@ -358,43 +353,10 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
|
|||
return entityNbt;
|
||||
}
|
||||
|
||||
void getCollissionShapes(ShapeContext context, Consumer<VoxelShape> output) {
|
||||
getCollissionShapes(getAppearance(), context, output);
|
||||
getAttachments().forEach(e -> getCollissionShapes(e, context, output));
|
||||
@Override
|
||||
public void getCollissionShapes(ShapeContext context, Consumer<VoxelShape> output) {
|
||||
EntityCollisions.getCollissionShapes(getAppearance(), context, output);
|
||||
getAttachments().forEach(e -> EntityCollisions.getCollissionShapes(e, context, output));
|
||||
}
|
||||
|
||||
private static void getCollissionShapes(@Nullable Entity entity, ShapeContext context, Consumer<VoxelShape> output) {
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity.isCollidable()) {
|
||||
output.accept(VoxelShapes.cuboid(entity.getBoundingBox()));
|
||||
} else if (entity instanceof FallingBlockEntity) {
|
||||
BlockPos pos = entity.getBlockPos();
|
||||
output.accept(((FallingBlockEntity) entity).getBlockState()
|
||||
.getCollisionShape(entity.world, entity.getBlockPos(), context)
|
||||
.offset(pos.getX(), pos.getY(), pos.getZ())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<VoxelShape> getColissonShapes(@Nullable Entity entity, WorldAccess world, Box box) {
|
||||
List<VoxelShape> shapes = new ArrayList<>();
|
||||
ShapeContext ctx = entity == null ? ShapeContext.absent() : ShapeContext.of(entity);
|
||||
VoxelShape entityShape = VoxelShapes.cuboid(box.expand(1.0E-6D));
|
||||
|
||||
world.getOtherEntities(entity, box.expand(0.5), e -> {
|
||||
Caster.of(e).flatMap(c -> c.getSpellSlot().get(SpellPredicate.IS_DISGUISE, false)).ifPresent(p -> {
|
||||
p.getDisguise().getCollissionShapes(ctx, shape -> {
|
||||
if (!shape.isEmpty() && VoxelShapes.matchesAnywhere(shape, entityShape, BooleanBiFunction.AND)) {
|
||||
shapes.add(shape);
|
||||
}
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
return shapes;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
package com.minelittlepony.unicopia.entity.collision;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||
|
||||
import net.minecraft.block.ShapeContext;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.FallingBlockEntity;
|
||||
import net.minecraft.util.function.BooleanBiFunction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
import net.minecraft.util.shape.VoxelShapes;
|
||||
import net.minecraft.world.WorldAccess;
|
||||
|
||||
public class EntityCollisions {
|
||||
|
||||
public static void getCollissionShapes(@Nullable Entity entity, ShapeContext context, Consumer<VoxelShape> output) {
|
||||
if (entity == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (entity.isCollidable()) {
|
||||
output.accept(VoxelShapes.cuboid(entity.getBoundingBox()));
|
||||
if (entity instanceof ComplexCollidable collidable) {
|
||||
collidable.getCollissionShapes(context, output);
|
||||
}
|
||||
} else if (entity instanceof FallingBlockEntity) {
|
||||
BlockPos pos = entity.getBlockPos();
|
||||
output.accept(((FallingBlockEntity) entity).getBlockState()
|
||||
.getCollisionShape(entity.world, entity.getBlockPos(), context)
|
||||
.offset(pos.getX(), pos.getY(), pos.getZ())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public static List<VoxelShape> getColissonShapes(@Nullable Entity entity, WorldAccess world, Box box) {
|
||||
ShapeContext ctx = entity == null ? ShapeContext.absent() : ShapeContext.of(entity);
|
||||
return collectCollisionBoxes(box, collector -> {
|
||||
world.getOtherEntities(entity, box.expand(50), e -> {
|
||||
Caster.of(e).flatMap(c -> c.getSpellSlot().get(SpellPredicate.IS_DISGUISE, false)).ifPresent(p -> {
|
||||
p.getDisguise().getCollissionShapes(ctx, collector);
|
||||
});
|
||||
if (e instanceof ComplexCollidable collidable) {
|
||||
collidable.getCollissionShapes(ctx, collector);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static List<VoxelShape> collectCollisionBoxes(Box box, Consumer<Consumer<VoxelShape>> generator) {
|
||||
List<VoxelShape> shapes = new ArrayList<>();
|
||||
VoxelShape entityShape = VoxelShapes.cuboid(box.expand(1.0E-6D));
|
||||
generator.accept(shape -> {
|
||||
if (!shape.isEmpty() && VoxelShapes.matchesAnywhere(shape, entityShape, BooleanBiFunction.AND)) {
|
||||
shapes.add(shape);
|
||||
}
|
||||
});
|
||||
return shapes;
|
||||
}
|
||||
|
||||
public interface ComplexCollidable {
|
||||
void getCollissionShapes(ShapeContext context, Consumer<VoxelShape> output);
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ import org.spongepowered.asm.mixin.injection.ModifyVariable;
|
|||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import com.minelittlepony.unicopia.BlockDestructionManager;
|
||||
import com.minelittlepony.unicopia.entity.behaviour.EntityAppearance;
|
||||
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
|
||||
import com.minelittlepony.unicopia.entity.duck.RotatedView;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
|
@ -51,7 +51,7 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source
|
|||
@Override
|
||||
public List<VoxelShape> getEntityCollisions(@Nullable Entity entity, Box box) {
|
||||
if (box.getAverageSideLength() >= 1.0E-7D) {
|
||||
List<VoxelShape> shapes = EntityAppearance.getColissonShapes(entity, this, box);
|
||||
List<VoxelShape> shapes = EntityCollisions.getColissonShapes(entity, this, box);
|
||||
if (!shapes.isEmpty()) {
|
||||
return Stream.concat(shapes.stream(), WorldAccess.super.getEntityCollisions(entity, box).stream()).toList();
|
||||
}
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 3 KiB |
Loading…
Reference in a new issue