Init
This commit is contained in:
280
content/world/portals/portal-systems.en.md
Normal file
280
content/world/portals/portal-systems.en.md
Normal file
@@ -0,0 +1,280 @@
|
||||
---
|
||||
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);
|
||||
```
|
||||
Reference in New Issue
Block a user