Files
Documentation/content/world/portals/portal-systems.en.md
2026-01-20 20:33:59 +01:00

7.8 KiB

title, type, weight
title type weight
Portal Systems docs 2

Portal systems handle the runtime logic for portal tracking, void events, and instance management.

Package: com.hypixel.hytale.builtin.portals.systems

Portal Tracker Systems

TrackerSystem

Tracks players entering and leaving portal worlds:

public class TrackerSystem extends RefSystem<EntityStore> {
    // Called when player enters portal world
    @Override
    public void onEntityAdded(Ref<EntityStore> ref, AddReason reason,
                              Store<EntityStore> store,
                              CommandBuffer<EntityStore> commandBuffer) {
        PortalWorld portalWorld = store.getResource(PortalWorld.getResourceType());
        if (!portalWorld.exists()) return;

        // Send portal UI to player
        PlayerRef playerRef = commandBuffer.getComponent(ref, PlayerRef.getComponentType());
        UpdatePortal packet = portalWorld.createFullPacket(world);
        playerRef.getPacketHandler().write(packet);
    }

    // Called when player leaves portal world
    @Override
    public void onEntityRemove(Ref<EntityStore> ref, RemoveReason reason,
                               Store<EntityStore> store,
                               CommandBuffer<EntityStore> commandBuffer) {
        // Clear UI state
        playerRef.getPacketHandler().write(new UpdatePortal(null, null));
        portalWorld.getSeesUi().remove(playerRef.getUuid());
    }

    @Override
    public Query<EntityStore> getQuery() {
        return Query.and(Player.getComponentType(), PlayerRef.getComponentType());
    }
}

UiTickingSystem

Updates portal UI every second:

public class UiTickingSystem extends DelayedEntitySystem<EntityStore> {
    public UiTickingSystem() {
        super(1.0f);  // Tick every 1 second
    }

    @Override
    public void tick(float dt, int index, ArchetypeChunk<EntityStore> archetypeChunk,
                     Store<EntityStore> store, CommandBuffer<EntityStore> commandBuffer) {
        PortalWorld portalWorld = store.getResource(PortalWorld.getResourceType());
        if (!portalWorld.exists()) return;

        // Send updated time to player
        UpdatePortal packet = portalWorld.createUpdatePacket(world);
        playerRef.getPacketHandler().write(packet);
    }
}

Portal Destination Systems

PortalInvalidDestinationSystem

Handles portals with invalid destinations:

public class PortalInvalidDestinationSystem {
    // Turns off portals when destination world closes
    public static void turnOffPortalsInWorld(World world, World closedWorld) {
        // Find all portals pointing to closedWorld
        // Set their destination to null
        // Update block state to "off"
    }
}

CloseWorldWhenBreakingDeviceSystems

Handles portal device destruction:

// When portal device component is removed
public class ComponentRemoved extends System<ChunkStore> {
    // Close the destination world
}

// When portal block entity is removed
public class EntityRemoved extends System<ChunkStore> {
    // Close the destination world
}

Void Event Systems

VoidEventRefSystem

Manages void event entity references:

public class VoidEventRefSystem extends System<EntityStore> {
    // Tracks void event entity lifecycle
    // Updates PortalWorld.voidEventRef
}

VoidEventStagesSystem

Progresses through void event stages:

public class VoidEventStagesSystem extends System<EntityStore> {
    // Checks elapsed time
    // Activates next stage when time threshold reached
    // Updates VoidEvent.activeStage
}

VoidInvasionPortalsSpawnSystem

Spawns invasion portals during void events:

public class VoidInvasionPortalsSpawnSystem extends System<EntityStore> {
    // Creates void spawner entities
    // Uses spatial hash grid to maintain minimum distance
}

VoidSpawnerSystems.Instantiate

Instantiates void spawner entities:

public class Instantiate extends System<EntityStore> {
    // Creates spawner entity from config
    // Adds to VoidEvent's spatial grid
}

