Skip to content
34 changes: 19 additions & 15 deletions src/main/java/twilightforest/entity/CharmEffect.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,23 @@

import net.minecraft.core.particles.ItemParticleOption;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Mth;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.ItemSupplier;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.annotation.Nonnull;

public class CharmEffect extends Entity implements ItemSupplier {
private static final double DISTANCE = 0.75D;
private double interpTargetX;
Expand All @@ -32,17 +34,18 @@ public class CharmEffect extends Entity implements ItemSupplier {
private LivingEntity orbiter;
private ItemStack displayItem = new ItemStack(Items.BARRIER);

public CharmEffect(EntityType<? extends CharmEffect> type, Level level) {
public CharmEffect(EntityType<? extends @NotNull CharmEffect> type, Level level) {
super(type, level);
}

@SuppressWarnings("this-escape")
public CharmEffect(EntityType<? extends CharmEffect> type, Level level, LivingEntity owner, ItemStack item) {
public CharmEffect(EntityType<? extends @NotNull CharmEffect> type, Level level, LivingEntity owner, ItemStack item) {
this(type, level);
this.orbiter = owner;
this.displayItem = item;

this.moveTo(owner.getX(), owner.getY() + owner.getEyeHeight(), owner.getZ(), owner.getYRot(), owner.getXRot());
this.setPos(owner.getX(), owner.getY() + owner.getEyeHeight(), owner.getZ());
this.setRot(owner.getYRot(), owner.getXRot());

Vec3 look = new Vec3(DISTANCE, 0, 0);
double x = getX() + (look.x() * DISTANCE);
Expand Down Expand Up @@ -73,15 +76,16 @@ public void tick() {
if (this.orbiter != null) {
float rotation = this.tickCount / 10.0F + this.offset;
Vec3 look = new Vec3(DISTANCE, 0, 0).yRot(rotation);
this.moveTo(this.orbiter.getX() + look.x(), this.orbiter.getY() + this.orbiter.getEyeHeight(), this.orbiter.getZ() + look.z(), this.orbiter.getYRot(), this.orbiter.getXRot());
this.setPos(this.orbiter.getX() + look.x(), this.orbiter.getY() + this.orbiter.getEyeHeight(), this.orbiter.getZ() + look.z());
this.setRot(this.orbiter.getYRot(), this.orbiter.getXRot());
}

if (!this.displayItem.isEmpty()) {
double dx = getX() + 0.25 * (this.random.nextDouble() - this.random.nextDouble());
double dy = getY() + 0.25 * (this.random.nextDouble() - this.random.nextDouble());
double dz = getZ() + 0.25 * (this.random.nextDouble() - this.random.nextDouble());

this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.displayItem), dx, dy, dz, 0, 0.2, 0);
this.level().addParticle(new ItemParticleOption(ParticleTypes.ITEM, this.displayItem.getItem()), dx, dy, dz, 0, 0.2, 0);
}

if (this.tickCount > 200 || (this.orbiter != null && (!this.orbiter.isAlive() || this.orbiter.isInvisible()))) {
Expand All @@ -90,7 +94,7 @@ public void tick() {
}

@Override
public void lerpTo(double x, double y, double z, float yaw, float pitch, int posRotationIncrements) {
public void lerpPositionAndRotationStep(int posRotationIncrements, double x, double y, double z, double yaw, double pitch) {
this.interpTargetX = x;
this.interpTargetY = y;
this.interpTargetZ = z;
Expand All @@ -100,19 +104,19 @@ public void lerpTo(double x, double y, double z, float yaw, float pitch, int pos
}

@Override
protected void defineSynchedData(SynchedEntityData.Builder builder) {
protected void defineSynchedData(SynchedEntityData.Builder builder) {}

}
@Override
protected void readAdditionalSaveData(ValueInput valueInput) {}

@Override
protected void readAdditionalSaveData(CompoundTag cmp) {
}
protected void addAdditionalSaveData(ValueOutput valueOutput) {}

@Override
protected void addAdditionalSaveData(CompoundTag cmp) {
public boolean hurtServer(ServerLevel serverLevel, DamageSource damageSource, float v) {
return false;
}

@Nonnull
@Override
public ItemStack getItem() {
return this.displayItem;
Expand Down
38 changes: 21 additions & 17 deletions src/main/java/twilightforest/entity/EnforcedHomePoint.java
Original file line number Diff line number Diff line change
@@ -1,55 +1,59 @@
package twilightforest.entity;

import com.mojang.serialization.Codec;
import net.minecraft.core.BlockPos;
import net.minecraft.core.GlobalPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceKey;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.PathfinderMob;
import net.minecraft.world.entity.ai.goal.GoalSelector;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import twilightforest.TwilightForestMod;
import twilightforest.entity.ai.goal.AttemptToGoHomeGoal;
import twilightforest.init.TFDimension;

public interface EnforcedHomePoint {

default <T extends PathfinderMob & EnforcedHomePoint> void addRestrictionGoals(T entity, GoalSelector selector) {
selector.addGoal(5, new AttemptToGoHomeGoal<>(entity, 1.25D));
}

default void saveHomePointToNbt(ValueOutput tag) {
if (this.getRestrictionPoint() != null) {
GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, this.getRestrictionPoint()).resultOrPartial(TwilightForestMod.LOGGER::error).ifPresent(tag1 -> tag.put("HomePos", tag1));
tag.store("HomePos", GlobalPos.CODEC, this.getRestrictionPoint());
}
}

default void loadHomePointFromNbt(ValueInput tag) {
//properly load old home points, just assume theyre set in TF
if (tag.contains("Home", 9)) {
ListTag nbttaglist = tag.getList("Home", 6);
double hx = nbttaglist.getDouble(0);
double hy = nbttaglist.getDouble(1);
double hz = nbttaglist.getDouble(2);
this.setRestrictionPoint(GlobalPos.of(TFDimension.DIMENSION_KEY, BlockPos.containing(hx, hy, hz)));
var modernPos = tag.read("HomePos", GlobalPos.CODEC);

if (modernPos.isPresent()) {
this.setRestrictionPoint(modernPos.get());
} else {
if (tag.contains("HomePos")) {
this.setRestrictionPoint(GlobalPos.CODEC.parse(NbtOps.INSTANCE, tag.get("HomePos")).resultOrPartial(TwilightForestMod.LOGGER::error).orElse(null));
}
tag.read("Home", Codec.DOUBLE.listOf()).ifPresent(doubleList -> {
if (doubleList.size() >= 3) {
double hx = doubleList.get(0);
double hy = doubleList.get(1);
double hz = doubleList.get(2);

this.setRestrictionPoint(GlobalPos.of(
TFDimension.DIMENSION_KEY,
BlockPos.containing(hx, hy, hz)
));
}
});
}
}


default boolean isMobWithinHomeArea(Entity entity) {
if (!this.isRestrictionPointValid(entity.level().dimension())) return true;
return this.getRestrictionPoint().pos().distSqr(entity.blockPosition()) < (double) (this.getHomeRadius() * this.getHomeRadius());
}

default boolean isRestrictionPointValid(ResourceKey<Level> currentMobLevel) {
default boolean isRestrictionPointValid(ResourceKey<@NotNull Level> currentMobLevel) {
return this.getRestrictionPoint() != null && this.getRestrictionPoint().dimension().equals(currentMobLevel);
}

Expand Down
73 changes: 41 additions & 32 deletions src/main/java/twilightforest/entity/MagicPainting.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
package twilightforest.entity;

import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
Expand All @@ -16,11 +16,14 @@
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MoverType;
import net.minecraft.world.entity.decoration.HangingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.gamerules.GameRules;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
Expand All @@ -37,9 +40,11 @@
import java.util.Optional;

public class MagicPainting extends HangingEntity {
private static final EntityDataAccessor<Holder<MagicPaintingVariant>> MAGIC_PAINTING_VARIANT = SynchedEntityData.defineId(MagicPainting.class, TFDataSerializers.MAGIC_PAINTING_VARIANT.value());
private static final EntityDataAccessor<@NotNull Holder<@NotNull MagicPaintingVariant>> MAGIC_PAINTING_VARIANT = SynchedEntityData.defineId(MagicPainting.class, TFDataSerializers.MAGIC_PAINTING_VARIANT.value());

public MagicPainting(EntityType<? extends MagicPainting> entityType, Level level) {
private Direction direction;

public MagicPainting(EntityType<? extends @NotNull MagicPainting> entityType, Level level) {
super(entityType, level);
}

Expand All @@ -49,7 +54,7 @@ private MagicPainting(Level level, BlockPos pos) {

@Override
protected void defineSynchedData(SynchedEntityData.Builder builder) {
builder.define(MAGIC_PAINTING_VARIANT, this.getReg().getHolderOrThrow(MagicPaintingVariants.DEFAULT));
builder.define(MAGIC_PAINTING_VARIANT, this.getReg().getOrThrow(MagicPaintingVariants.DEFAULT));
}

@Override
Expand All @@ -59,18 +64,18 @@ public void onSyncedDataUpdated(EntityDataAccessor<?> pKey) {
}
}

public void setVariant(Holder<MagicPaintingVariant> variant) {
public void setVariant(Holder<@NotNull MagicPaintingVariant> variant) {
this.getEntityData().set(MAGIC_PAINTING_VARIANT, variant);
}

public Holder<MagicPaintingVariant> getVariant() {
public Holder<@NotNull MagicPaintingVariant> getVariant() {
return this.getEntityData().get(MAGIC_PAINTING_VARIANT);
}

public static Optional<MagicPainting> create(Level level, BlockPos pos, Direction direction) {
MagicPainting magicPainting = new MagicPainting(level, pos);
List<Holder<MagicPaintingVariant>> list = new ArrayList<>();
level.registryAccess().registryOrThrow(TFRegistries.Keys.MAGIC_PAINTINGS).holders().forEach(list::add);
List<Holder.Reference<@NotNull MagicPaintingVariant>> list = new ArrayList<>();
level.registryAccess().lookupOrThrow(TFRegistries.Keys.MAGIC_PAINTINGS).listElements().forEach(list::add);
if (list.isEmpty()) {
return Optional.empty();
} else {
Expand All @@ -83,8 +88,8 @@ public static Optional<MagicPainting> create(Level level, BlockPos pos, Directio
return Optional.empty();
} else {
int biggestPossibleArea = list.stream().mapToInt(MagicPainting::variantArea).max().orElse(0);
list.removeIf((variantArea) -> variantArea(variantArea) < biggestPossibleArea);
Optional<Holder<MagicPaintingVariant>> optional = Util.getRandomSafe(list, magicPainting.random);
list.removeIf((variant) -> variantArea(variant) < biggestPossibleArea);
Optional<Holder.Reference<@NotNull MagicPaintingVariant>> optional = Util.getRandomSafe(list, magicPainting.random);
if (optional.isEmpty()) {
return Optional.empty();
} else {
Expand All @@ -96,7 +101,7 @@ public static Optional<MagicPainting> create(Level level, BlockPos pos, Directio
}
}

private static int variantArea(Holder<MagicPaintingVariant> variant) {
private static int variantArea(Holder<@NotNull MagicPaintingVariant> variant) {
return variantArea(variant.value());
}

Expand All @@ -105,29 +110,29 @@ private static int variantArea(MagicPaintingVariant variant) {
}

@Override
public void addAdditionalSaveData(CompoundTag tag) {
protected void addAdditionalSaveData(ValueOutput output) {
Identifier location = this.getReg().getKey(this.getVariant().value());
if (location != null) tag.putString("variant", location.toString());
tag.putByte("facing", (byte) this.direction.get2DDataValue());
super.addAdditionalSaveData(tag);
if (location != null) output.putString("variant", location.toString());
output.putByte("facing", (byte) this.direction.get2DDataValue());
super.addAdditionalSaveData(output);
}

@Override
public void readAdditionalSaveData(CompoundTag tag) {
if (tag.contains("variant")) {
Identifier location = Identifier.tryParse(tag.getString("variant"));
public void readAdditionalSaveData(ValueInput input) {
if (!input.getStringOr("variant", "-1").equals("-1")) {
Identifier location = Identifier.tryParse(input.getString("variant").get());
if (location != null) {
this.setVariant(this.getReg().getHolder(location).orElse(this.getReg().getHolderOrThrow(MagicPaintingVariants.DEFAULT)));
this.setVariant(this.getReg().get(location).orElse(this.getReg().getOrThrow(MagicPaintingVariants.DEFAULT)));
}
}

this.direction = Direction.from2DDataValue(tag.getByte("facing"));
super.readAdditionalSaveData(tag);
this.direction = Direction.from2DDataValue(input.getByteOr("facing", (byte) 0));
super.readAdditionalSaveData(input);
this.setDirection(this.direction);
}

protected Registry<MagicPaintingVariant> getReg() {
return this.registryAccess().registryOrThrow(TFRegistries.Keys.MAGIC_PAINTINGS);
protected Registry<@NotNull MagicPaintingVariant> getReg() {
return this.registryAccess().lookupOrThrow(TFRegistries.Keys.MAGIC_PAINTINGS);
}

@Override
Expand All @@ -150,16 +155,16 @@ private double offsetForPaintingSize(int size) {
}

@Override
public void dropItem(@Nullable Entity entity) {
if (this.level().getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
public void dropItem(ServerLevel serverLevel, @Nullable Entity entity) {
if (serverLevel.getGameRules().get(GameRules.ENTITY_DROPS)) {
this.playSound(SoundEvents.PAINTING_BREAK, 1.0F, 1.0F);
if (entity instanceof Player player) {
if (player.getAbilities().instabuild) {
return;
}
}

this.spawnAtLocation(this.getPickResult());
this.spawnAtLocation(serverLevel, this.getPickResult());
}
}

Expand All @@ -169,22 +174,27 @@ public void playPlacementSound() {
}

@Override
public void moveTo(double x, double y, double z, float yaw, float pitch) {
this.setPos(x, y, z);
public void move(MoverType moverType, Vec3 delta) {
this.setPos(delta.x, delta.y, delta.z);
}

@Override
public void lerpTo(double x, double y, double z, float yaw, float pitch, int posRotationIncrements) {
public void moveTowardsClosestSpace(double x, double y, double z) {
this.setPos(x, y, z);
}

@Override
protected void lerpPositionAndRotationStep(int stepsToTarget, double targetX, double targetY, double targetZ, double targetYRot, double targetXRot) {
this.setPos(targetX, targetY, targetZ);
}

@Override
public Vec3 trackingPosition() {
return Vec3.atLowerCornerOf(this.pos);
}

@Override
public Packet<ClientGamePacketListener> getAddEntityPacket(ServerEntity entity) {
public Packet<@NotNull ClientGamePacketListener> getAddEntityPacket(ServerEntity entity) {
return new ClientboundAddEntityPacket(this, this.direction.get3DDataValue(), this.getPos());
}

Expand All @@ -195,7 +205,6 @@ public void recreateFromPacket(ClientboundAddEntityPacket packet) {
}

@Override
@NotNull
public ItemStack getPickResult() {
ItemStack itemStack = new ItemStack(TFItems.MAGIC_PAINTING.get());
itemStack.set(TFDataComponents.MAGIC_PAINTING_VARIANT, this.getVariant());
Expand Down
Loading
Loading