mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 03:26:44 +01:00
Add item textures and basket/balloon designs, and try to prevent players from falling out
This commit is contained in:
parent
f7777358e2
commit
0fad11c346
13 changed files with 180 additions and 61 deletions
|
@ -1,5 +1,6 @@
|
||||||
package com.minelittlepony.unicopia.client.render.entity;
|
package com.minelittlepony.unicopia.client.render.entity;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
|
@ -19,8 +20,8 @@ import net.minecraft.util.math.Box;
|
||||||
public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
||||||
public AirBalloonEntityRenderer(EntityRendererFactory.Context context) {
|
public AirBalloonEntityRenderer(EntityRendererFactory.Context context) {
|
||||||
super(context, new AirBalloonEntityModel(AirBalloonEntityModel.getBasketModelData().createModel()), 0);
|
super(context, new AirBalloonEntityModel(AirBalloonEntityModel.getBasketModelData().createModel()), 0);
|
||||||
addFeature(new BalloonFeature("burner", new AirBalloonEntityModel(AirBalloonEntityModel.getBurnerModelData().createModel()), this, AirBalloonEntity::hasBurner));
|
addFeature(new BalloonFeature(new AirBalloonEntityModel(AirBalloonEntityModel.getBurnerModelData().createModel()), this, AirBalloonEntity::hasBurner, e -> getComponentTexture("burner")));
|
||||||
addFeature(new BalloonFeature("canopy", new AirBalloonEntityModel(AirBalloonEntityModel.getCanopyModelData().createModel()), this, AirBalloonEntity::hasBalloon));
|
addFeature(new BalloonFeature(new AirBalloonEntityModel(AirBalloonEntityModel.getCanopyModelData().createModel()), this, AirBalloonEntity::hasBalloon, e -> getComponentTexture("canopy/" + e.getDesign().asString())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -36,7 +37,7 @@ public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getTexture(AirBalloonEntity entity) {
|
public Identifier getTexture(AirBalloonEntity entity) {
|
||||||
return getComponentTexture(entity, "basket");
|
return getComponentTexture("basket/" + entity.getBasketType().asString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -44,29 +45,30 @@ public class AirBalloonEntityRenderer extends MobEntityRenderer<AirBalloonEntity
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Identifier getComponentTexture(AirBalloonEntity entity, String componentName) {
|
private Identifier getComponentTexture(String componentName) {
|
||||||
return Unicopia.id("textures/entity/air_balloon/" + componentName + ".png");
|
return Unicopia.id("textures/entity/air_balloon/" + componentName + ".png");
|
||||||
}
|
}
|
||||||
|
|
||||||
final class BalloonFeature extends FeatureRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
final class BalloonFeature extends FeatureRenderer<AirBalloonEntity, AirBalloonEntityModel> {
|
||||||
private final AirBalloonEntityModel model;
|
private final AirBalloonEntityModel model;
|
||||||
private final Predicate<AirBalloonEntity> visibilityTest;
|
private final Predicate<AirBalloonEntity> visibilityTest;
|
||||||
private final String componentName;
|
private final Function<AirBalloonEntity, Identifier> textureFunc;
|
||||||
|
|
||||||
public BalloonFeature(String componentName, AirBalloonEntityModel model,
|
public BalloonFeature(AirBalloonEntityModel model,
|
||||||
FeatureRendererContext<AirBalloonEntity, AirBalloonEntityModel> context,
|
FeatureRendererContext<AirBalloonEntity, AirBalloonEntityModel> context,
|
||||||
Predicate<AirBalloonEntity> visibilityTest) {
|
Predicate<AirBalloonEntity> visibilityTest,
|
||||||
|
Function<AirBalloonEntity, Identifier> textureFunc) {
|
||||||
super(context);
|
super(context);
|
||||||
this.componentName = componentName;
|
|
||||||
this.model = model;
|
this.model = model;
|
||||||
this.visibilityTest = visibilityTest;
|
this.visibilityTest = visibilityTest;
|
||||||
|
this.textureFunc = textureFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, AirBalloonEntity entity,
|
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, AirBalloonEntity entity,
|
||||||
float limbAngle, float limbDistance, float tickDelta, float animationProgress, float yaw, float pitch) {
|
float limbAngle, float limbDistance, float tickDelta, float animationProgress, float yaw, float pitch) {
|
||||||
if (visibilityTest.test(entity)) {
|
if (visibilityTest.test(entity)) {
|
||||||
render(getModel(), model, getComponentTexture(entity, componentName), matrices, vertices, light, entity, limbAngle, limbDistance, 0, yaw, pitch, tickDelta, 1, 1, 1);
|
render(getModel(), model, textureFunc.apply(entity), matrices, vertices, light, entity, limbAngle, limbDistance, 0, yaw, pitch, tickDelta, 1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,36 +5,42 @@ import net.minecraft.entity.*;
|
||||||
import net.minecraft.entity.data.*;
|
import net.minecraft.entity.data.*;
|
||||||
import net.minecraft.entity.mob.FlyingEntity;
|
import net.minecraft.entity.mob.FlyingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.vehicle.BoatEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.StringIdentifiable;
|
||||||
|
import net.minecraft.util.function.ValueLists;
|
||||||
import net.minecraft.util.math.*;
|
import net.minecraft.util.math.*;
|
||||||
import net.minecraft.util.math.random.Random;
|
import net.minecraft.util.math.random.Random;
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
import net.minecraft.util.shape.VoxelShape;
|
||||||
import net.minecraft.util.shape.VoxelShapes;
|
import net.minecraft.util.shape.VoxelShapes;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.minecraft.world.event.GameEvent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.IntFunction;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
|
import com.minelittlepony.unicopia.entity.collision.EntityCollisions;
|
||||||
import com.minelittlepony.unicopia.entity.collision.MultiBox;
|
import com.minelittlepony.unicopia.entity.collision.MultiBox;
|
||||||
import com.minelittlepony.unicopia.entity.duck.EntityDuck;
|
import com.minelittlepony.unicopia.entity.duck.EntityDuck;
|
||||||
import com.minelittlepony.unicopia.item.UItems;
|
import com.minelittlepony.unicopia.item.HotAirBalloonItem;
|
||||||
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
import com.minelittlepony.unicopia.server.world.WeatherConditions;
|
||||||
|
|
||||||
public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.ComplexCollidable, MultiBoundingBoxEntity {
|
public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.ComplexCollidable, MultiBoundingBoxEntity {
|
||||||
private static final byte HAS_BALLOON = 1;
|
|
||||||
private static final byte HAS_BURNER = 2;
|
private static final byte HAS_BURNER = 2;
|
||||||
private static final byte BURNER_ACTIVE = 4;
|
private static final byte BURNER_ACTIVE = 4;
|
||||||
private static final TrackedData<Integer> FLAGS = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
private static final TrackedData<Integer> BURNER_FLAGS = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
private static final TrackedData<Integer> BOOSTING = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
private static final TrackedData<Integer> BOOSTING = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
private static final TrackedData<Integer> INFLATION = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
private static final TrackedData<Integer> INFLATION = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
private static final TrackedData<Integer> BASKET_TYPE = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
private static final TrackedData<Integer> BALLOON_DESIGN = DataTracker.registerData(AirBalloonEntity.class, TrackedDataHandlerRegistry.INTEGER);
|
||||||
|
|
||||||
private boolean prevBoosting;
|
private boolean prevBoosting;
|
||||||
private int prevInflation;
|
private int prevInflation;
|
||||||
|
@ -43,23 +49,38 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
|
|
||||||
public AirBalloonEntity(EntityType<? extends AirBalloonEntity> type, World world) {
|
public AirBalloonEntity(EntityType<? extends AirBalloonEntity> type, World world) {
|
||||||
super(type, world);
|
super(type, world);
|
||||||
|
intersectionChecked = true;
|
||||||
setPersistent();
|
setPersistent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initDataTracker() {
|
protected void initDataTracker() {
|
||||||
super.initDataTracker();
|
super.initDataTracker();
|
||||||
dataTracker.startTracking(FLAGS, 0);
|
dataTracker.startTracking(BURNER_FLAGS, 0);
|
||||||
dataTracker.startTracking(BOOSTING, 0);
|
dataTracker.startTracking(BOOSTING, 0);
|
||||||
dataTracker.startTracking(INFLATION, 0);
|
dataTracker.startTracking(INFLATION, 0);
|
||||||
|
dataTracker.startTracking(BASKET_TYPE, 0);
|
||||||
|
dataTracker.startTracking(BALLOON_DESIGN, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoatEntity.Type getBasketType() {
|
||||||
|
return BoatEntity.Type.getType(dataTracker.get(BASKET_TYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBasketType(BoatEntity.Type type) {
|
||||||
|
dataTracker.set(BASKET_TYPE, type.ordinal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public BalloonDesign getDesign() {
|
||||||
|
return BalloonDesign.getType(dataTracker.get(BALLOON_DESIGN));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDesign(BalloonDesign design) {
|
||||||
|
dataTracker.set(BALLOON_DESIGN, design.ordinal());
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBalloon() {
|
public boolean hasBalloon() {
|
||||||
return getFlag(HAS_BALLOON);
|
return getDesign() != BalloonDesign.NONE;
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasBalloon(boolean hasBalloon) {
|
|
||||||
setFlag(HAS_BALLOON, hasBalloon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasBurner() {
|
public boolean hasBurner() {
|
||||||
|
@ -87,7 +108,7 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isBurnerActive() {
|
public boolean isBurnerActive() {
|
||||||
return getFlag((byte)(HAS_BURNER | BURNER_ACTIVE | HAS_BALLOON));
|
return hasBalloon() && getFlag((byte)(HAS_BURNER | BURNER_ACTIVE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBurnerActive(boolean burnerActive) {
|
public void setBurnerActive(boolean burnerActive) {
|
||||||
|
@ -103,12 +124,12 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean getFlag(byte flag) {
|
private boolean getFlag(byte flag) {
|
||||||
return (dataTracker.get(FLAGS).intValue() & flag) == flag;
|
return (dataTracker.get(BURNER_FLAGS).intValue() & flag) == flag;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setFlag(byte flag, boolean val) {
|
private void setFlag(byte flag, boolean val) {
|
||||||
int v = dataTracker.get(FLAGS);
|
int v = dataTracker.get(BURNER_FLAGS);
|
||||||
dataTracker.set(FLAGS, val ? (v | flag) : (v & ~flag));
|
dataTracker.set(BURNER_FLAGS, val ? (v | flag) : (v & ~flag));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isAirworthy() {
|
private boolean isAirworthy() {
|
||||||
|
@ -212,20 +233,23 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
prevBoosting = boosting;
|
prevBoosting = boosting;
|
||||||
oldPosition = getPos();
|
oldPosition = getPos();
|
||||||
|
|
||||||
for (Box box : getBoundingBoxes()) {
|
|
||||||
for (Entity e : getWorld().getOtherEntities(this, box.expand(0, 0.5, 0).stretch(getVelocity().multiply(-1)))) {
|
|
||||||
updatePassenger(e, box, e.getY() > getY() + 3);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getFireTicks() > 0) {
|
if (getFireTicks() > 0) {
|
||||||
setFireTicks(1);
|
setFireTicks(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updatePassengers();
|
||||||
super.tick();
|
super.tick();
|
||||||
setBoundingBox(MultiBox.of(getBoundingBox(), getBoundingBoxes()));
|
setBoundingBox(MultiBox.of(getBoundingBox(), getBoundingBoxes()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void updatePassengers() {
|
||||||
|
for (Box box : getBoundingBoxes()) {
|
||||||
|
for (Entity e : getWorld().getOtherEntities(this, box.expand(getVelocity().length()).expand(0, 0.5, 0))) {
|
||||||
|
updatePassenger(e, box, e.getY() > getY() + 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updatePassenger(Entity e, Box box, boolean inBalloon) {
|
private void updatePassenger(Entity e, Box box, boolean inBalloon) {
|
||||||
|
|
||||||
double height = box.getYLength();
|
double height = box.getYLength();
|
||||||
|
@ -239,7 +263,14 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
e.setVelocity(e.getVelocity().multiply(0.1, 0.5, 0.1));
|
if (manualVelocity.length() > 0.01 || getVelocity().length() > 0.3) {
|
||||||
|
e.setVelocity(e.getVelocity().multiply(0.1, 0.5, 0.1));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getVelocity().y < 0) {
|
||||||
|
e.addVelocity(0, getVelocity().y, 0);
|
||||||
|
Living.updateVelocity(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (inBalloon && !e.isSneaky() && Math.abs(e.getVelocity().y) > 0.079) {
|
if (inBalloon && !e.isSneaky() && Math.abs(e.getVelocity().y) > 0.079) {
|
||||||
e.setVelocity(e.getVelocity().multiply(1, e.getVelocity().y < 0 ? -0.9 : 1.2, 1).add(0, 0.8, 0));
|
e.setVelocity(e.getVelocity().multiply(1, e.getVelocity().y < 0 ? -0.9 : 1.2, 1).add(0, 0.8, 0));
|
||||||
|
@ -257,8 +288,10 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
if (getWorld().isClient) {
|
if (getWorld().isClient) {
|
||||||
if (e.distanceTraveled > ((EntityDuck)e).getNextStepSoundDistance()) {
|
if (e.distanceTraveled > ((EntityDuck)e).getNextStepSoundDistance()) {
|
||||||
e.distanceTraveled--;
|
e.distanceTraveled--;
|
||||||
|
|
||||||
e.playSound(inBalloon ? SoundEvents.BLOCK_WOOL_STEP : SoundEvents.BLOCK_BAMBOO_STEP, 0.5F, 1);
|
e.playSound(inBalloon ? SoundEvents.BLOCK_WOOL_STEP : SoundEvents.BLOCK_BAMBOO_STEP, 0.5F, 1);
|
||||||
|
if (!e.isSneaky()) {
|
||||||
|
getWorld().emitGameEvent(e, GameEvent.STEP, getBlockPos());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -276,6 +309,7 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
}
|
}
|
||||||
stack.damage(1, player, p -> p.sendEquipmentBreakStatus(hand == Hand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND));
|
stack.damage(1, player, p -> p.sendEquipmentBreakStatus(hand == Hand.MAIN_HAND ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND));
|
||||||
playSound(SoundEvents.ITEM_FLINTANDSTEEL_USE, 1, 1);
|
playSound(SoundEvents.ITEM_FLINTANDSTEEL_USE, 1, 1);
|
||||||
|
getWorld().emitGameEvent(this, GameEvent.ENTITY_INTERACT, getBlockPos());
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,11 +321,11 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
}
|
}
|
||||||
} else if (stack.isEmpty() && isBurnerActive()) {
|
} else if (stack.isEmpty() && isBurnerActive()) {
|
||||||
setBoostTicks(50);
|
setBoostTicks(50);
|
||||||
|
getWorld().emitGameEvent(this, GameEvent.ENTITY_INTERACT, getBlockPos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendMessage(Text.literal(hitPos + ""));
|
|
||||||
return ActionResult.PASS;
|
return ActionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,14 +333,13 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
protected ActionResult interactMob(PlayerEntity player, Hand hand) {
|
protected ActionResult interactMob(PlayerEntity player, Hand hand) {
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
|
||||||
|
if (stack.getItem() instanceof HotAirBalloonItem balloon && !hasBalloon()) {
|
||||||
|
|
||||||
if (stack.isOf(UItems.LARGE_BALLOON) && !hasBalloon()) {
|
|
||||||
if (!player.getAbilities().creativeMode) {
|
if (!player.getAbilities().creativeMode) {
|
||||||
stack.decrement(1);
|
stack.decrement(1);
|
||||||
}
|
}
|
||||||
playSound(SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 1, 1);
|
playSound(SoundEvents.ITEM_ARMOR_EQUIP_LEATHER, 1, 1);
|
||||||
setHasBalloon(true);
|
getWorld().emitGameEvent(this, GameEvent.ENTITY_INTERACT, getBlockPos());
|
||||||
|
setDesign(HotAirBalloonItem.getDesign(getWorld(), stack));
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,6 +348,7 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
stack.decrement(1);
|
stack.decrement(1);
|
||||||
}
|
}
|
||||||
playSound(SoundEvents.ENTITY_IRON_GOLEM_DAMAGE, 0.2F, 1);
|
playSound(SoundEvents.ENTITY_IRON_GOLEM_DAMAGE, 0.2F, 1);
|
||||||
|
getWorld().emitGameEvent(this, GameEvent.ENTITY_INTERACT, getBlockPos());
|
||||||
setHasBurner(true);
|
setHasBurner(true);
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -334,6 +368,7 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void pushAwayFrom(Entity entity) {
|
public void pushAwayFrom(Entity entity) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -341,6 +376,12 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Entity.MoveEffect getMoveEffect() {
|
||||||
|
return Entity.MoveEffect.EVENTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Box getVisibilityBoundingBox() {
|
public Box getVisibilityBoundingBox() {
|
||||||
if (hasBalloon()) {
|
if (hasBalloon()) {
|
||||||
|
@ -391,7 +432,8 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
@Override
|
@Override
|
||||||
public void readCustomDataFromNbt(NbtCompound compound) {
|
public void readCustomDataFromNbt(NbtCompound compound) {
|
||||||
super.readCustomDataFromNbt(compound);
|
super.readCustomDataFromNbt(compound);
|
||||||
setHasBalloon(compound.getBoolean("hasBalloon"));
|
setBasketType(BoatEntity.Type.getType(compound.getString("basketType")));
|
||||||
|
setDesign(BalloonDesign.getType(compound.getString("design")));
|
||||||
setHasBurner(compound.getBoolean("hasBurner"));
|
setHasBurner(compound.getBoolean("hasBurner"));
|
||||||
setBurnerActive(compound.getBoolean("burnerActive"));
|
setBurnerActive(compound.getBoolean("burnerActive"));
|
||||||
setBoostTicks(compound.getInt("boostTicks"));
|
setBoostTicks(compound.getInt("boostTicks"));
|
||||||
|
@ -402,12 +444,37 @@ public class AirBalloonEntity extends FlyingEntity implements EntityCollisions.C
|
||||||
@Override
|
@Override
|
||||||
public void writeCustomDataToNbt(NbtCompound compound) {
|
public void writeCustomDataToNbt(NbtCompound compound) {
|
||||||
super.writeCustomDataToNbt(compound);
|
super.writeCustomDataToNbt(compound);
|
||||||
compound.putBoolean("hasBalloon", hasBalloon());
|
compound.putString("design", getDesign().asString());
|
||||||
|
compound.putString("basket", getBasketType().asString());
|
||||||
compound.putBoolean("hasBurner", hasBurner());
|
compound.putBoolean("hasBurner", hasBurner());
|
||||||
compound.putBoolean("burnerActive", isBurnerActive());
|
compound.putBoolean("burnerActive", isBurnerActive());
|
||||||
compound.putInt("boostTicks", getBoostTicks());
|
compound.putInt("boostTicks", getBoostTicks());
|
||||||
compound.putInt("inflationAmount", getInflation());
|
compound.putInt("inflationAmount", getInflation());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
public enum BalloonDesign implements StringIdentifiable {
|
||||||
|
NONE,
|
||||||
|
LUNA;
|
||||||
|
|
||||||
|
public static final StringIdentifiable.Codec<BalloonDesign> CODEC = StringIdentifiable.createCodec(BalloonDesign::values);
|
||||||
|
private static final IntFunction<BalloonDesign> BY_ID = ValueLists.<BalloonDesign>createIdToValueFunction(Enum::ordinal, values(), ValueLists.OutOfBoundsHandling.ZERO);
|
||||||
|
|
||||||
|
private final String name = name().toLowerCase(Locale.ROOT);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String asString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BalloonDesign getType(int type) {
|
||||||
|
return BY_ID.apply(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BalloonDesign getType(String name) {
|
||||||
|
return CODEC.byId(name, LUNA);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -77,6 +77,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Vec3d supportPositionOffset;
|
private Vec3d supportPositionOffset;
|
||||||
|
private int ticksOutsideVehicle;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Caster<?> attacker;
|
private Caster<?> attacker;
|
||||||
|
@ -181,6 +182,9 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
|
|
||||||
public void setSupportingEntity(Entity supportingEntity) {
|
public void setSupportingEntity(Entity supportingEntity) {
|
||||||
this.supportingEntity = supportingEntity;
|
this.supportingEntity = supportingEntity;
|
||||||
|
if (supportingEntity != null) {
|
||||||
|
ticksOutsideVehicle = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPositionOffset(@Nullable Vec3d positionOffset) {
|
public void setPositionOffset(@Nullable Vec3d positionOffset) {
|
||||||
|
@ -191,19 +195,6 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
setPositionOffset(supportingEntity == null ? null : entity.getPos().subtract(supportingEntity.getPos()));
|
setPositionOffset(supportingEntity == null ? null : entity.getPos().subtract(supportingEntity.getPos()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void checkGroundCollission(Entity entity, Box box) {
|
|
||||||
double height = box.getYLength();
|
|
||||||
|
|
||||||
if (height < 3 || entity.getBoundingBox().minY > box.minY + height / 2D) {
|
|
||||||
if (entity.getBoundingBox().minY < box.maxY) {
|
|
||||||
entity.setPos(entity.getX(), box.maxY - 0.002, entity.getZ());
|
|
||||||
}
|
|
||||||
if (entity.getBoundingBox().minY > box.maxY) {
|
|
||||||
entity.setPos(entity.getX(), box.maxY - 0.002, entity.getZ());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateRelativePosition(Box box) {
|
public void updateRelativePosition(Box box) {
|
||||||
if (supportingEntity == null || supportPositionOffset == null) {
|
if (supportingEntity == null || supportPositionOffset == null) {
|
||||||
return;
|
return;
|
||||||
|
@ -251,11 +242,16 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
|
|
||||||
public void updateSupportingEntity() {
|
public void updateSupportingEntity() {
|
||||||
if (supportingEntity != null) {
|
if (supportingEntity != null) {
|
||||||
Box ownBox = entity.getBoundingBox().expand(0.1);
|
Box ownBox = entity.getBoundingBox()
|
||||||
|
.stretch(entity.getVelocity())
|
||||||
|
.expand(0.1, 0.5, 0.1)
|
||||||
|
.stretch(supportingEntity.getVelocity().multiply(-2));
|
||||||
|
|
||||||
MultiBoundingBoxEntity.getBoundingBoxes(supportingEntity).stream().filter(box -> {
|
MultiBoundingBoxEntity.getBoundingBoxes(supportingEntity).stream()
|
||||||
return box.expand(0, 0.5, 0).intersects(ownBox);
|
.filter(box -> box.stretch(supportingEntity.getVelocity()).expand(0, 0.5, 0).intersects(ownBox))
|
||||||
}).findFirst().ifPresentOrElse(box -> {
|
.findFirst()
|
||||||
|
.ifPresentOrElse(box -> {
|
||||||
|
ticksOutsideVehicle = 0;
|
||||||
if (supportPositionOffset == null) {
|
if (supportPositionOffset == null) {
|
||||||
updatePositionOffset();
|
updatePositionOffset();
|
||||||
} else {
|
} else {
|
||||||
|
@ -265,8 +261,14 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
entity.verticalCollision = true;
|
entity.verticalCollision = true;
|
||||||
entity.groundCollision = true;
|
entity.groundCollision = true;
|
||||||
}, () -> {
|
}, () -> {
|
||||||
supportingEntity = null;
|
// Rubberband passengers to try and prevent players falling out when the velocity changes suddenly
|
||||||
supportPositionOffset = null;
|
if (ticksOutsideVehicle++ > 30) {
|
||||||
|
supportingEntity = null;
|
||||||
|
supportPositionOffset = null;
|
||||||
|
Unicopia.LOGGER.info("Entity left vehicle");
|
||||||
|
} else {
|
||||||
|
supportPositionOffset = supportPositionOffset.multiply(0.25, 1, 0.25);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,7 +322,10 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
|
||||||
}
|
}
|
||||||
|
|
||||||
updateDragonBreath();
|
updateDragonBreath();
|
||||||
updatePositionOffset();
|
|
||||||
|
if (ticksOutsideVehicle == 0) {
|
||||||
|
updatePositionOffset();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateAttributeModifier(UUID id, EntityAttribute attribute, float desiredValue, Float2ObjectFunction<EntityAttributeModifier> modifierSupplier, boolean permanent) {
|
public void updateAttributeModifier(UUID id, EntityAttribute attribute, float desiredValue, Float2ObjectFunction<EntityAttributeModifier> modifierSupplier, boolean permanent) {
|
||||||
|
|
|
@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.util.Dispensable;
|
||||||
import net.minecraft.block.DispenserBlock;
|
import net.minecraft.block.DispenserBlock;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.vehicle.BoatEntity;
|
||||||
import net.minecraft.item.BoatItem;
|
import net.minecraft.item.BoatItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -31,8 +32,11 @@ public class BasketItem extends Item implements Dispensable {
|
||||||
private static final Predicate<Entity> RIDERS = EntityPredicates.EXCEPT_SPECTATOR.and(Entity::canHit);
|
private static final Predicate<Entity> RIDERS = EntityPredicates.EXCEPT_SPECTATOR.and(Entity::canHit);
|
||||||
private static final double REACH = 5;
|
private static final double REACH = 5;
|
||||||
|
|
||||||
public BasketItem(Item.Settings settings) {
|
private final BoatEntity.Type type;
|
||||||
|
|
||||||
|
public BasketItem(BoatEntity.Type type, Item.Settings settings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
|
this.type = type;
|
||||||
DispenserBlock.registerBehavior(this, createDispenserBehaviour());
|
DispenserBlock.registerBehavior(this, createDispenserBehaviour());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +75,7 @@ public class BasketItem extends Item implements Dispensable {
|
||||||
entity.updatePositionAndAngles(x, y, z, 0, 0);
|
entity.updatePositionAndAngles(x, y, z, 0, 0);
|
||||||
entity.setHeadYaw(yaw);
|
entity.setHeadYaw(yaw);
|
||||||
entity.setBodyYaw(yaw);
|
entity.setBodyYaw(yaw);
|
||||||
|
entity.setBasketType(type);
|
||||||
if (!world.isSpaceEmpty(entity, entity.getBoundingBox())) {
|
if (!world.isSpaceEmpty(entity, entity.getBoundingBox())) {
|
||||||
return TypedActionResult.fail(stack);
|
return TypedActionResult.fail(stack);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.AirBalloonEntity;
|
||||||
|
|
||||||
|
import net.minecraft.item.Item;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class HotAirBalloonItem extends Item {
|
||||||
|
|
||||||
|
public HotAirBalloonItem(Settings settings) {
|
||||||
|
super(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AirBalloonEntity.BalloonDesign getDesign(World world, ItemStack stack) {
|
||||||
|
String design;
|
||||||
|
if (stack.hasNbt() && !(design = stack.getNbt().getString("design")).isEmpty()) {
|
||||||
|
return AirBalloonEntity.BalloonDesign.getType(design);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ordinal = 1 + world.getRandom().nextInt(AirBalloonEntity.BalloonDesign.values().length - 1);
|
||||||
|
return AirBalloonEntity.BalloonDesign.getType(ordinal);
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
|
||||||
import com.minelittlepony.unicopia.item.group.UItemGroups;
|
import com.minelittlepony.unicopia.item.group.UItemGroups;
|
||||||
import com.minelittlepony.unicopia.item.toxin.UFoodComponents;
|
import com.minelittlepony.unicopia.item.toxin.UFoodComponents;
|
||||||
|
|
||||||
|
import net.minecraft.entity.vehicle.BoatEntity;
|
||||||
import net.minecraft.item.*;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.item.Item.Settings;
|
import net.minecraft.item.Item.Settings;
|
||||||
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
|
||||||
|
@ -118,8 +119,8 @@ public interface UItems {
|
||||||
Item BUTTERFLY = register("butterfly", new Item(new Item.Settings().food(UFoodComponents.INSECTS)), ItemGroups.FOOD_AND_DRINK);
|
Item BUTTERFLY = register("butterfly", new Item(new Item.Settings().food(UFoodComponents.INSECTS)), ItemGroups.FOOD_AND_DRINK);
|
||||||
|
|
||||||
Item SPELLBOOK = register("spellbook", new SpellbookItem(new Item.Settings().maxCount(1).rarity(Rarity.UNCOMMON)), ItemGroups.TOOLS);
|
Item SPELLBOOK = register("spellbook", new SpellbookItem(new Item.Settings().maxCount(1).rarity(Rarity.UNCOMMON)), ItemGroups.TOOLS);
|
||||||
Item BASKET = register("basket", new BasketItem(new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
|
Item OAK_BASKET = register("oak_basket", new BasketItem(BoatEntity.Type.OAK, new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
|
||||||
Item LARGE_BALLOON = register("large_balloon", new Item(new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
|
Item GIANT_BALLOON = register("giant_balloon", new HotAirBalloonItem(new Item.Settings().maxCount(1)), ItemGroups.FUNCTIONAL);
|
||||||
|
|
||||||
AmuletItem PEGASUS_AMULET = register("pegasus_amulet", new PegasusAmuletItem(new FabricItemSettings()
|
AmuletItem PEGASUS_AMULET = register("pegasus_amulet", new PegasusAmuletItem(new FabricItemSettings()
|
||||||
.maxCount(1)
|
.maxCount(1)
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
"item.unicopia.friendship_bracelet.issuer": "Signed by %s",
|
"item.unicopia.friendship_bracelet.issuer": "Signed by %s",
|
||||||
"item.unicopia.friendship_bracelet.glowing": "Glowing",
|
"item.unicopia.friendship_bracelet.glowing": "Glowing",
|
||||||
|
|
||||||
|
"item.unicopia.oak_basket": "Oak Basket",
|
||||||
|
"item.unicopia.giant_balloon": "Giant Balloon",
|
||||||
|
|
||||||
"item.unicopia.spellbook": "Spellbook",
|
"item.unicopia.spellbook": "Spellbook",
|
||||||
"emi.category.unicopia.spellbook": "Spellbook",
|
"emi.category.unicopia.spellbook": "Spellbook",
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/giant_balloon"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"parent": "item/generated",
|
||||||
|
"textures": {
|
||||||
|
"layer0": "unicopia:item/oak_basket"
|
||||||
|
}
|
||||||
|
}
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 6.5 KiB |
Before Width: | Height: | Size: 9.2 KiB After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.5 KiB |
BIN
src/main/resources/assets/unicopia/textures/item/oak_basket.png
Normal file
BIN
src/main/resources/assets/unicopia/textures/item/oak_basket.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.4 KiB |
Loading…
Reference in a new issue