6 Commits

35 changed files with 1106 additions and 192 deletions

49
TODO.md
View File

@@ -1,9 +1,10 @@
## Levels:
- use first line as background image name
- ignore comments in lvl files
- check when sphere bounces from one end to the other endlessly w/o
any solids in between. this is a game lock and equals game over
- Start the game end timer and add a score FIXME: put the actual max
reachable score into the level definition along with the minimum
steps required to reach it, also add a step counter
@@ -11,25 +12,35 @@
- Grid Observer:
https://github.com/mlange-42/arche/issues/374
Screenshot:
Yes, since *ebiten.Image implements the standard image.Image interface
I just made a screenshot example (in Draw() function):
if inpututil.IsKeyJustPressed(ebiten.KeyS) {
f, err := os.Create("screenshot.png")
if err != nil {
log.Fatal("can't create file: ", err)
}
png.Encode(f, screen)
}
- Add some final message when the player reaches the last level, start
from scratch or a message to buy me some beer, whatever
- Calculate obstacle collision the same as solid collision with future
velocity and included snap in so that the player ends up right on
the edge of the obstacle and not inside as it is now
- Check player-player collisions!
- Add player mergers, possibly as an option, so maybe we could have
different primary and secondary players: one pair can merge, the
other not. Like S + s and M + m or something.
- Add shaders for animation (player destruction etc)
- Add player HUD + Stats (as hud_system!)
## Collider Rework
- do not use the map anymore for collision detection
- central collision_system
- add Collider component with callback funcs to call on certain events
- callback types:
- rect intersect (== future collision)
- collision resolve (set new position)
- pass over foreign rect (to e.g. change sprite while flying over sprite)
- pass over done (switch sprite)
- check for all moving objects against non-moving ones like moving
obstacle, player, bullet, laser
- check if executing callbacks within query loop is allowed
- callback function needs to be able to modify other components, so
possibly use observers for them, e.g.:
Collider.IntersectResolve => func(newpos) {player.pos = newpos; player.vel = stop}
- in the end it must be possible to add new entities without the need
to write a collision check for them, but have collision detection anyway!

View File

@@ -4,7 +4,7 @@ Background: background-lila
#######
# #
#o #
# t #
#> S <#
# #

View File

@@ -4,11 +4,11 @@ Background: background-lila
#############
# #
# t #
#> S # #
# ># >#
#< # #
# v# <#
# ># ^#
#< #W#####
# o v# o#
#############

View File

@@ -4,13 +4,13 @@ Background: background-lila
##########
# v#
########W#
# v #
# #
#S s#
# #
#^ #
##########
############
# o #
######## #

View File

@@ -0,0 +1,17 @@
Description: space
Background: background-lila
#
S
#

View File

