---
title: Portal Commands
type: docs
weight: 3
---

Commands for managing portals, fragments, and void events.

**Package:** `com.hypixel.hytale.builtin.portals.commands`

## Player Commands

### /leave

Leave the current portal world and return to the origin world.

```
/leave
```

**Behavior:**
- Only works when inside a portal world
- Uncurses all items in inventory before leaving
- Teleports player back to the portal device location

**Implementation:**
```java
public class LeaveCommand extends AbstractPlayerCommand {
    @Override
    protected void execute(CommandContext context, Store<EntityStore> store,
                          Ref<EntityStore> ref, PlayerRef playerRef, World world) {
        PortalWorld portalWorld = store.getResource(PortalWorld.getResourceType());
        if (!portalWorld.exists()) {
            playerRef.sendMessage(MESSAGE_NOT_IN_PORTAL);
            return;
        }

        // Remove curse from all items
        CursedItems.uncurseAll(player.getInventory().getCombinedEverything());

        // Exit the instance
        InstancesPlugin.exitInstance(ref, store);
    }
}
```

## Fragment Commands

### /fragment

Parent command for fragment management.

```
/fragment <subcommand>
```

| Subcommand | Description |
|------------|-------------|
| `timer` | Modify fragment time remaining |

### /fragment timer

Set the remaining time for the current portal fragment.

```
/fragment timer <seconds>
```

**Arguments:**

| Argument | Type | Description |
|----------|------|-------------|
| `seconds` | INTEGER | New remaining time in seconds |

**Example:**
```
/fragment timer 300    # Set 5 minutes remaining
/fragment timer 60     # Set 1 minute remaining
```

**Implementation:**
```java
public class TimerFragmentCommand extends PortalWorldCommandBase {
    private final RequiredArg<Integer> remainingSecondsArg;

    @Override
    protected void execute(CommandContext context, World world,
                          PortalWorld portalWorld, Store<EntityStore> store) {
        int before = (int) portalWorld.getRemainingSeconds(world);
        int desired = remainingSecondsArg.get(context);
        portalWorld.setRemainingSeconds(world, desired);
        // Reports: "Changed from {before} to {after}"
    }
}
```

## Void Event Commands

### /voidevent

Parent command for void event management.

```
/voidevent <subcommand>
```

| Subcommand | Description |
|------------|-------------|
| `start` | Start a void event |

### /voidevent start

Start a void invasion event in the current world.

```
/voidevent start [--override]
```

**Flags:**

| Flag | Description |
|------|-------------|
| `--override` | Force start even if not in a portal world |

**Behavior:**
- If already in a portal world with void event active: fails
- If not in portal world without `--override`: fails
- With `--override`: creates temporary portal world configuration
- Sets remaining time to 1 second to trigger void event

**Implementation:**
```java
public class StartVoidEventCommand extends AbstractWorldCommand {
    private final FlagArg overrideWorld;

    @Override
    protected void execute(CommandContext context, World world,
                          Store<EntityStore> store) {
        PortalWorld portalWorld = store.getResource(PortalWorld.getResourceType());

        // Check if already running
        if (portalWorld.exists() && portalWorld.isVoidEventActive()) {
            context.sendMessage("Void event already running");
            return;
        }

        // If not in portal world, require --override
        if (!portalWorld.exists()) {
            if (!overrideWorld.get(context)) {
                context.sendMessage("Not in portal world");
                return;
            }
            // Set up temporary portal world config
            portalWorld.init(portalType, timeLimit, removalCondition, config);
        }

        // Trigger void event by setting timer to 1 second
        portalWorld.setRemainingSeconds(world, 1.0);
    }
}
```

## Utility Commands

### /cursehelditem

Mark the currently held item as cursed (debug/testing command).

```
/cursehelditem
```

**Behavior:**
- Adds curse marker to item in main hand
- Cursed items are lost when player dies in portal world

## Command Base Classes

### PortalWorldCommandBase

Base class for commands that require a portal world:

```java
public abstract class PortalWorldCommandBase extends AbstractWorldCommand {
    @Override
    protected final void execute(CommandContext context, World world,
                                Store<EntityStore> store) {
        PortalWorld portalWorld = store.getResource(PortalWorld.getResourceType());
        if (!portalWorld.exists()) {
            context.sendMessage(MESSAGE_NOT_IN_PORTAL);
            return;
        }
        execute(context, world, portalWorld, store);
    }

    protected abstract void execute(CommandContext context, World world,
                                   PortalWorld portalWorld,
                                   Store<EntityStore> store);
}
```

## Command Registration

Commands are registered in PortalsPlugin setup:

```java
this.getCommandRegistry().registerCommand(new LeaveCommand());
this.getCommandRegistry().registerCommand(new CursedHeldItemCommand());
this.getCommandRegistry().registerCommand(new VoidEventCommands());
this.getCommandRegistry().registerCommand(new FragmentCommands());
```

## Messages

Portal commands use translation keys for messages:

| Key | Description |
|-----|-------------|
| `server.commands.leave.notInPortal` | Not in a portal world |
| `server.commands.leave.uncursedTemp` | Items were uncursed |
| `server.commands.portals.notInPortal` | Not in portal world |
| `server.commands.voidevent.start.alreadyRunning` | Void event active |
| `server.commands.voidevent.start.success` | Void event started |
| `server.commands.fragment.timer.success` | Timer changed |
