Projectile System
The Projectile System handles spawning and simulating projectiles like arrows, spells, and thrown items with configurable physics.
Core Components
Section titled “Core Components”ProjectileModule
Section titled “ProjectileModule”The main module class for the projectile system.
Location: com.hypixel.hytale.server.core.modules.projectile.ProjectileModule
Dependencies: EntityModule, CollisionModule
// Get the module instanceProjectileModule module = ProjectileModule.get();
// Spawn a projectileRef<EntityStore> projectileRef = module.spawnProjectile( creatorRef, commandBuffer, config, position, direction);Projectile Component
Section titled “Projectile Component”Marker component that identifies an entity as a projectile.
Location: com.hypixel.hytale.server.core.modules.projectile.component.Projectile
// Get component typeComponentType<EntityStore, Projectile> type = Projectile.getComponentType();
// Check if entity is a projectileboolean isProjectile = store.hasComponent(entityRef, type);
// Add projectile componentholder.ensureComponent(Projectile.getComponentType());PredictedProjectile Component
Section titled “PredictedProjectile Component”Component for client-predicted projectiles to sync with server.
Location: com.hypixel.hytale.server.core.modules.projectile.component.PredictedProjectile
ComponentType<EntityStore, PredictedProjectile> type = ProjectileModule.get().getPredictedProjectileComponentType();Projectile Configuration
Section titled “Projectile Configuration”Projectiles are configured through JSON assets.
ProjectileConfig
Section titled “ProjectileConfig”Location: com.hypixel.hytale.server.core.modules.projectile.config.ProjectileConfig
Asset Path: Projectile/{id}.json
{ "Physics": { "Type": "Standard", "Density": 700.0, "Gravity": 9.8, "Bounciness": 0.3, "BounceCount": 3, "TerminalVelocityAir": 50.0, "DensityAir": 1.2, "TerminalVelocityWater": 10.0, "DensityWater": 998.0 }, "Model": "hytale:projectile/arrow", "LaunchForce": 30.0, "SpawnOffset": { "x": 0.0, "y": 1.6, "z": 0.0 }, "SpawnRotationOffset": { "pitch": 0.0, "yaw": 0.0, "roll": 0.0 }, "Interactions": { "ProjectileImpact": "hytale:arrow_impact" }, "LaunchLocalSoundEventId": "hytale:bow_shoot", "LaunchWorldSoundEventId": "hytale:bow_shoot_world", "ProjectileSoundEventId": "hytale:arrow_flight"}Key Configuration Fields:
Physics- Physics configuration (see Physics Config below)Model- Model asset ID for the projectileLaunchForce- Initial velocity multiplierSpawnOffset- Offset from spawner positionSpawnRotationOffset- Rotation offset in degreesInteractions- Map of InteractionType to RootInteraction IDsLaunchLocalSoundEventId- Sound played to shooterLaunchWorldSoundEventId- 3D positioned sound for nearby playersProjectileSoundEventId- Looping sound attached to projectile
// Get projectile config from asset storeProjectileConfig config = ProjectileConfig.getAssetMap().getAsset("hytale:arrow");
// Access config propertiesPhysicsConfig physics = config.getPhysicsConfig();Model model = config.getModel();double launchForce = config.getLaunchForce();Map<InteractionType, String> interactions = config.getInteractions();Physics System
Section titled “Physics System”PhysicsConfig
Section titled “PhysicsConfig”Base interface for projectile physics configurations.
Location: com.hypixel.hytale.server.core.modules.projectile.config.PhysicsConfig
public interface PhysicsConfig { double getGravity();
void apply( Holder<EntityStore> holder, Ref<EntityStore> creatorRef, Vector3d velocity, ComponentAccessor<EntityStore> componentAccessor, boolean predicted );
com.hypixel.hytale.protocol.PhysicsConfig toPacket();}StandardPhysicsConfig
Section titled “StandardPhysicsConfig”Standard ballistic physics implementation with air resistance, gravity, and bouncing.
Location: com.hypixel.hytale.server.core.modules.projectile.config.StandardPhysicsConfig
Physics Properties:
Basic Physics:
Density(default: 700.0) - Projectile density in kg/m³Gravity(default: 0.0) - Gravity accelerationBounciness(0.0-1.0) - Energy retained on bounceBounceCount(default: -1) - Max bounces (-1 = unlimited)BounceLimit(default: 0.4) - Minimum velocity to bounceSticksVertically(default: false) - Stick to walls when vertical
Rotation:
ComputeYaw(default: true) - Auto-calculate yaw from velocityComputePitch(default: true) - Auto-calculate pitch from velocityRotationMode- How rotation is calculated:VelocityDamped- Smooth rotation following velocityVelocity- Instant rotation to velocity directionNone- No automatic rotation
RotationForce(default: 3.0) - Rotation smoothing factorSpeedRotationFactor(default: 2.0) - Speed influence on rotation
Air Physics:
TerminalVelocityAir(default: 1.0) - Max speed in airDensityAir(default: 1.2) - Air density for drag calculation
Water Physics:
TerminalVelocityWater(default: 1.0) - Max speed in waterDensityWater(default: 998.0) - Water densityHitWaterImpulseLoss(default: 0.2) - Energy lost entering waterSwimmingDampingFactor(default: 1.0) - Additional water drag
Rolling Physics:
AllowRolling(default: false) - Can projectile roll on groundRollingFrictionFactor(default: 0.99) - Friction when rollingRollingSpeed(default: 0.1) - Angular velocity when rolling
Other:
MoveOutOfSolidSpeed(default: 0.0) - Speed to escape stuck in blocks
StandardPhysicsProvider
Section titled “StandardPhysicsProvider”Component added to projectiles using StandardPhysicsConfig that stores physics state.
Location: com.hypixel.hytale.server.core.modules.projectile.config.StandardPhysicsProvider
ComponentType<EntityStore, StandardPhysicsProvider> type = ProjectileModule.get().getStandardPhysicsProviderComponentType();Ballistic Data
Section titled “Ballistic Data”BallisticData Interface
Section titled “BallisticData Interface”Provides trajectory calculation data for client prediction.
Location: com.hypixel.hytale.server.core.modules.projectile.config.BallisticData
public interface BallisticData { double getGravity();}BallisticDataProvider
Section titled “BallisticDataProvider”Component that provides BallisticData for an interaction.
Location: com.hypixel.hytale.server.core.modules.projectile.config.BallisticDataProvider
Spawning Projectiles
Section titled “Spawning Projectiles”Basic Spawning
Section titled “Basic Spawning”// Get projectile configProjectileConfig config = ProjectileConfig.getAssetMap() .getAsset("hytale:fireball");
// Define spawn position and directionVector3d position = new Vector3d(100, 64, 100);Vector3d direction = new Vector3d(1, 0, 0); // East direction
// Spawn projectileRef<EntityStore> projectileRef = ProjectileModule.get().spawnProjectile( shooterRef, // Creator entity reference commandBuffer, // Command buffer for adding entity config, // Projectile configuration position, // Spawn position direction // Launch direction (normalized));Predicted Spawning
Section titled “Predicted Spawning”For client-side prediction synchronization:
// Client generates UUID for predictionUUID predictionId = UUID.randomUUID();
// Server spawns with same UUIDRef<EntityStore> projectileRef = ProjectileModule.get().spawnProjectile( predictionId, // Prediction UUID (null for server-only) shooterRef, commandBuffer, config, position, direction);Projectile Spawning Details
Section titled “Projectile Spawning Details”When a projectile is spawned, the following happens:
-
Transform Setup:
- Position is offset by
SpawnOffsetfrom config - Direction is adjusted by
SpawnRotationOffset - Initial rotation is calculated from direction
- Position is offset by
-
Components Added:
TransformComponent- Position and rotationHeadRotation- Rotation trackingModelComponent- Visual modelBoundingBox- Collision bounds from modelNetworkId- Network sync IDProjectile- Projectile markerVelocity- Initial velocity vectorDespawnComponent- Auto-despawn after 5 minutesAudioComponent- Optional looping sound- Physics provider (e.g.,
StandardPhysicsProvider)
-
Interactions:
- Interactions from config are added to
Interactionscomponent ProjectileSpawninteraction runs if creator has InteractionManager
- Interactions from config are added to
-
Sounds:
LaunchWorldSoundEventplays at spawn positionLaunchLocalSoundEventplays for shooterProjectileSoundEventloops with projectile
Collision Handling
Section titled “Collision Handling”Impact Events
Section titled “Impact Events”When a projectile collides, the ProjectileImpact interaction runs:
{ "Interactions": { "ProjectileImpact": "hytale:arrow_stick" }}The impact interaction receives context about the collision:
- Hit entity (if any)
- Hit block position (if any)
- Impact point
- Impact normal
Bounce Behavior
Section titled “Bounce Behavior”Configure bouncing with physics properties:
{ "Physics": { "Type": "Standard", "Bounciness": 0.6, "BounceCount": 5, "BounceLimit": 0.5 }}- Projectile bounces when hitting surfaces
- Each bounce consumes one count (if limited)
- Velocity is multiplied by
Bounciness - Stops bouncing when speed <
BounceLimit
Sticking Behavior
Section titled “Sticking Behavior”Make projectiles stick to walls:
{ "Physics": { "Type": "Standard", "SticksVertically": true, "Bounciness": 0.0 }}Projectile Interactions
Section titled “Projectile Interactions”ProjectileInteraction
Section titled “ProjectileInteraction”Interaction type that spawns a projectile.
Location: com.hypixel.hytale.server.core.modules.projectile.interaction.ProjectileInteraction
{ "Type": "Projectile", "Config": "hytale:arrow"}Can be used in any interaction chain to launch a projectile.
Systems
Section titled “Systems”StandardPhysicsTickSystem
Section titled “StandardPhysicsTickSystem”Updates projectile physics each tick for entities with StandardPhysicsProvider.
Location: com.hypixel.hytale.server.core.modules.projectile.system.StandardPhysicsTickSystem
Handles:
- Gravity application
- Velocity updates
- Drag/air resistance
- Water physics
- Collision detection
- Rotation updates
- Bouncing
- Rolling
PredictedProjectileSystems
Section titled “PredictedProjectileSystems”Systems for handling client-predicted projectiles.
Location: com.hypixel.hytale.server.core.modules.projectile.system.PredictedProjectileSystems
EntityTrackerUpdate: Updates entity tracker for predicted projectiles.
Example: Arrow Projectile
Section titled “Example: Arrow Projectile”{ "Physics": { "Type": "Standard", "Density": 700.0, "Gravity": 20.0, "Bounciness": 0.0, "SticksVertically": true, "TerminalVelocityAir": 80.0, "ComputeYaw": true, "ComputePitch": true, "RotationMode": "VelocityDamped" }, "Model": "hytale:projectile/arrow", "LaunchForce": 40.0, "SpawnOffset": {"x": 0.0, "y": 1.5, "z": 0.5}, "Interactions": { "ProjectileImpact": "hytale:arrow_impact" }, "LaunchWorldSoundEventId": "hytale:bow_shoot"}Example: Bouncing Grenade
Section titled “Example: Bouncing Grenade”{ "Physics": { "Type": "Standard", "Density": 1200.0, "Gravity": 20.0, "Bounciness": 0.7, "BounceCount": 10, "BounceLimit": 1.0, "AllowRolling": true, "RollingFrictionFactor": 0.95 }, "Model": "hytale:projectile/grenade", "LaunchForce": 25.0, "Interactions": { "ProjectileImpact": "hytale:grenade_bounce" }}Example: Magic Missile
Section titled “Example: Magic Missile”{ "Physics": { "Type": "Standard", "Density": 100.0, "Gravity": 0.0, "TerminalVelocityAir": 60.0, "DensityAir": 0.5, "ComputeYaw": true, "ComputePitch": true, "RotationMode": "Velocity" }, "Model": "hytale:projectile/magic_missile", "LaunchForce": 50.0, "SpawnOffset": {"x": 0.0, "y": 1.6, "z": 0.0}, "Interactions": { "ProjectileImpact": "hytale:magic_explosion" }, "ProjectileSoundEventId": "hytale:magic_whoosh"}Example: Spawning from Code
Section titled “Example: Spawning from Code”public class FireballLauncher { public void launchFireball( Ref<EntityStore> shooterRef, CommandBuffer<EntityStore> commandBuffer ) { // Get config ProjectileConfig config = ProjectileConfig.getAssetMap() .getAsset("mymod:fireball"); if (config == null) return;
// Get shooter transform TransformComponent transform = commandBuffer.getComponent( shooterRef, TransformComponent.getComponentType() ); if (transform == null) return;
// Calculate launch position and direction Vector3d position = transform.getPosition().clone(); position.y += 1.6; // Eye height
Vector3d direction = new Vector3d( transform.getRotation().getYaw(), transform.getRotation().getPitch() );
// Spawn projectile Ref<EntityStore> projectile = ProjectileModule.get().spawnProjectile( shooterRef, commandBuffer, config, position, direction );
// Projectile now exists and will be simulated by StandardPhysicsTickSystem }}Collision and Impact Consumers
Section titled “Collision and Impact Consumers”ImpactConsumer
Section titled “ImpactConsumer”Handler for when projectiles impact surfaces.
Location: com.hypixel.hytale.server.core.modules.projectile.config.ImpactConsumer
BounceConsumer
Section titled “BounceConsumer”Handler for when projectiles bounce off surfaces.
Location: com.hypixel.hytale.server.core.modules.projectile.config.BounceConsumer
These are internal interfaces used by physics systems for handling collision events.