A powerful API for Minecraft mods that enables advanced wall climbing mechanics for entities. This API allows mod developers to easily add spider-like wall climbing behavior to any mob.
- Full 3D Wall Climbing: Entities can walk on walls, ceilings, and any surface
- Smooth Orientation Transitions: Natural-looking transitions when moving between surfaces
- Custom Pathfinding: Advanced pathfinding that understands 3D movement
- Render Helpers: Easy-to-use rendering utilities for proper model orientation
- Cross-Platform: Works on both Fabric and NeoForge
Add the GitHub Packages repository to your build.gradle or settings.gradle:
repositories {
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/Nyfaria/AdvancedWallClimberAPI")
credentials {
// Use your GitHub username and a Personal Access Token with read:packages scope
username = project.findProperty("gpr.user") ?: System.getenv("GITHUB_ACTOR")
password = project.findProperty("gpr.key") ?: System.getenv("GITHUB_TOKEN")
}
}
}GitHub Packages requires authentication even for public packages. Create a Personal Access Token (PAT) with read:packages scope:
- Go to GitHub → Settings → Developer settings → Personal access tokens → Tokens (classic)
- Generate a new token with
read:packagesscope - Add to your
~/.gradle/gradle.properties:
gpr.user=YOUR_GITHUB_USERNAME
gpr.key=YOUR_PERSONAL_ACCESS_TOKENdependencies {
compileOnly "com.nyfaria.awcapi:awcapi-common:1.0.0+1.21.1"
}dependencies {
modImplementation "com.nyfaria.awcapi:awcapi-fabric:1.0.0+1.21.1"
}dependencies {
implementation "com.nyfaria.awcapi:awcapi-neoforge:1.0.0+1.21.1"
}Make your entity implement IAdvancedClimber:
public class MyClimbingMob extends PathfinderMob implements IAdvancedClimber {
private final ClimberComponent climberComponent;
public MyClimbingMob(EntityType<? extends MyClimbingMob> type, Level level) {
super(type, level);
this.climberComponent = new ClimberComponent(this);
// Initialize climbing controllers
this.moveControl = new ClimberMoveController<>(this);
this.lookControl = new ClimberLookController<>(this);
this.jumpControl = new ClimberJumpController<>(this);
}
@Override
public ClimberComponent getClimberComponent() {
return climberComponent;
}
@Override
public Mob asMob() {
return this;
}
@Override
public float getMovementSpeed() {
return (float) getAttributeValue(Attributes.MOVEMENT_SPEED);
}
@Override
public float getBlockSlipperiness(BlockPos pos) {
return level().getBlockState(pos).getBlock().getFriction() * 0.91f;
}
@Override
public boolean canClimbOnBlock(BlockState state, BlockPos pos) {
return true; // Or add custom logic for non-climbable blocks
}
}Override these methods in your entity class:
@Override
protected PathNavigation createNavigation(Level level) {
ClimberPathNavigator<MyClimbingMob> navigator = new ClimberPathNavigator<>(this, level, false);
navigator.setCanFloat(true);
return navigator;
}
@Override
public void aiStep() {
ClimberHelper.livingTickClimber(this);
super.aiStep();
}
@Override
public void tick() {
super.tick();
ClimberHelper.tickClimber(this);
}
@Override
public void move(MoverType type, Vec3 movement) {
ClimberHelper.handleMove(this, type, movement, true);
super.move(type, movement);
ClimberHelper.handleMove(this, type, movement, false);
}
@Override
public void travel(Vec3 travelVector) {
if (!ClimberHelper.handleTravel(this, travelVector)) {
super.travel(travelVector);
}
ClimberHelper.postTravel(this, travelVector);
}
@Override
public void jumpFromGround() {
if (!ClimberHelper.handleJump(this)) {
super.jumpFromGround();
}
}
@Override
public BlockPos getOnPos() {
return ClimberHelper.getAdjustedOnPosition(this, super.getOnPos());
}
@Override
public boolean onClimbable() {
return false; // Disable vanilla climbing
}For proper model orientation, use the render helpers:
public static void onPreRenderLiving(LivingEntity entity, float partialTicks, PoseStack poseStack) {
if (entity instanceof IAdvancedClimber climber) {
Orientation orientation = climber.getOrientation();
Orientation renderOrientation = climber.getClimberComponent().getRenderOrientation();
if (renderOrientation != null) {
poseStack.mulPose(renderOrientation.getRotation());
// Apply attachment offset
ClimberComponent component = climber.getClimberComponent();
poseStack.translate(
component.getAttachmentOffset(Direction.Axis.X, partialTicks),
component.getAttachmentOffset(Direction.Axis.Y, partialTicks),
component.getAttachmentOffset(Direction.Axis.Z, partialTicks)
);
}
}
}If you want to add climbing to vanilla entities like Spider:
@Mixin(Spider.class)
public abstract class SpiderMixin extends Monster implements IAdvancedClimber {
@Unique
private ClimberComponent climberComponent;
protected SpiderMixin(EntityType<? extends Monster> type, Level level) {
super(type, level);
}
@Inject(method = "<init>", at = @At("RETURN"))
private void onInit(EntityType<?> type, Level level, CallbackInfo ci) {
this.climberComponent = new ClimberComponent(this);
this.moveControl = new ClimberMoveController<>(this);
this.lookControl = new ClimberLookController<>(this);
this.jumpControl = new ClimberJumpController<>(this);
}
@Override
public ClimberComponent getClimberComponent() {
return climberComponent;
}
// ... implement other IAdvancedClimber methods
}The main interface your entity must implement:
| Method | Description |
|---|---|
getClimberComponent() |
Returns the ClimberComponent instance |
asMob() |
Returns the entity as a Mob |
getMovementSpeed() |
Returns the entity's movement speed |
getBlockSlipperiness(BlockPos) |
Returns slipperiness for a block position |
canClimbOnBlock(BlockState, BlockPos) |
Whether the entity can climb on a specific block |
getOrientation() |
Gets the current orientation |
getVerticalOffset(float) |
Gets the vertical offset for rendering |
| Method | Description |
|---|---|
tickClimber(IAdvancedClimber) |
Call in entity's tick() |
livingTickClimber(IAdvancedClimber) |
Call in entity's aiStep() |
handleTravel(IAdvancedClimber, Vec3) |
Call in travel(), returns true if handled |
postTravel(IAdvancedClimber, Vec3) |
Call after travel() |
handleMove(IAdvancedClimber, MoverType, Vec3, boolean) |
Call before/after move() |
handleJump(IAdvancedClimber) |
Call in jumpFromGround(), returns true if handled |
getAdjustedOnPosition(IAdvancedClimber, BlockPos) |
Get adjusted ground position |
ClimberMoveController<T>- Handles 3D movementClimberLookController<T>- Handles looking in local spaceClimberJumpController<T>- Handles jumping from any surfaceClimberPathNavigator<T>- Pathfinding that understands wall climbing
git clone https://github.com/Nyfaria/AdvancedWallClimberAPI.git
cd AdvancedWallClimberAPI
./gradlew buildThe project automatically publishes to GitHub Packages when:
- A new release is created on GitHub
- The publish workflow is manually triggered
To publish manually:
./gradlew publishAll Rights Reserved - Contact Nyfaria for licensing inquiries.
- Nyfaria - Original author and maintainer
- Based on concepts from Nyf's Spiders mod
For issues and feature requests, please use the GitHub Issues page.