Skip to content

Customizing the Ball

MCTennis separates ball behavior from arena configuration. Every ball is defined in its own YAML file inside the /plugins/MCTennis/ball/ directory. Each file describes the visual appearance, the physics simulation, and exactly how players interact with the ball. You can create as many ball types as you like and switch between them per arena.


Setting the Ball for an Arena

Open your arena file at /plugins/MCTennis/arena/<arena_name>.yml and set the ballName property to the name value of the ball file you want to use:

# Unique identifier of the ball to use.
ballName: tennis_ball

Reload the arena after saving:

/mctennis reload

Ball File Structure

A ball file has three top-level sections: render, physics, and interactions.

name

The unique identifier for this ball. Must match the filename without the .yml extension and is used as the ballName value in the arena file.

name: tennis_ball

render — Visual Appearance

Controls how the ball looks in game.

Property Description
modelScale Global scale of the rendered ball entity. You can create giant balls by using values such as 2.0
visualItem.typeName The item type used as the ball skin, e.g. PLAYER_HEAD,397.
visualItem.skinBase64 Base64-encoded texture JSON pointing to a Minecraft skin URL. This is how you change the ball's texture.
rotationEnabled When true, the ball visually spins based on its velocity direction.
visualVerticalOffset Fine-tunes the vertical position of the rendered model relative to the physics entity.
renderDistance Distance in blocks within which the ball is rendered for players.
slimeVisible Legacy option. When true, the underlying Slime physics entity is rendered. Keep this false.
render:
  modelScale: 0.5
  visualItem:
    typeName: PLAYER_HEAD,397
    amount: '1'
    durability: '3'
    displayName: null
    skinBase64: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjZkYThhNzk3N2VjOTIxNGM1YjcwMWY5YWU3ZTE1NWI4ZWIyMWQxZDM3MTU5OGUxYjk4NzVjNGM4NWM2NWFlNiJ9fX0=
    lore: null
    nbt: null
    component: null
  rotationEnabled: true
  visualVerticalOffset: -0.4
  renderDistance: 60
  slimeVisible: false

physics — Simulation Properties

Controls how the ball behaves in the world.

Property Description
interactionBoundsSize Diameter of the hitbox used for click and interact detection. Enable F3+B in-game to visualize it.
collisionBoundsSize Diameter of the hitbox used for player body contact (touch/collide).
verticalOffset Vertical shift applied to the physics simulation boundary.
bounciness Coefficient of restitution. 0.0 = no bounce, 1.0 = perfectly elastic bounce.
mass Simulated weight of the ball. Higher mass requires more impulse to change velocity.
restVelocityThreshold Minimum speed before the ball is considered at rest and stops moving.
gravityModifier Downward acceleration applied per tick when airborne. Higher values make the ball fall faster.
airDrag Velocity reduction applied per tick while the ball is in the air.
rollingFriction Velocity reduction applied per tick while the ball rolls along the ground.
spinDrag Rate at which rotational spin decays per tick. 0.0 means spin never decays.
curveMultiplier How strongly active spin curves the flight path. Higher values create sharper arcs.
globalInteractionCooldownTicks Server-wide cooldown in ticks before another physics interaction can be processed.
perPlayerInteractionCooldownTicks Per-player cooldown in ticks to prevent rapid-fire interaction exploits.
fetchPlayerPositionsIntervalTicks How often (in ticks) player positions are refreshed for collision calculations.
physics:
  interactionBoundsSize: 1.5
  collisionBoundsSize: 1.0
  verticalOffset: -0.2
  bounciness: 0.9
  mass: 1.0
  restVelocityThreshold: 0.01
  gravityModifier: 0.0085
  airDrag: 0.0005
  rollingFriction: 0.1
  spinDrag: 0.05
  curveMultiplier: 0.05
  globalInteractionCooldownTicks: 20
  perPlayerInteractionCooldownTicks: 7
  fetchPlayerPositionsIntervalTicks: 2

interactions — Player Controls

Defines a list of rules that map player inputs to ball actions. Rules are evaluated in order; the first matching rule is applied.

Each rule has:

Property Description
triggerType The player input that activates this rule. See trigger types below.
conditionHotBarRangeStart First hotbar slot index (0–8) that allows this rule to fire.
conditionHotBarRangeEnd Last hotbar slot index (0–8) that allows this rule to fire. Use 08 to match all slots.
conditionGrabbedBySelf When true, this rule only fires if the triggering player is currently holding (grabbing) the ball.
executionType The action to perform: SHOOT to launch the ball, GRAB to attach it to the player.
horizontalImpulse Horizontal force applied to the ball in the player's facing direction.
verticalImpulse Vertical (upward) force applied to the ball.
spinImpulse Initial rotational spin around the Y-axis. Negative = left curve (slice), positive = right curve (hook).
effectName Name of a particle/sound effect to play on trigger. Leave empty for no effect.

