package com.xfestudio.mydimension.item;
import com.xfestudio.mydimension.client.RiftClient;
import com.xfestudio.mydimension.world.MindInstances;
import com.xfestudio.mydimension.world.MindTeamAccess;
import com.xfestudio.mydimension.world.MindType;
import com.xfestudio.mydimension.world.ModDimensions;
import com.xfestudio.mydimension.world.PrivateMindFeature;
import com.xfestudio.mydimension.world.portal.MindPortalManager;
import com.xfestudio.mydimension.world.SoaringMindChunkGenerator;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.util.ITeleporter;
import net.minecraftforge.fml.DistExecutor;
import java.util.function.Function;
import java.util.UUID;
public class RiftItem extends Item {
public static final double ETHEREAL_SURFACE_Y = 66.0D;
public static final String IMPORTED_TO_ETHEREAL_MIND = "mydimension_imported_to_ethereal_mind";
private static final int COPY_CHUNK_RADIUS = 1;
private static final String SELECTED_ACTION_TAG = "SelectedAction";
private static final String RETURN_POINT_TAG = "ReturnPoint";
private static final String MIND_POINTS_TAG = "MindPoints";
private static final String TEAM_OWNER_TAG = "TeamMindOwner";
private static final String TEAM_DIMENSION_TAG = "TeamMindDimension";
private static final String PLAYER_ANCHORS_TAG = "mydimension.RiftAnchors";
private static final String RETURN_DIMENSION_TAG = "Dimension";
private static final String RETURN_X_TAG = "X";
private static final String RETURN_Y_TAG = "Y";
private static final String RETURN_Z_TAG = "Z";
private static final String RETURN_Y_ROT_TAG = "YRot";
private static final String RETURN_X_ROT_TAG = "XRot";
public RiftItem(Properties properties) {
super(properties);
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (player.isShiftKeyDown()) {
if (level.isClientSide()) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RiftClient::openActionScreen);
return InteractionResultHolder.sidedSuccess(stack, true);
}
return InteractionResultHolder.consume(stack);
}
if (level.isClientSide()) {
return InteractionResultHolder.sidedSuccess(stack, true);
}
if (player instanceof ServerPlayer serverPlayer) {
executeSelectedAction(serverPlayer, stack);
serverPlayer.getCooldowns().addCooldown(this, 40);
}
return InteractionResultHolder.sidedSuccess(stack, false);
}
@Override
public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity target, InteractionHand hand) {
if (hand != InteractionHand.MAIN_HAND) {
return InteractionResult.PASS;
}
if (player.isShiftKeyDown()) {
if (player.level().isClientSide()) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RiftClient::openActionScreen);
return InteractionResult.SUCCESS;
}
return InteractionResult.CONSUME;
}
RiftAction action = getSelectedAction(stack);
if (!action.sendsMob()) {
return InteractionResult.PASS;
}
if (player.level().isClientSide()) {
return InteractionResult.SUCCESS;
}
if (player instanceof ServerPlayer serverPlayer) {
sendToMind(serverPlayer, target, stack, action);
}
return InteractionResult.CONSUME;
}
public static void setSelectedAction(ItemStack stack, RiftAction action) {
stack.getOrCreateTag().putString(SELECTED_ACTION_TAG, action.id());
if (action != RiftAction.VISIT_TEAM_MIND) {
stack.getOrCreateTag().remove(TEAM_OWNER_TAG);
stack.getOrCreateTag().remove(TEAM_DIMENSION_TAG);
}
}
@Override
public InteractionResult useOn(UseOnContext context) {
BlockState state = context.getLevel().getBlockState(context.getClickedPos());
if (state.is(com.xfestudio.mydimension.registry.ModBlocks.MIND_PORTAL_FRAME.get())
|| state.is(com.xfestudio.mydimension.registry.ModBlocks.MIND_PORTAL.get())) {
if (context.getLevel().isClientSide()) {
return InteractionResult.SUCCESS;
}
return MindPortalManager.useRiftOnPortal(context);
}
return super.useOn(context);
}
public static void setTeamMindTarget(ItemStack stack, UUID owner, ResourceKey<Level> baseDimension) {
CompoundTag tag = stack.getOrCreateTag();
tag.putString(SELECTED_ACTION_TAG, RiftAction.VISIT_TEAM_MIND.id());
tag.putUUID(TEAM_OWNER_TAG, owner);
tag.putString(TEAM_DIMENSION_TAG, baseDimension.location().toString());
}
public static PortalTarget resolvePortalTarget(ServerPlayer player, ItemStack stack) {
RiftAction action = getSelectedAction(stack);
ResourceKey<Level> baseDimension;
ResourceKey<Level> actualDimension;
UUID targetOwner = null;
Component displayName;
if (action == RiftAction.VISIT_TEAM_MIND) {
TeamMindTarget teamTarget = readTeamMindTarget(stack);
if (teamTarget == null || !MindTeamAccess.hasAccess(player.getServer(), teamTarget.owner(), player.getUUID())) {
player.displayClientMessage(Component.translatable("message.mydimension.team.not_allowed"), true);
return null;
}
baseDimension = teamTarget.baseDimension();
actualDimension = MindInstances.dimensionForOwner(player.getServer(), teamTarget.owner(), baseDimension);
targetOwner = teamTarget.owner();
String ownerName = MindTeamAccess.entrancesFor(player).stream()
.filter(entry -> entry.id().equals(teamTarget.owner()))
.map(MindTeamAccess.PlayerEntry::name)
.findFirst()
.orElse("?");
MindType type = MindType.fromBaseDimension(baseDimension);
displayName = Component.translatable("message.mydimension.portal.team_target", ownerName,
type == null ? Component.literal(baseDimension.location().toString()) : type.displayName());
} else if (action.teleportsPlayer()) {
baseDimension = action.targetDimension();
if (action.usesSharedDimension()) {
actualDimension = baseDimension;
} else {
targetOwner = player.getUUID();
actualDimension = MindInstances.dimensionForOwner(player.getServer(), player.getUUID(), baseDimension);
}
MindType type = MindType.fromBaseDimension(baseDimension);
displayName = type == null ? Component.literal(baseDimension.location().toString()) : type.displayName();
} else {
player.displayClientMessage(Component.translatable("message.mydimension.portal.invalid_target"), true);
return null;
}
if (actualDimension == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.no_slot"), true);
return null;
}
return new PortalTarget(baseDimension, actualDimension, targetOwner, displayName);
}
public static RiftAction getSelectedAction(ItemStack stack) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(SELECTED_ACTION_TAG)) {
return RiftAction.ETHEREAL_MIND;
}
return RiftAction.byId(tag.getString(SELECTED_ACTION_TAG));
}
private static void executeSelectedAction(ServerPlayer player, ItemStack stack) {
RiftAction action = getSelectedAction(stack);
if (action == RiftAction.SET_ANCHOR) {
setAnchor(player);
return;
}
if (action == RiftAction.VISIT_TEAM_MIND) {
teleportToTeamMind(player, stack);
return;
}
if (action.copiesSharedDimension()) {
copySharedDimension(player, action);
return;
}
if (action.sendsMob()) {
LivingEntity target = findLookedAtLivingEntity(player);
if (target == null || !sendToMind(player, target, stack, action)) {
player.displayClientMessage(Component.translatable("message.mydimension.no_mob_target"), true);
}
return;
}
teleport(player, stack, action);
}
private static void teleport(ServerPlayer player, ItemStack stack, RiftAction action) {
ResourceKey<Level> selectedDimension = action.targetDimension();
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension()
? selectedDimension
: MindInstances.dimensionFor(player, selectedDimension);
teleportToResolvedMind(player, stack, selectedDimension, actualTargetDimension);
}
private static void teleportToTeamMind(ServerPlayer player, ItemStack stack) {
TeamMindTarget target = readTeamMindTarget(stack);
if (!PrivateMindFeature.isEnabled() || target == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.unavailable"), true);
return;
}
ResourceKey<Level> actualTargetDimension = MindInstances.dimensionForOwner(
player.getServer(), target.owner(), target.baseDimension());
if (actualTargetDimension == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.no_slot"), true);
return;
}
boolean returning = player.level().dimension().equals(actualTargetDimension);
if (!returning && !MindTeamAccess.hasAccess(player.getServer(), target.owner(), player.getUUID())) {
player.displayClientMessage(Component.translatable("message.mydimension.team.not_allowed"), true);
return;
}
teleportToResolvedMind(player, stack, target.baseDimension(), actualTargetDimension);
}
private static void teleportToResolvedMind(ServerPlayer player, ItemStack stack,
ResourceKey<Level> selectedDimension,
ResourceKey<Level> actualTargetDimension) {
ServerLevel currentLevel = player.serverLevel();
ResourceKey<Level> currentDimension = currentLevel.dimension();
ResourceKey<Level> currentMindBase = ModDimensions.baseMindDimension(currentDimension);
boolean returningFromSelectedMind = currentDimension.equals(actualTargetDimension) && selectedDimension.equals(currentMindBase);
ReturnPoint returnPoint = returningFromSelectedMind ? readPoint(stack, RETURN_POINT_TAG) : null;
ReturnPoint mindPoint = returningFromSelectedMind ? null : readMindPoint(stack, actualTargetDimension);
ServerLevel targetLevel = returningFromSelectedMind ? getReturnLevel(player, returnPoint) : player.getServer().getLevel(actualTargetDimension);
if (targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return;
}
double x = player.getX();
double z = player.getZ();
EntryPoint entryPoint = returningFromSelectedMind ? new EntryPoint(x, overworldSpawnY(targetLevel), z) : safeEntryPoint(targetLevel, actualTargetDimension, x, z);
x = entryPoint.x();
double y = entryPoint.y();
z = entryPoint.z();
float yRot = player.getYRot();
float xRot = player.getXRot();
if (returningFromSelectedMind) {
if (returnPoint != null) {
x = returnPoint.x();
y = returnPoint.y();
z = returnPoint.z();
yRot = returnPoint.yRot();
xRot = returnPoint.xRot();
} else {
BlockPos spawn = targetLevel.getSharedSpawnPos();
x = spawn.getX() + 0.5D;
z = spawn.getZ() + 0.5D;
}
} else {
if (!ModDimensions.isMindDimension(currentDimension)) {
writePoint(stack, RETURN_POINT_TAG, player);
} else {
writeMindPoint(stack, currentDimension, player);
}
if (mindPoint != null) {
x = mindPoint.x();
y = mindPoint.y();
z = mindPoint.z();
yRot = mindPoint.yRot();
xRot = mindPoint.xRot();
}
if (ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(actualTargetDimension))) {
EntryPoint safe = safeEntryPoint(targetLevel, actualTargetDimension, x, z);
x = safe.x();
y = safe.y();
z = safe.z();
}
}
if (returningFromSelectedMind) {
writeMindPoint(stack, currentDimension, player);
}
targetLevel.playSound(null, player.blockPosition(), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1.0F, 1.0F);
player.teleportTo(targetLevel, x, y, z, yRot, xRot);
targetLevel.playSound(null, BlockPos.containing(x, y, z), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1.0F, 1.0F);
}
private static TeamMindTarget readTeamMindTarget(ItemStack stack) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.hasUUID(TEAM_OWNER_TAG)) {
return null;
}
ResourceLocation location = ResourceLocation.tryParse(tag.getString(TEAM_DIMENSION_TAG));
if (location == null) {
return null;
}
ResourceKey<Level> dimension = ResourceKey.create(Registries.DIMENSION, location);
ResourceKey<Level> baseDimension = ModDimensions.baseMindDimension(dimension);
if (baseDimension == null || !baseDimension.equals(dimension)) {
return null;
}
return new TeamMindTarget(tag.getUUID(TEAM_OWNER_TAG), baseDimension);
}
private static double overworldSpawnY(ServerLevel level) {
return level.getSharedSpawnPos().getY() + 1.0D;
}
private static double safeEntryY(ServerLevel level, ResourceKey<Level> dimension, double x, double z) {
return safeEntryPoint(level, dimension, x, z).y();
}
private static EntryPoint safeEntryPoint(ServerLevel level, ResourceKey<Level> dimension, double x, double z) {
int blockX = (int) Math.floor(x);
int blockZ = (int) Math.floor(z);
boolean soaringMind = ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(dimension));
int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockX, blockZ);
if (height > level.getMinBuildHeight()) {
return new EntryPoint(x, soaringMind ? height : height + 1.0D, z);
}
if (soaringMind) {
EntryPoint nearby = findNearbySurface(level, blockX, blockZ);
if (nearby != null) {
return nearby;
}
}
return new EntryPoint(x, ModDimensions.entryHeight(dimension), z);
}
private static EntryPoint findNearbySurface(ServerLevel level, int centerX, int centerZ) {
BlockPos surface = SoaringMindChunkGenerator.findNearestSurface(centerX, centerZ, 768);
if (surface == null) {
return null;
}
int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, surface.getX(), surface.getZ());
double y = height > level.getMinBuildHeight() ? height : surface.getY();
return new EntryPoint(surface.getX() + 0.5D, y, surface.getZ() + 0.5D);
}
public static boolean sendToMind(ServerPlayer player, LivingEntity target, ItemStack stack, RiftAction action) {
ResourceKey<Level> targetDimension = action.targetDimension();
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension() ? targetDimension : MindInstances.dimensionFor(player, targetDimension);
ServerLevel targetLevel = player.getServer().getLevel(actualTargetDimension);
if (targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return false;
}
target.getPersistentData().putBoolean(IMPORTED_TO_ETHEREAL_MIND, true);
target.stopRiding();
target.ejectPassengers();
AnchorPoint anchor = readAnchor(player, actualTargetDimension);
EntryPoint targetEntryPoint = safeEntryPoint(targetLevel, actualTargetDimension, player.getX(), player.getZ());
double targetX = anchor != null ? anchor.x() : targetEntryPoint.x();
double targetY = anchor != null ? anchor.y() : targetEntryPoint.y();
double targetZ = anchor != null ? anchor.z() : targetEntryPoint.z();
if (target.level().dimension().equals(actualTargetDimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.already_in_target_mind"), true);
return false;
}
Entity moved = target.changeDimension(targetLevel, new EtherealMindTeleporter(targetX, targetY, targetZ));
if (moved != null) {
moved.getPersistentData().putBoolean(IMPORTED_TO_ETHEREAL_MIND, true);
targetLevel.playSound(null, BlockPos.containing(moved.position()), SoundEvents.ENDERMAN_TELEPORT, SoundSource.NEUTRAL, 1.0F, 1.0F);
player.getCooldowns().addCooldown(stack.getItem(), 20);
return true;
}
return false;
}
private static void copySharedDimension(ServerPlayer player, RiftAction action) {
if (!player.isCreative()) {
player.displayClientMessage(Component.translatable("message.mydimension.copy_creative_only"), true);
return;
}
ResourceKey<Level> sourceDimension = action.targetDimension();
ResourceKey<Level> targetDimension = MindInstances.dimensionFor(player, sourceDimension);
if (sourceDimension.equals(targetDimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.copy_private_unavailable"), true);
return;
}
ServerLevel sourceLevel = player.getServer().getLevel(sourceDimension);
ServerLevel targetLevel = player.getServer().getLevel(targetDimension);
if (sourceLevel == null || targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return;
}
int copiedBlocks = copyNearbyBlocks(sourceLevel, targetLevel, player.blockPosition());
player.displayClientMessage(Component.translatable("message.mydimension.copy_done", copiedBlocks), true);
}
private static int copyNearbyBlocks(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos center) {
int centerChunkX = center.getX() >> 4;
int centerChunkZ = center.getZ() >> 4;
int minY = Math.max(sourceLevel.getMinBuildHeight(), targetLevel.getMinBuildHeight());
int maxY = Math.min(sourceLevel.getMaxBuildHeight(), targetLevel.getMaxBuildHeight());
BlockPos.MutableBlockPos sourcePos = new BlockPos.MutableBlockPos();
BlockPos.MutableBlockPos targetPos = new BlockPos.MutableBlockPos();
int copied = 0;
for (int chunkX = centerChunkX - COPY_CHUNK_RADIUS; chunkX <= centerChunkX + COPY_CHUNK_RADIUS; chunkX++) {
for (int chunkZ = centerChunkZ - COPY_CHUNK_RADIUS; chunkZ <= centerChunkZ + COPY_CHUNK_RADIUS; chunkZ++) {
sourceLevel.getChunk(chunkX, chunkZ);
targetLevel.getChunk(chunkX, chunkZ);
int minX = chunkX << 4;
int minZ = chunkZ << 4;
for (int x = minX; x < minX + 16; x++) {
for (int z = minZ; z < minZ + 16; z++) {
for (int y = minY; y < maxY; y++) {
sourcePos.set(x, y, z);
targetPos.set(x, y, z);
var state = sourceLevel.getBlockState(sourcePos);
targetLevel.setBlock(targetPos, state, 2);
copyBlockEntity(sourceLevel, targetLevel, sourcePos, targetPos);
copied++;
}
}
}
}
}
return copied;
}
private static void copyBlockEntity(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos sourcePos, BlockPos targetPos) {
BlockEntity sourceBlockEntity = sourceLevel.getBlockEntity(sourcePos);
if (sourceBlockEntity == null) {
return;
}
BlockEntity targetBlockEntity = targetLevel.getBlockEntity(targetPos);
if (targetBlockEntity == null) {
return;
}
CompoundTag tag = sourceBlockEntity.saveWithFullMetadata();
tag.putInt("x", targetPos.getX());
tag.putInt("y", targetPos.getY());
tag.putInt("z", targetPos.getZ());
targetBlockEntity.load(tag);
targetBlockEntity.setChanged();
}
private static LivingEntity findLookedAtLivingEntity(ServerPlayer player) {
double reach = 6.0D;
Vec3 eye = player.getEyePosition();
Vec3 look = player.getViewVector(1.0F);
Vec3 end = eye.add(look.scale(reach));
AABB searchBox = player.getBoundingBox().expandTowards(look.scale(reach)).inflate(1.0D);
EntityHitResult hit = ProjectileUtil.getEntityHitResult(
player.level(),
player,
eye,
end,
searchBox,
entity -> entity instanceof LivingEntity && entity.isAlive() && entity.isPickable() && entity != player,
0.3F
);
return hit != null && hit.getEntity() instanceof LivingEntity living ? living : null;
}
private static void setAnchor(ServerPlayer player) {
ResourceKey<Level> dimension = player.level().dimension();
if (!ModDimensions.isMindDimension(dimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.anchor_only_mind"), true);
return;
}
CompoundTag anchors = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
CompoundTag anchor = new CompoundTag();
anchor.putString(RETURN_DIMENSION_TAG, dimension.location().toString());
anchor.putDouble(RETURN_X_TAG, player.getX());
anchor.putDouble(RETURN_Y_TAG, player.getY());
anchor.putDouble(RETURN_Z_TAG, player.getZ());
anchors.put(dimension.location().toString(), anchor);
player.getPersistentData().put(PLAYER_ANCHORS_TAG, anchors);
player.displayClientMessage(Component.translatable("message.mydimension.anchor_set"), true);
}
public static AnchorPoint readAnchor(ServerPlayer player, ResourceKey<Level> dimension) {
CompoundTag anchors = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
String tagName = dimension.location().toString();
if (!anchors.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag anchor = anchors.getCompound(tagName);
ResourceLocation location = ResourceLocation.tryParse(anchor.getString(RETURN_DIMENSION_TAG));
if (location == null) {
return null;
}
return new AnchorPoint(
ResourceKey.create(Registries.DIMENSION, location),
anchor.getDouble(RETURN_X_TAG),
anchor.getDouble(RETURN_Y_TAG),
anchor.getDouble(RETURN_Z_TAG)
);
}
public static java.util.List<AnchorPoint> readAnchors(ServerPlayer player) {
java.util.List<AnchorPoint> anchors = new java.util.ArrayList<>();
CompoundTag tag = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
for (String key : tag.getAllKeys()) {
ResourceLocation location = ResourceLocation.tryParse(key);
if (location != null && tag.contains(key, CompoundTag.TAG_COMPOUND)) {
CompoundTag anchor = tag.getCompound(key);
anchors.add(new AnchorPoint(
ResourceKey.create(Registries.DIMENSION, location),
anchor.getDouble(RETURN_X_TAG),
anchor.getDouble(RETURN_Y_TAG),
anchor.getDouble(RETURN_Z_TAG)
));
}
}
return anchors;
}
private static void writePoint(ItemStack stack, String tagName, ServerPlayer player) {
CompoundTag point = new CompoundTag();
point.putString(RETURN_DIMENSION_TAG, player.level().dimension().location().toString());
point.putDouble(RETURN_X_TAG, player.getX());
point.putDouble(RETURN_Y_TAG, player.getY());
point.putDouble(RETURN_Z_TAG, player.getZ());
point.putFloat(RETURN_Y_ROT_TAG, player.getYRot());
point.putFloat(RETURN_X_ROT_TAG, player.getXRot());
stack.getOrCreateTag().put(tagName, point);
}
private static void writeMindPoint(ItemStack stack, ResourceKey<Level> dimension, ServerPlayer player) {
CompoundTag mindPoints = stack.getOrCreateTag().getCompound(MIND_POINTS_TAG);
writePointToTag(mindPoints, dimension.location().toString(), player);
stack.getOrCreateTag().put(MIND_POINTS_TAG, mindPoints);
}
private static void writePointToTag(CompoundTag parent, String tagName, ServerPlayer player) {
CompoundTag point = new CompoundTag();
point.putString(RETURN_DIMENSION_TAG, player.level().dimension().location().toString());
point.putDouble(RETURN_X_TAG, player.getX());
point.putDouble(RETURN_Y_TAG, player.getY());
point.putDouble(RETURN_Z_TAG, player.getZ());
point.putFloat(RETURN_Y_ROT_TAG, player.getYRot());
point.putFloat(RETURN_X_ROT_TAG, player.getXRot());
parent.put(tagName, point);
}
private static ReturnPoint readPoint(ItemStack stack, String tagName) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag point = tag.getCompound(tagName);
ResourceLocation dimension = ResourceLocation.tryParse(point.getString(RETURN_DIMENSION_TAG));
if (dimension == null) {
return null;
}
return new ReturnPoint(
ResourceKey.create(Registries.DIMENSION, dimension),
point.getDouble(RETURN_X_TAG),
point.getDouble(RETURN_Y_TAG),
point.getDouble(RETURN_Z_TAG),
point.getFloat(RETURN_Y_ROT_TAG),
point.getFloat(RETURN_X_ROT_TAG)
);
}
private static ReturnPoint readMindPoint(ItemStack stack, ResourceKey<Level> dimension) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(MIND_POINTS_TAG, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag mindPoints = tag.getCompound(MIND_POINTS_TAG);
String tagName = dimension.location().toString();
if (!mindPoints.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag point = mindPoints.getCompound(tagName);
return new ReturnPoint(
dimension,
point.getDouble(RETURN_X_TAG),
point.getDouble(RETURN_Y_TAG),
point.getDouble(RETURN_Z_TAG),
point.getFloat(RETURN_Y_ROT_TAG),
point.getFloat(RETURN_X_ROT_TAG)
);
}
private static ServerLevel getReturnLevel(ServerPlayer player, ReturnPoint returnPoint) {
if (returnPoint != null) {
ServerLevel savedLevel = player.getServer().getLevel(returnPoint.dimension());
if (savedLevel != null) {
return savedLevel;
}
}
return player.getServer().getLevel(Level.OVERWORLD);
}
private record ReturnPoint(ResourceKey<Level> dimension, double x, double y, double z, float yRot, float xRot) {
}
private record EntryPoint(double x, double y, double z) {
}
private record TeamMindTarget(UUID owner, ResourceKey<Level> baseDimension) {
}
public record AnchorPoint(ResourceKey<Level> dimension, double x, double y, double z) {
}
public record PortalTarget(ResourceKey<Level> baseDimension, ResourceKey<Level> dimension,
UUID owner, Component displayName) {
}
private static class EtherealMindTeleporter implements ITeleporter {
private final double x;
private final double y;
private final double z;
private EtherealMindTeleporter(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public PortalInfo getPortalInfo(Entity entity, ServerLevel destinationLevel, Function<ServerLevel, PortalInfo> defaultPortalInfo) {
return new PortalInfo(new Vec3(x, y, z), Vec3.ZERO, entity.getYRot(), entity.getXRot());
}
@Override
public Entity placeEntity(Entity entity, ServerLevel currentLevel, ServerLevel destinationLevel, float yaw, Function<Boolean, Entity> repositionEntity) {
Entity moved = repositionEntity.apply(false);
if (moved != null) {
moved.moveTo(x, y, z, moved.getYRot(), moved.getXRot());
moved.setDeltaMovement(Vec3.ZERO);
moved.setPortalCooldown();
}
return moved;
}
}
}
package com.xfestudio.mydimension.item;
import com.xfestudio.mydimension.client.RiftClient;
import com.xfestudio.mydimension.world.MindInstances;
import com.xfestudio.mydimension.world.MindTeamAccess;
import com.xfestudio.mydimension.world.MindType;
import com.xfestudio.mydimension.world.ModDimensions;
import com.xfestudio.mydimension.world.PrivateMindFeature;
import com.xfestudio.mydimension.world.portal.MindPortalManager;
import com.xfestudio.mydimension.world.SoaringMindChunkGenerator;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.portal.PortalInfo;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.common.util.ITeleporter;
import net.minecraftforge.fml.DistExecutor;
import java.util.function.Function;
import java.util.UUID;
public class RiftItem extends Item {
public static final double ETHEREAL_SURFACE_Y = 66.0D;
public static final String IMPORTED_TO_ETHEREAL_MIND = "mydimension_imported_to_ethereal_mind";
private static final int COPY_CHUNK_RADIUS = 1;
private static final String SELECTED_ACTION_TAG = "SelectedAction";
private static final String RETURN_POINT_TAG = "ReturnPoint";
private static final String MIND_POINTS_TAG = "MindPoints";
private static final String TEAM_OWNER_TAG = "TeamMindOwner";
private static final String TEAM_DIMENSION_TAG = "TeamMindDimension";
private static final String PLAYER_ANCHORS_TAG = "mydimension.RiftAnchors";
private static final String RETURN_DIMENSION_TAG = "Dimension";
private static final String RETURN_X_TAG = "X";
private static final String RETURN_Y_TAG = "Y";
private static final String RETURN_Z_TAG = "Z";
private static final String RETURN_Y_ROT_TAG = "YRot";
private static final String RETURN_X_ROT_TAG = "XRot";
public RiftItem(Properties properties) {
super(properties);
}
@Override
public InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand hand) {
ItemStack stack = player.getItemInHand(hand);
if (player.isShiftKeyDown()) {
if (level.isClientSide()) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RiftClient::openActionScreen);
return InteractionResultHolder.sidedSuccess(stack, true);
}
return InteractionResultHolder.consume(stack);
}
if (level.isClientSide()) {
return InteractionResultHolder.sidedSuccess(stack, true);
}
if (player instanceof ServerPlayer serverPlayer) {
executeSelectedAction(serverPlayer, stack);
serverPlayer.getCooldowns().addCooldown(this, 40);
}
return InteractionResultHolder.sidedSuccess(stack, false);
}
@Override
public InteractionResult interactLivingEntity(ItemStack stack, Player player, LivingEntity target, InteractionHand hand) {
if (hand != InteractionHand.MAIN_HAND) {
return InteractionResult.PASS;
}
if (player.isShiftKeyDown()) {
if (player.level().isClientSide()) {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> RiftClient::openActionScreen);
return InteractionResult.SUCCESS;
}
return InteractionResult.CONSUME;
}
RiftAction action = getSelectedAction(stack);
if (!action.sendsMob()) {
return InteractionResult.PASS;
}
if (player.level().isClientSide()) {
return InteractionResult.SUCCESS;
}
if (player instanceof ServerPlayer serverPlayer) {
sendToMind(serverPlayer, target, stack, action);
}
return InteractionResult.CONSUME;
}
public static void setSelectedAction(ItemStack stack, RiftAction action) {
stack.getOrCreateTag().putString(SELECTED_ACTION_TAG, action.id());
if (action != RiftAction.VISIT_TEAM_MIND) {
stack.getOrCreateTag().remove(TEAM_OWNER_TAG);
stack.getOrCreateTag().remove(TEAM_DIMENSION_TAG);
}
}
@Override
public InteractionResult useOn(UseOnContext context) {
BlockState state = context.getLevel().getBlockState(context.getClickedPos());
if (state.is(com.xfestudio.mydimension.registry.ModBlocks.MIND_PORTAL_FRAME.get())
|| state.is(com.xfestudio.mydimension.registry.ModBlocks.MIND_PORTAL.get())) {
if (context.getLevel().isClientSide()) {
return InteractionResult.SUCCESS;
}
return MindPortalManager.useRiftOnPortal(context);
}
return super.useOn(context);
}
public static void setTeamMindTarget(ItemStack stack, UUID owner, ResourceKey<Level> baseDimension) {
CompoundTag tag = stack.getOrCreateTag();
tag.putString(SELECTED_ACTION_TAG, RiftAction.VISIT_TEAM_MIND.id());
tag.putUUID(TEAM_OWNER_TAG, owner);
tag.putString(TEAM_DIMENSION_TAG, baseDimension.location().toString());
}
public static PortalTarget resolvePortalTarget(ServerPlayer player, ItemStack stack) {
RiftAction action = getSelectedAction(stack);
ResourceKey<Level> baseDimension;
ResourceKey<Level> actualDimension;
UUID targetOwner = null;
Component displayName;
if (action == RiftAction.VISIT_TEAM_MIND) {
TeamMindTarget teamTarget = readTeamMindTarget(stack);
if (teamTarget == null || !MindTeamAccess.hasAccess(player.getServer(), teamTarget.owner(), player.getUUID())) {
player.displayClientMessage(Component.translatable("message.mydimension.team.not_allowed"), true);
return null;
}
baseDimension = teamTarget.baseDimension();
actualDimension = MindInstances.dimensionForOwner(player.getServer(), teamTarget.owner(), baseDimension);
targetOwner = teamTarget.owner();
String ownerName = MindTeamAccess.entrancesFor(player).stream()
.filter(entry -> entry.id().equals(teamTarget.owner()))
.map(MindTeamAccess.PlayerEntry::name)
.findFirst()
.orElse("?");
MindType type = MindType.fromBaseDimension(baseDimension);
displayName = Component.translatable("message.mydimension.portal.team_target", ownerName,
type == null ? Component.literal(baseDimension.location().toString()) : type.displayName());
} else if (action.teleportsPlayer()) {
baseDimension = action.targetDimension();
if (action.usesSharedDimension()) {
actualDimension = baseDimension;
} else {
targetOwner = player.getUUID();
actualDimension = MindInstances.dimensionForOwner(player.getServer(), player.getUUID(), baseDimension);
}
MindType type = MindType.fromBaseDimension(baseDimension);
displayName = type == null ? Component.literal(baseDimension.location().toString()) : type.displayName();
} else {
player.displayClientMessage(Component.translatable("message.mydimension.portal.invalid_target"), true);
return null;
}
if (actualDimension == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.no_slot"), true);
return null;
}
return new PortalTarget(baseDimension, actualDimension, targetOwner, displayName);
}
public static RiftAction getSelectedAction(ItemStack stack) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(SELECTED_ACTION_TAG)) {
return RiftAction.ETHEREAL_MIND;
}
return RiftAction.byId(tag.getString(SELECTED_ACTION_TAG));
}
private static void executeSelectedAction(ServerPlayer player, ItemStack stack) {
RiftAction action = getSelectedAction(stack);
if (action == RiftAction.SET_ANCHOR) {
setAnchor(player);
return;
}
if (action == RiftAction.VISIT_TEAM_MIND) {
teleportToTeamMind(player, stack);
return;
}
if (action.copiesSharedDimension()) {
copySharedDimension(player, action);
return;
}
if (action.sendsMob()) {
LivingEntity target = findLookedAtLivingEntity(player);
if (target == null || !sendToMind(player, target, stack, action)) {
player.displayClientMessage(Component.translatable("message.mydimension.no_mob_target"), true);
}
return;
}
teleport(player, stack, action);
}
private static void teleport(ServerPlayer player, ItemStack stack, RiftAction action) {
ResourceKey<Level> selectedDimension = action.targetDimension();
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension()
? selectedDimension
: MindInstances.dimensionFor(player, selectedDimension);
teleportToResolvedMind(player, stack, selectedDimension, actualTargetDimension);
}
private static void teleportToTeamMind(ServerPlayer player, ItemStack stack) {
TeamMindTarget target = readTeamMindTarget(stack);
if (!PrivateMindFeature.isEnabled() || target == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.unavailable"), true);
return;
}
ResourceKey<Level> actualTargetDimension = MindInstances.dimensionForOwner(
player.getServer(), target.owner(), target.baseDimension());
if (actualTargetDimension == null) {
player.displayClientMessage(Component.translatable("message.mydimension.team.no_slot"), true);
return;
}
boolean returning = player.level().dimension().equals(actualTargetDimension);
if (!returning && !MindTeamAccess.hasAccess(player.getServer(), target.owner(), player.getUUID())) {
player.displayClientMessage(Component.translatable("message.mydimension.team.not_allowed"), true);
return;
}
teleportToResolvedMind(player, stack, target.baseDimension(), actualTargetDimension);
}
private static void teleportToResolvedMind(ServerPlayer player, ItemStack stack,
ResourceKey<Level> selectedDimension,
ResourceKey<Level> actualTargetDimension) {
ServerLevel currentLevel = player.serverLevel();
ResourceKey<Level> currentDimension = currentLevel.dimension();
ResourceKey<Level> currentMindBase = ModDimensions.baseMindDimension(currentDimension);
boolean returningFromSelectedMind = currentDimension.equals(actualTargetDimension) && selectedDimension.equals(currentMindBase);
ReturnPoint returnPoint = returningFromSelectedMind ? readPoint(stack, RETURN_POINT_TAG) : null;
ReturnPoint mindPoint = returningFromSelectedMind ? null : readMindPoint(stack, actualTargetDimension);
ServerLevel targetLevel = returningFromSelectedMind ? getReturnLevel(player, returnPoint) : player.getServer().getLevel(actualTargetDimension);
if (targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return;
}
double x = player.getX();
double z = player.getZ();
EntryPoint entryPoint = returningFromSelectedMind ? new EntryPoint(x, overworldSpawnY(targetLevel), z) : safeEntryPoint(targetLevel, actualTargetDimension, x, z);
x = entryPoint.x();
double y = entryPoint.y();
z = entryPoint.z();
float yRot = player.getYRot();
float xRot = player.getXRot();
if (returningFromSelectedMind) {
if (returnPoint != null) {
x = returnPoint.x();
y = returnPoint.y();
z = returnPoint.z();
yRot = returnPoint.yRot();
xRot = returnPoint.xRot();
} else {
BlockPos spawn = targetLevel.getSharedSpawnPos();
x = spawn.getX() + 0.5D;
z = spawn.getZ() + 0.5D;
}
} else {
if (!ModDimensions.isMindDimension(currentDimension)) {
writePoint(stack, RETURN_POINT_TAG, player);
} else {
writeMindPoint(stack, currentDimension, player);
}
if (mindPoint != null) {
x = mindPoint.x();
y = mindPoint.y();
z = mindPoint.z();
yRot = mindPoint.yRot();
xRot = mindPoint.xRot();
}
if (ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(actualTargetDimension))) {
EntryPoint safe = safeEntryPoint(targetLevel, actualTargetDimension, x, z);
x = safe.x();
y = safe.y();
z = safe.z();
}
}
if (returningFromSelectedMind) {
writeMindPoint(stack, currentDimension, player);
}
targetLevel.playSound(null, player.blockPosition(), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1.0F, 1.0F);
player.teleportTo(targetLevel, x, y, z, yRot, xRot);
targetLevel.playSound(null, BlockPos.containing(x, y, z), SoundEvents.ENDERMAN_TELEPORT, SoundSource.PLAYERS, 1.0F, 1.0F);
}
private static TeamMindTarget readTeamMindTarget(ItemStack stack) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.hasUUID(TEAM_OWNER_TAG)) {
return null;
}
ResourceLocation location = ResourceLocation.tryParse(tag.getString(TEAM_DIMENSION_TAG));
if (location == null) {
return null;
}
ResourceKey<Level> dimension = ResourceKey.create(Registries.DIMENSION, location);
ResourceKey<Level> baseDimension = ModDimensions.baseMindDimension(dimension);
if (baseDimension == null || !baseDimension.equals(dimension)) {
return null;
}
return new TeamMindTarget(tag.getUUID(TEAM_OWNER_TAG), baseDimension);
}
private static double overworldSpawnY(ServerLevel level) {
return level.getSharedSpawnPos().getY() + 1.0D;
}
private static double safeEntryY(ServerLevel level, ResourceKey<Level> dimension, double x, double z) {
return safeEntryPoint(level, dimension, x, z).y();
}
private static EntryPoint safeEntryPoint(ServerLevel level, ResourceKey<Level> dimension, double x, double z) {
int blockX = (int) Math.floor(x);
int blockZ = (int) Math.floor(z);
boolean soaringMind = ModDimensions.SOARING_MIND.equals(ModDimensions.baseMindDimension(dimension));
int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockX, blockZ);
if (height > level.getMinBuildHeight()) {
return new EntryPoint(x, soaringMind ? height : height + 1.0D, z);
}
if (soaringMind) {
EntryPoint nearby = findNearbySurface(level, blockX, blockZ);
if (nearby != null) {
return nearby;
}
}
return new EntryPoint(x, ModDimensions.entryHeight(dimension), z);
}
private static EntryPoint findNearbySurface(ServerLevel level, int centerX, int centerZ) {
BlockPos surface = SoaringMindChunkGenerator.findNearestSurface(centerX, centerZ, 768);
if (surface == null) {
return null;
}
int height = level.getHeight(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, surface.getX(), surface.getZ());
double y = height > level.getMinBuildHeight() ? height : surface.getY();
return new EntryPoint(surface.getX() + 0.5D, y, surface.getZ() + 0.5D);
}
public static boolean sendToMind(ServerPlayer player, LivingEntity target, ItemStack stack, RiftAction action) {
ResourceKey<Level> targetDimension = action.targetDimension();
ResourceKey<Level> actualTargetDimension = action.usesSharedDimension() ? targetDimension : MindInstances.dimensionFor(player, targetDimension);
ServerLevel targetLevel = player.getServer().getLevel(actualTargetDimension);
if (targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return false;
}
target.getPersistentData().putBoolean(IMPORTED_TO_ETHEREAL_MIND, true);
target.stopRiding();
target.ejectPassengers();
AnchorPoint anchor = readAnchor(player, actualTargetDimension);
EntryPoint targetEntryPoint = safeEntryPoint(targetLevel, actualTargetDimension, player.getX(), player.getZ());
double targetX = anchor != null ? anchor.x() : targetEntryPoint.x();
double targetY = anchor != null ? anchor.y() : targetEntryPoint.y();
double targetZ = anchor != null ? anchor.z() : targetEntryPoint.z();
if (target.level().dimension().equals(actualTargetDimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.already_in_target_mind"), true);
return false;
}
Entity moved = target.changeDimension(targetLevel, new EtherealMindTeleporter(targetX, targetY, targetZ));
if (moved != null) {
moved.getPersistentData().putBoolean(IMPORTED_TO_ETHEREAL_MIND, true);
targetLevel.playSound(null, BlockPos.containing(moved.position()), SoundEvents.ENDERMAN_TELEPORT, SoundSource.NEUTRAL, 1.0F, 1.0F);
player.getCooldowns().addCooldown(stack.getItem(), 20);
return true;
}
return false;
}
private static void copySharedDimension(ServerPlayer player, RiftAction action) {
if (!player.isCreative()) {
player.displayClientMessage(Component.translatable("message.mydimension.copy_creative_only"), true);
return;
}
ResourceKey<Level> sourceDimension = action.targetDimension();
ResourceKey<Level> targetDimension = MindInstances.dimensionFor(player, sourceDimension);
if (sourceDimension.equals(targetDimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.copy_private_unavailable"), true);
return;
}
ServerLevel sourceLevel = player.getServer().getLevel(sourceDimension);
ServerLevel targetLevel = player.getServer().getLevel(targetDimension);
if (sourceLevel == null || targetLevel == null) {
player.displayClientMessage(Component.translatable("message.mydimension.missing_dimension"), true);
return;
}
int copiedBlocks = copyNearbyBlocks(sourceLevel, targetLevel, player.blockPosition());
player.displayClientMessage(Component.translatable("message.mydimension.copy_done", copiedBlocks), true);
}
private static int copyNearbyBlocks(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos center) {
int centerChunkX = center.getX() >> 4;
int centerChunkZ = center.getZ() >> 4;
int minY = Math.max(sourceLevel.getMinBuildHeight(), targetLevel.getMinBuildHeight());
int maxY = Math.min(sourceLevel.getMaxBuildHeight(), targetLevel.getMaxBuildHeight());
BlockPos.MutableBlockPos sourcePos = new BlockPos.MutableBlockPos();
BlockPos.MutableBlockPos targetPos = new BlockPos.MutableBlockPos();
int copied = 0;
for (int chunkX = centerChunkX - COPY_CHUNK_RADIUS; chunkX <= centerChunkX + COPY_CHUNK_RADIUS; chunkX++) {
for (int chunkZ = centerChunkZ - COPY_CHUNK_RADIUS; chunkZ <= centerChunkZ + COPY_CHUNK_RADIUS; chunkZ++) {
sourceLevel.getChunk(chunkX, chunkZ);
targetLevel.getChunk(chunkX, chunkZ);
int minX = chunkX << 4;
int minZ = chunkZ << 4;
for (int x = minX; x < minX + 16; x++) {
for (int z = minZ; z < minZ + 16; z++) {
for (int y = minY; y < maxY; y++) {
sourcePos.set(x, y, z);
targetPos.set(x, y, z);
var state = sourceLevel.getBlockState(sourcePos);
targetLevel.setBlock(targetPos, state, 2);
copyBlockEntity(sourceLevel, targetLevel, sourcePos, targetPos);
copied++;
}
}
}
}
}
return copied;
}
private static void copyBlockEntity(ServerLevel sourceLevel, ServerLevel targetLevel, BlockPos sourcePos, BlockPos targetPos) {
BlockEntity sourceBlockEntity = sourceLevel.getBlockEntity(sourcePos);
if (sourceBlockEntity == null) {
return;
}
BlockEntity targetBlockEntity = targetLevel.getBlockEntity(targetPos);
if (targetBlockEntity == null) {
return;
}
CompoundTag tag = sourceBlockEntity.saveWithFullMetadata();
tag.putInt("x", targetPos.getX());
tag.putInt("y", targetPos.getY());
tag.putInt("z", targetPos.getZ());
targetBlockEntity.load(tag);
targetBlockEntity.setChanged();
}
private static LivingEntity findLookedAtLivingEntity(ServerPlayer player) {
double reach = 6.0D;
Vec3 eye = player.getEyePosition();
Vec3 look = player.getViewVector(1.0F);
Vec3 end = eye.add(look.scale(reach));
AABB searchBox = player.getBoundingBox().expandTowards(look.scale(reach)).inflate(1.0D);
EntityHitResult hit = ProjectileUtil.getEntityHitResult(
player.level(),
player,
eye,
end,
searchBox,
entity -> entity instanceof LivingEntity && entity.isAlive() && entity.isPickable() && entity != player,
0.3F
);
return hit != null && hit.getEntity() instanceof LivingEntity living ? living : null;
}
private static void setAnchor(ServerPlayer player) {
ResourceKey<Level> dimension = player.level().dimension();
if (!ModDimensions.isMindDimension(dimension)) {
player.displayClientMessage(Component.translatable("message.mydimension.anchor_only_mind"), true);
return;
}
CompoundTag anchors = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
CompoundTag anchor = new CompoundTag();
anchor.putString(RETURN_DIMENSION_TAG, dimension.location().toString());
anchor.putDouble(RETURN_X_TAG, player.getX());
anchor.putDouble(RETURN_Y_TAG, player.getY());
anchor.putDouble(RETURN_Z_TAG, player.getZ());
anchors.put(dimension.location().toString(), anchor);
player.getPersistentData().put(PLAYER_ANCHORS_TAG, anchors);
player.displayClientMessage(Component.translatable("message.mydimension.anchor_set"), true);
}
public static AnchorPoint readAnchor(ServerPlayer player, ResourceKey<Level> dimension) {
CompoundTag anchors = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
String tagName = dimension.location().toString();
if (!anchors.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag anchor = anchors.getCompound(tagName);
ResourceLocation location = ResourceLocation.tryParse(anchor.getString(RETURN_DIMENSION_TAG));
if (location == null) {
return null;
}
return new AnchorPoint(
ResourceKey.create(Registries.DIMENSION, location),
anchor.getDouble(RETURN_X_TAG),
anchor.getDouble(RETURN_Y_TAG),
anchor.getDouble(RETURN_Z_TAG)
);
}
public static java.util.List<AnchorPoint> readAnchors(ServerPlayer player) {
java.util.List<AnchorPoint> anchors = new java.util.ArrayList<>();
CompoundTag tag = player.getPersistentData().getCompound(PLAYER_ANCHORS_TAG);
for (String key : tag.getAllKeys()) {
ResourceLocation location = ResourceLocation.tryParse(key);
if (location != null && tag.contains(key, CompoundTag.TAG_COMPOUND)) {
CompoundTag anchor = tag.getCompound(key);
anchors.add(new AnchorPoint(
ResourceKey.create(Registries.DIMENSION, location),
anchor.getDouble(RETURN_X_TAG),
anchor.getDouble(RETURN_Y_TAG),
anchor.getDouble(RETURN_Z_TAG)
));
}
}
return anchors;
}
private static void writePoint(ItemStack stack, String tagName, ServerPlayer player) {
CompoundTag point = new CompoundTag();
point.putString(RETURN_DIMENSION_TAG, player.level().dimension().location().toString());
point.putDouble(RETURN_X_TAG, player.getX());
point.putDouble(RETURN_Y_TAG, player.getY());
point.putDouble(RETURN_Z_TAG, player.getZ());
point.putFloat(RETURN_Y_ROT_TAG, player.getYRot());
point.putFloat(RETURN_X_ROT_TAG, player.getXRot());
stack.getOrCreateTag().put(tagName, point);
}
private static void writeMindPoint(ItemStack stack, ResourceKey<Level> dimension, ServerPlayer player) {
CompoundTag mindPoints = stack.getOrCreateTag().getCompound(MIND_POINTS_TAG);
writePointToTag(mindPoints, dimension.location().toString(), player);
stack.getOrCreateTag().put(MIND_POINTS_TAG, mindPoints);
}
private static void writePointToTag(CompoundTag parent, String tagName, ServerPlayer player) {
CompoundTag point = new CompoundTag();
point.putString(RETURN_DIMENSION_TAG, player.level().dimension().location().toString());
point.putDouble(RETURN_X_TAG, player.getX());
point.putDouble(RETURN_Y_TAG, player.getY());
point.putDouble(RETURN_Z_TAG, player.getZ());
point.putFloat(RETURN_Y_ROT_TAG, player.getYRot());
point.putFloat(RETURN_X_ROT_TAG, player.getXRot());
parent.put(tagName, point);
}
private static ReturnPoint readPoint(ItemStack stack, String tagName) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag point = tag.getCompound(tagName);
ResourceLocation dimension = ResourceLocation.tryParse(point.getString(RETURN_DIMENSION_TAG));
if (dimension == null) {
return null;
}
return new ReturnPoint(
ResourceKey.create(Registries.DIMENSION, dimension),
point.getDouble(RETURN_X_TAG),
point.getDouble(RETURN_Y_TAG),
point.getDouble(RETURN_Z_TAG),
point.getFloat(RETURN_Y_ROT_TAG),
point.getFloat(RETURN_X_ROT_TAG)
);
}
private static ReturnPoint readMindPoint(ItemStack stack, ResourceKey<Level> dimension) {
CompoundTag tag = stack.getTag();
if (tag == null || !tag.contains(MIND_POINTS_TAG, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag mindPoints = tag.getCompound(MIND_POINTS_TAG);
String tagName = dimension.location().toString();
if (!mindPoints.contains(tagName, CompoundTag.TAG_COMPOUND)) {
return null;
}
CompoundTag point = mindPoints.getCompound(tagName);
return new ReturnPoint(
dimension,
point.getDouble(RETURN_X_TAG),
point.getDouble(RETURN_Y_TAG),
point.getDouble(RETURN_Z_TAG),
point.getFloat(RETURN_Y_ROT_TAG),
point.getFloat(RETURN_X_ROT_TAG)
);
}
private static ServerLevel getReturnLevel(ServerPlayer player, ReturnPoint returnPoint) {
if (returnPoint != null) {
ServerLevel savedLevel = player.getServer().getLevel(returnPoint.dimension());
if (savedLevel != null) {
return savedLevel;
}
}
return player.getServer().getLevel(Level.OVERWORLD);
}
private record ReturnPoint(ResourceKey<Level> dimension, double x, double y, double z, float yRot, float xRot) {
}
private record EntryPoint(double x, double y, double z) {
}
private record TeamMindTarget(UUID owner, ResourceKey<Level> baseDimension) {
}
public record AnchorPoint(ResourceKey<Level> dimension, double x, double y, double z) {
}
public record PortalTarget(ResourceKey<Level> baseDimension, ResourceKey<Level> dimension,
UUID owner, Component displayName) {
}
private static class EtherealMindTeleporter implements ITeleporter {
private final double x;
private final double y;
private final double z;
private EtherealMindTeleporter(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
@Override
public PortalInfo getPortalInfo(Entity entity, ServerLevel destinationLevel, Function<ServerLevel, PortalInfo> defaultPortalInfo) {
return new PortalInfo(new Vec3(x, y, z), Vec3.ZERO, entity.getYRot(), entity.getXRot());
}
@Override
public Entity placeEntity(Entity entity, ServerLevel currentLevel, ServerLevel destinationLevel, float yaw, Function<Boolean, Entity> repositionEntity) {
Entity moved = repositionEntity.apply(false);
if (moved != null) {
moved.moveTo(x, y, z, moved.getYRot(), moved.getXRot());
moved.setDeltaMovement(Vec3.ZERO);
moved.setPortalCooldown();
}
return moved;
}
}
}