StartVoidEventInFragmentSystem

Initiates void events in portal fragments:

public class StartVoidEventInFragmentSystem extends System<EntityStore> {
    // Checks if void invasion should start
    // Creates VoidEvent entity
    // Sets up first stage
}

Curse Systems

DiedInPortalSystem

Tracks player deaths in portal worlds:

public class DiedInPortalSystem extends System<EntityStore> {
    // On player death in portal world:
    // - Add player UUID to diedInWorld set
    // - Prevents re-entry
}

CurseItemDropsSystem

Marks dropped items as cursed:

public class CurseItemDropsSystem extends System<EntityStore> {
    // Items dropped in portal world become cursed
    // Cursed items are lost on death
}

DeleteCursedItemsOnSpawnSystem

Removes cursed items when player spawns:

public class DeleteCursedItemsOnSpawnSystem extends System<EntityStore> {
    // When player respawns after dying in portal
    // Remove all cursed items from inventory
}

Portal Interactions

EnterPortalInteraction

Handles entering a portal:

public class EnterPortalInteraction extends SimpleBlockInteraction {
    // Minimum time before allowing portal use
    public static final Duration MINIMUM_TIME_IN_WORLD = Duration.ofMillis(3000L);

    @Override
    protected void interactWithBlock(...) {
        // Check portal device exists
        // Verify destination world is alive
        // Check player hasn't died in target world
        // Teleport player to instance
    }
}

Target world states:

  • OKAY - Can enter
  • WORLD_DEAD - Destination closed
  • DIED_IN_WORLD - Player died there
  • NO_SPAWN_AVAILABLE - No spawn point

ReturnPortalInteraction

Handles returning from a portal world:

public class ReturnPortalInteraction extends SimpleBlockInteraction {
    // Minimum time before allowing return
    public static final Duration MINIMUM_TIME_IN_WORLD = Duration.ofSeconds(15L);

    // Warning shown before timer expires
    public static final Duration WARNING_TIME = Duration.ofSeconds(4L);

    @Override
    protected void interactWithBlock(...) {
        // Check minimum time elapsed
        // Uncurse all items
        // Exit instance
    }
}

System Registration

All systems are registered in PortalsPlugin setup:

// ChunkStore systems
this.getChunkStoreRegistry().registerSystem(new PortalInvalidDestinationSystem());
this.getChunkStoreRegistry().registerSystem(new CloseWorldWhenBreakingDeviceSystems.ComponentRemoved());
this.getChunkStoreRegistry().registerSystem(new CloseWorldWhenBreakingDeviceSystems.EntityRemoved());

// EntityStore systems
this.getEntityStoreRegistry().registerSystem(new PortalTrackerSystems.TrackerSystem());
this.getEntityStoreRegistry().registerSystem(new PortalTrackerSystems.UiTickingSystem());
this.getEntityStoreRegistry().registerSystem(new DiedInPortalSystem());
this.getEntityStoreRegistry().registerSystem(new CurseItemDropsSystem());
this.getEntityStoreRegistry().registerSystem(new DeleteCursedItemsOnSpawnSystem());
this.getEntityStoreRegistry().registerSystem(new VoidEventRefSystem());
this.getEntityStoreRegistry().registerSystem(new VoidInvasionPortalsSpawnSystem());
this.getEntityStoreRegistry().registerSystem(new VoidSpawnerSystems.Instantiate());
this.getEntityStoreRegistry().registerSystem(new StartVoidEventInFragmentSystem());
this.getEntityStoreRegistry().registerSystem(new VoidEventStagesSystem());

Interaction Registration

Portal interactions are registered as codec types:

this.getCodecRegistry(Interaction.CODEC)
    .register("Portal", EnterPortalInteraction.class, EnterPortalInteraction.CODEC)
    .register("PortalReturn", ReturnPortalInteraction.class, ReturnPortalInteraction.CODEC);