Jump to content

Recommended Posts

Posted (edited)

Hello, I'm doing block similar to grindstone from Horse Power and I have a question. How can I change horse navigation to move like this?

28RFwHJ.png

ZHIhDVq.png

Now i'm doing it like this: 

horse.goalSelector.addGoal(0, new HorseWalkGoal(horse)); // at BlockEntity#tick, don't know if it's correct

Goal class:

public class HorseWalkGoal extends Goal {
  public final Horse horse;
  public Path path;

  public HorseWalkGoal(Horse horse) {
    this.horse = horse;
    //points from picture
    this.path = horse.getNavigation().createPath(Set.of(
      horse.getLeashHolder().blockPosition().offset(3, -1, 3), 	//point 1
      horse.getLeashHolder().blockPosition().offset(3, -1, -3), //point 2
      horse.getLeashHolder().blockPosition().offset(-3, -1, -3), //point 3
      horse.getLeashHolder().blockPosition().offset(-3, -1, 3)), 0); //point 4
    this.setFlags(EnumSet.of(Flag.MOVE));
  }

  @Override
  public boolean canUse() {
    return horse.isLeashed() && this.isValid();
  }

  public boolean isValid() {
    Optional<HorseCrankBlockEntity> blockentity = horse.level.getBlockEntity(horse.getLeashHolder().blockPosition(), ModBlockEntities.HORSECRANK.get());
    return blockentity.isPresent() && blockentity.get().valid;
  }

  @Override
  public void stop() {
    horse.getNavigation().stop();
  }

  @Override
  public void tick() {
    if (this.horse.getNavigation().isDone()) {
      this.horse.getNavigation().moveTo(this.path, 1.5);
    }
  }

  @Override
  public boolean requiresUpdateEveryTick() {
    return true;
  }

  @Override
  public void start() {
    this.horse.getNavigation().moveTo(this.path, 1.5);
  }
}

I guess I use NavigationPath#createPath wrong. But how i must to?

 

Edited by Kitoglavch
Posted (edited)
2 hours ago, Kitoglavch said:
// at BlockEntity#tick, don't know if it's correct

Do not add this goal each tick, once is enough

2 hours ago, Kitoglavch said:

Hello, I'm doing block similar to grindstone from Horse Power and I have a question. How can I change horse navigation to move like this?

Calculate the positions (1, 2, 3, 4, ...) then call PathNavigation#moveTo for the first position,
wait until the horse has reached the position then continue with the same logic for the next position and repeat this step until you at the last position

Edited by Luis_ST
Posted
18 minutes ago, Kitoglavch said:
    if (this.horse.getNavigation().isDone()) {
      this.horse.getNavigation().moveTo(this.path, 1.5);
    }

ignore my first post, i think you forgot the ! there?

Posted (edited)
11 minutes ago, Luis_ST said:

you forgot the ! there?

It should be here? I thought this method returns true if navigation has no active path. 

I think it hepled. But anyway, there is a problem with Path. Horse still act strange and just move to the nearest point

https://i.imgur.com/CKTfkWp.mp4

Edited by Kitoglavch
Posted (edited)
4 minutes ago, Kitoglavch said:

I think it hepled. But anyway, there is a problem with Path. Horse still act strange and just move to the nearest point

are you sure the positions of the Path are correct
and you could use debugger to check how the goal is handled/called

Edit: try to place the Horse at a different spot

Edited by Luis_ST
Posted
Just now, Luis_ST said:

are you sure the positions of the Path are correct

i don't know if Path#createPath works as I suppose, but console logs me [BlockPos{x=58, y=-60, z=-457}, BlockPos{x=58, y=-60, z=-451}, BlockPos{x=64, y=-60, z=-457}, BlockPos{x=64, y=-60, z=-451}] from Set<BlockPos>, and it is what should be.

 

3 minutes ago, Luis_ST said:

and you could use debugger to check how the goal is handled/called

i put System.out.println in Goal#start, Goal#stop. It should work properly and add new goal once at the same time 

Posted
47 minutes ago, Kitoglavch said:
horse.goalSelector.addGoal(0, new HorseWalkGoal(horse)); // at BlockEntity#tick, don't know if it's correct

Maybe this is your issue, try to add only one Goal

Posted

what you mean? this action is called every tick due to "true" in if statement. i didn't understand what should i write in else statement

  if (!this.horse.getNavigation().isDone()) { // true
      this.horse.getNavigation().moveTo(this.path, 1.5);
    }
Posted

when the PathNavigation#isDone returns false in the corner you can try something like this:

if (!this.horse.getNavigation().isDone()) {
	this.horse.getNavigation().moveTo(this.path, 1.5);
} else {
	this.path = // create a new path
}

you also could try this, if the Path does not work correctly:

1 hour ago, Luis_ST said:

Calculate the positions (1, 2, 3, 4, ...) then call PathNavigation#moveTo for the first position,
wait until the horse has reached the position then continue with the same logic for the next position and repeat this step until you at the last position

Posted (edited)
13 hours ago, Luis_ST said:

you also could try this, if the Path does not work correctly:

sadly it didn't work. horse did the same

13 hours ago, Luis_ST said:

Calculate the positions (1, 2, 3, 4, ...) then call PathNavigation#moveTo for the first position,
wait until the horse has reached the position then continue with the same logic for the next position and repeat this step until you at the last position

I try this way now, but horse still acts not as supposed to (but much better than it was)

public class HorseWalkGoal extends Goal {
  public final Horse horse;
  public int goalStatus;
  public BlockPos horseCrankPos;
  public static int[][] offsets = new int[][] {{3, -1, 3}, {3, -1, -3}, {-3, -1, -3}, {-3, -1, 3}};

  public HorseWalkGoal(Horse horse, BlockPos pos) {
    this.horse = horse;
    this.horseCrankPos = pos;
    this.setFlags(EnumSet.of(Flag.MOVE));
  }

  @Override
  public boolean canUse() {
    return this.horse.isLeashed() && this.isValid();
  }

  public boolean isValid() {
    Optional<HorseCrankBlockEntity> blockentity = this.horse.level.getBlockEntity(this.horseCrankPos, ModBlockEntities.HORSECRANK.get());
    return blockentity.isPresent() && blockentity.get().valid;
  }

  @Override
  public void start() {
    this.horse.getNavigation().stop();
    if (this.horse.getNavigation().isDone()) {
      BlockPos pos = calculatePos(this.horseCrankPos, goalStatus);
      this.horse.getNavigation().moveTo(pos.getX(), pos.getY(), pos.getZ(), 1.5);
    }
  }

  @Override
  public void stop() {
    this.horse.getNavigation().stop();
  }

  @Override
  public void tick() {
    if (this.horse.getNavigation().isDone()) {
      this.incrementGoalStatus();
      BlockPos pos = calculatePos(this.horseCrankPos, goalStatus);
      this.horse.getNavigation().moveTo(pos.getX(), pos.getY(), pos.getZ(), 1.5);
    }
  }

  private void incrementGoalStatus() {
    this.goalStatus = (this.goalStatus + 1) % 4;
  }

  private BlockPos calculatePos(BlockPos pos, int goalStatus) {
    return pos.offset(offsets[goalStatus][0], offsets[goalStatus][1], offsets[goalStatus][2]);
  }

  @Override
  public boolean requiresUpdateEveryTick() {
    return true;
  }
}

https://i.imgur.com/GGC5tG7.mp4

Edited by Kitoglavch
Posted (edited)