@@ -25,18 +25,42 @@ type Tile struct {
Id byte
Sprite *ebiten.Image
Class string
Solid bool
Player bool
IsPrimary bool
Renderable bool
Velocity bool
Collectible bool
Transient bool
Particle int // -1=unused, 0-3 = show image of slice
Tiles []*ebiten.Image
TileNames []string // same thing, only the names
Obstacle bool
Direction int // obstacles
Solid bool // wall brick
Player bool // player sphere
IsPrimary bool // primary player sphere
Renderable bool // visible, has sprite
Velocity bool // movable
Collectible bool // collectible, vanishes once collected
Transient bool // turns into brick wall when traversed
Destroyable bool // turns into empty floor when bumped into twice
Particle int // -1=unused, 0-3 = show image of slice
Tiles []*ebiten.Image // has N sprites
TileNames []string // same thing, only the names
Obstacle bool // is an obstacle/enemy
Direction int // obstacle business end shows into this direction
}
func (tile *Tile) Clone() *Tile {
newtile := &Tile{
Id: tile.Id,
Sprite: tile.Sprite,
Class: tile.Class,
Solid: tile.Solid,
Player: tile.Player,
IsPrimary: tile.IsPrimary,
Renderable: tile.Renderable,
Velocity: tile.Velocity,
Collectible: tile.Collectible,
Transient: tile.Transient,
Destroyable: tile.Destroyable,
Particle: tile.Particle,
Tiles: tile.Tiles,
TileNames: tile.TileNames,
Obstacle: tile.Obstacle,
Direction: tile.Direction,
}
return newtile
}
const (
@@ -128,7 +152,7 @@ func NewTileTranswall(class []string) *Tile {
}
return &Tile{
Id: '*',
Id: 't',
Class: "transwall",
Solid: false,
Renderable: true,
@@ -139,6 +163,27 @@ func NewTileTranswall(class []string) *Tile {
}
}
func NewTileHiddenDoor(class []string) *Tile {
sprites := []*ebiten.Image{}
names := []string{}
for _, sprite := range class {
sprites = append(sprites, Assets[sprite])
names = append(names, sprite)
}
return &Tile{
Id: 'W',
Class: "hiddendoor",
Solid: false,
Renderable: true,
Destroyable: true,
Tiles: sprites,
Sprite: sprites[0], // initially use the first
TileNames: names,
}
}
// used to map level data bytes to actual tiles
type TileRegistry map[byte]*Tile
@@ -164,7 +209,8 @@ type RawLevel struct {
func InitTiles() TileRegistry {
return TileRegistry{
' ': {Id: ' ', Class: "floor", Renderable: false},
'#': NewTileBlock("block-grey32"),
//'#': NewTileBlock("block-grey32"),
'#': NewTileBlock("block-greycolored"),
'B': NewTileBlock("block-orange-32"),
'S': NewTilePlayer(Primary),
's': NewTilePlayer(Secondary),
@@ -183,6 +229,7 @@ func InitTiles() TileRegistry {
"particle-ring-6",
}),
't': NewTileTranswall([]string{"transwall", "block-orange-32"}),
'W': NewTileHiddenDoor([]string{"block-greycolored", "block-greycolored-damaged"}),
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
assets/sprites/hud.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

14
components/collider.go Normal file
View File

@@ -0,0 +1,14 @@
package components
import "github.com/mlange-42/arche/ecs"
// if the function returns true, the entity will be removed. The
// supplied entity is the target entitiy with which the checked one
// collided.
type Collider struct {
CollisionHandler func(*ecs.World, *Position, *Position, *Velocity, ecs.Entity) bool
EdgeHandler func(*ecs.World, *Position, *Position, *Velocity, ecs.Entity) bool
PassoverHandler func(*ecs.World, *Position, *Velocity, *ecs.Entity) bool
PassoverFinishedHandler func(*ecs.World, *Position, *Velocity, *ecs.Entity) bool
}

View File

@@ -16,10 +16,6 @@ type Particle struct {
Tiles []*ebiten.Image
}
type Speed struct {
Value int
}
// only tile entities will have those
type Tilish struct{}
type Solid struct{}

29
components/destroyable.go Normal file
View File

@@ -0,0 +1,29 @@
package components
import (
"log"
"github.com/hajimehoshi/ebiten/v2"
)
// A hidden door in a wall. If the player bumps into it once, it shows
// damage and it vanishes the next time.
type Destroyable struct {
Activated bool
Sprites []*ebiten.Image
Current int // sprite index
}
func (door *Destroyable) GetNext() *ebiten.Image {
if len(door.Sprites) > door.Current {
door.Current++
return door.Sprites[door.Current]
}
log.Fatalf("not enough sprites in transient tile, have %d sprites, index requested: %d",
len(door.Sprites), door.Current+1,
)
return nil
}

View File

@@ -34,7 +34,8 @@ func NewPosition(point image.Point, cellsize int) *Position {
func (position *Position) GetMoved(velosity *Velocity) *Position {
pos := &Position{}
pos.Update(position.X+velosity.Data.X, position.Y+velosity.Data.Y, position.Cellsize)
pos.Update(position.X+(velosity.Data.X*velosity.Speed),
position.Y+(velosity.Data.Y*velosity.Speed), position.Cellsize)
return pos
}
@@ -70,13 +71,13 @@ func (position *Position) String() string {
)
}
func (position *Position) Move(velocity *Velocity, speed *Speed) {
func (position *Position) Move(velocity *Velocity) {
// if velocity.Direction != 0 {
// slog.Debug("moving", "velocity", velocity, "speed", speed)
// }
position.Update(
position.X+(velocity.Data.X*speed.Value),
position.Y+(velocity.Data.Y*speed.Value),
position.X+(velocity.Data.X*velocity.Speed),
position.Y+(velocity.Data.Y*velocity.Speed),
)
}

View File

@@ -9,6 +9,7 @@ type Velocity struct {
Data Position
Direction int
PointingAt int
Speed int
}
func (velocity *Velocity) Set(new *Velocity) {

77
config/config.go Normal file
View File

@@ -0,0 +1,77 @@
package config
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/knadh/koanf"
"github.com/knadh/koanf/providers/env"
"github.com/knadh/koanf/providers/posflag"
flag "github.com/spf13/pflag"
)
const Usage string = `openquell [options]
-t --tps <ticks> Set ticks per second, default 60.
-d --debug Enable debugging output.
`
type Config struct {
TPS int `koanf:"tps"`
Loglevel string `koanf:"loglevel"`
Debug bool `koanf:"debug"` // loglevel=debug
Startlevel int
}
func InitConfig() (*Config, error) {
var kloader = koanf.New(".")
flagset := flag.NewFlagSet("config", flag.ContinueOnError)
flagset.BoolP("debug", "d", false, "enable debug log")
flagset.Usage = func() {
fmt.Println(Usage)
os.Exit(0)
}
flagset.IntP("tps", "t", 0, "TPS")
if err := flagset.Parse(os.Args[1:]); err != nil {
return nil, fmt.Errorf("failed to parse program arguments: %w", err)
}
if err := kloader.Load(env.Provider("OC_", ".", func(s string) string {
return strings.ReplaceAll(strings.ToLower(
strings.TrimPrefix(s, "OC_")), "_", ".")
}), nil); err != nil {
return nil, fmt.Errorf("error loading environment: %w", err)
}
if err := kloader.Load(posflag.Provider(flagset, ".", kloader), nil); err != nil {
return nil, fmt.Errorf("error loading flags: %w", err)
}
conf := &Config{}
if err := kloader.Unmarshal("", &conf); err != nil {
return nil, fmt.Errorf("error unmarshalling: %w", err)
}
switch conf.Loglevel {
case "debug":
conf.Debug = true
}
// are there any args left on commandline? if so threat them as adlinks
if len(flagset.Args()) > 0 {
level, err := strconv.Atoi(flagset.Args()[0])
if err != nil {
return nil, fmt.Errorf("failed to parse start level: %w", err)
}
conf.Startlevel = level
}
return conf, nil
}

View File

@@ -4,6 +4,7 @@ import (
"fmt"
"image"
"log/slog"
"openquell/config"
"openquell/observers"
"github.com/hajimehoshi/ebiten/v2"
@@ -18,9 +19,10 @@ type Game struct {
CurrentScene SceneName
Observer *observers.GameObserver
Levels []*Level // needed to feed select_scene
Config *config.Config
}
func NewGame(width, height, cellsize, startlevel int, startscene SceneName) *Game {
func NewGame(width, height, cellsize int, cfg *config.Config, startscene SceneName) *Game {
world := ecs.NewWorld()
game := &Game{
@@ -30,18 +32,20 @@ func NewGame(width, height, cellsize, startlevel int, startscene SceneName) *Gam
ScreenHeight: height,
Scenes: map[SceneName]Scene{},
Cellsize: cellsize,
Config: cfg,
}
observers.NewPlayerObserver(&world)
observers.NewParticleObserver(&world)
observers.NewObstacleObserver(&world)
game.Observer = observers.NewGameObserver(&world, startlevel, width, height, cellsize)
observers.NewEntityObserver(&world)
game.Observer = observers.NewGameObserver(&world, cfg.Startlevel, width, height, cellsize)
game.Scenes[Welcome] = NewWelcomeScene(game)
game.Scenes[Menu] = NewMenuScene(game)
game.Scenes[About] = NewAboutScene(game)
game.Scenes[Popup] = NewPopupScene(game)
game.Scenes[Play] = NewLevelScene(game, startlevel)
game.Scenes[Play] = NewLevelScene(game, cfg.Startlevel)
game.Scenes[Select] = NewSelectScene(game)
game.CurrentScene = startscene
@@ -96,7 +100,6 @@ func (game *Game) Update() error {
if next == Play {
// fresh setup of actual level every time we enter the play scene
//game.Scenes[Play] = NewLevelScene(game, gameobserver.CurrentLevel)
game.Scenes[Play].SetLevel(gameobserver.CurrentLevel)
}

View File

@@ -1,10 +1,12 @@
package game
import (
"fmt"
"log/slog"
"openquell/assets"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
)
type LevelScene struct {
@@ -69,12 +71,23 @@ func (scene *LevelScene) Update() error {
}
func (scene *LevelScene) Draw(screen *ebiten.Image) {
// FIXME: why not in Update() ?!?!?!
if scene.CurrentLevel != scene.Game.Observer.CurrentLevel {
slog.Debug("level", "current", scene.CurrentLevel,
"next", scene.Game.Observer.CurrentLevel)
scene.CurrentLevel = scene.Game.Observer.CurrentLevel
scene.Levels[scene.CurrentLevel].SetupGrid(scene.Game)
}
screen.Clear()
scene.Levels[scene.CurrentLevel].Draw(screen)
// FIXME: put into hud_system
op := &ebiten.DrawImageOptions{}
screen.DrawImage(assets.Assets["hud"], op)
ebitenutil.DebugPrintAt(screen, fmt.Sprintf(
"FPS: %02.f TPS: %02.f",
ebiten.ActualFPS(),
ebiten.ActualTPS(),
), 10, 10)
}

View File

@@ -3,6 +3,7 @@ package game
import (
"image"
"log"
"log/slog"
"openquell/assets"
"openquell/components"
"openquell/grid"
@@ -15,12 +16,16 @@ import (
"github.com/mlange-42/arche/ecs"
)
type Map map[image.Point]*assets.Tile
type BackupMap map[image.Point]assets.Tile
type Level struct {
Cellsize, Width, Height int
World *ecs.World
Name string
Description string
Mapslice map[image.Point]*assets.Tile
Mapslice Map
BackupMapslice Map
GridContainer *grid.GridContainer
Systems []systems.System
Grid *grid.Grid
@@ -36,6 +41,9 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
systemlist = append(systemlist, systems.NewCollectibleSystem(game.World))
systemlist = append(systemlist,
systems.NewCollisionSystem(game.World, gridcontainer))
systemlist = append(systemlist,
systems.NewPlayerSystem(game.World, gridcontainer))
@@ -45,16 +53,21 @@ func NewLevel(game *Game, cellsize int, plan *assets.RawLevel) *Level {
systemlist = append(systemlist, systems.NewTransientSystem(game.World, gridcontainer))
systemlist = append(systemlist, systems.NewDestroyableSystem(game.World, gridcontainer))
mapslice, backupmap := LevelToSlice(game, plan, cellsize)
return &Level{
Mapslice: LevelToSlice(game, plan, cellsize),
Cellsize: cellsize,
World: game.World,
Width: game.ScreenWidth,
Height: game.ScreenHeight,
Description: plan.Description,
Name: plan.Name,
GridContainer: gridcontainer,
Systems: systemlist,
Mapslice: mapslice,
BackupMapslice: backupmap,
Cellsize: cellsize,
World: game.World,
Width: game.ScreenWidth,
Height: game.ScreenHeight,
Description: plan.Description,
Name: plan.Name,
GridContainer: gridcontainer,
Systems: systemlist,
}
}
@@ -77,6 +90,12 @@ func (level *Level) Position2Point(position *components.Position) image.Point {
}
}
func (level *Level) RestoreMap() {
for point, tile := range level.BackupMapslice {
level.Mapslice[point] = tile.Clone()
}
}
func (level *Level) SetupGrid(game *Game) {
// generic variant does not work here:
// selector := generic.NewFilter1[components.Position]()
@@ -92,15 +111,20 @@ func (level *Level) SetupGrid(game *Game) {
playerobserver := observers.GetPlayerObserver(level.World)
playerobserver.RemoveEntities()
// get rid of possibly manipulated map
level.RestoreMap()
// setup world
slog.Debug("new grid?")
level.GridContainer.SetGrid(
grid.NewGrid(game.World, level.Cellsize, level.Width, level.Height, level.Mapslice))
}
// parses a RawLevel and generates a mapslice from it, which is being used as grid
func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) map[image.Point]*assets.Tile {
func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) (Map, Map) {
size := game.ScreenWidth * game.ScreenHeight
mapslice := make(map[image.Point]*assets.Tile, size)
mapslice := make(Map, size)
backupmap := make(Map, size)
for y, line := range strings.Split(string(level.Data), "\n") {
if len(line) != game.ScreenWidth/tilesize && y < game.ScreenHeight/tilesize {
@@ -113,9 +137,11 @@ func LevelToSlice(game *Game, level *assets.RawLevel, tilesize int) map[image.Po
log.Fatalf("unregistered tile type %c encountered", char)
}
mapslice[image.Point{x, y}] = assets.Tiles[byte(char)]
tile := assets.Tiles[byte(char)]
mapslice[image.Point{x, y}] = tile
backupmap[image.Point{x, y}] = tile.Clone()
}
}
return mapslice
return mapslice, backupmap
}

5
go.mod
View File

@@ -16,8 +16,13 @@ require (
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/hajimehoshi/ebiten v1.12.12 // indirect
github.com/jezek/xgb v1.1.0 // indirect
github.com/knadh/koanf v1.5.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.2 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/tinne26/etxt v0.0.8 // indirect
github.com/tlinden/yadu v0.1.3 // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect

345
go.sum
View File

@@ -1,20 +1,110 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aws/aws-sdk-go-v2 v1.9.2/go.mod h1:cK/D0BBs0b/oWPIcX/Z/obahJK1TT7IPVjy53i/mX/4=
github.com/aws/aws-sdk-go-v2/config v1.8.3/go.mod h1:4AEiLtAb8kLs7vgw2ZV3p2VZ1+hBavOc84hqxVNpCyw=
github.com/aws/aws-sdk-go-v2/credentials v1.4.3/go.mod h1:FNNC6nQZQUuyhq5aE5c7ata8o9e4ECGmS4lAXC7o1mQ=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.6.0/go.mod h1:gqlclDEZp4aqJOancXK6TN24aKhT0W0Ae9MHk3wzTMM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.4/go.mod h1:ZcBrrI3zBKlhGFNYWvju0I3TR93I7YIgAfy82Fh4lcQ=
github.com/aws/aws-sdk-go-v2/service/appconfig v1.4.2/go.mod h1:FZ3HkCe+b10uFZZkFdvf98LHW21k49W8o8J366lqVKY=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.3.2/go.mod h1:72HRZDLMtmVQiLG2tLfQcaWLCssELvGl+Zf2WVxMmR8=
github.com/aws/aws-sdk-go-v2/service/sso v1.4.2/go.mod h1:NBvT9R1MEF+Ud6ApJKM0G+IkPchKS7p7c2YPKwHmBOk=
github.com/aws/aws-sdk-go-v2/service/sts v1.7.2/go.mod h1:8EzeIqfWt2wWT4rJVu3f21TfrhJ8AEMzVybRNSb/b4g=
github.com/aws/smithy-go v1.8.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/ebitengine/purego v0.5.0 h1:JrMGKfRIAM4/QVKaesIIT7m/UVjTj5GYhRSQYwfVdpo=
github.com/ebitengine/purego v0.5.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/ebitengine/purego v0.6.0 h1:Yo9uBc1x+ETQbfEaf6wcBsjrQfCEnh/gaGUg7lguEJY=
github.com/ebitengine/purego v0.6.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
github.com/ebitenui/ebitenui v0.5.5 h1:L9UCWmiMlo4sG5TavQKmjfsnwMmYqkld2tXWZMmKkSA=
github.com/ebitenui/ebitenui v0.5.5/go.mod h1:CkzAwu9Ks32P+NC/7+iypdLA85Wqnn93UztPFE+kAH4=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200707082815-5321531c36a2/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b h1:GgabKamyOYguHqHjSkDACcgoPIz3w0Dis/zJ1wyHHHU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2-0.20181118220953-042da051cf31/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hajimehoshi/bitmapfont v1.3.0/go.mod h1:/Qb7yVjHYNUV4JdqNkPs6BSZwLjKqkZOMIp6jZD0KgE=
github.com/hajimehoshi/ebiten v1.12.12 h1:JvmF1bXRa+t+/CcLWxrJCRsdjs2GyBYBSiFAfIqDFlI=
github.com/hajimehoshi/ebiten v1.12.12/go.mod h1:1XI25ImVCDPJiXox4h9yK/CvN5sjDYnbF4oZcFzPXHw=
@@ -26,35 +116,176 @@ github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/go.mod
github.com/hajimehoshi/go-mp3 v0.3.1/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto v0.6.8/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hashicorp/consul/api v1.13.0/go.mod h1:ZlVrynguJKcYr54zGaDbaL3fOvKC9m72FhPvA8T35KQ=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-hclog v0.0.0-20180709165350-ff2cf002a8dd/go.mod h1:9bjs9uLqI8l75knNv3lV1kA55veR+WUPSiKIWcQHudI=
github.com/hashicorp/go-hclog v0.8.0/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY=
github.com/hashicorp/go-retryablehttp v0.5.4/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/hashicorp/vault/api v1.0.4/go.mod h1:gDcqh3WGcR1cpF5AJz/B1UFheUEneMoIospckxBxk6Q=
github.com/hashicorp/vault/sdk v0.1.13/go.mod h1:B+hVj7TpuQY1Y/GPbCpffmgd+tSEwvhkWnjtSYCaS2M=
github.com/hashicorp/yamux v0.0.0-20180604194846-3520598351bb/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hashicorp/yamux v0.0.0-20181012175058-2f1d1f20f75d/go.mod h1:+NfK9FKeTrX5uv1uIXGdwYDTeHna2qgaIlx54MXqjAM=
github.com/hjson/hjson-go/v4 v4.0.0/go.mod h1:KaYt3bTw3zhBjYqnXkYywcYctk0A2nxeEFTse3rH13E=
github.com/jakecoffman/cp v1.0.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/jfreymuth/oggvorbis v1.0.1/go.mod h1:NqS+K+UXKje0FUYUPosyQ+XTVvjmVjps1aEZH1sumIk=
github.com/jfreymuth/vorbis v1.0.0/go.mod h1:8zy3lUAm9K/rJJk223RKy6vjCZTWC61NA2QD06bfOE0=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/knadh/koanf v1.5.0 h1:q2TSd/3Pyc/5yP9ldIrSdIz26MCcyNQzW0pEAugLPNs=
github.com/knadh/koanf v1.5.0/go.mod h1:Hgyjp4y8v44hpZtPzs7JZfRAW5AhN7KfZcwv1RYggDs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mlange-42/arche v0.10.0 h1:fEFDAYMAnWa+xHc1oq4gVcA4PuEQOCGSRXSKITXawMw=
github.com/mlange-42/arche v0.10.0/go.mod h1:gJ5J8vBreqrf4TcBomBFPGnWdE5P3qa4LtxYHn1gDcg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/npillmayer/nestext v0.1.3/go.mod h1:h2lrijH8jpicr25dFY+oAJLyzlya6jhnuG+zWp9L0Uk=
github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAvS1LBMMhTE=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_golang v1.11.1/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tinne26/etxt v0.0.8 h1:rjb58jkMkapRGLmhBMWnT76E/nMTXC5P1Q956BRZkoc=
github.com/tinne26/etxt v0.0.8/go.mod h1:QM/hlNkstsKC39elTFNKAR34xsMb9QoVosf+g9wlYxM=
github.com/tlinden/yadu v0.1.2 h1:TYYVnUJwziRJ9YPbIbRf9ikmDw0Q8Ifixm+J/kBQFh8=
github.com/tlinden/yadu v0.1.2/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
github.com/tlinden/yadu v0.1.3 h1:5cRCUmj+l5yvlM2irtpFBIJwVV2DPEgYSaWvF19FtcY=
github.com/tlinden/yadu v0.1.3/go.mod h1:l3bRmHKL9zGAR6pnBHY2HRPxBecf7L74BoBgOOpTcUA=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.etcd.io/etcd/api/v3 v3.5.4/go.mod h1:5GB2vv4A4AOn3yk7MftYGHkUfGtDHnEraIjym4dYz5A=
go.etcd.io/etcd/client/pkg/v3 v3.5.4/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v3 v3.5.4/go.mod h1:ZaRkVgBZC+L+dLCjTcF1hRXpgZXQPOvnA/Ak/gq3kiY=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
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-20230817173708-d852ddb80c63 h1:m64FZMko/V45gv0bNmrNYoDEq8U5YUhetc9cBWKS1TQ=
@@ -67,6 +298,10 @@ golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+o
golang.org/x/image v0.0.0-20200801110659-972c09e46d76/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ=
golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
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-20210208171126-f462b3930c8f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
@@ -75,29 +310,80 @@ golang.org/x/mobile v0.0.0-20230922142353-e2f452493d57/go.mod h1:wEyOn6VvNW7tcf+
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190129075346-302c3dd5f1cc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200918174421-af09f7315aff/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -112,22 +398,81 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20181227161524-e6919f6577db/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200918232735-d647fc253266/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190404172233-64821d5d2107/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.22.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

View File

@@ -14,7 +14,7 @@ func (grid *Grid) GetSolidNeighborPosition(
return false, nil
}
// set to true, if we are already on the last tile in the current
// set to true if we are already on the last tile in the current
// direction, i.e. on the edge of the grid
edge := true
neighborpos := position.Point()
@@ -44,6 +44,9 @@ func (grid *Grid) GetSolidNeighborPosition(
newpos := components.NewPosition(neighborpos, grid.Tilesize)
// slog.Debug("SolidNeighbor?", "player", position.Point(),
// "neighbor", neighborpos, "edge", edge, "neighbor-solid",
// grid.Map[neighborpos].Solid, "newpos", newpos.Point())
if !edge && grid.Map[neighborpos].Solid {
return true, newpos
}

View File

@@ -6,6 +6,7 @@ import (
"openquell/assets"
"openquell/components"
"openquell/config"
"openquell/handlers"
"openquell/observers"
"github.com/mlange-42/arche/ecs"
@@ -33,8 +34,8 @@ func NewGrid(world *ecs.World,
components.Position,
components.Velocity,
components.Renderable,
components.Speed,
components.Player](world)
components.Player,
components.Collider](world)
solidmapper := generic.NewMap4[
components.Position,
@@ -49,11 +50,10 @@ func NewGrid(world *ecs.World,
components.Renderable,
components.Collectible](world)
obsmapper := generic.NewMap5[
obsmapper := generic.NewMap4[
components.Position,
components.Velocity,
components.Renderable,
components.Speed,
components.Obstacle](world)
transmapper := generic.NewMap3[
@@ -61,15 +61,22 @@ func NewGrid(world *ecs.World,
components.Renderable,
components.Transient](world)
doormapper := generic.NewMap3[
components.Position,
components.Renderable,
components.Destroyable](world)
var pos *components.Position
var vel *components.Velocity
var render *components.Renderable
var speed *components.Speed
var transient *components.Transient
var player *components.Player
var destroyable *components.Destroyable
var collider *components.Collider
playerobserver := observers.GetPlayerObserver(world)
obstacleobserver := observers.GetObstacleObserver(world)
entityobserver := observers.GetEntityObserver(world)
for point, tile := range mapslice {
switch tile.Renderable {
@@ -80,25 +87,35 @@ func NewGrid(world *ecs.World,
pos, render, _, _ = solidmapper.Get(entity)
case tile.Player:
entity := playermapper.New()
pos, _, render, speed, player = playermapper.Get(entity)
pos, vel, render, player, collider = playermapper.Get(entity)
playerobserver.AddEntity(entity)
speed.Value = config.PLAYERSPEED
vel.Speed = config.PLAYERSPEED
player.IsPrimary = tile.IsPrimary
player.Sprites = tile.Tiles
collider.CollisionHandler = handlers.HandlePlayerCollision
collider.EdgeHandler = handlers.HandlePlayerEdgeBump
case tile.Collectible:
entity := colmapper.New()
pos, render, _ = colmapper.Get(entity)
entityobserver.AddEntity(entity)
case tile.Obstacle:
entity := obsmapper.New()
pos, vel, render, speed, _ = obsmapper.Get(entity)
pos, vel, render, _ = obsmapper.Get(entity)
vel.Direction = tile.Direction
vel.PointingAt = tile.Direction
speed.Value = config.PLAYERSPEED
vel.Speed = config.PLAYERSPEED
obstacleobserver.AddEntity(entity)
entityobserver.AddEntity(entity)
case tile.Transient:
entity := transmapper.New()
pos, render, transient = transmapper.Get(entity)
transient.Sprites = tile.TileNames
entityobserver.AddEntity(entity)
case tile.Destroyable:
entity := doormapper.New()
pos, render, destroyable = doormapper.Get(entity)
destroyable.Sprites = tile.Tiles
entityobserver.AddEntity(entity)
default:
log.Fatalln("unsupported tile type encountered")
}
@@ -143,7 +160,15 @@ func (grid *Grid) GetTile(
return tile
}
func (grid *Grid) SetTile(tile *assets.Tile, point image.Point) {
func (grid *Grid) RemoveTile(point image.Point) {
delete(grid.Map, point)
}
func (grid *Grid) SetFloorTile(point image.Point) {
grid.Map[point] = assets.Tiles[' ']
}
func (grid *Grid) SetSolidTile(tile *assets.Tile, point image.Point) {
solidmapper := generic.NewMap4[
components.Position,
components.Renderable,

View File

@@ -0,0 +1,25 @@
package handlers
import (
"openquell/components"
. "openquell/config"
)
// type Collider struct {
// CollisionHandler func(*Position, *Position, *Velocity) bool
// EdgeHandler func(*Position, *Position, *Velocity) bool
// PassoverHandler func(*Position, *Velocity) bool
// PassoverFinishedHandler func(*Position, *Velocity) bool
// }
func HandleCollectibleCollision(pos, newpos *components.Position, velocity *components.Velocity) bool {
pos.Set(newpos)
velocity.Change(Stop)
return true
}
func HandleCollectibleEdgeBump(pos, newpos *components.Position, velocity *components.Velocity) bool {
pos.Set(newpos)
return true
}

View File

@@ -0,0 +1,72 @@
package handlers
import (
"openquell/components"
. "openquell/config"
"openquell/util"
"log/slog"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
// type Collider struct {
// CollisionHandler func(*Position, *Position, *Velocity) bool
// EdgeHandler func(*Position, *Position, *Velocity) bool
// PassoverHandler func(*Position, *Velocity) bool
// PassoverFinishedHandler func(*Position, *Velocity) bool
// }
func HandlePlayerCollision(world *ecs.World, pos, newpos *components.Position,
velocity *components.Velocity, target ecs.Entity) bool {
velmapper := generic.NewMap[components.Velocity](world)
wallmapper := generic.NewMap[components.Solid](world)
obsmapper := generic.NewMap[components.Obstacle](world)
if wallmapper.Has(target) {
pos.Set(newpos)
velocity.Change(Stop)
return true
}
if obsmapper.Has(target) {
obsvelocity := velmapper.Get(target)
if CheckObstacleSide(velocity, obsvelocity.Direction) {
// player died
return false
} else {
// bumped into nonlethal obstacle side, stop the
// player, set the obstacle in motion, if possible
obsvelocity.Set(velocity)
velocity.Change(Stop)
pos.Set(newpos)
}
}
return true
}
func HandlePlayerEdgeBump(world *ecs.World, playerpos,
newpos *components.Position, velocity *components.Velocity, target ecs.Entity) bool {
playerpos.Set(newpos)
return true
}
func CheckObstacleSide(playervelocity *components.Velocity, obsdirection int) bool {
movingdirection := playervelocity.InvertDirection()
if movingdirection == Stop || movingdirection == obsdirection {
slog.Debug("Damaging obstacle collision",
"playerdirection", util.DirectionStr(playervelocity.Direction),
"obsdirection", util.DirectionStr(obsdirection),
"movingdirection", util.DirectionStr(movingdirection),
)
return true
}
return false
}

22
main.go
View File

@@ -1,11 +1,14 @@
package main
import (
"fmt"
"log"
"log/slog"
"openquell/config"
"openquell/game"
"os"
"github.com/alecthomas/repr"
"github.com/hajimehoshi/ebiten/v2"
"github.com/tlinden/yadu"
)
@@ -20,22 +23,35 @@ func main() {
ebiten.SetWindowSize(width, height)
ebiten.SetWindowTitle("openquell")
config, err := config.InitConfig()
if err != nil {
log.Fatal(err)
}
repr.Print(config)
if config.TPS > 0 {
fmt.Printf("Setting TPS to %d\n", config.TPS)
ebiten.SetMaxTPS(config.TPS)
}
logLevel := &slog.LevelVar{}
opts := &yadu.Options{
Level: logLevel,
AddSource: true,
}
logLevel.Set(slog.LevelDebug)
if config.Debug {
logLevel.Set(slog.LevelDebug)
}
handler := yadu.NewHandler(os.Stdout, opts)
debuglogger := slog.New(handler)
slog.SetDefault(debuglogger)
g := game.NewGame(width, height, cellsize, 0, game.Welcome)
g := game.NewGame(width, height, cellsize, config, game.Welcome)
err := ebiten.RunGame(g)
err = ebiten.RunGame(g)
if err != nil {
log.Fatalf("unable to run game: %s", err)
}

View File

@@ -0,0 +1,50 @@
package observers
import (
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/ecs/event"
"github.com/mlange-42/arche/generic"
"github.com/mlange-42/arche/listener"
)
// will be added as an ecs.Resource to the world so we can use it in
// CollisionSystem to dynamically make it appear or disappear
type EntityObserver struct {
// we only have one obstacle so far, if we use multiple ones, turn
// this in to a map, see player_observer.go for an example
Entities map[ecs.Entity]int
}
func NewEntityObserver(world *ecs.World) {
observer := &EntityObserver{}
observer.Entities = make(map[ecs.Entity]int)
resmanger := generic.NewResource[EntityObserver](world)
resmanger.Add(observer)
listen := listener.NewCallback(
func(world *ecs.World, event ecs.EntityEvent) {
observerID := ecs.ResourceID[EntityObserver](world)
observer := world.Resources().Get(observerID).(*EntityObserver)
observer.RemoveEntity(event.Entity)
},
event.EntityRemoved,
)
world.SetListener(&listen)
}
func GetEntityObserver(world *ecs.World) *EntityObserver {
observerID := ecs.ResourceID[EntityObserver](world)
observer := world.Resources().Get(observerID).(*EntityObserver)
return observer
}
func (observer *EntityObserver) AddEntity(entity ecs.Entity) {
observer.Entities[entity] = 1
}
func (observer *EntityObserver) RemoveEntity(entity ecs.Entity) {
observer.Entities = make(map[ecs.Entity]int)
}

BIN
src/block-grey-damage.xcf Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -53,7 +53,7 @@ func (system *CollectibleSystem) Update() error {
playerposition := (*Position)(system.World.Get(player, posID))
playervelocity := (*Velocity)(system.World.Get(player, veloID))
ok, _ := playerposition.Intersects(colposition, playervelocity)
ok, _ := colposition.Intersects(playerposition, playervelocity)
if ok {
slog.Debug("bumped into collectible", "collectible", collectible)
particlepositions = append(particlepositions, colposition)

View File

@@ -0,0 +1,92 @@
package systems
import (
"openquell/components"
. "openquell/components"
"openquell/grid"
"openquell/observers"
"github.com/hajimehoshi/ebiten/v2"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
type CollisionSystem struct {
World *ecs.World
Selector *generic.Filter4[Position, Velocity, Renderable, Collider]
GridContainer *grid.GridContainer
}
func NewCollisionSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
system := &CollisionSystem{
Selector: generic.NewFilter4[Position, Velocity, Renderable, Collider](),
GridContainer: gridcontainer,
World: world,
}
return system
}
func (system CollisionSystem) Update() error {
entityobserver := observers.GetEntityObserver(system.World)
posID := ecs.ComponentID[components.Position](system.World)
EntitiesToRemove := []ecs.Entity{}
query := system.Selector.Query(system.World)
for query.Next() {
position, velocity, _, handler := query.Get()
if velocity.Moving() {
// check if we bump agains the screen edge
ok, newpos := system.GridContainer.Grid.BumpEdge(position, velocity)
if ok {
if handler.EdgeHandler != nil {
if !handler.EdgeHandler(system.World, position, newpos, velocity, query.Entity()) {
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
}
}
} else {
// check if we collide with some solid entity
ok, tilepos := system.GridContainer.Grid.GetSolidNeighborPosition(position, velocity, true)
if ok {
intersects, newpos := tilepos.Intersects(position, velocity)
if intersects {
if handler.CollisionHandler != nil {
if !handler.CollisionHandler(system.World, position, newpos, velocity, query.Entity()) {
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
}
}
}
}
}
// check if current entity bumps into another entity
for foreign_entity := range entityobserver.Entities {
if foreign_entity == query.Entity() {
// don't check entity against itself
continue
}
foreign_position := (*Position)(system.World.Get(foreign_entity, posID))
ok, newpos := foreign_position.Intersects(position, velocity)
if ok {
if handler.CollisionHandler != nil {
if !handler.CollisionHandler(system.World, position, newpos, velocity, foreign_entity) {
EntitiesToRemove = append(EntitiesToRemove, query.Entity())
}
}
}
}
}
}
for _, entity := range EntitiesToRemove {
system.World.RemoveEntity(entity)
}
return nil
}
func (system *CollisionSystem) Draw(screen *ebiten.Image) {}

View File

@@ -0,0 +1,112 @@
package systems
import (
"log/slog"
"openquell/components"
. "openquell/components"
. "openquell/config"
"openquell/grid"
"openquell/observers"
"github.com/hajimehoshi/ebiten/v2"
"github.com/mlange-42/arche/ecs"
"github.com/mlange-42/arche/generic"
)
type DestroyableSystem struct {
World *ecs.World
Selector *generic.Filter3[Position, Renderable, Destroyable]
GridContainer *grid.GridContainer
SolidMapper generic.Map4[ // needed for replacement
components.Position,
components.Renderable,
components.Tilish,
components.Solid]
}
type DoorToRemove struct {
Entity ecs.Entity
Position *components.Position
}
func NewDestroyableSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
solidmapper := generic.NewMap4[
components.Position,
components.Renderable,
components.Tilish,
components.Solid](world)
system := &DestroyableSystem{
Selector: generic.NewFilter3[Position, Renderable, Destroyable](),
World: world,
GridContainer: gridcontainer,
SolidMapper: solidmapper,
}
return system
}
func (system *DestroyableSystem) Update() error {
playerobserver := observers.GetPlayerObserver(system.World)
posID := ecs.ComponentID[components.Position](system.World)
veloID := ecs.ComponentID[components.Velocity](system.World)
query := system.Selector.Query(system.World)
EntitiestoRemove := []*DoorToRemove{}
for query.Next() {
doorposition, renderable, door := query.Get()
for player := range playerobserver.Entities {
if !system.World.Alive(player) {
continue
}
playerposition := (*Position)(system.World.Get(player, posID))
playervelocity := (*Velocity)(system.World.Get(player, veloID))
ok, newpos := doorposition.Intersects(playerposition, playervelocity)
if ok {
// player bumped into hidden wall, activate it, snap in player
slog.Debug("bump not die", "originalpos", playerposition)
playervelocity.Change(Stop)
playerposition.Set(newpos)
if door.Activated {
// player bumps into the door a second time, now hide it
EntitiestoRemove = append(EntitiestoRemove,
&DoorToRemove{Entity: query.Entity(), Position: doorposition})
} else {
slog.Debug("activating destroyable", "doorpos", doorposition)
door.Activated = true
renderable.Image = door.GetNext()
}
}
}
}
for _, door := range EntitiestoRemove {
slog.Debug("hiding destroyable", "doorpos", door.Position.Point())
// remove door entity
system.World.RemoveEntity(door.Entity)
}
return nil
}
func (system *DestroyableSystem) Draw(screen *ebiten.Image) {
// write transients (these are no tiles!)
op := &ebiten.DrawImageOptions{}
query := system.Selector.Query(system.World)
for query.Next() {
pos, render, _ := query.Get()
op.GeoM.Reset()
op.GeoM.Translate(float64(pos.X), float64(pos.Y))
screen.DrawImage(render.Image, op)
}
}

View File

@@ -3,6 +3,7 @@ package systems
import (
"image"
"image/draw"
"log/slog"
. "openquell/components"
"github.com/hajimehoshi/ebiten/v2"
@@ -44,8 +45,8 @@ func (system *GridSystem) Update() error { return nil }
func (system *GridSystem) Draw(screen *ebiten.Image) {
op := &ebiten.DrawImageOptions{}
query := system.Selector.Query(system.World)
if !system.UseCache || query.Count() != system.Count {
slog.Debug("entity number changes", "old", system.Count, "current", query.Count())
// map not cached or cacheable, write it to the cache
draw.Draw(system.Cache, system.Background.Bounds(), system.Background, image.ZP, draw.Src)
@@ -54,6 +55,7 @@ func (system *GridSystem) Draw(screen *ebiten.Image) {
for query.Next() {
sprite, pos, _ := query.Get()
//slog.Debug("drawing sprite", "sprite", sprite, "point", pos.Point())
draw.Draw(
system.Cache,
image.Rect(pos.X, pos.Y, pos.X+pos.Cellsize, pos.Y+pos.Cellsize),

View File

@@ -17,13 +17,13 @@ import (
type ObstacleSystem struct {
World *ecs.World
Selector *generic.Filter5[Position, Velocity, Obstacle, Renderable, Speed]
Selector *generic.Filter4[Position, Velocity, Obstacle, Renderable]
GridContainer *grid.GridContainer
}
func NewObstacleSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
system := &ObstacleSystem{
Selector: generic.NewFilter5[Position, Velocity, Obstacle, Renderable, Speed](),
Selector: generic.NewFilter4[Position, Velocity, Obstacle, Renderable](),
World: world,
GridContainer: gridcontainer,
}
@@ -34,86 +34,16 @@ func NewObstacleSystem(world *ecs.World, gridcontainer *grid.GridContainer) Syst
func (system *ObstacleSystem) Update() error {
playerobserver := observers.GetPlayerObserver(system.World)
gameobserver := observers.GetGameObserver(system.World)
obstacleobserver := observers.GetObstacleObserver(system.World)
if gameobserver.Lost {
return nil
}
posID := ecs.ComponentID[components.Position](system.World)
veloID := ecs.ComponentID[components.Velocity](system.World)
var gameover bool
EntitiesToRemove := []ecs.Entity{}
query := system.Selector.Query(system.World)
gameover := false
for query.Next() {
obsposition, obsvelocity, _, _, speed := query.Get()
// check if one player has bumped into current obstacle
for player := range playerobserver.Entities {
playerposition := (*Position)(system.World.Get(player, posID))
playervelocity := (*Velocity)(system.World.Get(player, veloID))
ok, newpos := obsposition.Intersects(playerposition, playervelocity)
if ok {
// slog.Debug("bumped into obstacle", "obstacle", obstacle)
if CheckObstacleSide(playervelocity, obsvelocity.Direction) {
// player died
EntitiesToRemove = append(EntitiesToRemove, player)
gameover = true
} else {
// bumped into nonlethal obstacle side, stop the
// player, set the obstacle in motion, if possible
slog.Debug("bump not die", "originalpos", playerposition)
obsvelocity.Set(playervelocity)
playervelocity.Change(Stop)
playerposition.Set(newpos)
}
}
}
// check if current obstacle bumped into another obstacle
for foreign_obstacle := range obstacleobserver.Entities {
if foreign_obstacle == query.Entity() {
// don't check obstacle against itself
continue
}
foreign_obstacle_position := (*Position)(system.World.Get(foreign_obstacle, posID))
ok, newpos := foreign_obstacle_position.Intersects(obsposition, obsvelocity)
if ok {
//slog.Debug("bumped into foreign obstacle", "obstacle", foreign_obstacle)
obsposition.Set(newpos)
obsvelocity.ResetDirectionAndStop()
}
}
// FIXME: this is the same loop as in player_system, unite the
// two, just iterate over all entities with pos,vel,render, dammit
if obsvelocity.Moving() {
ok, tilepos := system.GridContainer.Grid.GetSolidNeighborPosition(obsposition, obsvelocity, true)
if ok {
intersects, newpos := tilepos.Intersects(obsposition, obsvelocity)
if intersects {
// slog.Debug("collision with foreign obstacle detected", "tile",
// tilepos, "obs", obsposition, "new", newpos)
obsposition.Set(newpos)
obsvelocity.ResetDirectionAndStop()
}
}
obsposition.Move(obsvelocity, speed)
}
}
for _, entity := range EntitiesToRemove {
system.World.RemoveEntity(entity)
if len(playerobserver.Entities) == 0 {
// FIXME: check this in game or elsewhere
gameover = true
}
if gameover {
@@ -136,7 +66,7 @@ func (system *ObstacleSystem) Draw(screen *ebiten.Image) {
query := system.Selector.Query(system.World)
for query.Next() {
pos, _, _, sprite, _ := query.Get()
pos, _, _, sprite := query.Get()
op.GeoM.Reset()
op.GeoM.Translate(float64(pos.X), float64(pos.Y))

View File

@@ -14,13 +14,13 @@ import (
type PlayerSystem struct {
World *ecs.World
Selector *generic.Filter5[Position, Velocity, Player, Renderable, Speed]
Selector *generic.Filter4[Position, Velocity, Player, Renderable]
GridContainer *grid.GridContainer
}
func NewPlayerSystem(world *ecs.World, gridcontainer *grid.GridContainer) System {
system := &PlayerSystem{
Selector: generic.NewFilter5[Position, Velocity, Player, Renderable, Speed](),
Selector: generic.NewFilter4[Position, Velocity, Player, Renderable](),
GridContainer: gridcontainer,
World: world,
}
@@ -33,7 +33,7 @@ func (system PlayerSystem) Update() error {
switchable := false
query := system.Selector.Query(system.World)
for query.Next() {
_, _, player, _, _ := query.Get()
_, _, player, _ := query.Get()
if !player.IsPrimary {
switchable = true
}
@@ -42,7 +42,7 @@ func (system PlayerSystem) Update() error {
if switchable {
query := system.Selector.Query(system.World)
for query.Next() {
_, _, player, render, _ := query.Get()
_, _, player, render := query.Get()
if inpututil.IsKeyJustPressed(ebiten.KeyTab) {
slog.Debug("switch players")
if player.IsPrimary {
@@ -59,7 +59,7 @@ func (system PlayerSystem) Update() error {
// check player movements etc
query = system.Selector.Query(system.World)
for query.Next() {
playerposition, velocity, player, _, _ := query.Get()
_, velocity, player, _ := query.Get()
if !player.IsPrimary {
continue
@@ -75,36 +75,34 @@ func (system PlayerSystem) Update() error {
velocity.Change(South)
case ebiten.IsKeyPressed(ebiten.KeyUp):
velocity.Change(North)
case ebiten.IsKeyPressed(ebiten.Key1):
velocity.Speed = 1
case ebiten.IsKeyPressed(ebiten.Key2):
velocity.Speed = 2
case ebiten.IsKeyPressed(ebiten.Key3):
velocity.Speed = 3
case ebiten.IsKeyPressed(ebiten.Key4):
velocity.Speed = 4
case ebiten.IsKeyPressed(ebiten.Key5):
velocity.Speed = 5
case ebiten.IsKeyPressed(ebiten.Key6):
velocity.Speed = 6
case ebiten.IsKeyPressed(ebiten.Key7):
velocity.Speed = 7
case ebiten.IsKeyPressed(ebiten.Key8):
velocity.Speed = 8
case ebiten.IsKeyPressed(ebiten.Key9):
velocity.Speed = 9
// other keys: <tab>: switch player, etc
}
}
if velocity.Moving() {
ok, newpos := system.GridContainer.Grid.BumpEdge(playerposition, velocity)
if ok {
//slog.Debug("falling off the edge", "newpos", newpos)
playerposition.Set(newpos)
} else {
ok, tilepos := system.GridContainer.Grid.GetSolidNeighborPosition(playerposition, velocity, true)
if ok {
intersects, newpos := tilepos.Intersects(playerposition, velocity)
if intersects {
// slog.Debug("collision detected", "tile",
// tilepos, "player", playerposition, "new", newpos)
playerposition.Set(newpos)
velocity.Change(Stop)
}
}
}
}
}
query = system.Selector.Query(system.World)
for query.Next() {
// move player after obstacle or collectible updates
playerposition, velocity, _, _, speed := query.Get()
playerposition.Move(velocity, speed)
playerposition, velocity, _, _ := query.Get()
playerposition.Move(velocity)
}
return nil
@@ -116,7 +114,7 @@ func (system *PlayerSystem) Draw(screen *ebiten.Image) {
query := system.Selector.Query(system.World)
for query.Next() {
pos, _, _, sprite, _ := query.Get()
pos, _, _, sprite := query.Get()
op.GeoM.Reset()
op.GeoM.Translate(float64(pos.X), float64(pos.Y))

View File

@@ -60,6 +60,10 @@ func (system *TransientSystem) Update() error {
transientposition, _, transient := query.Get()
for player := range playerobserver.Entities {
if !system.World.Alive(player) {
continue
}
playerposition := (*Position)(system.World.Get(player, posID))
playervelocity := (*Velocity)(system.World.Get(player, veloID))
@@ -95,7 +99,7 @@ func (system *TransientSystem) Update() error {
// also setup the grid tile with a new solid, so that
// collision detection works
system.GridContainer.Grid.SetTile(
system.GridContainer.Grid.SetSolidTile(
assets.NewTileBlock(convertible.NewSprite),
convertible.Position.Point(),
)