diff --git a/src/main/java/io/lampnet/travelerssuitcase/block/SuitcaseBlock.java b/src/main/java/io/lampnet/travelerssuitcase/block/SuitcaseBlock.java index b66ff49..1c55792 100644 --- a/src/main/java/io/lampnet/travelerssuitcase/block/SuitcaseBlock.java +++ b/src/main/java/io/lampnet/travelerssuitcase/block/SuitcaseBlock.java @@ -46,12 +46,9 @@ import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; -import net.minecraft.world.Containers; import net.minecraft.world.item.DyeColor; import net.minecraft.network.protocol.game.ClientboundStopSoundPacket; -import net.minecraft.sounds.SoundSource; -import net.minecraft.sounds.SoundEvents; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -66,6 +63,11 @@ public class SuitcaseBlock extends BaseEntityBlock { private final static VoxelShape SHAPE_S = Block.box(0, 0, 2, 16, 4, 14); private final static VoxelShape SHAPE_E = Block.box(2, 0, 0, 14, 4, 16); private final static VoxelShape SHAPE_W = Block.box(2, 0, 0, 14, 4, 16); + + private static final int PORTAL_SEARCH_RADIUS = 50; + private static final int PORTAL_SEARCH_Y_MIN = -20; + private static final int PORTAL_SEARCH_Y_MAX = 40; + private static final double PORTAL_TELEPORT_Y_OFFSET = -3.0; public SuitcaseBlock(BlockBehaviour.Properties properties) { super(properties); @@ -119,42 +121,6 @@ public class SuitcaseBlock extends BaseEntityBlock { @Override public void onRemove(BlockState state, @NotNull Level world, @NotNull BlockPos pos, BlockState newState, boolean isMoving) { if (!state.is(newState.getBlock())) { - BlockEntity blockEntity = world.getBlockEntity(pos); - if (blockEntity instanceof SuitcaseBlockEntity suitcase) { - ItemStack itemStack = new ItemStack(this); - String boundKeystone = suitcase.getBoundKeystoneName(); - if (boundKeystone != null) { - CompoundTag beNbt = new CompoundTag(); - suitcase.saveAdditional(beNbt); - - if (!beNbt.isEmpty()) { - BlockItem.setBlockEntityData(itemStack, ModBlockEntities.SUITCASE_BLOCK_ENTITY.get(), beNbt); - } - - CompoundTag display = itemStack.getOrCreateTagElement("display"); - ListTag lore = new ListTag(); - String displayName = boundKeystone.replace("_", " "); - Component boundText; - if (suitcase.isLocked()) { - boundText = Component.literal("Bound to: §k" + displayName) - .withStyle(ChatFormatting.GRAY); - } else { - boundText = Component.literal("Bound to: " + displayName) - .withStyle(ChatFormatting.GRAY); - } - Component lockText = Component.literal(suitcase.isLocked() ? "§cLocked" : "§aUnlocked") - .withStyle(ChatFormatting.GRAY); - if (!suitcase.getEnteredPlayers().isEmpty()) { - Component warningText = Component.literal("§c⚠ Contains " + suitcase.getEnteredPlayers().size() + " Traveler's!") - .withStyle(ChatFormatting.RED); - lore.add(StringTag.valueOf(Component.Serializer.toJson(warningText))); - } - lore.add(StringTag.valueOf(Component.Serializer.toJson(boundText))); - lore.add(StringTag.valueOf(Component.Serializer.toJson(lockText))); - display.put("Lore", lore); - } - Containers.dropItemStack(world, pos.getX(), pos.getY(), pos.getZ(), itemStack); - } super.onRemove(state, world, pos, newState, isMoving); } } @@ -263,8 +229,16 @@ public class SuitcaseBlock extends BaseEntityBlock { player.fallDistance = 0f; PlayerEntryData ped = PlayerEntryData.get(targetWorld); + + // Find the portal block position in the pocket dimension + BlockPos portalPos = findPortalBlockInDimension(targetWorld); + if (portalPos != null) { + // Update the entry position to match the portal block location + Vec3 portalLocation = new Vec3(portalPos.getX() + 0.5, portalPos.getY() + PORTAL_TELEPORT_Y_OFFSET, portalPos.getZ() + 0.5); + ped.setEntry(portalLocation, 0f, 0f); + } + Vec3 dest = ped.getEntryPos(); - float yaw = ped.getEntryYaw(); float pitch = player.getXRot(); @@ -283,6 +257,24 @@ public class SuitcaseBlock extends BaseEntityBlock { } } + private BlockPos findPortalBlockInDimension(ServerLevel targetWorld) { + // Search around the structure placement area (0, 64, 0) for portal blocks + BlockPos structureCenter = new BlockPos(0, 64, 0); + + for (int x = -PORTAL_SEARCH_RADIUS; x <= PORTAL_SEARCH_RADIUS; x++) { + for (int y = PORTAL_SEARCH_Y_MIN; y <= PORTAL_SEARCH_Y_MAX; y++) { + for (int z = -PORTAL_SEARCH_RADIUS; z <= PORTAL_SEARCH_RADIUS; z++) { + BlockPos checkPos = structureCenter.offset(x, y, z); + if (targetWorld.getBlockState(checkPos).getBlock() instanceof PocketPortalBlock) { + return checkPos; + } + } + } + } + + return null; + } + @Override public @NotNull VoxelShape getShape(BlockState state, @NotNull BlockGetter world, @NotNull BlockPos pos, @NotNull CollisionContext context) { return switch (state.getValue(FACING)) { diff --git a/src/main/java/io/lampnet/travelerssuitcase/block/entity/SuitcaseBlockEntity.java b/src/main/java/io/lampnet/travelerssuitcase/block/entity/SuitcaseBlockEntity.java index 3168bab..d47c147 100644 --- a/src/main/java/io/lampnet/travelerssuitcase/block/entity/SuitcaseBlockEntity.java +++ b/src/main/java/io/lampnet/travelerssuitcase/block/entity/SuitcaseBlockEntity.java @@ -111,9 +111,9 @@ public class SuitcaseBlockEntity extends BlockEntity { if (data.uuid.equals(playerUuid)) { EnteredPlayerData exitData = new EnteredPlayerData( data.uuid, - this.worldPosition.getX() + 0.5, this.worldPosition.getY() + 1.0, this.worldPosition.getZ() + 0.5, + data.x, data.y, data.z, data.pitch, data.yaw, - this.worldPosition + data.suitcasePos != null ? data.suitcasePos : this.worldPosition ); enteredPlayers.remove(i); setChangedAndNotify(); diff --git a/src/main/java/io/lampnet/travelerssuitcase/mixin/ServerChunkManagerMixin.java b/src/main/java/io/lampnet/travelerssuitcase/mixin/ServerChunkManagerMixin.java index 32c07dc..94d40eb 100644 --- a/src/main/java/io/lampnet/travelerssuitcase/mixin/ServerChunkManagerMixin.java +++ b/src/main/java/io/lampnet/travelerssuitcase/mixin/ServerChunkManagerMixin.java @@ -21,9 +21,14 @@ public class ServerChunkManagerMixin { private void onRunDistanceManagerUpdates(CallbackInfoReturnable cir) { // Only apply special chunk processing logic to RuntimeWorld instances (fantasy dimensions) if (this.level instanceof RuntimeWorld) { - if (!((FantasyWorldAccess) this.level).fantasy$shouldTick()) { - cir.setReturnValue(false); + FantasyWorldAccess worldAccess = (FantasyWorldAccess) this.level; + // Always allow distance manager updates if chunks are loaded (prevents breaking entity initialization) + // Only block when world is truly empty AND configured not to tick when empty + if (this.level.getChunkSource().getLoadedChunksCount() > 0 || worldAccess.fantasy$shouldTick()) { + // Allow distance manager to run - this is critical for entity systems + return; } + cir.setReturnValue(false); } // Regular worlds (overworld, nether, end) process chunks normally without interference }