Use block bounding boxes

This commit is contained in:
Tom
2020-09-23 19:02:32 -07:00
parent eb6289da6a
commit 565b241f0e
4 changed files with 4071 additions and 3995 deletions

View File

@ -38,6 +38,7 @@ var (
safeWalkBlocks = make(map[world.BlockStatus]struct{}, 128) safeWalkBlocks = make(map[world.BlockStatus]struct{}, 128)
walkBlocks = []block.Block{ walkBlocks = []block.Block{
block.Air, block.Air,
block.CaveAir,
block.Grass, block.Grass,
block.Torch, block.Torch,
block.OakSign, block.OakSign,
@ -53,6 +54,7 @@ var (
block.JungleWallSign, block.JungleWallSign,
block.DarkOakWallSign, block.DarkOakWallSign,
block.Cornflower, block.Cornflower,
block.TallGrass,
} }
additionalCostBlocks = map[*block.Block]int{ additionalCostBlocks = map[*block.Block]int{
@ -92,3 +94,7 @@ func AirLikeBlock(bID world.BlockStatus) bool {
_, ok := safeWalkBlocks[bID] _, ok := safeWalkBlocks[bID]
return ok return ok
} }
func IsLadder(bID world.BlockStatus) bool {
return uint32(bID) >= block.Ladder.MinStateID && uint32(bID) <= block.Ladder.MaxStateID
}

View File

@ -3,11 +3,13 @@
package phy package phy
import ( import (
"fmt"
"math" "math"
"github.com/Tnze/go-mc/bot/path" "github.com/Tnze/go-mc/bot/path"
"github.com/Tnze/go-mc/bot/world" "github.com/Tnze/go-mc/bot/world"
"github.com/Tnze/go-mc/bot/world/entity/player" "github.com/Tnze/go-mc/bot/world/entity/player"
"github.com/Tnze/go-mc/data/block/shape"
) )
const ( const (
@ -18,8 +20,9 @@ const (
maxYawChange = 33 maxYawChange = 33
maxPitchChange = 11 maxPitchChange = 11
stepHeight = 0.6 stepHeight = 0.6
minJumpTicks = 14 minJumpTicks = 14
ladderMaxSpeed = 0.15
gravity = 0.08 gravity = 0.08
drag = 0.98 drag = 0.98
@ -59,6 +62,7 @@ func (s *State) ServerPositionUpdate(player player.Pos, w World) error {
s.Pos = path.Point{X: player.X, Y: player.Y, Z: player.Z} s.Pos = path.Point{X: player.X, Y: player.Y, Z: player.Z}
s.Yaw, s.Pitch = float64(player.Yaw), float64(player.Pitch) s.Yaw, s.Pitch = float64(player.Yaw), float64(player.Pitch)
s.Vel = path.Point{} s.Vel = path.Point{}
fmt.Println("TELEPORT!")
s.onGround, s.collision.vertical, s.collision.horizontal = false, false, false s.onGround, s.collision.vertical, s.collision.horizontal = false, false, false
s.Run = true s.Run = true
return nil return nil
@ -76,12 +80,24 @@ func (s *State) surroundings(query AABB, w World) Surrounds {
minZ, maxZ := int(math.Floor(query.Z.Min)), int(math.Floor(query.Z.Max))+1 minZ, maxZ := int(math.Floor(query.Z.Min)), int(math.Floor(query.Z.Max))+1
minX, maxX := int(math.Floor(query.X.Min)), int(math.Floor(query.X.Max))+1 minX, maxX := int(math.Floor(query.X.Min)), int(math.Floor(query.X.Max))+1
out := Surrounds(make([]AABB, 0, abs(maxY, minY)*abs(maxZ, minZ)*abs(maxX, minX))) out := Surrounds(make([]AABB, 0, abs(maxY, minY)*abs(maxZ, minZ)*abs(maxX, minX)*2))
for y := minY; y < maxY; y++ { for y := minY; y < maxY; y++ {
for z := minZ; z < maxZ; z++ { for z := minZ; z < maxZ; z++ {
for x := minX; x < maxX; x++ { for x := minX; x < maxX; x++ {
if block := w.GetBlockStatus(x, y, z); !path.AirLikeBlock(block) { bStateID := w.GetBlockStatus(x, y, z)
out = append(out, AABB{X: MinMax{Max: 1}, Y: MinMax{Max: 1}, Z: MinMax{Max: 1}, Block: block}.Offset(float64(x), float64(y), float64(z))) if !path.AirLikeBlock(bStateID) {
bbs, err := shape.CollisionBoxes(bStateID)
if err != nil {
panic(err)
}
for _, box := range bbs {
out = append(out, AABB{
X: MinMax{Min: box.Min.X, Max: box.Max.X},
Y: MinMax{Min: box.Min.Y, Max: box.Max.Y},
Z: MinMax{Min: box.Min.Z, Max: box.Max.Z},
Block: bStateID,
}.Offset(float64(x), float64(y), float64(z)))
}
} }
} }
} }
@ -124,7 +140,7 @@ func (s *State) Tick(input path.Inputs, w World) error {
} }
//fmt.Printf("pY = %.2f, maxblockY = %.1f (delta = %.1f)\n", bb.Y.Min, y, bb.Y.Min-y) //fmt.Printf("pY = %.2f, maxblockY = %.1f (delta = %.1f)\n", bb.Y.Min, y, bb.Y.Min-y)
if d := bb.Y.Min - y; d >= -stepHeight && d < stepHeight-1 { if d := bb.Y.Min - y; d >= -stepHeight && d < stepHeight-1 {
bb := player.Offset(0, stepHeight, 0) bb := player.Offset(0, -d, 0)
player, newVel = s.computeCollision(bb, bb.Extend(s.Vel.X, s.Vel.Y, s.Vel.Z), w) player, newVel = s.computeCollision(bb, bb.Extend(s.Vel.X, s.Vel.Y, s.Vel.Z), w)
} }
@ -195,6 +211,14 @@ func (s *State) tickVelocity(input path.Inputs, w World) {
s.Vel.Y *= drag s.Vel.Y *= drag
s.Vel.X *= inertia s.Vel.X *= inertia
s.Vel.Z *= inertia s.Vel.Z *= inertia
lower := w.GetBlockStatus(int(math.Floor(s.Pos.X)), int(math.Floor(s.Pos.Y)), int(math.Floor(s.Pos.Z)))
if path.IsLadder(lower) {
s.Vel.X = math.Min(math.Max(-ladderMaxSpeed, s.Vel.X), ladderMaxSpeed)
s.Vel.Z = math.Min(math.Max(-ladderMaxSpeed, s.Vel.Z), ladderMaxSpeed)
s.Vel.Y = math.Min(math.Max(-ladderMaxSpeed, s.Vel.Y), ladderMaxSpeed)
fmt.Println(s.Vel)
}
} }
func (s *State) computeCollision(bb, query AABB, w World) (outBB AABB, outVel path.Point) { func (s *State) computeCollision(bb, query AABB, w World) (outBB AABB, outVel path.Point) {

View File

@ -43,6 +43,7 @@ func main() {
package shape package shape
import ( import (
"github.com/Tnze/go-mc/bot/world"
"github.com/Tnze/go-mc/data/block" "github.com/Tnze/go-mc/data/block"
) )
@ -63,6 +64,27 @@ type BoundingBox struct {
Min,Max BoundingTriplet Min,Max BoundingTriplet
} }
// CollisionBoxes returns the set of bounding boxes for that block state ID.
func CollisionBoxes(bStateID world.BlockStatus) ([]BoundingBox, error) {
bID := block.StateID[uint32(bStateID)]
if bID == 0 {
return nil, fmt.Errorf("unknown state ID: %v", bStateID)
}
b, ok := block.ByID[bID]
if !ok {
return nil, fmt.Errorf("unknown block ID: %v", bID)
}
shapes, ok := ByBlockID[bID]
if !ok {
return nil, fmt.Errorf("unknown shape for block ID: %v", bID)
}
shapeIdx := (uint32(bStateID) - b.MinStateID) % uint32(len(shapes))
if int(shapeIdx) > len(shapes) {
return nil, fmt.Errorf("shape index out of bounds: %v >= %v", shapeIdx, len(shapes))
}
return Dimensions[shapes[shapeIdx]].Boxes, nil
}
`) `)
fmt.Println() fmt.Println()

File diff suppressed because it is too large Load Diff