Merge pull request #85 from twitchyliquid64/master
Implement physics + pathfinding over slabs
This commit is contained in:
@ -51,6 +51,62 @@ var (
|
||||
block.AndesiteStairs,
|
||||
block.RedNetherBrickStairs,
|
||||
block.PolishedAndesiteStairs,
|
||||
block.OakSlab,
|
||||
block.AcaciaSlab,
|
||||
block.DarkOakSlab,
|
||||
block.RedSandstoneSlab,
|
||||
block.PolishedGraniteSlab,
|
||||
block.SmoothRedSandstoneSlab,
|
||||
block.MossyStoneBrickSlab,
|
||||
block.PolishedDioriteSlab,
|
||||
block.MossyCobblestoneSlab,
|
||||
block.EndStoneBrickSlab,
|
||||
block.StoneSlab,
|
||||
block.SmoothSandstoneSlab,
|
||||
block.SmoothQuartzSlab,
|
||||
block.GraniteSlab,
|
||||
block.AndesiteSlab,
|
||||
block.RedNetherBrickSlab,
|
||||
block.PolishedAndesiteSlab,
|
||||
}
|
||||
|
||||
slabs = map[block.ID]struct{}{
|
||||
block.OakSlab.ID: struct{}{},
|
||||
block.AcaciaSlab.ID: struct{}{},
|
||||
block.DarkOakSlab.ID: struct{}{},
|
||||
block.RedSandstoneSlab.ID: struct{}{},
|
||||
block.PolishedGraniteSlab.ID: struct{}{},
|
||||
block.SmoothRedSandstoneSlab.ID: struct{}{},
|
||||
block.MossyStoneBrickSlab.ID: struct{}{},
|
||||
block.PolishedDioriteSlab.ID: struct{}{},
|
||||
block.MossyCobblestoneSlab.ID: struct{}{},
|
||||
block.EndStoneBrickSlab.ID: struct{}{},
|
||||
block.StoneSlab.ID: struct{}{},
|
||||
block.SmoothSandstoneSlab.ID: struct{}{},
|
||||
block.SmoothQuartzSlab.ID: struct{}{},
|
||||
block.GraniteSlab.ID: struct{}{},
|
||||
block.AndesiteSlab.ID: struct{}{},
|
||||
block.RedNetherBrickSlab.ID: struct{}{},
|
||||
block.PolishedAndesiteSlab.ID: struct{}{},
|
||||
}
|
||||
stairs = map[block.ID]struct{}{
|
||||
block.OakStairs.ID: struct{}{},
|
||||
block.AcaciaStairs.ID: struct{}{},
|
||||
block.DarkOakStairs.ID: struct{}{},
|
||||
block.RedSandstoneStairs.ID: struct{}{},
|
||||
block.PolishedGraniteStairs.ID: struct{}{},
|
||||
block.SmoothRedSandstoneStairs.ID: struct{}{},
|
||||
block.MossyStoneBrickStairs.ID: struct{}{},
|
||||
block.PolishedDioriteStairs.ID: struct{}{},
|
||||
block.MossyCobblestoneStairs.ID: struct{}{},
|
||||
block.EndStoneBrickStairs.ID: struct{}{},
|
||||
block.StoneStairs.ID: struct{}{},
|
||||
block.SmoothSandstoneStairs.ID: struct{}{},
|
||||
block.SmoothQuartzStairs.ID: struct{}{},
|
||||
block.GraniteStairs.ID: struct{}{},
|
||||
block.AndesiteStairs.ID: struct{}{},
|
||||
block.RedNetherBrickStairs.ID: struct{}{},
|
||||
block.PolishedAndesiteStairs.ID: struct{}{},
|
||||
}
|
||||
|
||||
safeWalkBlocks = make(map[world.BlockStatus]struct{}, 128)
|
||||
@ -116,3 +172,8 @@ func AirLikeBlock(bID world.BlockStatus) bool {
|
||||
func IsLadder(bID world.BlockStatus) bool {
|
||||
return uint32(bID) >= block.Ladder.MinStateID && uint32(bID) <= block.Ladder.MaxStateID
|
||||
}
|
||||
|
||||
func IsSlab(bID world.BlockStatus) bool {
|
||||
_, isSlab := slabs[block.StateID[uint32(bID)]]
|
||||
return isSlab
|
||||
}
|
||||
|
@ -64,6 +64,11 @@ func StairsDirection(bStateID world.BlockStatus) Direction {
|
||||
return Direction(((uint32(bStateID) - block.ByID[b].MinStateID) / 20) & 0x3)
|
||||
}
|
||||
|
||||
func SlabIsBottom(bStateID world.BlockStatus) bool {
|
||||
b := block.StateID[uint32(bStateID)]
|
||||
return ((uint32(bStateID)-block.ByID[b].MinStateID)&0xE)>>1 == 1
|
||||
}
|
||||
|
||||
// Movement represents a single type of movement in a path.
|
||||
type Movement uint8
|
||||
|
||||
|
@ -4,7 +4,6 @@ package path
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Tnze/go-mc/bot/world"
|
||||
@ -51,6 +50,7 @@ func (n *Nav) Path() (path []astar.Pather, distance float64, found bool) {
|
||||
type Tile struct {
|
||||
Nav *Nav
|
||||
|
||||
HalfBlock bool
|
||||
Movement Movement
|
||||
Pos V3
|
||||
BlockStatus world.BlockStatus
|
||||
@ -89,11 +89,13 @@ func (t Tile) PathNeighbors() []astar.Pather {
|
||||
possible := m.Possible(t.Nav, pos.X, pos.Y, pos.Z, t.Pos, t.Movement)
|
||||
// fmt.Printf("%v-%v: Trying (%v) %v: possible=%v\n", t.Movement, t.Pos, pos, m, possible)
|
||||
if possible {
|
||||
bStateID := t.Nav.World.GetBlockStatus(pos.X, pos.Y, pos.Z)
|
||||
possibles = append(possibles, Tile{
|
||||
Nav: t.Nav,
|
||||
Movement: m,
|
||||
Pos: pos,
|
||||
BlockStatus: t.Nav.World.GetBlockStatus(pos.X, pos.Y, pos.Z),
|
||||
BlockStatus: bStateID,
|
||||
HalfBlock: IsSlab(bStateID) && SlabIsBottom(bStateID),
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -147,14 +149,17 @@ func (t Tile) Inputs(pos, deltaPos, vel Point, runTime time.Duration) Inputs {
|
||||
case AscendNorth, AscendSouth, AscendEast, AscendWest:
|
||||
var (
|
||||
b = block.ByID[block.StateID[uint32(t.BlockStatus)]]
|
||||
isStairs = strings.HasSuffix(b.Name, "_stairs")
|
||||
_, isStairs = stairs[b.ID]
|
||||
_, isSlab = slabs[b.ID]
|
||||
maybeStuck = runTime < 1250*time.Millisecond
|
||||
dist2 = math.Sqrt(deltaPos.X*deltaPos.X + deltaPos.Z*deltaPos.Z)
|
||||
)
|
||||
out.Jump = dist2 < 1.75 && deltaPos.Y < -0.81
|
||||
|
||||
switch {
|
||||
case isStairs:
|
||||
// Special logic for stairs: Try to go towards the downwards edge initially.
|
||||
if isStairs && dist2 > (0.9*0.9) && deltaPos.Y < 0 {
|
||||
if dist2 > (0.9*0.9) && deltaPos.Y < 0 {
|
||||
if x, _, z := StairsDirection(t.BlockStatus).Offset(); dist2 > (0.9*0.9) && deltaPos.Y < 0 {
|
||||
pos.X += (0.49 * float64(x))
|
||||
pos.Z += (0.49 * float64(z))
|
||||
@ -168,6 +173,10 @@ func (t Tile) Inputs(pos, deltaPos, vel Point, runTime time.Duration) Inputs {
|
||||
Jump: out.Jump && !maybeStuck,
|
||||
}
|
||||
}
|
||||
// We dont need to jump for slabs, so only jump if we get stuck.
|
||||
case isSlab:
|
||||
out.Jump = out.Jump && !maybeStuck
|
||||
}
|
||||
|
||||
// Turn off the throttle if we get stuck on the jump.
|
||||
if dist2 < 1 && deltaPos.Y < 0 && vel.Y == 0 {
|
||||
@ -192,5 +201,11 @@ func (t Tile) IsComplete(d Point) bool {
|
||||
return (d.X*d.X+d.Z*d.Z) < (0.22*0.22) && d.Y >= -0.065
|
||||
}
|
||||
|
||||
return (d.X*d.X+d.Z*d.Z) < (0.18*0.18) && d.Y >= -0.065 && d.Y <= 0.08
|
||||
yLowerCutoff := -0.065
|
||||
if t.HalfBlock {
|
||||
yLowerCutoff -= 0.5
|
||||
}
|
||||
|
||||
// fmt.Println(t.HalfBlock, d.Y, d.Y >= yLowerCutoff, d.Y <= 0.08)
|
||||
return (d.X*d.X+d.Z*d.Z) < (0.18*0.18) && d.Y >= yLowerCutoff && d.Y <= 0.08
|
||||
}
|
||||
|
@ -215,7 +215,7 @@ func (s *State) tickPosition(w World) {
|
||||
if s.onGround || (s.Vel.Y != newVel.Y && s.Vel.Y < 0) {
|
||||
bb := s.BB()
|
||||
//fmt.Printf("Player pos = %0.2f, %0.2f, %0.2f\n", bb.X.Min, bb.Y.Min, bb.Z.Min)
|
||||
surroundings := s.surroundings(bb.Offset(s.Vel.X, stepHeight, s.Vel.Y), w)
|
||||
surroundings := s.surroundings(bb.Offset(s.Vel.X, stepHeight, s.Vel.Z), w)
|
||||
outVel := s.Vel
|
||||
|
||||
outVel.Y = stepHeight
|
||||
@ -243,7 +243,7 @@ func (s *State) tickPosition(w World) {
|
||||
|
||||
oldMove := newVel.X*newVel.X + newVel.Z*newVel.Z
|
||||
newMove := outVel.X*outVel.X + outVel.Z*outVel.Z
|
||||
// fmt.Printf("oldMove = %0.2f, newMove = %0.2f\n", oldMove*1000, newMove*1000)
|
||||
// fmt.Printf("oldMove/newmove = %v, (%0.2f >= %0.6f) = %v\n", oldMove >= newMove, outVel.Y, 0.000002-stepHeight, outVel.Y <= (0.000002-stepHeight))
|
||||
if oldMove >= newMove || outVel.Y <= (0.000002-stepHeight) {
|
||||
// fmt.Println("nope")
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user