Improve playfield display and scaling
This commit is contained in:
parent
4aa44246f2
commit
e6a3c0527c
13 changed files with 423 additions and 359 deletions
|
@ -1,5 +1,6 @@
|
|||
0.1.1:
|
||||
- Add game browser and support custom game creation
|
||||
- Improve playfield display and scaling
|
||||
- Add website and version to title screen
|
||||
- Kick inactive players
|
||||
|
||||
|
|
|
@ -60,7 +60,14 @@ func main() {
|
|||
|
||||
sshServer := &ssh.SSHServer{ListenAddress: listenAddressSSH, NetrisBinary: netrisBinary, NetrisAddress: netrisAddress}
|
||||
|
||||
server := game.NewServer([]game.ServerInterface{sshServer})
|
||||
logLevel := game.LogStandard
|
||||
if logVerbose {
|
||||
logLevel = game.LogVerbose
|
||||
} else if logDebug {
|
||||
logLevel = game.LogDebug
|
||||
}
|
||||
|
||||
server := game.NewServer([]game.ServerInterface{sshServer}, logLevel)
|
||||
|
||||
logger := make(chan string, game.LogQueueSize)
|
||||
go func() {
|
||||
|
@ -91,20 +98,4 @@ func main() {
|
|||
<-done
|
||||
|
||||
server.StopListening()
|
||||
|
||||
/*
|
||||
i, err := strconv.Atoi(flag.Arg(0))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
minos, err := mino.Generate(i)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, m := range minos {
|
||||
log.Println(m.Render())
|
||||
log.Println()
|
||||
log.Println()
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ var (
|
|||
renderBuffer bytes.Buffer
|
||||
|
||||
multiplayerMatrixSize int
|
||||
extraScreenPadding int
|
||||
screenPadding int
|
||||
|
||||
screenW, screenH int
|
||||
newScreenW, newScreenH int
|
||||
|
@ -48,7 +48,7 @@ var (
|
|||
nickname = "Anonymous"
|
||||
nicknameDraft string
|
||||
|
||||
inputHeight, mainHeight, newLogLines int
|
||||
inputHeight, mainHeight, previewWidth, newLogLines int
|
||||
|
||||
profileCPU *os.File
|
||||
|
||||
|
@ -67,26 +67,6 @@ var (
|
|||
|
||||
const DefaultStatusText = "Press Enter to chat, Z/X to rotate, arrow keys or HJKL to move/drop"
|
||||
|
||||
// TODO: Darken ghost color?
|
||||
var renderBlock = map[mino.Block][]byte{
|
||||
mino.BlockNone: []byte(" "),
|
||||
mino.BlockGhostBlue: []byte("[#2864ff]▓[#ffffff]"), // 1a53ff
|
||||
mino.BlockSolidBlue: []byte("[#2864ff]█[#ffffff]"),
|
||||
mino.BlockGhostCyan: []byte("[#00eeee]▓[#ffffff]"),
|
||||
mino.BlockSolidCyan: []byte("[#00eeee]█[#ffffff]"),
|
||||
mino.BlockGhostRed: []byte("[#ee0000]▓[#ffffff]"),
|
||||
mino.BlockSolidRed: []byte("[#ee0000]█[#ffffff]"),
|
||||
mino.BlockGhostYellow: []byte("[#dddd00]▓[#ffffff]"),
|
||||
mino.BlockSolidYellow: []byte("[#dddd00]█[#ffffff]"),
|
||||
mino.BlockGhostMagenta: []byte("[#c000cc]▓[#ffffff]"),
|
||||
mino.BlockSolidMagenta: []byte("[#c000cc]█[#ffffff]"),
|
||||
mino.BlockGhostGreen: []byte("[#00e900]▓[#ffffff]"),
|
||||
mino.BlockSolidGreen: []byte("[#00e900]█[#ffffff]"),
|
||||
mino.BlockGhostOrange: []byte("[#ff7308]▓[#ffffff]"),
|
||||
mino.BlockSolidOrange: []byte("[#ff7308]█[#ffffff]"),
|
||||
mino.BlockGarbage: []byte("[#bbbbbb]█[#ffffff]"),
|
||||
}
|
||||
|
||||
var (
|
||||
renderHLine = []byte(string(tcell.RuneHLine))
|
||||
renderVLine = []byte(string(tcell.RuneVLine))
|
||||
|
@ -124,6 +104,9 @@ func resetPlayerSettingsForm() {
|
|||
})
|
||||
}
|
||||
|
||||
// BS 1: 10x10
|
||||
// BS 2: 20x20
|
||||
// BS 3: 30x40
|
||||
func handleResize(screen tcell.Screen) {
|
||||
newScreenW, newScreenH = screen.Size()
|
||||
if newScreenW == screenW && newScreenH == screenH {
|
||||
|
@ -133,45 +116,68 @@ func handleResize(screen tcell.Screen) {
|
|||
screenW, screenH = newScreenW, newScreenH
|
||||
|
||||
if !fixedBlockSize {
|
||||
if screenW >= 80 && screenH >= 44 {
|
||||
if screenW >= 80 && screenH >= 46 {
|
||||
blockSize = 3
|
||||
} else if screenW >= 80 && screenH >= 24 {
|
||||
blockSize = 2
|
||||
} else {
|
||||
blockSize = 1
|
||||
}
|
||||
}
|
||||
|
||||
mainHeight = (20 * blockSize) + 2
|
||||
xMultiplier := 1
|
||||
if blockSize == 2 {
|
||||
xMultiplier = 2
|
||||
} else if blockSize == 3 {
|
||||
xMultiplier = 3
|
||||
}
|
||||
|
||||
if blockSize == 1 {
|
||||
mainHeight = 10 + 3
|
||||
} else if blockSize == 2 {
|
||||
mainHeight = 20 + 3
|
||||
} else {
|
||||
mainHeight = 40 + 3
|
||||
}
|
||||
|
||||
if screenH > mainHeight+9 {
|
||||
extraScreenPadding = 3
|
||||
screenPadding = 2
|
||||
mainHeight++
|
||||
inputHeight = 2
|
||||
} else if screenH > mainHeight+7 {
|
||||
extraScreenPadding = 2
|
||||
mainHeight++
|
||||
inputHeight = 2
|
||||
} else if screenH > mainHeight+5 {
|
||||
extraScreenPadding = 1
|
||||
screenPadding = 2
|
||||
mainHeight++
|
||||
inputHeight = 1
|
||||
} else if screenH > mainHeight+2 {
|
||||
extraScreenPadding = 0
|
||||
} else if screenH > mainHeight+5 {
|
||||
screenPadding = 1
|
||||
mainHeight++
|
||||
inputHeight = 1
|
||||
} else if screenH > mainHeight+3 {
|
||||
screenPadding = 1
|
||||
inputHeight = 1
|
||||
} else {
|
||||
extraScreenPadding = 0
|
||||
inputHeight = 1
|
||||
screenPadding = 0
|
||||
inputHeight = 0
|
||||
}
|
||||
|
||||
multiplayerMatrixSize = ((screenW - extraScreenPadding) - ((10 * blockSize) + 16)) / ((10 * blockSize) + 4)
|
||||
if blockSize == 1 {
|
||||
previewWidth = 9
|
||||
} else if blockSize == 2 {
|
||||
previewWidth = 10
|
||||
} else {
|
||||
previewWidth = 14
|
||||
}
|
||||
|
||||
newLogLines = ((screenH - mainHeight) - inputHeight) - extraScreenPadding
|
||||
multiplayerMatrixSize = ((screenW - screenPadding) - ((10 * xMultiplier) + previewWidth + 6)) / ((10 * xMultiplier) + 4)
|
||||
|
||||
newLogLines = ((screenH - mainHeight) - inputHeight) - screenPadding
|
||||
if newLogLines > 0 {
|
||||
showLogLines = newLogLines
|
||||
} else {
|
||||
showLogLines = 1
|
||||
}
|
||||
|
||||
gameGrid.SetRows(mainHeight+extraScreenPadding, inputHeight, -1).SetColumns(1+extraScreenPadding, 4+(10*blockSize), 10, -1)
|
||||
gameGrid.SetRows(screenPadding, mainHeight, inputHeight, -1).SetColumns(screenPadding+1, 4+(10*xMultiplier), previewWidth, -1)
|
||||
|
||||
draw <- event.DrawAll
|
||||
}
|
||||
|
@ -181,9 +187,8 @@ func drawAll() {
|
|||
return
|
||||
}
|
||||
|
||||
renderPlayerMatrix()
|
||||
renderPreviewMatrix()
|
||||
renderMultiplayerMatrix()
|
||||
renderPlayerGUI()
|
||||
renderMultiplayerGUI()
|
||||
}
|
||||
|
||||
func drawMessages() {
|
||||
|
@ -191,12 +196,11 @@ func drawMessages() {
|
|||
}
|
||||
|
||||
func drawPlayerMatrix() {
|
||||
renderPlayerMatrix()
|
||||
renderPreviewMatrix()
|
||||
renderPlayerGUI()
|
||||
}
|
||||
|
||||
func drawMultiplayerMatrixes() {
|
||||
renderMultiplayerMatrix()
|
||||
renderMultiplayerGUI()
|
||||
}
|
||||
|
||||
func handleDraw() {
|
||||
|
@ -250,12 +254,18 @@ func setShowDetails(active bool) {
|
|||
draw <- event.DrawAll
|
||||
}
|
||||
|
||||
func renderPreviewMatrix() {
|
||||
func renderPlayerGUI() {
|
||||
g := activeGame
|
||||
if g == nil || len(g.Players) == 0 || g.Players[g.LocalPlayer].Matrix.Bag == nil {
|
||||
if g == nil || len(g.Players) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
renderLock.Lock()
|
||||
renderMatrixes([]*mino.Matrix{g.Players[g.LocalPlayer].Matrix})
|
||||
mtx.Clear()
|
||||
mtx.Write(renderBuffer.Bytes())
|
||||
renderLock.Unlock()
|
||||
|
||||
player := g.Players[g.LocalPlayer]
|
||||
m := g.Players[g.LocalPlayer].Matrix
|
||||
|
||||
|
@ -284,12 +294,14 @@ func renderPreviewMatrix() {
|
|||
}
|
||||
|
||||
renderLock.Lock()
|
||||
renderMatrix(g.Players[g.LocalPlayer].Preview)
|
||||
renderMatrixes([]*mino.Matrix{g.Players[g.LocalPlayer].Preview})
|
||||
|
||||
if blockSize > 1 {
|
||||
renderBuffer.WriteString(fmt.Sprintf("\n\n\n\n\n Combo\n\n %d\n\n\n\n\n Timer\n\n %.0f\n\n\n\n\nPending\n\n %d\n\n\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
|
||||
} else {
|
||||
renderBuffer.WriteString(fmt.Sprintf("\n\n Combo\n\n %d\n\n Timer\n\n %.0f\n\nPending\n\n %d\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
|
||||
if blockSize == 1 {
|
||||
renderBuffer.WriteString(fmt.Sprintf(" Combo\n %d\n\n Timer\n %.0f\n\nPending\n %d\n\n Speed\n %s", combo, comboTime, m.PendingGarbage, speed))
|
||||
} else if blockSize == 2 {
|
||||
renderBuffer.WriteString(fmt.Sprintf("\n Combo\n\n %d\n\n\n Timer\n\n %.0f\n\n\nPending\n\n %d\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
|
||||
} else if blockSize == 3 {
|
||||
renderBuffer.WriteString(fmt.Sprintf("\n\n\n\n\n Combo\n\n %d\n\n\n\n\n\n Timer\n\n %.0f\n\n\n\n\n\n Pending\n\n %d\n\n\n\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
|
||||
}
|
||||
|
||||
side.Clear()
|
||||
|
@ -299,20 +311,7 @@ func renderPreviewMatrix() {
|
|||
m.Unlock()
|
||||
}
|
||||
|
||||
func renderPlayerMatrix() {
|
||||
g := activeGame
|
||||
if g == nil || len(g.Players) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
renderLock.Lock()
|
||||
renderMatrix(g.Players[g.LocalPlayer].Matrix)
|
||||
mtx.Clear()
|
||||
mtx.Write(renderBuffer.Bytes())
|
||||
renderLock.Unlock()
|
||||
}
|
||||
|
||||
func renderMultiplayerMatrix() {
|
||||
func renderMultiplayerGUI() {
|
||||
g := activeGame
|
||||
if g == nil {
|
||||
return
|
||||
|
@ -364,87 +363,6 @@ func renderMultiplayerMatrix() {
|
|||
renderLock.Unlock()
|
||||
}
|
||||
|
||||
func renderMatrix(m *mino.Matrix) {
|
||||
renderBuffer.Reset()
|
||||
|
||||
if m == nil {
|
||||
return
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
m.DrawPiecesL()
|
||||
|
||||
bs := blockSize
|
||||
if m.Type == mino.MatrixPreview {
|
||||
// Draw preview matrix at block size 2 max
|
||||
|
||||
if bs > 2 {
|
||||
bs = 2
|
||||
}
|
||||
if bs > 1 {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
} else if m.Type == mino.MatrixCustom {
|
||||
bs = 1
|
||||
}
|
||||
|
||||
for i := 0; i < extraScreenPadding; i++ {
|
||||
if m.Type == mino.MatrixStandard && i == extraScreenPadding-1 {
|
||||
renderBuffer.Write(renderULCorner)
|
||||
for x := 0; x < m.W*bs; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
}
|
||||
renderBuffer.Write(renderURCorner)
|
||||
}
|
||||
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
|
||||
for y := m.H - 1; y >= 0; y-- {
|
||||
for j := 0; j < bs; j++ {
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
} else {
|
||||
iPieceNext := m.Bag != nil && m.Bag.Next().String() == mino.TetrominoI
|
||||
if bs == 1 {
|
||||
renderBuffer.WriteRune(' ')
|
||||
renderBuffer.WriteRune(' ')
|
||||
} else if !iPieceNext {
|
||||
renderBuffer.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
for x := 0; x < m.W; x++ {
|
||||
for k := 0; k < bs; k++ {
|
||||
renderBuffer.Write(renderBlock[m.Block(x, y)])
|
||||
}
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
}
|
||||
|
||||
if y != 0 || m.Type != mino.MatrixCustom {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if m.Type != mino.MatrixStandard {
|
||||
return
|
||||
}
|
||||
|
||||
renderBuffer.Write(renderLLCorner)
|
||||
for x := 0; x < m.W*bs; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
}
|
||||
renderBuffer.Write(renderLRCorner)
|
||||
|
||||
renderBuffer.WriteRune('\n')
|
||||
renderPlayerDetails(m, bs)
|
||||
}
|
||||
|
||||
func renderPlayerDetails(m *mino.Matrix, bs int) {
|
||||
var buf string
|
||||
if !showDetails {
|
||||
|
@ -473,55 +391,74 @@ func renderPlayerDetails(m *mino.Matrix, bs int) {
|
|||
|
||||
func renderMatrixes(mx []*mino.Matrix) {
|
||||
renderBuffer.Reset()
|
||||
|
||||
if mx == nil {
|
||||
if mx == nil || len(mx) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
bs := blockSize
|
||||
mt := mx[0].Type
|
||||
mh := mx[0].H
|
||||
div := " "
|
||||
|
||||
var nextPieceWidth = 0
|
||||
if mt == mino.MatrixPreview {
|
||||
renderBuffer.WriteRune('\n')
|
||||
if mx[0].Bag != nil {
|
||||
p := mx[0].Bag.Next()
|
||||
nextPieceWidth, _ = p.Size()
|
||||
if nextPieceWidth == 2 && blockSize == 1 {
|
||||
nextPieceWidth = 3
|
||||
}
|
||||
}
|
||||
} else if mt == mino.MatrixCustom {
|
||||
bs = 1
|
||||
}
|
||||
|
||||
for i := range mx {
|
||||
mx[i].Lock()
|
||||
mx[i].DrawPiecesL()
|
||||
}
|
||||
|
||||
div := " "
|
||||
|
||||
height := mx[0].H
|
||||
|
||||
for i := 0; i < extraScreenPadding; i++ {
|
||||
if i == extraScreenPadding-1 {
|
||||
for i := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
renderBuffer.Write(renderULCorner)
|
||||
for x := 0; x < mx[i].W*blockSize; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
}
|
||||
renderBuffer.Write(renderURCorner)
|
||||
if mt == mino.MatrixStandard {
|
||||
for i := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
}
|
||||
|
||||
renderBuffer.Write(renderULCorner)
|
||||
for x := 0; x < mx[i].W*bs; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
}
|
||||
renderBuffer.Write(renderURCorner)
|
||||
}
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
|
||||
for y := height - 1; y >= 0; y-- {
|
||||
for j := 0; j < blockSize; j++ {
|
||||
for i := range mx {
|
||||
m := mx[i]
|
||||
|
||||
if bs == 1 {
|
||||
for y := mh - 1; y >= 0; y -= 2 {
|
||||
for i, m := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
} else if m.Type == mino.MatrixPreview {
|
||||
renderBuffer.WriteRune(' ')
|
||||
|
||||
if nextPieceWidth < 4 {
|
||||
renderBuffer.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
for x := 0; x < m.W; x++ {
|
||||
for j := 0; j < blockSize; j++ {
|
||||
renderBuffer.Write(renderBlock[m.Block(x, y)])
|
||||
}
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y-1).Color())
|
||||
renderBuffer.WriteRune(':')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('▄')
|
||||
renderBuffer.Write([]byte("[-:-]"))
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
|
@ -529,30 +466,107 @@ func renderMatrixes(mx []*mino.Matrix) {
|
|||
}
|
||||
}
|
||||
|
||||
renderBuffer.WriteRune('\n')
|
||||
if y != 0 || mt != mino.MatrixCustom {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
} else if bs == 2 {
|
||||
for y := mh - 1; y >= 0; y-- {
|
||||
for i, m := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
} else if m.Type == mino.MatrixPreview {
|
||||
for pad := 0; pad < 3-nextPieceWidth; pad++ {
|
||||
renderBuffer.WriteRune(' ')
|
||||
renderBuffer.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
for x := 0; x < m.W; x++ {
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.Write([]byte("[-]"))
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
}
|
||||
}
|
||||
|
||||
if y != 0 || mt != mino.MatrixCustom {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for y := mh - 1; y >= 0; y-- {
|
||||
for repeat := 0; repeat < 2; repeat++ {
|
||||
for i, m := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
} else if m.Type == mino.MatrixPreview {
|
||||
if nextPieceWidth == 2 {
|
||||
renderBuffer.WriteRune(' ')
|
||||
renderBuffer.WriteRune(' ')
|
||||
} else if nextPieceWidth < 4 {
|
||||
renderBuffer.WriteRune(' ')
|
||||
}
|
||||
}
|
||||
|
||||
for x := 0; x < m.W; x++ {
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.Write([]byte("[-]"))
|
||||
}
|
||||
|
||||
if m.Type == mino.MatrixStandard {
|
||||
renderBuffer.Write(renderVLine)
|
||||
}
|
||||
}
|
||||
|
||||
if y != 0 || mt != mino.MatrixCustom {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for i := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
if mt == mino.MatrixStandard {
|
||||
for i := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
renderBuffer.Write(renderLLCorner)
|
||||
for x := 0; x < mx[i].W*bs; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
}
|
||||
renderBuffer.Write(renderLRCorner)
|
||||
}
|
||||
|
||||
renderBuffer.Write(renderLLCorner)
|
||||
for x := 0; x < mx[i].W*blockSize; x++ {
|
||||
renderBuffer.Write(renderHLine)
|
||||
renderBuffer.WriteRune('\n')
|
||||
|
||||
for i, m := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
renderPlayerDetails(m, bs)
|
||||
}
|
||||
renderBuffer.Write(renderLRCorner)
|
||||
}
|
||||
|
||||
renderBuffer.WriteRune('\n')
|
||||
|
||||
for i, m := range mx {
|
||||
if i > 0 {
|
||||
renderBuffer.WriteString(div)
|
||||
}
|
||||
|
||||
renderPlayerDetails(m, blockSize)
|
||||
}
|
||||
|
||||
for i := range mx {
|
||||
|
|
|
@ -32,8 +32,7 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
})
|
||||
|
||||
gameGrid = tview.NewGrid().
|
||||
SetBorders(false).
|
||||
SetRows(2+(20*blockSize)+extraScreenPadding, -1)
|
||||
SetBorders(false)
|
||||
|
||||
mtx = tview.NewTextView().
|
||||
SetScrollable(false).
|
||||
|
@ -67,13 +66,14 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
SetWrap(true).
|
||||
SetWordWrap(true)
|
||||
|
||||
gameGrid.SetColumns(1, 4+(10*blockSize), 10, -1).
|
||||
AddItem(pad, 0, 0, 2, 1, 0, 0, false).
|
||||
AddItem(mtx, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(side, 0, 2, 1, 1, 0, 0, false).
|
||||
AddItem(buffer, 0, 3, 1, 1, 0, 0, false).
|
||||
AddItem(inputView, 1, 1, 1, 3, 0, 0, true).
|
||||
AddItem(recent, 2, 1, 1, 3, 0, 0, true)
|
||||
gameGrid.
|
||||
AddItem(pad, 0, 0, 4, 1, 0, 0, false).
|
||||
AddItem(pad, 0, 1, 1, 2, 0, 0, false).
|
||||
AddItem(mtx, 1, 1, 1, 1, 0, 0, false).
|
||||
AddItem(side, 1, 2, 1, 1, 0, 0, false).
|
||||
AddItem(buffer, 1, 3, 1, 1, 0, 0, false).
|
||||
AddItem(inputView, 2, 1, 1, 3, 0, 0, true).
|
||||
AddItem(recent, 3, 1, 1, 3, 0, 0, true)
|
||||
|
||||
// Set up title screen
|
||||
|
||||
|
@ -89,9 +89,9 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
addToRight bool
|
||||
i int
|
||||
)
|
||||
for y := 0; y < 6; y++ {
|
||||
for y := 0; y < 11; y++ {
|
||||
for x := 0; x < 4; x++ {
|
||||
piece = mino.NewPiece(minos[i], mino.Point{x * 5, (y * 5)})
|
||||
piece = mino.NewPiece(minos[i], mino.Point{(x * 5) + 2, (y * 5)})
|
||||
|
||||
i++
|
||||
if i == len(minos) {
|
||||
|
@ -137,13 +137,13 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
buttonC = tview.NewButton("C")
|
||||
buttonLabelC = tview.NewTextView().SetTextAlign(tview.AlignCenter)
|
||||
|
||||
titleNameGrid := tview.NewGrid().SetRows(5).
|
||||
titleNameGrid := tview.NewGrid().SetRows(3).
|
||||
AddItem(titleName, 0, 0, 1, 1, 0, 0, false).
|
||||
AddItem(tview.NewTextView().SetText(SubTitle+game.Version), 1, 0, 1, 1, 0, 0, false)
|
||||
|
||||
titleGrid = tview.NewGrid().
|
||||
SetRows(7, 3, 3, 3, 3, 3, 2).
|
||||
SetColumns(-1, 38, -1).
|
||||
SetRows(5, 3, 3, 3, 3, 3, 4).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 7, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 7, 1, 0, 0, false).
|
||||
|
@ -167,8 +167,8 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
gameListHeader = tview.NewTextView().SetTextAlign(tview.AlignCenter)
|
||||
|
||||
gameListGrid = tview.NewGrid().
|
||||
SetRows(7, 1, -1, 1, 3).
|
||||
SetColumns(-1, 38, -1).
|
||||
SetRows(5, 1, -1, 1, 3).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 5, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 5, 1, 0, 0, false).
|
||||
|
@ -219,8 +219,8 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
SetWordWrap(false).SetText("New Game")
|
||||
|
||||
newGameGrid = tview.NewGrid().
|
||||
SetRows(7, 2, 1, 1, 1, 1, 1, 1, 1, -1, 3).
|
||||
SetColumns(-1, 38, -1).
|
||||
SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, -1, 3).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 11, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 11, 1, 0, 0, false).
|
||||
|
@ -246,8 +246,8 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
playerSettingsForm = tview.NewForm().SetButtonsAlign(tview.AlignCenter)
|
||||
|
||||
playerSettingsGrid = tview.NewGrid().
|
||||
SetRows(7, 2, -1, 1).
|
||||
SetColumns(-1, 38, -1).
|
||||
SetRows(5, 2, -1, 1).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 4, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 4, 1, 0, 0, false).
|
||||
|
@ -305,8 +305,8 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
AddItem(pad, 0, 4, 1, 1, 0, 0, false)
|
||||
|
||||
gameSettingsGrid = tview.NewGrid().
|
||||
SetRows(7, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1).
|
||||
SetColumns(-1, 38, -1).
|
||||
SetRows(5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 16, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 16, 1, 0, 0, false).
|
||||
|
@ -394,7 +394,7 @@ func newTitleMatrixSide() *mino.Matrix {
|
|||
}
|
||||
}()
|
||||
|
||||
m := mino.NewMatrix(21, 24, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
m := mino.NewMatrix(21, 48, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
|
||||
return m
|
||||
}
|
||||
|
@ -412,7 +412,7 @@ func newTitleMatrixName() *mino.Matrix {
|
|||
}
|
||||
}()
|
||||
|
||||
m := mino.NewMatrix(36, 7, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
m := mino.NewMatrix(36, 5, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
|
||||
centerStart := (m.W / 2) - 17
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ func handleKeypress(ev *tcell.EventKey) *tcell.EventKey {
|
|||
titleScreen = 5
|
||||
titleSelectedButton = 0
|
||||
|
||||
modal := tview.NewModal().SetText("Joining another server by IP via GUI is not yet implemented.\nPlease re-launch netris with the --connect argument instead.\n\nPress Escape to go back").ClearButtons()
|
||||
modal := tview.NewModal().SetText("Joining another server by IP via GUI is not yet implemented.\nPlease re-launch netris with the --connect argument instead.\n\nPress Escape to return.").ClearButtons()
|
||||
app.SetRoot(modal, true)
|
||||
} else if titleSelectedButton == 3 {
|
||||
titleScreen = 0
|
||||
|
|
|
@ -19,7 +19,7 @@ func TestRenderMatrix(t *testing.T) {
|
|||
|
||||
m.AddTestBlocks()
|
||||
|
||||
renderMatrix(m)
|
||||
renderPlayerMatrix(m)
|
||||
}
|
||||
|
||||
func BenchmarkRenderStandardMatrix(b *testing.B) {
|
||||
|
@ -39,7 +39,7 @@ func BenchmarkRenderStandardMatrix(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
renderMatrix(m)
|
||||
renderPlayerMatrix(m)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +60,7 @@ func BenchmarkRenderLargeMatrix(b *testing.B) {
|
|||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
renderMatrix(m)
|
||||
renderPlayerMatrix(m)
|
||||
}
|
||||
|
||||
blockSize = 1
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
SubTitle = " .rocketnine.space v"
|
||||
SubTitle = " .rocketnine.space v"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -300,15 +300,15 @@ func renderTitle() {
|
|||
|
||||
renderLock.Lock()
|
||||
|
||||
renderMatrix(titleMatrix)
|
||||
renderMatrixes([]*mino.Matrix{titleMatrix})
|
||||
titleName.Clear()
|
||||
titleName.Write(renderBuffer.Bytes())
|
||||
|
||||
renderMatrix(titleMatrixL)
|
||||
renderMatrixes([]*mino.Matrix{titleMatrixL})
|
||||
titleL.Clear()
|
||||
titleL.Write(renderBuffer.Bytes())
|
||||
|
||||
renderMatrix(titleMatrixR)
|
||||
renderMatrixes([]*mino.Matrix{titleMatrixR})
|
||||
titleR.Clear()
|
||||
titleR.Write(renderBuffer.Bytes())
|
||||
|
||||
|
@ -316,7 +316,7 @@ func renderTitle() {
|
|||
}
|
||||
|
||||
func renderGameList() {
|
||||
w := 36
|
||||
w := 32
|
||||
|
||||
gameListView.Clear()
|
||||
gameListView.Write(renderULCorner)
|
||||
|
@ -327,7 +327,7 @@ func renderGameList() {
|
|||
gameListView.Write([]byte("\n"))
|
||||
|
||||
gameListView.Write(renderVLine)
|
||||
gameListView.Write([]byte(fmt.Sprintf("%-29s%s", "Game", "Players")))
|
||||
gameListView.Write([]byte(fmt.Sprintf("%-25s%s", "Game", "Players")))
|
||||
gameListView.Write(renderVLine)
|
||||
gameListView.Write([]byte("\n"))
|
||||
|
||||
|
@ -338,7 +338,7 @@ func renderGameList() {
|
|||
gameListView.Write(renderRTee)
|
||||
gameListView.Write([]byte("\n"))
|
||||
|
||||
h := 8
|
||||
h := 9
|
||||
|
||||
for i, g := range gameList {
|
||||
p := strconv.Itoa(g.Players)
|
||||
|
@ -350,7 +350,7 @@ func renderGameList() {
|
|||
if titleSelectedButton == 0 && gameListSelected == i {
|
||||
gameListView.Write([]byte("[#000000:#FFFFFF]"))
|
||||
}
|
||||
gameListView.Write([]byte(fmt.Sprintf("%-29s%7s", g.Name, p)))
|
||||
gameListView.Write([]byte(fmt.Sprintf("%-25s%7s", g.Name, p)))
|
||||
if titleSelectedButton == 0 && gameListSelected == i {
|
||||
gameListView.Write([]byte("[-:-]"))
|
||||
}
|
||||
|
|
|
@ -26,7 +26,11 @@ import (
|
|||
var (
|
||||
done = make(chan bool)
|
||||
|
||||
activeGame *game.Game
|
||||
activeGame *game.Game
|
||||
activeGameConn *game.Conn
|
||||
|
||||
server *game.Server
|
||||
localListenDir string
|
||||
|
||||
connectAddress string
|
||||
serverAddress string
|
||||
|
@ -62,7 +66,7 @@ func main() {
|
|||
|
||||
log.Println()
|
||||
log.Println()
|
||||
log.Fatalf("panic: %+v", r)
|
||||
log.Fatalf("caught panic: %+v", r)
|
||||
}
|
||||
}()
|
||||
|
||||
|
@ -143,13 +147,18 @@ func main() {
|
|||
connectAddress = serverAddress
|
||||
}
|
||||
|
||||
var (
|
||||
server *game.Server
|
||||
localListenDir string
|
||||
)
|
||||
|
||||
go func(server *game.Server) {
|
||||
go func() {
|
||||
<-done
|
||||
|
||||
if activeGameConn != nil {
|
||||
if server == nil {
|
||||
activeGameConn.Write(&game.GameCommandDisconnect{})
|
||||
activeGameConn.Wait()
|
||||
}
|
||||
|
||||
activeGameConn.Close()
|
||||
}
|
||||
|
||||
if server != nil {
|
||||
server.StopListening()
|
||||
}
|
||||
|
@ -160,7 +169,7 @@ func main() {
|
|||
closeGUI()
|
||||
|
||||
os.Exit(0)
|
||||
}(server)
|
||||
}()
|
||||
|
||||
for {
|
||||
gameID := <-joinGame
|
||||
|
@ -184,7 +193,7 @@ func main() {
|
|||
logMessage(fmt.Sprintf("* Connecting to %s...", connectAddress))
|
||||
}
|
||||
|
||||
s, err := game.Connect(connectAddress)
|
||||
activeGameConn, err = game.Connect(connectAddress)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
@ -206,7 +215,7 @@ func main() {
|
|||
newGame = &game.ListedGame{Name: game.GameName(newGameNameInput.GetText()), MaxPlayers: maxPlayers, SpeedLimit: speedLimit}
|
||||
}
|
||||
|
||||
activeGame, err = s.JoinGame(nickname, gameID, newGame, logger, draw)
|
||||
activeGame, err = activeGameConn.JoinGame(nickname, gameID, newGame, logger, draw)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to connect to %s: %s", connectAddress, err)
|
||||
}
|
||||
|
@ -222,7 +231,7 @@ func main() {
|
|||
joinedGame = true
|
||||
setTitleVisible(false)
|
||||
|
||||
server = game.NewServer(nil)
|
||||
server = game.NewServer(nil, logLevel)
|
||||
|
||||
server.Logger = make(chan string, game.LogQueueSize)
|
||||
if logDebug || logVerbose {
|
||||
|
@ -247,14 +256,14 @@ func main() {
|
|||
|
||||
go server.Listen(localListenAddress)
|
||||
|
||||
localServerConn, err := game.Connect(localListenAddress)
|
||||
activeGameConn, err = game.Connect(localListenAddress)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
log.Fatalf("failed to create local game: %s", err)
|
||||
}
|
||||
|
||||
activeGame, err = localServerConn.JoinGame(nickname, event.GameIDNewLocal, nil, logger, draw)
|
||||
activeGame, err = activeGameConn.JoinGame(nickname, event.GameIDNewLocal, nil, logger, draw)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatalf("failed to join local game: %s", err)
|
||||
}
|
||||
|
||||
activeGame.LogLevel = logLevel
|
||||
|
@ -271,7 +280,7 @@ func main() {
|
|||
for i := range startMatrixSplit {
|
||||
token, err = strconv.Atoi(startMatrixSplit[i])
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("failed to parse initial matrix on token #%d", i))
|
||||
log.Fatalf("failed to parse custom matrix on token #%d", i)
|
||||
}
|
||||
if i%2 == 1 {
|
||||
activeGame.Players[activeGame.LocalPlayer].Matrix.SetBlock(x, token, mino.BlockGarbage, false)
|
||||
|
|
|
@ -137,7 +137,7 @@ func (s *Conn) handleRead() {
|
|||
um = func(mgc interface{}) {
|
||||
err := json.Unmarshal(msg.Data, mgc)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
s.Close()
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -147,7 +147,7 @@ func (s *Conn) handleRead() {
|
|||
|
||||
err := json.Unmarshal(scanner.Bytes(), &msg)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
break
|
||||
}
|
||||
|
||||
s.LastTransfer = time.Now()
|
||||
|
@ -216,7 +216,7 @@ func (s *Conn) handleRead() {
|
|||
um(&mgc)
|
||||
gc = &mgc
|
||||
default:
|
||||
// TODO Place beind debug log level
|
||||
// TODO Require at least debug log level
|
||||
log.Println("unknown serverconn command", scanner.Text())
|
||||
continue
|
||||
}
|
||||
|
@ -228,8 +228,7 @@ func (s *Conn) handleRead() {
|
|||
|
||||
err = s.conn.SetReadDeadline(time.Now().Add(ConnTimeout))
|
||||
if err != nil {
|
||||
s.Close()
|
||||
return
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -292,8 +291,9 @@ func (s *Conn) Close() {
|
|||
|
||||
s.Terminated = true
|
||||
|
||||
s.conn.Close()
|
||||
|
||||
go func() {
|
||||
s.conn.Close()
|
||||
s.Wait()
|
||||
close(s.In)
|
||||
close(s.out)
|
||||
|
|
|
@ -148,7 +148,8 @@ func (g *Game) AddPlayerL(p *Player) {
|
|||
|
||||
g.Players[p.Player] = p
|
||||
|
||||
p.Preview = mino.NewMatrix(g.Rank, g.Rank-1, 0, 1, g.Event, g.draw, mino.MatrixPreview)
|
||||
// TODO Verify rank-2 is valid for all playable rank previews
|
||||
p.Preview = mino.NewMatrix(g.Rank, g.Rank-2, 0, 1, g.Event, g.draw, mino.MatrixPreview)
|
||||
p.Preview.PlayerName = p.Name
|
||||
|
||||
p.Matrix = mino.NewMatrix(10, 20, 4, 1, g.Event, g.draw, mino.MatrixStandard)
|
||||
|
@ -258,7 +259,7 @@ func (g *Game) StartL(seed int64) int64 {
|
|||
g.TimeStarted = time.Now()
|
||||
|
||||
if g.LocalPlayer == PlayerUnknown {
|
||||
panic("Player unknown")
|
||||
log.Fatal("failed to start game: player unknown")
|
||||
}
|
||||
|
||||
if seed == 0 {
|
||||
|
@ -269,7 +270,7 @@ func (g *Game) StartL(seed int64) int64 {
|
|||
for _, p := range g.Players {
|
||||
bag, err := mino.NewBag(g.Seed, g.Minos, 10)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatalf("failed to start game: failed to create bag: %s", err)
|
||||
}
|
||||
|
||||
p.Preview.AttachBag(bag)
|
||||
|
@ -277,9 +278,10 @@ func (g *Game) StartL(seed int64) int64 {
|
|||
}
|
||||
|
||||
// Take piece on host as well to give initial position for start of game
|
||||
for _, p := range g.Players {
|
||||
for playerID, p := range g.Players {
|
||||
if !p.Matrix.TakePiece() {
|
||||
g.Log(LogStandard, "Failed to take piece while starting game for player ", p.Player)
|
||||
g.RemovePlayerL(playerID)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,14 +429,10 @@ func (g *Game) handleDistributeMatrixes() {
|
|||
g.setGameOverL(true)
|
||||
|
||||
winner := "Tie!"
|
||||
if remainingPlayer != -1 {
|
||||
winner = g.Players[remainingPlayer].Name
|
||||
}
|
||||
g.WriteAllL(&GameCommandGameOver{Player: 0, Winner: winner})
|
||||
|
||||
var otherPlayers string
|
||||
for i := range g.Players {
|
||||
if i == remainingPlayer {
|
||||
winner = g.Players[remainingPlayer].Name
|
||||
continue
|
||||
}
|
||||
if otherPlayers != "" {
|
||||
|
@ -444,6 +442,8 @@ func (g *Game) handleDistributeMatrixes() {
|
|||
otherPlayers += g.Players[i].Name
|
||||
}
|
||||
|
||||
g.WriteAllL(&GameCommandGameOver{Winner: winner})
|
||||
|
||||
g.WriteMessage("Game over - winner: " + winner)
|
||||
g.WriteMessage("Garbage sent/received:")
|
||||
for _, p := range g.Players {
|
||||
|
@ -772,7 +772,10 @@ func (g *Game) handleDropTerminatedPlayers() {
|
|||
for {
|
||||
time.Sleep(15 * time.Second)
|
||||
|
||||
g.Lock()
|
||||
|
||||
if g.Terminated {
|
||||
g.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -781,13 +784,15 @@ func (g *Game) handleDropTerminatedPlayers() {
|
|||
g.RemovePlayerL(playerID)
|
||||
}
|
||||
}
|
||||
|
||||
g.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func GameName(name string) string {
|
||||
name = gameNameRegexp.ReplaceAllString(strings.TrimSpace(name), "")
|
||||
if len(name) > 28 {
|
||||
name = name[:28]
|
||||
if len(name) > 24 {
|
||||
name = name[:24]
|
||||
} else if name == "" {
|
||||
name = "netris"
|
||||
}
|
||||
|
|
|
@ -33,6 +33,8 @@ type Server struct {
|
|||
|
||||
created time.Time
|
||||
|
||||
logLevel int
|
||||
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
|
@ -47,11 +49,11 @@ type ServerInterface interface {
|
|||
Shutdown(reason string)
|
||||
}
|
||||
|
||||
func NewServer(si []ServerInterface) *Server {
|
||||
func NewServer(si []ServerInterface, logLevel int) *Server {
|
||||
in := make(chan GameCommandInterface, CommandQueueSize)
|
||||
out := make(chan GameCommandInterface, CommandQueueSize)
|
||||
|
||||
s := &Server{I: si, In: in, Out: out, Games: make(map[int]*Game), created: time.Now()}
|
||||
s := &Server{I: si, In: in, Out: out, Games: make(map[int]*Game), created: time.Now(), logLevel: logLevel}
|
||||
|
||||
var (
|
||||
g *Game
|
||||
|
@ -123,6 +125,7 @@ func (s *Server) NewGame() (*Game, error) {
|
|||
}
|
||||
|
||||
g.ID = gameID
|
||||
g.LogLevel = s.logLevel
|
||||
|
||||
s.Games[gameID] = g
|
||||
|
||||
|
@ -163,7 +166,7 @@ func (s *Server) FindGame(p *Player, gameID int, newGame ListedGame) *Game {
|
|||
// Create a custom game
|
||||
g, err = s.NewGame()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatalf("failed to create custom game: %s", err)
|
||||
}
|
||||
|
||||
g.Lock()
|
||||
|
@ -205,7 +208,7 @@ func (s *Server) FindGame(p *Player, gameID int, newGame ListedGame) *Game {
|
|||
// Create a local game
|
||||
g, err = s.NewGame()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
log.Fatalf("failed to create local game: %s", err)
|
||||
}
|
||||
|
||||
g.Local = true
|
||||
|
@ -335,94 +338,87 @@ func (s *Server) handleGameCommands(pl *Player, g *Game) {
|
|||
|
||||
g.Lock()
|
||||
|
||||
switch c {
|
||||
case CommandMessage:
|
||||
if p, ok := e.(*GameCommandMessage); ok {
|
||||
if player, ok := g.Players[p.SourcePlayer]; ok {
|
||||
s.Logf("<%s> %s", player.Name, p.Message)
|
||||
switch p := e.(type) {
|
||||
case *GameCommandDisconnect:
|
||||
log.Printf("%+v", g.Players)
|
||||
if _, ok := g.Players[p.SourcePlayer]; ok {
|
||||
g.RemovePlayerL(p.SourcePlayer)
|
||||
}
|
||||
case *GameCommandMessage:
|
||||
if player, ok := g.Players[p.SourcePlayer]; ok {
|
||||
s.Logf("<%s> %s", player.Name, p.Message)
|
||||
|
||||
msg := strings.ReplaceAll(strings.TrimSpace(p.Message), "\n", "")
|
||||
if msg != "" {
|
||||
g.WriteAllL(&GameCommandMessage{Player: p.SourcePlayer, Message: msg})
|
||||
}
|
||||
msg := strings.ReplaceAll(strings.TrimSpace(p.Message), "\n", "")
|
||||
if msg != "" {
|
||||
g.WriteAllL(&GameCommandMessage{Player: p.SourcePlayer, Message: msg})
|
||||
}
|
||||
}
|
||||
case CommandNickname:
|
||||
if p, ok := e.(*GameCommandNickname); ok {
|
||||
if player, ok := g.Players[p.SourcePlayer]; ok {
|
||||
newNick := Nickname(p.Nickname)
|
||||
if newNick != "" && newNick != player.Name {
|
||||
oldNick := player.Name
|
||||
player.Name = newNick
|
||||
case *GameCommandNickname:
|
||||
if player, ok := g.Players[p.SourcePlayer]; ok {
|
||||
newNick := Nickname(p.Nickname)
|
||||
if newNick != "" && newNick != player.Name {
|
||||
oldNick := player.Name
|
||||
player.Name = newNick
|
||||
|
||||
g.Logf(LogStandard, "* %s is now known as %s", oldNick, newNick)
|
||||
g.WriteAllL(&GameCommandNickname{Player: p.SourcePlayer, Nickname: newNick})
|
||||
}
|
||||
g.Logf(LogStandard, "* %s is now known as %s", oldNick, newNick)
|
||||
g.WriteAllL(&GameCommandNickname{Player: p.SourcePlayer, Nickname: newNick})
|
||||
}
|
||||
}
|
||||
case CommandUpdateMatrix:
|
||||
if p, ok := e.(*GameCommandUpdateMatrix); ok {
|
||||
if pl, ok := g.Players[p.SourcePlayer]; ok {
|
||||
for _, m := range p.Matrixes {
|
||||
pl.Matrix.Replace(m)
|
||||
case *GameCommandUpdateMatrix:
|
||||
if pl, ok := g.Players[p.SourcePlayer]; ok {
|
||||
for _, m := range p.Matrixes {
|
||||
pl.Matrix.Replace(m)
|
||||
|
||||
if g.SpeedLimit > 0 && m.Speed > g.SpeedLimit+5 && time.Since(g.TimeStarted) > 7*time.Second {
|
||||
pl.Matrix.SetGameOver()
|
||||
if g.SpeedLimit > 0 && m.Speed > g.SpeedLimit+5 && time.Since(g.TimeStarted) > 7*time.Second {
|
||||
pl.Matrix.SetGameOver()
|
||||
|
||||
g.WriteMessage(fmt.Sprintf("%s went too fast and crashed", pl.Name))
|
||||
g.WriteAllL(&GameCommandGameOver{Player: p.SourcePlayer})
|
||||
}
|
||||
}
|
||||
|
||||
m := pl.Matrix
|
||||
spawn := m.SpawnLocation(m.P)
|
||||
if m.P != nil && spawn.X >= 0 && spawn.Y >= 0 && m.P.X != spawn.X {
|
||||
pl.Moved = time.Now()
|
||||
pl.Idle = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
case CommandGameOver:
|
||||
if p, ok := e.(*GameCommandGameOver); ok {
|
||||
g.Players[p.SourcePlayer].Matrix.SetGameOver()
|
||||
|
||||
g.WriteMessage(fmt.Sprintf("%s was knocked out", g.Players[p.SourcePlayer].Name))
|
||||
g.WriteAllL(&GameCommandGameOver{Player: p.SourcePlayer})
|
||||
}
|
||||
case CommandSendGarbage:
|
||||
if p, ok := e.(*GameCommandSendGarbage); ok {
|
||||
leastGarbagePlayer := -1
|
||||
leastGarbage := -1
|
||||
for playerID, player := range g.Players {
|
||||
if playerID == p.SourcePlayer || player.Matrix.GameOver {
|
||||
continue
|
||||
}
|
||||
|
||||
if leastGarbage == -1 || player.totalGarbageReceived < leastGarbage {
|
||||
leastGarbagePlayer = playerID
|
||||
leastGarbage = player.totalGarbageReceived
|
||||
g.WriteMessage(fmt.Sprintf("%s went too fast and crashed", pl.Name))
|
||||
g.WriteAllL(&GameCommandGameOver{Player: p.SourcePlayer})
|
||||
}
|
||||
}
|
||||
|
||||
if leastGarbagePlayer != -1 {
|
||||
g.Players[leastGarbagePlayer].totalGarbageReceived += p.Lines
|
||||
g.Players[leastGarbagePlayer].pendingGarbage += p.Lines
|
||||
|
||||
g.Players[p.SourcePlayer].totalGarbageSent += p.Lines
|
||||
m := pl.Matrix
|
||||
spawn := m.SpawnLocation(m.P)
|
||||
if m.P != nil && spawn.X >= 0 && spawn.Y >= 0 && m.P.X != spawn.X {
|
||||
pl.Moved = time.Now()
|
||||
pl.Idle = 0
|
||||
}
|
||||
}
|
||||
case CommandStats:
|
||||
if p, ok := e.(*GameCommandStats); ok {
|
||||
players := 0
|
||||
games := 0
|
||||
case *GameCommandGameOver:
|
||||
g.Players[p.SourcePlayer].Matrix.SetGameOver()
|
||||
|
||||
for _, g := range s.Games {
|
||||
players += len(g.Players)
|
||||
games++
|
||||
g.WriteMessage(fmt.Sprintf("%s was knocked out", g.Players[p.SourcePlayer].Name))
|
||||
g.WriteAllL(&GameCommandGameOver{Player: p.SourcePlayer})
|
||||
case *GameCommandSendGarbage:
|
||||
leastGarbagePlayer := -1
|
||||
leastGarbage := -1
|
||||
for playerID, player := range g.Players {
|
||||
if playerID == p.SourcePlayer || player.Matrix.GameOver {
|
||||
continue
|
||||
}
|
||||
|
||||
g.Players[p.SourcePlayer].Write(&GameCommandStats{Created: s.created, Players: players, Games: games})
|
||||
if leastGarbage == -1 || player.totalGarbageReceived < leastGarbage {
|
||||
leastGarbagePlayer = playerID
|
||||
leastGarbage = player.totalGarbageReceived
|
||||
}
|
||||
}
|
||||
|
||||
if leastGarbagePlayer != -1 {
|
||||
g.Players[leastGarbagePlayer].totalGarbageReceived += p.Lines
|
||||
g.Players[leastGarbagePlayer].pendingGarbage += p.Lines
|
||||
|
||||
g.Players[p.SourcePlayer].totalGarbageSent += p.Lines
|
||||
}
|
||||
case *GameCommandStats:
|
||||
players := 0
|
||||
games := 0
|
||||
|
||||
for _, g := range s.Games {
|
||||
players += len(g.Players)
|
||||
games++
|
||||
}
|
||||
|
||||
g.Players[p.SourcePlayer].Write(&GameCommandStats{Created: s.created, Players: players, Games: games})
|
||||
}
|
||||
|
||||
g.Unlock()
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"context"
|
||||