281 lines
7.8 KiB
Markdown
281 lines
7.8 KiB
Markdown
---
|
|
title: Portal Systems
|
|
type: docs
|
|
weight: 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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
// 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:
|
|
|
|
```java
|
|
public class VoidEventRefSystem extends System<EntityStore> {
|
|
// Tracks void event entity lifecycle
|
|
// Updates PortalWorld.voidEventRef
|
|
}
|
|
```
|
|
|
|
### VoidEventStagesSystem
|
|
|
|
Progresses through void event stages:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
public class VoidInvasionPortalsSpawnSystem extends System<EntityStore> {
|
|
// Creates void spawner entities
|
|
// Uses spatial hash grid to maintain minimum distance
|
|
}
|
|
```
|
|
|
|
### VoidSpawnerSystems.Instantiate
|
|
|
|
Instantiates void spawner entities:
|
|
|
|
```java
|
|
public class Instantiate extends System<EntityStore> {
|
|
// Creates spawner entity from config
|
|
// Adds to VoidEvent's spatial grid
|
|
}
|
|
```
|
|
|
|
### StartVoidEventInFragmentSystem
|
|
|
|
Initiates void events in portal fragments:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
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:
|
|
|
|
```java
|
|
// 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:
|
|
|
|
```java
|
|
this.getCodecRegistry(Interaction.CODEC)
|
|
.register("Portal", EnterPortalInteraction.class, EnterPortalInteraction.CODEC)
|
|
.register("PortalReturn", ReturnPortalInteraction.class, ReturnPortalInteraction.CODEC);
|
|
```
|