Usage
Quick Start Guide
1. Implement IAdvancedClimber
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);
ClimberHelper.initClimber(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
}
}
2. Override Required Methods
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
}
3. Client-Side Rendering
For proper model orientation, use the render helpers in your renderer:
@Override
public void render(S renderState, PoseStack poseStack, MultiBufferSource buffer, int color) {
ClientClimberHelper.postRenderClimber(renderState, poseStack, buffer);
super.render(renderState, poseStack, buffer, color);
ClientClimberHelper.postRenderClimber(renderState, poseStack, buffer);
}
@Override
public void extractRenderState(LivingEntity climber, S renderState, float partialeTicks) {
super.extractRenderState(climber, renderState, partialeTicks);
ClientClimberHelper.extractClimbingRenderState(climber, renderState, partialeTicks);
}
And your render state must implement IAdvancedClimberRenderState
4. Using with Mixins (for vanilla entities)
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);
ClimberHelper.initClimber(this);
}
@Override
public ClimberComponent getClimberComponent() {
return climberComponent;
}
// ... implement other IAdvancedClimber methods
}
See SpiderMixin for more details.