Ok I decided to use the same way like in Horse Power (1.12.2) in BlockEntity tick. It looks like horse slightly understand what it need to do, but this way still doesn't work properly. What can be wrong here?

  public static double[][] offsetsXZ = {{-1.5, -1.5}, {0, -1.5}, {1, -1.5}, {1, 0}, {1, 1}, {0, 1}, {-1.5, 1}, {-1.5, 0}};
  public AABB[] searchAreas = new AABB[8];
  public int origin = -1, target = origin;
  @Override
  public void load(CompoundTag tag) {
	// ^ other load
    this.origin = tag.getInt("origin");
    this.target = tag.getInt("target");
  }

  @Override
  protected void saveAdditional(CompoundTag tag) {
	// ^ other save
    tag.putInt("origin", this.origin);
    tag.putInt("target", this.target);
  }

public static <T extends BlockEntity> void tick(Level p_155253_, BlockPos p_155254_, BlockState p_155255_, T p_155256_) {
    if (!p_155253_.isClientSide) {
      HorseCrankBlockEntity blockentity = (HorseCrankBlockEntity) p_155256_;
      int oldPower = blockentity.power, oldHorseId = blockentity.horseId, oldLeashId = blockentity.leashId;
      boolean oldValid = blockentity.valid;
      Horse horse = blockentity.getHorse();
      blockentity.verifyIntegrity();
      blockentity.calculatePower();
      if (horse != null && blockentity.valid) {
        if (oldValid != blockentity.valid) {
          blockentity.target = blockentity.findClosestPoint();
        }
        Vector3d pos = blockentity.calculatePos(blockentity.target);
        double x = pos.x;
        double y = pos.y;
        double z = pos.z;
        if (blockentity.searchAreas[blockentity.target] == null)
          blockentity.searchAreas[blockentity.target] = new AABB(x - 0.5, y - 0.5, z - 0.5, x + 0.5, y + 0.5, z + 0.5);
        if (horse.getBoundingBox().intersects(blockentity.searchAreas[blockentity.target])) {
          int next = blockentity.target + 1;
          int previous = blockentity.target - 1;
          if (next >= offsetsXZ.length)
            next = 0;
          if (previous < 0)
            previous = offsetsXZ.length - 1;
          if (blockentity.origin != blockentity.target && blockentity.target != previous) {
            blockentity.origin = blockentity.target;
          }
          blockentity.target = next;
        }
        if (blockentity.target != -1 && !horse.getNavigation().isDone()) {
          pos = blockentity.calculatePos(blockentity.target);
          x = pos.x;
          y = pos.y;
          z = pos.z;
          horse.getNavigation().moveTo(x, y, z, 1D);
          System.out.println(String.format("%f;%f;%f;%d;%s", x, y, z, blockentity.target, horse.getNavigation().getPath()));
        }
      }
      if (oldPower != blockentity.power || oldValid != blockentity.valid || oldHorseId != blockentity.horseId || oldLeashId != blockentity.leashId) {
        p_155253_.sendBlockUpdated(p_155254_, p_155255_, p_155255_, 2);
      }
      p_155256_.setChanged();
    }
  }

  private int findClosestPoint() {
    if (horseId != -1) {
      double distance = Double.MAX_VALUE;
      int closest = 0;
      for (int i = 0; i < offsetsXZ.length; i++) {
        double tmp = distanceToPoint(i);
        if (tmp < distance) {
          distance = tmp;
          closest = i;
        }
      }
      return closest;
    }
    return 0;
  }

  private double distanceToPoint(int point) {
    Vector3d pos = calculatePos(point);
    return this.getHorse().distanceToSqr(pos.x, pos.y, pos.z);
  }

  private Vector3d calculatePos(int point) {
    double x = this.getBlockPos().getX() + offsetsXZ[point][0] * 2;
    double y = this.getBlockPos().getY() - 1;
    double z = this.getBlockPos().getZ() + offsetsXZ[point][1] * 2;
    return new Vector3d(x, y, z);
  }

https://imgur.com/loLgEAu

Edited by Kitoglavch
video

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.