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 0–8 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
- Create a new file in
/plugins/MCTennis/ball/, for examplemy_ball.yml. - Set
name: my_ballat the top of the file. - Copy the
render,physics, andinteractionssections fromtennis_ball.ymlas a starting point. - Adjust the properties to your liking.
- Set
ballName: my_ballin 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.