Rewrite as client for bgammon.org
This commit is contained in:
parent
67cb241e1e
commit
fe9268f21e
16 changed files with 417 additions and 766 deletions
141
LICENSE
141
LICENSE
|
@ -1,5 +1,5 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
|
@ -7,17 +7,15 @@
|
|||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
software for all its users.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
|
@ -26,44 +24,34 @@ them if you wish), that you receive source code or can get it if you
|
|||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
@ -72,7 +60,7 @@ modification follow.
|
|||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
@ -549,35 +537,45 @@ to collect a royalty for further conveying from those to whom you convey
|
|||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
the GNU Affero General Public License from time to time. Such new versions
|
||||
will be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Program specifies that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
|
@ -635,40 +633,29 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
|
41
README.md
41
README.md
|
@ -1,43 +1,16 @@
|
|||
# boxcars
|
||||
[![Donate](https://img.shields.io/liberapay/receives/rocketnine.space.svg?logo=liberapay)](https://liberapay.com/rocketnine.space)
|
||||
|
||||
Online backgammon client ([FIBS](http://fibs.com))
|
||||
# boxcars - Graphical backgammon client for bgammon.org
|
||||
[![Donate](https://img.shields.io/liberapay/receives/rocket9labs.com.svg?logo=liberapay)](https://liberapay.com/rocket9labs.com)
|
||||
|
||||
**Note:** This application is in pre-alpha state. Here be dragons.
|
||||
|
||||
## Play
|
||||
|
||||
There are several ways to play Boxcars.
|
||||
|
||||
### Browser (recommended)
|
||||
|
||||
Visit https://boxcars.rocketnine.space
|
||||
|
||||
### Desktop
|
||||
|
||||
**Note:** You will need to install the dependencies listed for [your platform](https://github.com/hajimehoshi/ebiten/blob/main/README.md#platforms).
|
||||
|
||||
Run the following command to build a `boxcars` executable:
|
||||
|
||||
`go install code.rocketnine.space/tslocum/boxcars@latest`
|
||||
|
||||
Run `~/go/bin/boxcars` to play.
|
||||
|
||||
### Android
|
||||
|
||||
*Coming soon*
|
||||
|
||||
## Gameplay notes
|
||||
|
||||
- To bear off a piece, drag it from your home on to the bar.
|
||||
|
||||
## Support
|
||||
|
||||
Please share issues and suggestions [here](https://code.rocketnine.space/tslocum/boxcars/issues).
|
||||
Please share issues and suggestions [here](https://code.rocket9labs.com/tslocum/boxcars/issues).
|
||||
|
||||
## Dependencies
|
||||
|
||||
- [ebiten](https://github.com/hajimehoshi/ebiten) - 2D game engine
|
||||
- [draw2d](https://github.com/llgcode/draw2d) - 2D shape drawing
|
||||
- [kibodo](https://code.rocketnine.space/tslocum/kibodo) - On-screen keyboard
|
||||
- [ebitengine](https://github.com/hajimehoshi/ebiten) - Game engine
|
||||
- [draw2d](https://github.com/llgcode/draw2d) - Shape drawing
|
||||
- [messeji](https://code.rocket9labs.com/tslocum/messeji) - Text display and input widgets
|
||||
- [kibodo](https://code.rocket9labs.com/tslocum/kibodo) - On-screen keyboard
|
||||
- [resize](https://github.com/nfnt/resize) - Image resizing
|
||||
|
|
|
@ -3,12 +3,6 @@
|
|||
|
||||
package main
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/fibs"
|
||||
)
|
||||
|
||||
func init() {
|
||||
fibs.DefaultProxyAddress = "wss://fibsproxy.rocketnine.space"
|
||||
|
||||
AutoWatch = true
|
||||
}
|
||||
|
|
4
flags.go
4
flags.go
|
@ -6,13 +6,13 @@ package main
|
|||
import (
|
||||
"flag"
|
||||
|
||||
"code.rocketnine.space/tslocum/boxcars/game"
|
||||
"code.rocket9labs.com/tslocum/boxcars/game"
|
||||
)
|
||||
|
||||
func parseFlags(g *game.Game) {
|
||||
flag.StringVar(&g.Username, "username", "", "Username")
|
||||
flag.StringVar(&g.Password, "password", "", "Password")
|
||||
flag.StringVar(&g.ServerAddress, "address", "fibs.com:4321", "Server address")
|
||||
flag.StringVar(&g.ServerAddress, "address", game.DefaultServerAddress, "Server address")
|
||||
flag.BoolVar(&g.Watch, "watch", false, "Watch random game")
|
||||
flag.BoolVar(&g.TV, "tv", false, "Watch random games continuously")
|
||||
flag.IntVar(&g.Debug, "debug", 0, "Print debug information")
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"net/http"
|
||||
"syscall/js"
|
||||
|
||||
"code.rocketnine.space/tslocum/boxcars/game"
|
||||
"code.rocket9labs.com/tslocum/boxcars/game"
|
||||
)
|
||||
|
||||
func parseFlags(g *game.Game) {
|
||||
|
|
159
game/board.go
159
game/board.go
|
@ -8,8 +8,9 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/fibs"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
|
@ -30,8 +31,8 @@ type board struct {
|
|||
|
||||
Sprites *Sprites
|
||||
|
||||
spaces [][]*Sprite // Space contents
|
||||
spaceRects [][4]int
|
||||
spaceSprites [][]*Sprite // Space contents
|
||||
spaceSpriteRects [][4]int
|
||||
|
||||
dragging *Sprite
|
||||
moving *Sprite // Moving automatically
|
||||
|
@ -46,16 +47,15 @@ type board struct {
|
|||
verticalBorderSize float64
|
||||
overlapSize float64
|
||||
|
||||
lastDirection int
|
||||
lastPlayerNumber int
|
||||
|
||||
s []string
|
||||
v []int
|
||||
gameState *bgammon.GameState
|
||||
|
||||
drawFrame chan bool
|
||||
|
||||
debug int // Print and draw debug information
|
||||
|
||||
Client *fibs.Client
|
||||
Client *Client
|
||||
|
||||
dragX, dragY int
|
||||
}
|
||||
|
@ -71,11 +71,12 @@ func NewBoard() *board {
|
|||
sprites: make([]*Sprite, 30),
|
||||
num: 30,
|
||||
},
|
||||
spaces: make([][]*Sprite, 26),
|
||||
spaceRects: make([][4]int, 26),
|
||||
s: make([]string, 2),
|
||||
v: make([]int, 42),
|
||||
drawFrame: make(chan bool, 10),
|
||||
spaceSprites: make([][]*Sprite, 26),
|
||||
spaceSpriteRects: make([][4]int, 26),
|
||||
drawFrame: make(chan bool, 10),
|
||||
gameState: &bgammon.GameState{
|
||||
Game: bgammon.NewGame(),
|
||||
},
|
||||
}
|
||||
|
||||
for i := range b.Sprites.sprites {
|
||||
|
@ -92,7 +93,7 @@ func NewBoard() *board {
|
|||
}
|
||||
}
|
||||
|
||||
b.spaces[space] = append(b.spaces[space], s)
|
||||
b.spaceSprites[space] = append(b.spaceSprites[space], s)
|
||||
}
|
||||
|
||||
go b.handleDraw()
|
||||
|
@ -373,7 +374,7 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
|
||||
b.iterateSpaces(func(space int) {
|
||||
var numPieces int
|
||||
for i, sprite := range b.spaces[space] {
|
||||
for i, sprite := range b.spaceSprites[space] {
|
||||
if sprite == b.dragging || sprite == b.moving {
|
||||
continue
|
||||
}
|
||||
|
@ -448,7 +449,7 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
opponentColor := color.Black
|
||||
playerBorderColor := lightCheckerColor
|
||||
opponentBorderColor := darkCheckerColor
|
||||
if b.v[fibs.StatePlayerColor] == -1 {
|
||||
if b.gameState.PlayerNumber == 1 {
|
||||
playerColor = color.Black
|
||||
opponentColor = color.White
|
||||
playerBorderColor = darkCheckerColor
|
||||
|
@ -481,10 +482,11 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
return img
|
||||
}
|
||||
|
||||
if b.s[fibs.StateOpponentName] != "" {
|
||||
label := fmt.Sprintf("%s %d %d", b.s[fibs.StateOpponentName], b.v[fibs.StateOpponentDice1], b.v[fibs.StateOpponentDice2])
|
||||
opponent := b.gameState.OpponentPlayer()
|
||||
if opponent.Name != "" {
|
||||
label := fmt.Sprintf("%s %d %d", opponent.Name, b.gameState.Roll1, b.gameState.Roll2)
|
||||
|
||||
img := drawLabel(label, opponentColor, b.v[fibs.StateTurn] != b.v[fibs.StatePlayerColor], opponentBorderColor)
|
||||
img := drawLabel(label, opponentColor, b.gameState.Turn != b.gameState.PlayerNumber, opponentBorderColor)
|
||||
bounds := img.Bounds()
|
||||
|
||||
x := int(((float64(b.innerW) - borderSize) / 4) - (float64(bounds.Dx()) / 2))
|
||||
|
@ -497,10 +499,11 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
|
||||
// Draw player name and dice
|
||||
|
||||
if b.s[fibs.StatePlayerName] != "" {
|
||||
label := fmt.Sprintf("%s %d %d", b.s[fibs.StatePlayerName], b.v[fibs.StatePlayerDice1], b.v[fibs.StatePlayerDice2])
|
||||
player := b.gameState.LocalPlayer()
|
||||
if player.Name != "" {
|
||||
label := fmt.Sprintf("%s %d %d", player.Name, b.gameState.Roll1, b.gameState.Roll2)
|
||||
|
||||
img := drawLabel(label, playerColor, b.v[fibs.StateTurn] == b.v[fibs.StatePlayerColor], playerBorderColor)
|
||||
img := drawLabel(label, playerColor, b.gameState.Turn == b.gameState.PlayerNumber, playerBorderColor)
|
||||
bounds := img.Bounds()
|
||||
|
||||
x := ((b.innerW / 4) * 3) - (bounds.Dx() / 2)
|
||||
|
@ -512,7 +515,7 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
|
||||
}
|
||||
|
||||
if len(b.Client.Board.GetPreMoves()) > 0 {
|
||||
if len(b.gameState.Moves) > 0 {
|
||||
x, y, w, h := b.resetButtonRect()
|
||||
baseImg := image.NewRGBA(image.Rect(0, 0, w, h))
|
||||
|
||||
|
@ -549,7 +552,7 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
}
|
||||
|
||||
if b.debug == 2 {
|
||||
homeStart, homeEnd := b.Client.Board.PlayerHomeSpaces()
|
||||
homeStart, homeEnd := bgammon.HomeRange(b.gameState.PlayerNumber)
|
||||
b.iterateSpaces(func(space int) {
|
||||
x, y, w, h := b.spaceRect(space)
|
||||
spaceImage := ebiten.NewImage(w, h)
|
||||
|
@ -557,9 +560,9 @@ func (b *board) draw(screen *ebiten.Image) {
|
|||
if space >= homeStart && space <= homeEnd {
|
||||
br += "H"
|
||||
}
|
||||
if space == b.Client.Board.PlayerBarSpace() {
|
||||
if space == bgammon.SpaceBarPlayer {
|
||||
br += "(PB)"
|
||||
} else if space == 25-b.Client.Board.PlayerBarSpace() {
|
||||
} else if space == bgammon.SpaceBarOpponent {
|
||||
br += "(OB)"
|
||||
}
|
||||
ebitenutil.DebugPrint(spaceImage, fmt.Sprintf(" %d %s", space, br))
|
||||
|
@ -629,7 +632,7 @@ func (b *board) offsetPosition(x, y int) (int, int) {
|
|||
// Do not call _positionCheckers directly. Call ProcessState instead.
|
||||
func (b *board) _positionCheckers() {
|
||||
for space := 0; space < 26; space++ {
|
||||
sprites := b.spaces[space]
|
||||
sprites := b.spaceSprites[space]
|
||||
|
||||
for i := range sprites {
|
||||
s := sprites[i]
|
||||
|
@ -652,7 +655,7 @@ func (b *board) spriteAt(x, y int) *Sprite {
|
|||
if space == -1 {
|
||||
return nil
|
||||
}
|
||||
pieces := b.spaces[space]
|
||||
pieces := b.spaceSprites[space]
|
||||
if len(pieces) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
@ -677,7 +680,7 @@ func (b *board) iterateSpaces(f func(space int)) {
|
|||
}
|
||||
|
||||
func (b *board) translateSpace(space int) int {
|
||||
if b.v[fibs.StateDirection] == -1 {
|
||||
/*if b.gameState.PlayerNumber == 2 {
|
||||
// Spaces range from 24 - 1.
|
||||
if space == 0 || space == 25 {
|
||||
space = 25 - space
|
||||
|
@ -686,7 +689,8 @@ func (b *board) translateSpace(space int) int {
|
|||
} else {
|
||||
space = space - 12
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// TODO
|
||||
return space
|
||||
}
|
||||
|
||||
|
@ -728,13 +732,13 @@ func (b *board) setSpaceRects() {
|
|||
|
||||
h = int((float64(b.h) - (b.verticalBorderSize * 2)) / 2)
|
||||
|
||||
b.spaceRects[trueSpace] = [4]int{x, y, w, h}
|
||||
b.spaceSpriteRects[trueSpace] = [4]int{x, y, w, h}
|
||||
}
|
||||
}
|
||||
|
||||
// relX, relY
|
||||
func (b *board) spaceRect(space int) (x, y, w, h int) {
|
||||
rect := b.spaceRects[space]
|
||||
rect := b.spaceSpriteRects[space]
|
||||
return rect[0], rect[1], rect[2], rect[3]
|
||||
}
|
||||
|
||||
|
@ -742,7 +746,7 @@ func (b *board) bottomRow(space int) bool {
|
|||
bottomStart := 1
|
||||
bottomEnd := 12
|
||||
bottomBar := 25
|
||||
if b.v[fibs.StateDirection] == 1 {
|
||||
if b.gameState.PlayerNumber == 2 {
|
||||
bottomStart = 13
|
||||
bottomEnd = 24
|
||||
bottomBar = 0
|
||||
|
@ -784,38 +788,20 @@ func (b *board) stackSpaceRect(space int, stack int) (x, y, w, h int) {
|
|||
return x, y, w, h
|
||||
}
|
||||
|
||||
func (b *board) SetState(s []string, v []int) {
|
||||
log.Printf("OLD %+v", b.v)
|
||||
log.Printf("NEW %+v", v)
|
||||
|
||||
for i := 0; i < 26; i++ {
|
||||
var str string
|
||||
if b.v[fibs.StateBoardSpace0+i] != v[fibs.StateBoardSpace0+i] {
|
||||
str = "^^^"
|
||||
}
|
||||
log.Printf("SPACE %d WAS %d, NOW %d %s", i, b.v[fibs.StateBoardSpace0+i], v[fibs.StateBoardSpace0+i], str)
|
||||
}
|
||||
copy(b.s, s)
|
||||
copy(b.v, v)
|
||||
b.ProcessState()
|
||||
}
|
||||
|
||||
func (b *board) ProcessState() {
|
||||
v := b.v
|
||||
|
||||
if b.lastDirection != v[fibs.StateDirection] {
|
||||
if b.lastPlayerNumber != b.gameState.PlayerNumber {
|
||||
b.setSpaceRects()
|
||||
}
|
||||
b.lastDirection = v[fibs.StateDirection]
|
||||
b.lastPlayerNumber = b.gameState.PlayerNumber
|
||||
|
||||
b.Sprites = &Sprites{}
|
||||
b.spaces = make([][]*Sprite, 26)
|
||||
for space := 0; space < 26; space++ {
|
||||
spaceValue := v[fibs.StateBoardSpace0+space]
|
||||
b.spaceSprites = make([][]*Sprite, 26)
|
||||
for space := 0; space < bgammon.BoardSpaces; space++ {
|
||||
spaceValue := b.gameState.Board[space]
|
||||
|
||||
white := spaceValue > 0
|
||||
if spaceValue == 0 {
|
||||
white = v[fibs.StatePlayerColor] == 1
|
||||
white = b.gameState.PlayerNumber == 2
|
||||
}
|
||||
|
||||
abs := spaceValue
|
||||
|
@ -825,18 +811,19 @@ func (b *board) ProcessState() {
|
|||
|
||||
var preMovesTo int
|
||||
var preMovesFrom int
|
||||
if b.Client != nil {
|
||||
/*if b.Client != nil {
|
||||
preMovesTo = b.Client.Board.Premoveto[space]
|
||||
preMovesFrom = b.Client.Board.Premovefrom[space]
|
||||
}
|
||||
}*/
|
||||
// TODO
|
||||
|
||||
for i := 0; i < abs+(preMovesTo-preMovesFrom); i++ {
|
||||
s := b.newSprite(white)
|
||||
if i >= abs {
|
||||
s.colorWhite = v[fibs.StatePlayerColor] == 1
|
||||
s.colorWhite = b.gameState.PlayerNumber == 2
|
||||
s.premove = true
|
||||
}
|
||||
b.spaces[space] = append(b.spaces[space], s)
|
||||
b.spaceSprites[space] = append(b.spaceSprites[space], s)
|
||||
b.Sprites.sprites = append(b.Sprites.sprites, s)
|
||||
}
|
||||
}
|
||||
|
@ -847,15 +834,15 @@ func (b *board) ProcessState() {
|
|||
|
||||
// _movePiece returns after moving the piece.
|
||||
func (b *board) _movePiece(sprite *Sprite, from int, to int, speed int, pause bool) {
|
||||
moveTime := (750 * time.Millisecond) / time.Duration(speed)
|
||||
pauseTime := 500 * time.Millisecond
|
||||
moveTime := (650 * time.Millisecond) / time.Duration(speed)
|
||||
pauseTime := 250 * time.Millisecond
|
||||
|
||||
b.moving = sprite
|
||||
|
||||
space := to // Immediately go to target space
|
||||
|
||||
stack := len(b.spaces[space])
|
||||
if stack == 1 && sprite.colorWhite != b.spaces[space][0].colorWhite {
|
||||
stack := len(b.spaceSprites[space])
|
||||
if stack == 1 && sprite.colorWhite != b.spaceSprites[space][0].colorWhite {
|
||||
stack = 0 // Hit
|
||||
} else if space != to {
|
||||
stack++
|
||||
|
@ -879,16 +866,16 @@ func (b *board) _movePiece(sprite *Sprite, from int, to int, speed int, pause bo
|
|||
ebiten.ScheduleFrame()
|
||||
|
||||
/*homeSpace := b.Client.Board.PlayerHomeSpace()
|
||||
if b.v[fibs.StateTurn] != b.v[fibs.StatePlayerColor] {
|
||||
if b.gameState.Turn != b.gameState.Player {
|
||||
homeSpace = 25 - homeSpace
|
||||
}
|
||||
|
||||
if to != homeSpace {*/
|
||||
b.spaces[to] = append(b.spaces[to], sprite)
|
||||
b.spaceSprites[to] = append(b.spaceSprites[to], sprite)
|
||||
/*}*/
|
||||
for i, s := range b.spaces[from] {
|
||||
for i, s := range b.spaceSprites[from] {
|
||||
if s == sprite {
|
||||
b.spaces[from] = append(b.spaces[from][:i], b.spaces[from][i+1:]...)
|
||||
b.spaceSprites[from] = append(b.spaceSprites[from][:i], b.spaceSprites[from][i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -903,7 +890,7 @@ func (b *board) _movePiece(sprite *Sprite, from int, to int, speed int, pause bo
|
|||
|
||||
// movePiece returns when finished moving the piece.
|
||||
func (b *board) movePiece(from int, to int) {
|
||||
pieces := b.spaces[from]
|
||||
pieces := b.spaceSprites[from]
|
||||
if len(pieces) == 0 {
|
||||
log.Printf("%d-%d: NO PIECES AT SPACE %d", from, to, from)
|
||||
os.Exit(1)
|
||||
|
@ -913,17 +900,17 @@ func (b *board) movePiece(from int, to int) {
|
|||
sprite := pieces[len(pieces)-1]
|
||||
|
||||
var moveAfter *Sprite
|
||||
if len(b.spaces[to]) == 1 {
|
||||
if sprite.colorWhite != b.spaces[to][0].colorWhite {
|
||||
moveAfter = b.spaces[to][0]
|
||||
if len(b.spaceSprites[to]) == 1 {
|
||||
if sprite.colorWhite != b.spaceSprites[to][0].colorWhite {
|
||||
moveAfter = b.spaceSprites[to][0]
|
||||
}
|
||||
}
|
||||
|
||||
b._movePiece(sprite, from, to, 1, moveAfter == nil)
|
||||
if moveAfter != nil {
|
||||
bar := b.Client.Board.PlayerBarSpace()
|
||||
if b.v[fibs.StateTurn] == b.v[fibs.StatePlayerColor] {
|
||||
bar = 25 - bar
|
||||
bar := bgammon.SpaceBarOpponent
|
||||
if b.gameState.Turn == b.gameState.PlayerNumber {
|
||||
bar = bgammon.SpaceBarPlayer
|
||||
}
|
||||
b._movePiece(moveAfter, to, bar, 1, true)
|
||||
}
|
||||
|
@ -931,16 +918,16 @@ func (b *board) movePiece(from int, to int) {
|
|||
|
||||
// WatchingGame returns whether the active game is being watched.
|
||||
func (b *board) watchingGame() bool {
|
||||
return !b.playingGame() && b.s[fibs.StatePlayerName] != "" && b.s[fibs.StateOpponentName] != ""
|
||||
return !b.playingGame() && false // TODO
|
||||
}
|
||||
|
||||
// PlayingGame returns whether the active game is being played.
|
||||
func (b *board) playingGame() bool {
|
||||
return b.s[fibs.StatePlayerName] == "You" || b.s[fibs.StateOpponentName] == "You"
|
||||
return b.gameState.Player1.Name != "" || b.gameState.Player2.Name != ""
|
||||
}
|
||||
|
||||
func (b *board) playerTurn() bool {
|
||||
return b.playingGame() && b.v[fibs.StateTurn] == b.v[fibs.StatePlayerColor]
|
||||
return b.playingGame() && b.gameState.Turn == b.gameState.PlayerNumber
|
||||
}
|
||||
|
||||
func (b *board) update() {
|
||||
|
@ -952,14 +939,15 @@ func (b *board) update() {
|
|||
// TODO allow grabbing multiple pieces by grabbing further down the stack
|
||||
|
||||
handleReset := func(x, y int) bool {
|
||||
if len(b.Client.Board.GetPreMoves()) > 0 {
|
||||
/*if len(b.gameState.Moves) > 0 {
|
||||
rx, ry, rw, rh := b.resetButtonRect()
|
||||
if x >= rx && x <= rx+rw && y >= ry && y <= ry+rh {
|
||||
b.Client.Board.ResetPreMoves()
|
||||
b.ProcessState()
|
||||
return true
|
||||
}
|
||||
}
|
||||
}*/
|
||||
panic("RESET") // TODO
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -1017,17 +1005,18 @@ func (b *board) update() {
|
|||
if dropped != nil {
|
||||
index := b.spaceAt(x, y)
|
||||
// Bear off by dragging outside the board.
|
||||
if index == fibs.SpaceUnknown && b.Client.Board.PlayerPieceAreHome() {
|
||||
index = b.Client.Board.PlayerBearOffSpace()
|
||||
if index == -1 {
|
||||
// TODO check if all pieces are home
|
||||
index = bgammon.SpaceHomePlayer
|
||||
}
|
||||
if index >= 0 && b.Client != nil {
|
||||
ADDPREMOVE:
|
||||
for space, pieces := range b.spaces {
|
||||
for space, pieces := range b.spaceSprites {
|
||||
for _, piece := range pieces {
|
||||
if piece == dropped {
|
||||
if space != index {
|
||||
b.Client.Board.SetSelection(1, space)
|
||||
b.Client.Board.AddPreMove(space, index)
|
||||
//b.Client.Board.SetSelection(1, space)
|
||||
b.Client.Out <- []byte(fmt.Sprintf("move %d/%d", space, index))
|
||||
}
|
||||
break ADDPREMOVE
|
||||
}
|
||||
|
|
1
game/buffer.go
Normal file
1
game/buffer.go
Normal file
|
@ -0,0 +1 @@
|
|||
package game
|
117
game/client.go
Normal file
117
game/client.go
Normal file
|
@ -0,0 +1,117 @@
|
|||
package game
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/gobwas/ws/wsutil"
|
||||
|
||||
"code.rocket9labs.com/tslocum/bgammon"
|
||||
|
||||
"github.com/gobwas/ws"
|
||||
)
|
||||
|
||||
type Client struct {
|
||||
Address string
|
||||
Username string
|
||||
Password string
|
||||
Events chan interface{}
|
||||
Out chan []byte
|
||||
conn *net.TCPConn
|
||||
}
|
||||
|
||||
func newClient(address string, username string, password string) *Client {
|
||||
const bufferSize = 10
|
||||
return &Client{
|
||||
Address: address,
|
||||
Username: username,
|
||||
Password: password,
|
||||
Events: make(chan interface{}, bufferSize),
|
||||
Out: make(chan []byte, bufferSize),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) Connect() {
|
||||
if c.conn != nil {
|
||||
return // TODO reconnect
|
||||
}
|
||||
|
||||
conn, br, _, err := ws.Dial(context.Background(), c.Address)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
c.conn = conn.(*net.TCPConn)
|
||||
|
||||
if br != nil {
|
||||
ws.PutReader(br)
|
||||
}
|
||||
|
||||
// Log in.
|
||||
loginInfo := c.Username
|
||||
if c.Username != "" && c.Password != "" {
|
||||
loginInfo = fmt.Sprintf("%s %s", c.Username, c.Password)
|
||||
}
|
||||
c.Out <- []byte(fmt.Sprintf("lj %s\nlist\n", loginInfo))
|
||||
|
||||
go c.handleWrite()
|
||||
c.handleRead()
|
||||
}
|
||||
func (c *Client) handleWrite() {
|
||||
for buf := range c.Out {
|
||||
split := bytes.Split(buf, []byte("\n"))
|
||||
for i := range split {
|
||||
if len(split[i]) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
err := wsutil.WriteClientMessage(c.conn, ws.OpText, split[i])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
//if debug > 0 {
|
||||
log.Println(fmt.Sprintf("-> %s", split[i]))
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) handleRead() {
|
||||
if c.conn == nil {
|
||||
panic("nil con")
|
||||
}
|
||||
|
||||
var messages []wsutil.Message
|
||||
var err error
|
||||
|
||||
var i int
|
||||
for {
|
||||
log.Printf("READ FRAME %d", i)
|
||||
i++
|
||||
|
||||
messages, err = wsutil.ReadServerMessage(c.conn, messages[:0])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
for _, msg := range messages {
|
||||
ev, err := bgammon.DecodeEvent(msg.Payload)
|
||||
if err != nil {
|
||||
log.Printf("message: %s", msg.Payload)
|
||||
panic(err)
|
||||
}
|
||||
c.Events <- ev
|
||||
|
||||
//if debug > 0 {
|
||||
log.Println(fmt.Sprintf("<- %s", msg.Payload))
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Client) LoggedIn() bool {
|
||||
return c.conn != nil
|
||||
}
|
96
game/game.go
96
game/game.go
|
@ -14,7 +14,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"code.rocketnine.space/tslocum/fibs"
|
||||
"code.rocketnine.space/tslocum/messeji"
|
||||
|
||||
"code.rocketnine.space/tslocum/kibodo"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||
|
@ -33,6 +34,28 @@ var debugExtra []byte
|
|||
|
||||
var debugGame *Game
|
||||
|
||||
var mplusNormalFont font.Face
|
||||
|
||||
func init() {
|
||||
tt, err := opentype.Parse(fonts.MPlus1pRegular_ttf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
const dpi = 72
|
||||
mplusNormalFont, err = opentype.NewFace(tt, &opentype.FaceOptions{
|
||||
Size: 28,
|
||||
DPI: dpi,
|
||||
Hinting: font.HintingFull,
|
||||
})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
StatusWriter = messeji.NewTextField(mplusNormalFont)
|
||||
GameWriter = messeji.NewTextField(mplusNormalFont)
|
||||
}
|
||||
|
||||
var (
|
||||
imgCheckerLight *ebiten.Image
|
||||
imgCheckerDark *ebiten.Image
|
||||
|
@ -41,6 +64,9 @@ var (
|
|||
mediumFont font.Face
|
||||
monoFont font.Face
|
||||
largeFont font.Face
|
||||
|
||||
StatusWriter *messeji.TextField
|
||||
GameWriter *messeji.TextField
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -48,7 +74,7 @@ var (
|
|||
darkCheckerColor = color.RGBA{0, 0, 0, 255}
|
||||
)
|
||||
|
||||
const defaultServerAddress = "fibs.com:4321"
|
||||
const DefaultServerAddress = "ws://localhost:1338" // TODO
|
||||
|
||||
const maxStatusWidthRatio = 0.5
|
||||
|
||||
|
@ -179,12 +205,12 @@ type Game struct {
|
|||
Watch bool
|
||||
TV bool
|
||||
|
||||
Client *fibs.Client
|
||||
Client *Client
|
||||
|
||||
Board *board
|
||||
|
||||
lobby *lobby
|
||||
pendingWho []*fibs.WhoInfo
|
||||
pendingWho []*WhoInfo
|
||||
|
||||
runeBuffer []rune
|
||||
inputBuffer string
|
||||
|
@ -227,9 +253,6 @@ func NewGame() *Game {
|
|||
|
||||
g.statusBuffer.acceptInput = true
|
||||
|
||||
fibs.StatusWriter = NewMessageHandler(g.statusBuffer.buffers[0])
|
||||
fibs.GameWriter = NewMessageHandler(g.gameBuffer.buffers[0])
|
||||
|
||||
// TODO
|
||||
go func() {
|
||||
/*
|
||||
|
@ -253,9 +276,9 @@ func NewGame() *Game {
|
|||
}
|
||||
|
||||
func (g *Game) handleEvents() {
|
||||
for e := range g.Client.Event {
|
||||
switch event := e.(type) {
|
||||
case *fibs.EventWho:
|
||||
for ev := range g.Client.Events {
|
||||
/*switch event := e.(type) {
|
||||
case *EventWho:
|
||||
if viewBoard || g.lobby.refresh {
|
||||
g.lobby.setWhoInfo(event.Who)
|
||||
|
||||
|
@ -266,19 +289,22 @@ func (g *Game) handleEvents() {
|
|||
} else {
|
||||
g.pendingWho = event.Who
|
||||
}
|
||||
case *fibs.EventBoardState:
|
||||
case *EventBoardState:
|
||||
log.Println("EVENTBOARDSTATE START")
|
||||
g.Board.SetState(event.S, event.V)
|
||||
// set gamestate var
|
||||
// TODO
|
||||
b.ProcessState()
|
||||
log.Println("EVENTBOARDSTATE FINISH")
|
||||
case *fibs.EventMove:
|
||||
case *EventMove:
|
||||
log.Printf("EVENTMOVE START %d %d", event.From, event.To)
|
||||
g.Board.movePiece(event.From, event.To)
|
||||
log.Println("EVENTMOVE FINISH")
|
||||
case *fibs.EventDraw:
|
||||
case *EventDraw:
|
||||
log.Println("EVENTDRAW START")
|
||||
g.Board.ProcessState()
|
||||
log.Println("EVENTDRAW FINISH")
|
||||
}
|
||||
}*/
|
||||
log.Printf("EVENT %+v", ev)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -287,9 +313,9 @@ func (g *Game) Connect() {
|
|||
|
||||
address := g.ServerAddress
|
||||
if address == "" {
|
||||
address = defaultServerAddress
|
||||
address = DefaultServerAddress
|
||||
}
|
||||
g.Client = fibs.NewClient(address, g.Username, g.Password)
|
||||
g.Client = newClient(address, g.Username, g.Password)
|
||||
g.lobby.c = g.Client
|
||||
g.Board.Client = g.Client
|
||||
g.statusBuffer.client = g.Client
|
||||
|
@ -310,12 +336,7 @@ func (g *Game) Connect() {
|
|||
}()
|
||||
}
|
||||
|
||||
go func() {
|
||||
err := c.Connect()
|
||||
if err != nil {
|
||||
fibs.StatusWriter.Write([]byte(err.Error()))
|
||||
}
|
||||
}()
|
||||
go c.Connect()
|
||||
}
|
||||
|
||||
// Separate update function for all normal update logic, as Update may only be
|
||||
|
@ -454,7 +475,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
|||
|
||||
const welcomeText = `Please enter your FIBS username and password.
|
||||
If you do not have a FIBS account yet, visit
|
||||
http://www.fibs.com/help.html#register`
|
||||
http://www.com/help.html#register`
|
||||
debugBox := image.NewRGBA(image.Rect(0, 0, g.screenW, g.screenH))
|
||||
debugImg := ebiten.NewImageFromImage(debugBox)
|
||||
|
||||
|
@ -671,3 +692,30 @@ func (m *messageHandler) Write(p []byte) (n int, err error) {
|
|||
m.t.Write(p)
|
||||
return len(p), nil
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
type WhoInfo struct {
|
||||
Username string
|
||||
Opponent string
|
||||
Watching string
|
||||
Ready bool
|
||||
Away bool
|
||||
Rating int
|
||||
Experience int
|
||||
Idle int
|
||||
LoginTime int
|
||||
ClientName string
|
||||
}
|
||||
|
||||
func (w *WhoInfo) String() string {
|
||||
opponent := "In the lobby"
|
||||
if w.Opponent != "" && w.Opponent != "-" {
|
||||
opponent = "playing against " + w.Opponent
|
||||
}
|
||||
clientName := ""
|
||||
if w.ClientName != "" && w.ClientName != "-" {
|
||||
clientName = " using " + w.ClientName
|
||||
}
|
||||
return fmt.Sprintf("%s (rated %d with %d exp) is %s%s", w.Username, w.Rating, w.Experience, opponent, clientName)
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"sort"
|
||||
"strings"
|
||||
|
||||
"code.rocketnine.space/tslocum/fibs"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
|
@ -43,7 +42,7 @@ type lobby struct {
|
|||
entryH float64
|
||||
buttonBarHeight int
|
||||
|
||||
who []*fibs.WhoInfo
|
||||
who []*WhoInfo
|
||||
|
||||
touchIDs []ebiten.TouchID
|
||||
|
||||
|
@ -59,9 +58,9 @@ type lobby struct {
|
|||
|
||||
op *ebiten.DrawImageOptions
|
||||
|
||||
c *fibs.Client
|
||||
c *Client
|
||||
|
||||
inviteUser *fibs.WhoInfo
|
||||
inviteUser *WhoInfo
|
||||
invitePoints int
|
||||
|
||||
refresh bool
|
||||
|
@ -75,7 +74,7 @@ func NewLobby() *lobby {
|
|||
return l
|
||||
}
|
||||
|
||||
func (l *lobby) setWhoInfo(who []*fibs.WhoInfo) {
|
||||
func (l *lobby) setWhoInfo(who []*WhoInfo) {
|
||||
l.who = who
|
||||
|
||||
sort.Slice(l.who, func(i, j int) bool {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package mobile
|
||||
|
||||
import (
|
||||
"code.rocketnine.space/tslocum/boxcars/game"
|
||||
"code.rocket9labs.com/tslocum/boxcars/game"
|
||||
"github.com/hajimehoshi/ebiten/v2/mobile"
|
||||
)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"code.rocketnine.space/tslocum/fibs"
|
||||
"github.com/hajimehoshi/ebiten/v2"
|
||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
||||
"github.com/hajimehoshi/ebiten/v2/text"
|
||||
|
@ -61,7 +60,7 @@ type tabbedBuffers struct {
|
|||
|
||||
inputBuffer []byte
|
||||
|
||||
client *fibs.Client
|
||||
client *Client
|
||||
|
||||
chatFont font.Face
|
||||
chatFontSize int
|
||||
|
@ -247,7 +246,7 @@ func (t *tabbedBuffers) update() {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
fibs.StatusWriter.Write([]byte("* You have not connected to a server yet"))
|
||||
StatusWriter.Write([]byte("* You have not connected to a server yet"))
|
||||
}
|
||||
t.inputBuffer = nil
|
||||
|
||||
|
|
37
go.mod
37
go.mod
|
@ -1,29 +1,28 @@
|
|||
module code.rocketnine.space/tslocum/boxcars
|
||||
module code.rocket9labs.com/tslocum/boxcars
|
||||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
code.rocketnine.space/tslocum/fibs v0.0.0-20211112042838-16c24d47934a
|
||||
code.rocketnine.space/tslocum/kibodo v0.0.0-20211027223129-7b870790d865
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.2
|
||||
github.com/llgcode/draw2d v0.0.0-20210904075650-80aa0a2a901d
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20230913074653-cf99329267a8
|
||||
code.rocketnine.space/tslocum/kibodo v1.0.0
|
||||
code.rocketnine.space/tslocum/messeji v1.0.3
|
||||
github.com/gobwas/ws v1.3.0
|
||||
github.com/hajimehoshi/ebiten/v2 v2.5.9
|
||||
github.com/llgcode/draw2d v0.0.0-20230723155556-e595d7c7e75e
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
|
||||
golang.org/x/image v0.0.0-20211028202545-6944b10bf410
|
||||
golang.org/x/image v0.12.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be // indirect
|
||||
github.com/ebitengine/purego v0.4.0 // indirect
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect
|
||||
github.com/gobwas/httphead v0.1.0 // indirect
|
||||
github.com/gobwas/pool v0.2.1 // indirect
|
||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
|
||||
github.com/klauspost/compress v1.13.6 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.1 // indirect
|
||||
github.com/reiver/go-oi v1.0.0 // indirect
|
||||
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e // indirect
|
||||
golang.org/x/exp v0.0.0-20211111183329-cb5df436b1a8 // indirect
|
||||
golang.org/x/mobile v0.0.0-20211109191125-d61a72f26a1a // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20211112193437-faf0a1b62c6b // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
github.com/jezek/xgb v1.1.0 // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20230905200255-921286631fa9 // indirect
|
||||
golang.org/x/mobile v0.0.0-20230906132913-2077a3224571 // indirect
|
||||
golang.org/x/sync v0.3.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
)
|
||||
|
|
554
go.sum
554
go.sum
|
@ -1,523 +1,71 @@
|
|||
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=
|
||||
code.rocketnine.space/tslocum/fibs v0.0.0-20211112042838-16c24d47934a h1:iKYMwcn8EPPHRr0GyuCdTSpte0eeZSUPU+MC+fy09hg=
|
||||
code.rocketnine.space/tslocum/fibs v0.0.0-20211112042838-16c24d47934a/go.mod h1:zxixHM4hy1D4t6peJ79AcYa0lCl5+PaeAybgaRD2qp0=
|
||||
code.rocketnine.space/tslocum/kibodo v0.0.0-20211027223129-7b870790d865 h1:Sm6hHfKceNAPvGw+zOmQm5u+TePLJgZzz8zyk2Q/HC0=
|
||||
code.rocketnine.space/tslocum/kibodo v0.0.0-20211027223129-7b870790d865/go.mod h1:pQfyfr10kXO/Cqw/T+bTDEg3Xbhjxb4vn/vaPzPW/Vk=
|
||||
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
|
||||
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/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
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/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
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/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
|
||||
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
|
||||
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
|
||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||
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/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
|
||||
github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
|
||||
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/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
|
||||
github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
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/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3 h1:ahKqKTFpO5KTPHxWZjEdPScmYaGtLo8Y4DMHoEsnp14=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/go-gl/gl v0.0.0-20180407155706-68e253793080/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
|
||||
github.com/go-gl/glfw v0.0.0-20180426074136-46a8d530c326 h1:QqWaXlVeUGwSH7hO8giZP2Y06Qjl1LWR+FWC22YQsU8=
|
||||
github.com/go-gl/glfw v0.0.0-20180426074136-46a8d530c326/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be h1:Z28GdQBfKOL8tNHjvaDn3wHDO7AzTRkmAXvHvnopp98=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be/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/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
|
||||
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-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee h1:s+21KNqlpePfkah2I+gwHF8xmJWRjooY+5248k6m4A0=
|
||||
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
|
||||
github.com/gobwas/pool v0.2.0 h1:QEmUOlnSjWtnpRGHF3SauEiOsy82Cup83Vf2LcMlnc8=
|
||||
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.0.2 h1:CoAavW/wd/kulfZmSIBt6p24n4j7tHgNVCjsfHVNUbo=
|
||||
github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM=
|
||||
github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20230913074653-cf99329267a8 h1:wdSojaTDI9adSY/4exRCTwaon8BOLecQBSmvb5S4r7Q=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20230913074653-cf99329267a8/go.mod h1:LS/m5Zq7/93dP8XJrLkL1T5ZTwtddkN8X9TyRrrdCkQ=
|
||||
code.rocketnine.space/tslocum/kibodo v1.0.0 h1:/xs59UCuo+NGs89ABilARlowQnmIsjbNVjss57W5O7k=
|
||||
code.rocketnine.space/tslocum/kibodo v1.0.0/go.mod h1:xYmBfho98sIbB+Gtf8SU5GDQD9HOSqOtZ64eZnlHmRI=
|
||||
code.rocketnine.space/tslocum/messeji v1.0.3 h1:o0HqUckStFUFE2SkYrkzRHoAY7QT7cTsuRQ7JEmfw6w=
|
||||
code.rocketnine.space/tslocum/messeji v1.0.3/go.mod h1:bSXsyjvKhFXQ7GsUxWZdO2JX83xOT/VTqFCR04thk+c=
|
||||
github.com/ebitengine/purego v0.4.0 h1:RQVuMIxQPQ5iCGEJvjQ17YOK+1tMKjVau2FUMvXH4HE=
|
||||
github.com/ebitengine/purego v0.4.0/go.mod h1:ah1In8AOtksoNK6yk5z1HTJeUkC1Ez4Wk2idgGslMwQ=
|
||||
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/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
|
||||
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
|
||||
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
||||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.3.0 h1:sbeU3Y4Qzlb+MOzIe6mQGf7QR4Hkv6ZD0qhGkBFL2O0=
|
||||
github.com/gobwas/ws v1.3.0/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
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/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
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.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls=
|
||||
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/btree v1.0.0/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.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
|
||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
|
||||
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.1.3 h1:JefUkL0M4nrdVwVq7MMZxSTh6mSxOylm+C4Anoucbb0=
|
||||
github.com/hajimehoshi/bitmapfont/v2 v2.1.3/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.1/go.mod h1:olKl/qqhMBBAm2oI7Zy292nCtE+nitlmYKNF3UpbFn0=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.2 h1:92E+ogdNyH1P/LlvMQ7vonbFDh6bl+O7Ak+H1HX0RX8=
|
||||
github.com/hajimehoshi/ebiten/v2 v2.2.2/go.mod h1:olKl/qqhMBBAm2oI7Zy292nCtE+nitlmYKNF3UpbFn0=
|
||||
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
|
||||
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
|
||||
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
|
||||
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-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
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.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
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/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
|
||||
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
|
||||
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
|
||||
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
|
||||
github.com/jakecoffman/cp v1.1.0/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 h1:dy+DS31tGEGCsZzB45HmJJNHjur8GDgtRNX9U7HnSX4=
|
||||
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240/go.mod h1:3P4UH/k22rXyHIJD2w4h2XMqPX4Of/eySEZq9L6wqc4=
|
||||
github.com/jfreymuth/oggvorbis v1.0.3/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
|
||||
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
|
||||
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
|
||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
|
||||
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/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/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/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
|
||||