Available Trigger Types

Category Types
Left Click LEFT_CLICK, JUMP_LEFT_CLICK, SNEAK_LEFT_CLICK, SPRINT_LEFT_CLICK
Right Click RIGHT_CLICK, JUMP_RIGHT_CLICK, SNEAK_RIGHT_CLICK, SPRINT_RIGHT_CLICK
Collision COLLIDE, JUMP_COLLIDE, SNEAK_COLLIDE, SPRINT_COLLIDE

Tennis Ball

The tennis ball is the default ball used in MCTennis arenas. It is found in /plugins/MCTennis/ball/tennis_ball.yml.


tennis_ball.yml — Tennis Ball

The tennis ball is tuned for precise, controlled play. It is smaller than a tennis ball (modelScale: 0.5), bounces very high (bounciness: 0.9), and floats with very low gravity (gravityModifier: 0.0085) and minimal air drag (airDrag: 0.0005). The active hotbar slot determines how hard the player hits the ball — left slots for a soft touch, center for a medium hit, and right slots for a full power shot.

How to Play

Hotbar Slots Action Effect
Slots 1–3 (left) LEFT_CLICK Soft tap (h: 0.2, v: 0.2)
Slots 4–6 (center) LEFT_CLICK Medium hit (h: 0.35, v: 0.2)
Slots 7–9 (right) LEFT_CLICK Power shot (h: 0.5, v: 0.2)

Hotbar Slots

The hotbar slot index is 0-based in configuration (0 = slot 1, 8 = slot 9).

Configuration

name: tennis_ball
render:
  modelScale: 0.5
  visualItem:
    typeName: PLAYER_HEAD,397
    amount: '1'
    durability: '3'
    displayName: null
    skinBase64: eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjZkYThhNzk3N2VjOTIxNGM1YjcwMWY5YWU3ZTE1NWI4ZWIyMWQxZDM3MTU5OGUxYjk4NzVjNGM4NWM2NWFlNiJ9fX0=
    lore: null
    nbt: null
    component: null
  rotationEnabled: true
  visualVerticalOffset: -0.4
  renderDistance: 60
  slimeVisible: false
physics:
  interactionBoundsSize: 1.5
  collisionBoundsSize: 1.0
  verticalOffset: -0.2
  bounciness: 0.9
  mass: 1.0
  restVelocityThreshold: 0.01
  gravityModifier: 0.0085
  airDrag: 0.0005
  rollingFriction: 0.1
  spinDrag: 0.05
  curveMultiplier: 0.05
  globalInteractionCooldownTicks: 20
  perPlayerInteractionCooldownTicks: 7
  fetchPlayerPositionsIntervalTicks: 2
interactions:
  # Soft tap — left slots (1–3)
  - triggerType: LEFT_CLICK
    conditionHotBarRangeStart: 0
    conditionHotBarRangeEnd: 2
    conditionGrabbedBySelf: false
    executionType: SHOOT
    horizontalImpulse: 0.2
    verticalImpulse: 0.2
    spinImpulse: 0.0
    effectName: ball_kick
  # Medium hit — center slots (4–6)
  - triggerType: LEFT_CLICK
    conditionHotBarRangeStart: 3
    conditionHotBarRangeEnd: 5
    conditionGrabbedBySelf: false
    executionType: SHOOT
    horizontalImpulse: 0.35
    verticalImpulse: 0.2
    spinImpulse: 0.0
    effectName: ball_kick
  # Power shot — right slots (7–9)
  - triggerType: LEFT_CLICK
    conditionHotBarRangeStart: 6
    conditionHotBarRangeEnd: 8
    conditionGrabbedBySelf: false
    executionType: SHOOT
    horizontalImpulse: 0.5
    verticalImpulse: 0.2
    spinImpulse: 0.0
    effectName: ball_kick

To use this ball in an arena:

ballName: tennis_ball

Creating a Custom Ball

  1. Create a new file in /plugins/MCTennis/ball/, for example my_ball.yml.
  2. Set name: my_ball at the top of the file.
  3. Copy the render, physics, and interactions sections from tennis_ball.yml as a starting point.
  4. Adjust the properties to your liking.
  5. Set ballName: my_ball in your arena file and reload the arena.

Changing the Ball Texture

Find a Minecraft head texture you like on a site like minecraft-heads.com. Copy the Value field (a Base64 string) and paste it into visualItem.skinBase64.

Tuning Physics

Start with gravityModifier, bounciness, and rollingFriction — these three values have the biggest impact on how the ball feels. Small changes (e.g. 0.01) can make a noticeable difference.