From 3412c4338c82a40725e0c471b36cc784689ef4fc Mon Sep 17 00:00:00 2001 From: Tim Sarbin Date: Sun, 2 Feb 2020 12:46:19 -0500 Subject: [PATCH] Added pathfinding and (buggy) collision data. (#285) --- d2common/d2fileformats/d2ds1/ds1.go | 1 + d2core/d2map/animated_entity.go | 63 ++++++++----- d2core/d2map/engine.go | 33 ++++++- d2core/d2map/hero.go | 4 +- d2core/d2map/region.go | 131 +++++++++++++++++++++++++++- d2game/d2player/game_controls.go | 10 ++- go.mod | 1 + go.sum | 11 ++- 8 files changed, 225 insertions(+), 29 deletions(-) diff --git a/d2common/d2fileformats/d2ds1/ds1.go b/d2common/d2fileformats/d2ds1/ds1.go index 6e15ffde..151ec9c5 100644 --- a/d2common/d2fileformats/d2ds1/ds1.go +++ b/d2common/d2fileformats/d2ds1/ds1.go @@ -179,6 +179,7 @@ func LoadDS1(fileData []byte) DS1 { newObject.X = br.GetInt32() newObject.Y = br.GetInt32() newObject.Flags = br.GetInt32() + //TODO: There's a crash here, we aren't loading this data right.... newObject.Lookup = d2datadict.LookupObject(int(ds1.Act), int(newObject.Type), int(newObject.Id)) if newObject.Lookup != nil && newObject.Lookup.ObjectsTxtId != -1 { newObject.ObjectInfo = d2datadict.Objects[newObject.Lookup.ObjectsTxtId] diff --git a/d2core/d2map/animated_entity.go b/d2core/d2map/animated_entity.go index 49207cd2..e1e9bbc5 100644 --- a/d2core/d2map/animated_entity.go +++ b/d2core/d2map/animated_entity.go @@ -1,6 +1,7 @@ package d2map import ( + "github.com/beefsack/go-astar" "math" "math/rand" @@ -25,6 +26,7 @@ type AnimatedEntity struct { TargetY float64 action int32 repetitions int + path []astar.Pather composite *d2asset.Composite } @@ -41,6 +43,7 @@ func CreateAnimatedEntity(x, y int32, object *d2datadict.ObjectLookupRecord, pal entity.LocationY = float64(y) entity.TargetX = entity.LocationX entity.TargetY = entity.LocationY + entity.path = []astar.Pather{} entity.TileX = int(entity.LocationX / 5) entity.TileY = int(entity.LocationY / 5) @@ -69,6 +72,9 @@ func (v AnimatedEntity) Wait() bool { return v.composite.GetPlayedCount() > v.repetitions } +func (v *AnimatedEntity) SetPath(path []astar.Pather) { + v.path = path +} // Render draws this animated entity onto the target func (v *AnimatedEntity) Render(target d2render.Surface) { target.PushTranslation( @@ -120,27 +126,44 @@ func (v *AnimatedEntity) Step(tickTime float64) { v.TileX = int(v.LocationX / 5) v.TileY = int(v.LocationY / 5) - if v.LocationX == v.TargetX && v.LocationY == v.TargetY { - v.repetitions = 3 + rand.Intn(5) - newAnimationMode := d2enum.AnimationModeObjectNeutral - // TODO: Figure out what 1-3 are for, 4 is correct. - switch v.action { - case 1: - newAnimationMode = d2enum.AnimationModeMonsterNeutral - case 2: - newAnimationMode = d2enum.AnimationModeMonsterNeutral - case 3: - newAnimationMode = d2enum.AnimationModeMonsterNeutral - case 4: - newAnimationMode = d2enum.AnimationModeMonsterSkill1 - v.repetitions = 0 - } - - v.composite.ResetPlayedCount() - if v.animationMode != newAnimationMode.String() { - v.SetMode(newAnimationMode.String(), v.weaponClass, v.direction) - } + if (v.LocationX != v.TargetX) || (v.LocationY != v.TargetY) { + return } + + if len(v.path) > 0 { + v.SetTarget(v.path[0].(*PathTile).X * 5, v.path[0].(*PathTile).Y * 5, 1) + + if len(v.path) > 1 { + v.path = v.path[1:] + } else { + v.path = []astar.Pather{} + } + return + } + + v.repetitions = 3 + rand.Intn(5) + newAnimationMode := d2enum.AnimationModeObjectNeutral + // TODO: Figure out what 1-3 are for, 4 is correct. + switch v.action { + case 1: + newAnimationMode = d2enum.AnimationModeMonsterNeutral + case 2: + newAnimationMode = d2enum.AnimationModeMonsterNeutral + case 3: + newAnimationMode = d2enum.AnimationModeMonsterNeutral + case 4: + newAnimationMode = d2enum.AnimationModeMonsterSkill1 + v.repetitions = 0 + } + + v.composite.ResetPlayedCount() + if v.animationMode != newAnimationMode.String() { + v.SetMode(newAnimationMode.String(), v.weaponClass, v.direction) + } +} + +func (v *AnimatedEntity) HasPathFinding() bool { + return len(v.path) > 0 } // SetTarget sets target coordinates and changes animation based on proximity and direction diff --git a/d2core/d2map/engine.go b/d2core/d2map/engine.go index 06836fea..3f22d93f 100644 --- a/d2core/d2map/engine.go +++ b/d2core/d2map/engine.go @@ -1,6 +1,8 @@ package d2map import ( + "github.com/beefsack/go-astar" + "math" "strings" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2gamestate" @@ -98,15 +100,20 @@ func (m *MapEngine) GenerateAct1Overworld() { if strings.Contains(region.regionPath, "E1") { region, entities := loadRegion(m.gameState.Seed, region.tileRect.Width-1, 0, d2enum.RegionAct1Town, 2, -1) - m.regions = append(m.regions, region) + m.AppendRegion(region) m.entities = append(m.entities, entities...) } else if strings.Contains(region.regionPath, "S1") { region, entities := loadRegion(m.gameState.Seed, 0, region.tileRect.Height-1, d2enum.RegionAct1Town, 3, -1) - m.regions = append(m.regions, region) + m.AppendRegion(region) m.entities = append(m.entities, entities...) } } +func (m *MapEngine) AppendRegion(region *MapRegion) { + // TODO: Stitch together region.walkableArea + m.regions = append(m.regions, region) +} + func (m *MapEngine) GetRegionAtTile(x, y int) *MapRegion { for _, region := range m.regions { if region.tileRect.IsInRect(x, y) { @@ -143,3 +150,25 @@ func (m *MapEngine) Render(target d2render.Surface) { } } } + +func (m *MapEngine) PathFind(startX, startY, endX, endY float64) (path []astar.Pather, distance float64, found bool){ + startTileX := int(math.Floor(startX)) + startTileY := int(math.Floor(startY)) + startSubtileX := int((startX - float64(int(startX))) * 5) + startSubtileY := int((startY - float64(int(startY))) * 5) + startRegion := m.GetRegionAtTile(startTileX, startTileY) + startNode := &startRegion.walkableArea[startSubtileY + ((startTileY - startRegion.tileRect.Top) * 5)][startSubtileX + ((startTileX - startRegion.tileRect.Left) * 5)] + + endTileX := int(math.Floor(endX)) + endTileY := int(math.Floor(endY)) + endSubtileX := int((endX - float64(int(endX))) * 5) + endSubtileY := int((endY - float64(int(endY))) * 5) + endRegion := m.GetRegionAtTile(endTileX, endTileY) + endNode := &endRegion.walkableArea[endSubtileY + ((endTileY - endRegion.tileRect.Top) * 5)][endSubtileX + ((endTileX - endRegion.tileRect.Left) * 5)] + + path, distance, found = astar.Path(endNode, startNode) + if path != nil { + path = path[1:] + } + return +} diff --git a/d2core/d2map/hero.go b/d2core/d2map/hero.go index 712133c8..6c10071d 100644 --- a/d2core/d2map/hero.go +++ b/d2core/d2map/hero.go @@ -43,9 +43,9 @@ func CreateHero(x, y int32, direction int, heroType d2enum.Hero, equipment d2inv } func (v *Hero) Advance(tickTime float64) { - // TODO: Pathfinding if v.AnimatedEntity.LocationX != v.AnimatedEntity.TargetX || - v.AnimatedEntity.LocationY != v.AnimatedEntity.TargetY { + v.AnimatedEntity.LocationY != v.AnimatedEntity.TargetY || + v.AnimatedEntity.HasPathFinding(){ v.AnimatedEntity.Step(tickTime) } diff --git a/d2core/d2map/region.go b/d2core/d2map/region.go index bb7348df..bbf30fda 100644 --- a/d2core/d2map/region.go +++ b/d2core/d2map/region.go @@ -16,8 +16,64 @@ import ( "github.com/OpenDiablo2/OpenDiablo2/d2core/d2asset" "github.com/OpenDiablo2/OpenDiablo2/d2core/d2render" + "github.com/beefsack/go-astar" ) +type PathTile struct { + Walkable bool + Up, Down, Left, Right, UpLeft, UpRight, DownLeft, DownRight *PathTile + X, Y float64 +} + +func (t *PathTile) PathNeighbors() []astar.Pather { + result := make([]astar.Pather, 0) + if t.Up != nil { + result = append(result, t.Up) + } + if t.Right != nil { + result = append(result, t.Right) + } + if t.Down != nil { + result = append(result, t.Down) + } + if t.Left != nil { + result = append(result, t.Left) + } + if t.UpLeft != nil { + result = append(result, t.UpLeft) + } + if t.UpRight != nil { + result = append(result, t.UpRight) + } + if t.DownLeft != nil { + result = append(result, t.DownLeft) + } + if t.DownRight != nil { + result = append(result, t.DownRight) + } + + return result +} + +func (t *PathTile) PathNeighborCost(to astar.Pather) float64 { + return 1 // No cost specifics currently... +} + +func (t *PathTile) PathEstimatedCost(to astar.Pather) float64 { + toT := to.(*PathTile) + absX := toT.X - t.X + if absX < 0 { + absX = -absX + } + absY := toT.Y - t.Y + if absY < 0 { + absY = -absY + } + r := absX + absY + + return r +} + type MapRegion struct { tileRect d2common.Rectangle regionPath string @@ -32,6 +88,7 @@ type MapRegion struct { seed int64 currentFrame int lastFrameTime float64 + walkableArea [][]PathTile } func loadRegion(seed int64, tileOffsetX, tileOffsetY int, levelType d2enum.RegionIdType, levelPreset int, fileIndex int) (*MapRegion, []MapEntity) { @@ -91,10 +148,68 @@ func loadRegion(seed int64, tileOffsetX, tileOffsetY int, levelType d2enum.Regio entities := region.loadEntities() region.loadSpecials() region.generateTileCache() - + region.generateWalkableMatrix() return region, entities } +func (mr *MapRegion) generateWalkableMatrix() { + mr.walkableArea = make([][]PathTile, mr.tileRect.Height * 5) + for y := 0; y < mr.tileRect.Height * 5; y++ { + mr.walkableArea[y] = make([]PathTile, mr.tileRect.Width * 5) + ty := int(float64(y) / 5.0) + for x := 0; x < mr.tileRect.Width * 5; x++ { + tx := int(float64(x) / 5.0) + tile := mr.GetTile(tx, ty) + isBlocked := false + for _, floor := range tile.Floors { + tileData := mr.GetTileData(int32(floor.Style), int32(floor.Sequence), d2enum.Floor) + tileSubAttrs := &d2dt1.SubTileFlags{} + if tileData != nil { + tileSubAttrs = tileData.GetSubTileFlags(x % 5, 4 - (y % 5)) + } + isBlocked = isBlocked || tileSubAttrs.BlockWalk + if isBlocked { + break + } + } + if !isBlocked { + for _, wall := range tile.Walls { + tileData := mr.GetTileData(int32(wall.Style), int32(wall.Sequence), d2enum.Floor) + tileSubAttrs := &d2dt1.SubTileFlags{} + if tileData != nil { + tileSubAttrs = tileData.GetSubTileFlags(x % 5, 4 - (y % 5)) + } + isBlocked = isBlocked || tileSubAttrs.BlockPlayerWalk + if isBlocked { + break + } + } + } + mr.walkableArea[y][x] = PathTile{ + Walkable: !isBlocked, + X: float64(x) / 5.0, + Y: float64(y) / 5.0, + } + if !isBlocked && y > 0 && mr.walkableArea[y-1][x].Walkable { + mr.walkableArea[y][x].Up = &mr.walkableArea[y-1][x] + mr.walkableArea[y-1][x].Down = &mr.walkableArea[y][x] + } + if !isBlocked && x > 0 && mr.walkableArea[y][x-1].Walkable { + mr.walkableArea[y][x].Left = &mr.walkableArea[y][x-1] + mr.walkableArea[y][x-1].Right = &mr.walkableArea[y][x] + } + if !isBlocked && x > 0 && y > 0 && mr.walkableArea[y-1][x-1].Walkable { + mr.walkableArea[y][x].UpLeft = &mr.walkableArea[y-1][x-1] + mr.walkableArea[y-1][x-1].DownRight = &mr.walkableArea[y][x] + } + if !isBlocked && y > 0 && x < (mr.tileRect.Width * 5) && mr.walkableArea[y-1][x+1].Walkable { + mr.walkableArea[y][x].UpRight = &mr.walkableArea[y-1][x+1] + mr.walkableArea[y-1][x+1].DownLeft = &mr.walkableArea[y][x] + } + } + } +} + func (mr *MapRegion) GetTileRect() d2common.Rectangle { return mr.tileRect } @@ -406,6 +521,7 @@ func (mr *MapRegion) renderTileDebug(x, y int, debugVisLevel int, viewport *View } subTileColor := color.RGBA{R: 80, G: 80, B: 255, A: 50} tileColor := color.RGBA{R: 255, G: 255, B: 255, A: 100} + tileCollisionColor := color.RGBA{R: 128, G:0, B:0, A:100} screenX1, screenY1 := viewport.WorldToScreen(float64(x), float64(y)) screenX2, screenY2 := viewport.WorldToScreen(float64(x+1), float64(y)) @@ -440,6 +556,19 @@ func (mr *MapRegion) renderTileDebug(x, y int, debugVisLevel int, viewport *View target.DrawText("f: %v-%v", floor.Style, floor.Sequence) target.Pop() } + + for yy := 0; yy < 5; yy++ { + for xx := 0; xx < 5; xx++ { + isoX := (xx - yy) * 16 + isoY := (xx + yy) * 8 + target.PushTranslation(isoX-3, isoY+4) + var walkableArea = mr.walkableArea[yy + (ay * 5)][xx + (ax * 5)] + if !walkableArea.Walkable { + target.DrawRect(5, 5, tileCollisionColor) + } + target.Pop() + } + } } } } diff --git a/d2game/d2player/game_controls.go b/d2game/d2player/game_controls.go index ae034070..b2498ab3 100644 --- a/d2game/d2player/game_controls.go +++ b/d2game/d2player/game_controls.go @@ -48,10 +48,16 @@ func (g *GameControls) OnKeyDown(event d2input.KeyEvent) bool { func (g *GameControls) OnMouseButtonDown(event d2input.MouseEvent) bool { if event.Button == d2input.MouseButtonLeft { px, py := g.mapEngine.ScreenToWorld(event.X, event.Y) - g.hero.AnimatedEntity.SetTarget(px*5, py*5, 1) + px = float64(int(px * 10)) / 10.0 + py = float64(int(py * 10)) / 10.0 + heroPosX := g.hero.AnimatedEntity.LocationX / 5.0 + heroPosY := g.hero.AnimatedEntity.LocationY / 5.0 + path, _, found := g.mapEngine.PathFind(heroPosX, heroPosY, px, py) + if found { + g.hero.AnimatedEntity.SetPath(path) + } return true } - return false } diff --git a/go.mod b/go.mod index 13b90899..11270668 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/JoshVarga/blast v0.0.0-20180421040937-681c804fb9f0 github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d // indirect + github.com/beefsack/go-astar v0.0.0-20171024231011-f324bbb0d6f7 github.com/go-restruct/restruct v0.0.0-20191227155143-5734170a48a1 github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200102072751-e66f1fb71e2e github.com/stretchr/testify v1.4.0 diff --git a/go.sum b/go.sum index 019bd4a6..164ce5fa 100644 --- a/go.sum +++ b/go.sum @@ -6,6 +6,8 @@ github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafo github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E= github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= +github.com/beefsack/go-astar v0.0.0-20171024231011-f324bbb0d6f7 h1:dX/NcR4V4sY+xio5sjMUUaBfmXz/7UH4R7S//oVPqhY= +github.com/beefsack/go-astar v0.0.0-20171024231011-f324bbb0d6f7/go.mod h1:Cu3t5VeqE8kXjUBeNXWQprfuaP5UCIc5ggGjgMx9KFc= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1 h1:QbL/5oDUmRBzO9/Z7Seo6zf912W/a6Sr4Eu0G/3Jho0= @@ -18,8 +20,6 @@ github.com/gofrs/flock v0.7.1 h1:DP+LD/t0njgoPBvT5MJLeliUIVQR03hiKR6vezdwHlc= github.com/gofrs/flock v0.7.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/hajimehoshi/bitmapfont v1.2.0/go.mod h1:h9QrPk6Ktb2neObTlAbma6Ini1xgMjbJ3w7ysmD7IOU= -github.com/hajimehoshi/ebiten v1.10.3 h1:ywrEsXclsjrdKIhYYrmy/yxLFCd1y4efGVsnFRl8OLU= -github.com/hajimehoshi/ebiten v1.10.3/go.mod h1:i9dIEUf5/MuPtbK1/wHR0PB7ZtqhjOxxg+U1xfxapcY= github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200102072751-e66f1fb71e2e h1:NRGAeXOSMrAo0f4GPaUoiF61eo0wWrfgONPSTZA6Zhg= github.com/hajimehoshi/ebiten v1.11.0-alpha.2.0.20200102072751-e66f1fb71e2e/go.mod h1:0SLvfr8iI2NxzpNB/olBM+dLN9Ur5a9szG13wOgQ0nQ= github.com/hajimehoshi/go-mp3 v0.2.1/go.mod h1:Rr+2P46iH6PwTPVgSsEwBkon0CK5DxCAeX/Rp65DCTE= @@ -29,8 +29,10 @@ github.com/hajimehoshi/oto v0.5.4/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2h github.com/jakecoffman/cp v0.1.0/go.mod h1:a3xPx9N8RyFAACD644t2dj/nK4SuLg1v+jL61m2yVo4= github.com/jfreymuth/oggvorbis v1.0.0/go.mod h1:abe6F9QRjuU9l+2jek3gj46lu40N4qlYxh2grqkLEDM= github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= @@ -44,15 +46,18 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= +golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136 h1:A1gGSx58LAGVHUUsOf7IiR0u8Xb6W51gRwfDBhkdcaw= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= golang.org/x/mobile v0.0.0-20191025110607-73ccc5ba0426/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ= +golang.org/x/mobile v0.0.0-20191115022231-f0c40035f2ba h1:NVszahdZPQTROdO0F5gnXdZhGl2lXFb9w7Ek1F2Pbmk= golang.org/x/mobile v0.0.0-20191115022231-f0c40035f2ba/go.mod h1:p895TfNkDgPEmEQrNiOtIl3j98d/tGU95djDj7NfyjQ= golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -64,6 +69,7 @@ golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191115151921-52ab43148777 h1:wejkGHRTr38uaKRqECZlsCsJ1/TGxIyFbH32x5zUdu4= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= @@ -74,6 +80,7 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=