Added ability to leave game when arranging.
Added player name and icon in discovery screen.
Now removing join game buttons of games no longer advertised
Change-Id: I07f361462df1dd21525ec48499092b9e11e50898
diff --git a/go/Makefile b/go/Makefile
index 2144da3..8e58388 100644
--- a/go/Makefile
+++ b/go/Makefile
@@ -35,7 +35,6 @@
--alsologtostderr=false \
--root-dir=tmp/$(name) \
--name=users/$(email)/croupier/$(name) \
- --v23.proxy=proxy \
--v23.credentials=credentials \
--v23.permissions.literal='{"Admin":{"In":["..."]},"Write":{"In":["..."]},"Read":{"In":["..."]},"Resolve":{"In":["..."]},"Debug":{"In":["..."]}}'
@@ -51,4 +50,5 @@
all: fmt
# Switch mountpoints by replacing the --name flag in syncbase with the following line:
-# --name=/192.168.86.254:8101/croupier/$(name) \
\ No newline at end of file
+#
+#--name=/192.168.86.254:8101/croupier/$(name) \
\ No newline at end of file
diff --git a/go/src/hearts/Makefile b/go/src/hearts/Makefile
index 9b44e5c..0185275 100644
--- a/go/src/hearts/Makefile
+++ b/go/src/hearts/Makefile
@@ -13,7 +13,6 @@
hearts: fmt credentials
jiri go build hearts
./hearts \
- --v23.proxy=proxy \
--v23.tcp.address=:$(syncbase_port) \
--v23.credentials=credentials
diff --git a/go/src/hearts/assets/Apostrophe.png b/go/src/hearts/assets/Apostrophe.png
new file mode 100644
index 0000000..e09a9c4
--- /dev/null
+++ b/go/src/hearts/assets/Apostrophe.png
Binary files differ
diff --git a/go/src/hearts/assets/Quit.png b/go/src/hearts/assets/Quit.png
new file mode 100644
index 0000000..d266994
--- /dev/null
+++ b/go/src/hearts/assets/Quit.png
Binary files differ
diff --git a/go/src/hearts/img/reposition/reposition.go b/go/src/hearts/img/reposition/reposition.go
index f037498..d4503e0 100644
--- a/go/src/hearts/img/reposition/reposition.go
+++ b/go/src/hearts/img/reposition/reposition.go
@@ -283,7 +283,7 @@
bannerImgs := make([]*staticimg.StaticImg, 0)
cards := make([]*card.Card, 0)
bannerImgs = append(bannerImgs, u.Other...)
- bannerImgs = append(bannerImgs, u.Buttons[0])
+ bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
cards = append(cards, u.TableCards...)
@@ -327,7 +327,7 @@
bannerImgs := make([]*staticimg.StaticImg, 0)
cards := make([]*card.Card, 0)
bannerImgs = append(bannerImgs, u.Other...)
- bannerImgs = append(bannerImgs, u.Buttons[0])
+ bannerImgs = append(bannerImgs, u.Buttons["toggleSplit"])
tableImgs = append(tableImgs, u.DropTargets...)
tableImgs = append(tableImgs, u.BackgroundImgs[:u.NumPlayers]...)
cards = append(cards, u.TableCards...)
@@ -555,14 +555,19 @@
}
func BringNodeToFront(n *sprite.Node, u *uistate.UIState) {
- u.Scene.RemoveChild(n)
- u.Scene.AppendChild(n)
+ if n.Parent == u.Scene {
+ u.Scene.RemoveChild(n)
+ }
+ if n.Parent != u.Scene {
+ u.Scene.AppendChild(n)
+ }
}
func SwitchOnChan(animChan, quitChan chan bool, f func(), u *uistate.UIState) {
select {
case <-quitChan:
RemoveAnimChan(quitChan, u)
+ f()
return
case <-animChan:
RemoveAnimChan(quitChan, u)
diff --git a/go/src/hearts/img/resize/resize.go b/go/src/hearts/img/resize/resize.go
index 8fdbd28..fde54d3 100644
--- a/go/src/hearts/img/resize/resize.go
+++ b/go/src/hearts/img/resize/resize.go
@@ -38,9 +38,14 @@
adjustCardArray(u.TableCards, oldWindowSize, u.WindowSize, u.Eng)
adjustImgArray(u.DropTargets, oldWindowSize, u.WindowSize, u.Eng)
adjustImgArray(u.BackgroundImgs, oldWindowSize, u.WindowSize, u.Eng)
- adjustImgArray(u.Buttons, oldWindowSize, u.WindowSize, u.Eng)
adjustImgArray(u.EmptySuitImgs, oldWindowSize, u.WindowSize, u.Eng)
adjustImgArray(u.Other, oldWindowSize, u.WindowSize, u.Eng)
+ adjustImgArray(u.ModText, oldWindowSize, u.WindowSize, u.Eng)
+ buttons := make([]*staticimg.StaticImg, 0)
+ for _, b := range u.Buttons {
+ buttons = append(buttons, b)
+ }
+ adjustImgArray(buttons, oldWindowSize, u.WindowSize, u.Eng)
}
// Returns coordinates for images with same width and height but in new positions proportional to the screen
diff --git a/go/src/hearts/img/staticimg/staticimg.go b/go/src/hearts/img/staticimg/staticimg.go
index 97900a1..871b6f8 100644
--- a/go/src/hearts/img/staticimg/staticimg.go
+++ b/go/src/hearts/img/staticimg/staticimg.go
@@ -38,7 +38,7 @@
// cardHere is used if the StaticImg instance is a drop target
cardHere *card.Card
// info contains any additional information contained in the image (eg. game syncgroup address, in a join game button)
- info []string
+ info string
}
// Returns the node of s
@@ -81,7 +81,7 @@
}
// Returns the additional info associated with s
-func (s *StaticImg) GetInfo() []string {
+func (s *StaticImg) GetInfo() string {
return s.info
}
@@ -124,6 +124,6 @@
}
// Sets the additional info of s
-func (s *StaticImg) SetInfo(i []string) {
+func (s *StaticImg) SetInfo(i string) {
s.info = i
}
diff --git a/go/src/hearts/img/texture/texture.go b/go/src/hearts/img/texture/texture.go
index 2bec090..187f3ab 100644
--- a/go/src/hearts/img/texture/texture.go
+++ b/go/src/hearts/img/texture/texture.go
@@ -240,10 +240,10 @@
"E-Lower.png", "F-Lower.png", "G-Lower.png", "H-Lower.png", "I-Lower.png", "J-Lower.png", "K-Lower.png", "L-Lower.png",
"M-Lower.png", "N-Lower.png", "O-Lower.png", "P-Lower.png", "Q-Lower.png", "R-Lower.png", "S-Lower.png", "T-Lower.png",
"U-Lower.png", "V-Lower.png", "W-Lower.png", "X-Lower.png", "Y-Lower.png", "Z-Lower.png", "Space.png", "Colon.png", "Bang.png",
- "1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png", "8.png", "9.png", "0.png", "1-Red.png", "2-Red.png", "3-Red.png",
- "4-Red.png", "5-Red.png", "6-Red.png", "7-Red.png", "8-Red.png", "9-Red.png", "0-Red.png", "1-DBlue.png", "2-DBlue.png",
- "3-DBlue.png", "4-DBlue.png", "5-DBlue.png", "6-DBlue.png", "7-DBlue.png", "8-DBlue.png", "9-DBlue.png", "0-DBlue.png",
- "A-Upper-DBlue.png", "B-Upper-DBlue.png",
+ "Apostrophe.png", "1.png", "2.png", "3.png", "4.png", "5.png", "6.png", "7.png", "8.png", "9.png", "0.png", "1-Red.png",
+ "2-Red.png", "3-Red.png", "4-Red.png", "5-Red.png", "6-Red.png", "7-Red.png", "8-Red.png", "9-Red.png", "0-Red.png",
+ "1-DBlue.png", "2-DBlue.png", "3-DBlue.png", "4-DBlue.png", "5-DBlue.png", "6-DBlue.png", "7-DBlue.png", "8-DBlue.png",
+ "9-DBlue.png", "0-DBlue.png", "A-Upper-DBlue.png", "B-Upper-DBlue.png",
"C-Upper-DBlue.png", "D-Upper-DBlue.png", "E-Upper-DBlue.png", "F-Upper-DBlue.png", "G-Upper-DBlue.png", "H-Upper-DBlue.png",
"I-Upper-DBlue.png", "J-Upper-DBlue.png", "K-Upper-DBlue.png", "L-Upper-DBlue.png", "M-Upper-DBlue.png", "N-Upper-DBlue.png",
"O-Upper-DBlue.png", "P-Upper-DBlue.png", "Q-Upper-DBlue.png", "R-Upper-DBlue.png", "S-Upper-DBlue.png", "T-Upper-DBlue.png",
@@ -272,7 +272,7 @@
"U-Lower-Gray.png", "V-Lower-Gray.png", "W-Lower-Gray.png", "X-Lower-Gray.png", "Y-Lower-Gray.png", "Z-Lower-Gray.png",
"Space-Gray.png", "RoundedRectangle-DBlue.png", "RoundedRectangle-LBlue.png", "RoundedRectangle-Gray.png", "Rectangle-LBlue.png",
"Rectangle-DBlue.png", "HorizontalPullTab.png", "VerticalPullTab.png", "NewGame.png", "NewRound.png", "JoinGame.png", "Period.png",
- "SitSpot.png", "WatchSpot.png", "StartBlue.png", "StartGray.png", "Restart.png", "Visibility.png", "VisibilityOff.png",
+ "SitSpot.png", "WatchSpot.png", "StartBlue.png", "StartGray.png", "Restart.png", "Visibility.png", "VisibilityOff.png", "Quit.png",
}
for _, f := range boundedImgs {
a, err := asset.Open(f)
diff --git a/go/src/hearts/img/uistate/uistate.go b/go/src/hearts/img/uistate/uistate.go
index 9cfae3d..bb5c898 100644
--- a/go/src/hearts/img/uistate/uistate.go
+++ b/go/src/hearts/img/uistate/uistate.go
@@ -8,6 +8,8 @@
package uistate
import (
+ "encoding/json"
+ "fmt"
"time"
"hearts/img/coords"
@@ -62,7 +64,7 @@
BackgroundImgs []*staticimg.StaticImg
EmptySuitImgs []*staticimg.StaticImg
DropTargets []*staticimg.StaticImg
- Buttons []*staticimg.StaticImg
+ Buttons map[string]*staticimg.StaticImg
Other []*staticimg.StaticImg
ModText []*staticimg.StaticImg
CurCard *card.Card // the card that is currently clicked on
@@ -91,6 +93,7 @@
CurPlayerIndex int // the player number of this player
Ctx *context.T
Service syncbase.Service
+ LogSG string // name of the game log syncgroup the user is currently in
Debug bool // true if debugging, adds extra functionality to switch between players
SequentialPhases bool // true if trying to match Croupier Flutter Pass -> Take -> Play phase system
SwitchingViews bool // true if currently animating between play and split views
@@ -102,6 +105,7 @@
AnimChans []chan bool // keeps track of all 'quit' channels in animations so their goroutines can be stopped
SGChan chan bool // pass in a bool to stop advertising the syncgroup
ScanChan chan bool // pass in a bool to stop scanning for syncgroups
+ DiscGroups map[string]*DiscStruct // contains a set of addresses and game start data for each advertised game found
}
func MakeUIState() *UIState {
@@ -112,7 +116,7 @@
BackgroundImgs: make([]*staticimg.StaticImg, 0),
EmptySuitImgs: make([]*staticimg.StaticImg, 0),
DropTargets: make([]*staticimg.StaticImg, 0),
- Buttons: make([]*staticimg.StaticImg, 0),
+ Buttons: make(map[string]*staticimg.StaticImg),
Other: make([]*staticimg.StaticImg, 0),
ModText: make([]*staticimg.StaticImg, 0),
LastMouseXY: coords.MakeVec(-1, -1),
@@ -136,6 +140,7 @@
UserData: make(map[int]map[string]interface{}),
PlayerData: make(map[int]int),
AnimChans: make([]chan bool, 0),
+ DiscGroups: make(map[string]*DiscStruct),
CurPlayerIndex: -1,
}
}
@@ -166,3 +171,23 @@
}
return u.Texs[u.UserData[userID][Device].(string)]
}
+
+type DiscStruct struct {
+ SettingsAddr string
+ LogAddr string
+ GameStartData map[string]interface{}
+}
+
+func MakeDiscStruct(s, l, g string) *DiscStruct {
+ gameStartData := []byte(g)
+ var dataMap map[string]interface{}
+ err := json.Unmarshal(gameStartData, &dataMap)
+ if err != nil {
+ fmt.Println("Unmarshal error:", err)
+ }
+ return &DiscStruct{
+ SettingsAddr: s,
+ LogAddr: l,
+ GameStartData: dataMap,
+ }
+}
diff --git a/go/src/hearts/img/view/view.go b/go/src/hearts/img/view/view.go
index 99f9cba..41dd84c 100644
--- a/go/src/hearts/img/view/view.go
+++ b/go/src/hearts/img/view/view.go
@@ -9,6 +9,7 @@
package view
import (
+ "fmt"
"sort"
"strconv"
"time"
@@ -49,14 +50,18 @@
addArrangePlayer(3, arrangeDim, arrangeBlockLength, u)
// table
watchPos := coords.MakeVec((u.WindowSize.X-arrangeDim.X)/2, (u.WindowSize.Y+arrangeBlockLength)/2-2*arrangeDim.Y-4*u.Padding)
- u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(watchImg, watchPos, arrangeDim, u))
+ u.Buttons["joinTable"] = texture.MakeImgWithoutAlt(watchImg, watchPos, arrangeDim, u)
+ quitImg := u.Texs["Quit.png"]
+ quitDim := u.CardDim
+ quitPos := coords.MakeVec(u.Padding, u.TopPadding+10)
+ u.Buttons["exit"] = texture.MakeImgWithoutAlt(quitImg, quitPos, quitDim, u)
if u.IsOwner {
startImg := u.Texs["StartBlue.png"]
startAlt := u.Texs["StartGray.png"]
startDim := coords.MakeVec(2*u.CardDim.X, u.CardDim.Y)
startPos := u.WindowSize.MinusVec(startDim).Minus(u.BottomPadding)
display := u.CurTable.AllReadyForNewRound()
- u.Buttons = append(u.Buttons, texture.MakeImgWithAlt(startImg, startAlt, startPos, startDim, display, u))
+ u.Buttons["start"] = texture.MakeImgWithAlt(startImg, startAlt, startPos, startDim, display, u)
}
}
@@ -76,7 +81,7 @@
}
// Discovery view: Displays a menu of possible games to join
-func LoadDiscoveryView(discChan chan []string, u *uistate.UIState) {
+func LoadDiscoveryView(u *uistate.UIState) {
u.CurView = uistate.Discovery
reposition.ResetAnims(u)
resetImgs(u)
@@ -84,18 +89,37 @@
newGameImg := u.Texs["NewGame.png"]
newGameDim := coords.MakeVec(2*u.CardDim.X, u.CardDim.Y)
newGamePos := coords.MakeVec((u.WindowSize.X-newGameDim.X)/2, u.TopPadding)
- u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(newGameImg, newGamePos, newGameDim, u))
+ u.Buttons["newGame"] = texture.MakeImgWithoutAlt(newGameImg, newGamePos, newGameDim, u)
buttonNum := 1
- go func() {
- for u.CurView == uistate.Discovery {
- sgSet := <-discChan
- joinGameImg := u.Texs["JoinGame.png"]
- joinGamePos := coords.MakeVec(newGamePos.X, newGamePos.Y+float32(buttonNum)*(newGameDim.Y+u.Padding))
- u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(joinGameImg, joinGamePos, newGameDim, u))
- u.Buttons[buttonNum].SetInfo(sgSet)
- buttonNum++
+ for _, d := range u.DiscGroups {
+ if d != nil {
+ dataMap := d.GameStartData
+ creatorID := int(dataMap["ownerID"].(float64))
+ if u.UserData[creatorID] != nil {
+ bgBannerDim := coords.MakeVec(u.WindowSize.X, u.CardDim.Y+(4*u.Padding/5))
+ bgBannerPos := coords.MakeVec(0, newGamePos.Y+float32(buttonNum)*(bgBannerDim.Y+u.Padding))
+ playerIconImg := u.Texs[u.UserData[creatorID]["avatar"].(string)]
+ playerIconDim := u.CardDim
+ playerIconPos := coords.MakeVec(u.BottomPadding, bgBannerPos.Y+2*u.Padding/5)
+ u.BackgroundImgs = append(u.BackgroundImgs,
+ texture.MakeImgWithoutAlt(playerIconImg, playerIconPos, playerIconDim, u))
+ creatorName := u.UserData[creatorID]["name"].(string)
+ gameText := creatorName + "'s game"
+ scaler := float32(6)
+ maxWidth := u.WindowSize.X - 3*u.CardDim.X - 4*u.Padding
+ left := coords.MakeVec(playerIconPos.X+playerIconDim.X+u.Padding, playerIconPos.Y+playerIconDim.Y/2-10)
+ textImgs := texture.MakeStringImgLeftAlign(gameText, "", "", true, left, scaler, maxWidth, u)
+ for _, img := range textImgs {
+ u.BackgroundImgs = append(u.BackgroundImgs, img)
+ }
+ joinGameImg := u.Texs["JoinGame.png"]
+ joinGamePos := coords.MakeVec(u.WindowSize.X-u.BottomPadding-newGameDim.X, newGamePos.Y+float32(buttonNum)*(bgBannerDim.Y+u.Padding))
+ u.Buttons[fmt.Sprintf("joinGame-%d", buttonNum)] = texture.MakeImgWithoutAlt(joinGameImg, joinGamePos, newGameDim, u)
+ u.Buttons[fmt.Sprintf("joinGame-%d", buttonNum)].SetInfo(d.LogAddr)
+ buttonNum++
+ }
}
- }()
+ }
}
// Table View: Displays the table. Intended for public devices
@@ -190,8 +214,7 @@
playerIconY := u.WindowSize.Y - u.TableCardDim.Y - u.BottomPadding - u.Padding - u.PlayerIconDim.Y
playerIconPos := coords.MakeVec(playerIconX, playerIconY)
if u.Debug {
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
+ u.Buttons["player0"] = texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u)
} else {
u.BackgroundImgs = append(u.BackgroundImgs,
texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
@@ -218,8 +241,7 @@
u.PlayerIconDim.Y - u.Padding
playerIconPos = coords.MakeVec(playerIconX, playerIconY)
if u.Debug {
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
+ u.Buttons["player1"] = texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u)
} else {
u.BackgroundImgs = append(u.BackgroundImgs,
texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
@@ -242,8 +264,7 @@
playerIconY = u.TopPadding + u.TableCardDim.Y + u.Padding
playerIconPos = coords.MakeVec(playerIconX, playerIconY)
if u.Debug {
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
+ u.Buttons["player2"] = texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u)
} else {
u.BackgroundImgs = append(u.BackgroundImgs,
texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
@@ -269,8 +290,7 @@
u.PlayerIconDim.Y - u.Padding
playerIconPos = coords.MakeVec(playerIconX, playerIconY)
if u.Debug {
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
+ u.Buttons["player3"] = texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u)
} else {
u.BackgroundImgs = append(u.BackgroundImgs,
texture.MakeImgWithoutAlt(playerIconImage, playerIconPos, u.PlayerIconDim, u))
@@ -440,11 +460,15 @@
func ChangePlayMessage(message string, u *uistate.UIState) {
// remove text and replace with message
for _, img := range u.Other {
- u.Scene.RemoveChild(img.GetNode())
+ if img.GetNode().Parent == u.Scene {
+ u.Scene.RemoveChild(img.GetNode())
+ }
}
- u.Scene.RemoveChild(u.Buttons[0].GetNode())
+ if u.Buttons["toggleSplit"].GetNode().Parent == u.Scene {
+ u.Scene.RemoveChild(u.Buttons["toggleSplit"].GetNode())
+ }
u.Other = make([]*staticimg.StaticImg, 0)
- u.Buttons = make([]*staticimg.StaticImg, 0)
+ u.Buttons = make(map[string]*staticimg.StaticImg)
addPlayHeader(message, false, u)
for _, img := range u.Other {
reposition.BringNodeToFront(img.GetNode(), u)
@@ -471,9 +495,8 @@
sitPos = coords.MakeVec((u.WindowSize.X-arrangeDim.X)/2+arrangeDim.X+2*u.Padding, (u.WindowSize.Y+arrangeBlockLength)/2-2*arrangeDim.Y-4*u.Padding)
}
if u.PlayerData[player] == 0 {
- u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(sitImg, sitPos, arrangeDim, u))
+ u.Buttons[fmt.Sprintf("joinPlayer-%d", player)] = texture.MakeImgWithoutAlt(sitImg, sitPos, arrangeDim, u)
} else {
- u.Buttons = append(u.Buttons, texture.MakeImgWithoutAlt(sitImg, sitPos, coords.MakeVec(0, 0), u))
avatar := uistate.GetAvatar(player, u)
u.BackgroundImgs = append(u.BackgroundImgs, texture.MakeImgWithoutAlt(avatar, sitPos, arrangeDim, u))
name := uistate.GetName(player, u)
@@ -629,8 +652,7 @@
pullTabAlt := u.Texs["VisibilityOff.png"]
pullTabDim := u.CardDim.DividedBy(2)
pullTabPos := headerPos.PlusVec(headerDimensions).MinusVec(pullTabDim).Minus(u.Padding)
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithAlt(pullTabImage, pullTabAlt, pullTabPos, pullTabDim, !beforeSplitAnimation, u))
+ u.Buttons["toggleSplit"] = texture.MakeImgWithAlt(pullTabImage, pullTabAlt, pullTabPos, pullTabDim, !beforeSplitAnimation, u)
// adding text
color := "DBlue"
scaler := float32(4)
@@ -764,7 +786,9 @@
func SetNumTricksTable(u *uistate.UIState) {
// remove old num tricks
for _, img := range u.Other {
- u.Scene.RemoveChild(img.GetNode())
+ if img.GetNode().Parent == u.Scene {
+ u.Scene.RemoveChild(img.GetNode())
+ }
}
u.Other = make([]*staticimg.StaticImg, 0)
// set new num tricks
@@ -804,11 +828,13 @@
func SetNumTricksHand(u *uistate.UIState) {
// remove old num tricks
for _, img := range u.ModText {
- u.Scene.RemoveChild(img.GetNode())
+ if img.GetNode().Parent == u.Scene {
+ u.Scene.RemoveChild(img.GetNode())
+ }
}
u.ModText = make([]*staticimg.StaticImg, 0)
// set new num tricks
- b := u.Buttons[0]
+ b := u.Buttons["toggleSplit"]
center := coords.MakeVec(u.Padding+b.GetDimensions().X/2, b.GetCurrent().Y-3*u.Padding)
scaler := float32(4)
max := b.GetDimensions().Y
@@ -886,8 +912,7 @@
pullTabImage := u.Texs["VerticalPullTab.png"]
pullTabSpotPos := coords.MakeVec(2*u.BottomPadding, passBannerPos.Y)
pullTabSpotDim := coords.MakeVec(4*u.BottomPadding, u.CardDim.Y+2*u.Padding)
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithAlt(pullTabImage, pullTabSpotImage, pullTabSpotPos, pullTabSpotDim, false, u))
+ u.Buttons["dragPass"] = texture.MakeImgWithAlt(pullTabImage, pullTabSpotImage, pullTabSpotPos, pullTabSpotDim, false, u)
// adding text
textLeft := coords.MakeVec(pullTabSpotPos.X+pullTabSpotDim.X/2, passBannerPos.Y-20)
scaler := float32(5)
@@ -1075,8 +1100,7 @@
}
buttonDim := coords.MakeVec(2*u.CardDim.X, 3*u.CardDim.Y/4)
buttonPos := coords.MakeVec((u.WindowSize.X-buttonDim.X)/2, u.WindowSize.Y-buttonDim.Y-u.BottomPadding)
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(buttonImg, buttonPos, buttonDim, u))
+ u.Buttons["ready"] = texture.MakeImgWithoutAlt(buttonImg, buttonPos, buttonDim, u)
}
func resetImgs(u *uistate.UIState) {
@@ -1085,7 +1109,7 @@
u.BackgroundImgs = make([]*staticimg.StaticImg, 0)
u.EmptySuitImgs = make([]*staticimg.StaticImg, 0)
u.DropTargets = make([]*staticimg.StaticImg, 0)
- u.Buttons = make([]*staticimg.StaticImg, 0)
+ u.Buttons = make(map[string]*staticimg.StaticImg)
u.Other = make([]*staticimg.StaticImg, 0)
u.ModText = make([]*staticimg.StaticImg, 0)
}
@@ -1103,12 +1127,10 @@
buttonDim := u.CardDim
debugTableImage := u.Texs["BakuSquare.png"]
debugTablePos := u.WindowSize.MinusVec(buttonDim)
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(debugTableImage, debugTablePos, buttonDim, u))
+ u.Buttons["table"] = texture.MakeImgWithoutAlt(debugTableImage, debugTablePos, buttonDim, u)
debugPassImage := u.Texs["Clubs-2.png"]
debugPassPos := coords.MakeVec(u.WindowSize.X-2*buttonDim.X, u.WindowSize.Y-buttonDim.Y)
- u.Buttons = append(u.Buttons,
- texture.MakeImgWithoutAlt(debugPassImage, debugPassPos, buttonDim, u))
+ u.Buttons["hand"] = texture.MakeImgWithoutAlt(debugPassImage, debugPassPos, buttonDim, u)
}
// Helper function that returns the largest int in a non-negative int array (not index of largest int)
diff --git a/go/src/hearts/main.go b/go/src/hearts/main.go
index 8526f23..de2ab74 100644
--- a/go/src/hearts/main.go
+++ b/go/src/hearts/main.go
@@ -123,10 +123,9 @@
func onPaint(glctx gl.Context, sz size.Event, u *uistate.UIState) {
if u.CurView == uistate.None {
- discChan := make(chan []string)
u.ScanChan = make(chan bool)
- go sync.ScanForSG(discChan, u.Ctx, u.ScanChan)
- view.LoadDiscoveryView(discChan, u)
+ go sync.ScanForSG(u.Ctx, u.ScanChan, u)
+ view.LoadDiscoveryView(u)
}
glctx.ClearColor(1, 1, 1, 1)
glctx.Clear(gl.COLOR_BUFFER_BIT)
diff --git a/go/src/hearts/sync/client.go b/go/src/hearts/sync/client.go
index c126c7c..27b721d 100644
--- a/go/src/hearts/sync/client.go
+++ b/go/src/hearts/sync/client.go
@@ -8,10 +8,9 @@
import (
"fmt"
- "strconv"
- "strings"
"hearts/img/uistate"
+ "hearts/img/view"
"v.io/v23/context"
"v.io/v23/discovery"
@@ -24,7 +23,7 @@
)
// Searches for new syncgroups being advertised, sends found syncgroups to sgChan
-func ScanForSG(sgChan chan []string, ctx *context.T, quit chan bool) {
+func ScanForSG(ctx *context.T, quit chan bool, u *uistate.UIState) {
mdns, err := mdns.New("")
if err != nil {
ctx.Fatalf("Plugin failed: %v", err)
@@ -40,10 +39,13 @@
for {
select {
case update := <-ch:
- sgNames := GetSG(instances, update)
- if sgNames != nil {
- sgChan <- sgNames
+ key, discStruct := GetSG(instances, update, u)
+ if discStruct != nil {
+ settingsAddr := discStruct.SettingsAddr
+ JoinSettingsSyncgroup(settingsAddr, u)
+ u.DiscGroups[key] = discStruct
}
+ view.LoadDiscoveryView(u)
case <-signals.ShutdownOnSignals(ctx):
break loop
case <-quit:
@@ -53,25 +55,28 @@
}
// Returns the addresses of any discovered syncgroups that contain croupier game information
-func GetSG(instances map[string]string, update discovery.Update) []string {
- switch u := update.(type) {
+func GetSG(instances map[string]string, update discovery.Update, u *uistate.UIState) (string, *uistate.DiscStruct) {
+ switch uType := update.(type) {
case discovery.UpdateFound:
- found := u.Value
+ found := uType.Value
instances[string(found.Service.InstanceId)] = found.Service.InstanceName
fmt.Printf("Discovered %q: Instance=%x, Interface=%q, Addrs=%v\n", found.Service.InstanceName, found.Service.InstanceId, found.Service.InterfaceName, found.Service.Addrs)
if found.Service.InterfaceName == CroupierInterface {
- return []string{found.Service.Attrs["settings_sgname"], found.Service.Addrs[0]}
+ key := found.Service.InstanceId
+ ds := uistate.MakeDiscStruct(found.Service.Attrs["settings_sgname"], found.Service.Addrs[0], found.Service.Attrs["game_start_data"])
+ return key, ds
}
case discovery.UpdateLost:
- lost := u.Value
+ lost := uType.Value
name, ok := instances[string(lost.InstanceId)]
if !ok {
name = "unknown"
}
delete(instances, string(lost.InstanceId))
+ u.DiscGroups[lost.InstanceId] = nil
fmt.Printf("Lost %q: Instance=%x\n", name, lost.InstanceId)
}
- return nil
+ return "", nil
}
// Returns a watchstream of the data in the table
@@ -107,17 +112,15 @@
ch <- false
} else {
fmt.Println("Syncgroup joined")
- // Set UIState GameID
- tmp := strings.Split(logName, "-")
- gameID, _ := strconv.Atoi(tmp[len(tmp)-1])
- u.GameID = gameID
- go UpdateGame(u)
+ if u.LogSG != logName {
+ resetGame(logName, false, u)
+ }
ch <- true
}
}
// Joins player settings syncgroup
-func JoinSettingsSyncgroup(ch chan bool, settingsName string, u *uistate.UIState) {
+func JoinSettingsSyncgroup(settingsName string, u *uistate.UIState) {
fmt.Println("Joining user settings syncgroup")
app := u.Service.App(AppName)
db := app.NoSQLDatabase(DbName, nil)
@@ -126,10 +129,8 @@
_, err := settingsSg.Join(u.Ctx, myInfoJoiner)
if err != nil {
fmt.Println("SYNCGROUP JOIN ERROR: ", err)
- ch <- false
} else {
fmt.Println("Syncgroup joined")
- ch <- true
}
}
diff --git a/go/src/hearts/sync/server.go b/go/src/hearts/sync/server.go
index 155830d..03887be 100644
--- a/go/src/hearts/sync/server.go
+++ b/go/src/hearts/sync/server.go
@@ -10,6 +10,8 @@
"encoding/json"
"fmt"
"math/rand"
+ "strconv"
+ "strings"
"hearts/img/uistate"
@@ -167,7 +169,9 @@
}
} else {
fmt.Println("Syncgroup created")
- go UpdateGame(u)
+ if logSGName != u.LogSG {
+ resetGame(logSGName, true, u)
+ }
ch <- logSGName
}
}
@@ -214,3 +218,15 @@
ch <- settingsSGName
}
}
+
+func resetGame(logName string, creator bool, u *uistate.UIState) {
+ u.PlayerData = make(map[int]int)
+ u.CurPlayerIndex = -1
+ u.LogSG = logName
+ if !creator {
+ tmp := strings.Split(logName, "-")
+ gameID, _ := strconv.Atoi(tmp[len(tmp)-1])
+ u.GameID = gameID
+ }
+ go UpdateGame(u)
+}
diff --git a/go/src/hearts/sync/util.go b/go/src/hearts/sync/util.go
index cf72edd..f5a77b1 100644
--- a/go/src/hearts/sync/util.go
+++ b/go/src/hearts/sync/util.go
@@ -13,11 +13,11 @@
UserID = 4444
UserColor = 16777215
UserAvatar = "player3.jpeg"
- UserName = "Dan"
+ UserName = "D"
SBName = "syncbase3"
AppName = "app"
DbName = "db"
LogName = "games"
SettingsName = "table_settings"
- CroupierInterface = "CroupierSettingsAndGameEmily"
+ CroupierInterface = "CroupierSettingsAndGame"
)
diff --git a/go/src/hearts/sync/watch.go b/go/src/hearts/sync/watch.go
index 0184ec4..3cf301b 100644
--- a/go/src/hearts/sync/watch.go
+++ b/go/src/hearts/sync/watch.go
@@ -40,19 +40,20 @@
stream, err := WatchData(SettingsName, "users", u)
if err != nil {
fmt.Println("WatchData error:", err)
- }
- for {
- if updateExists := stream.Advance(); updateExists {
- c := stream.Change()
- if c.ChangeType == nosql.PutChange {
- key := c.Row
- var value []byte
- if err := c.Value(&value); err != nil {
- fmt.Println("Value error:", err)
+ } else {
+ for {
+ if updateExists := stream.Advance(); updateExists {
+ c := stream.Change()
+ if c.ChangeType == nosql.PutChange {
+ key := c.Row
+ var value []byte
+ if err := c.Value(&value); err != nil {
+ fmt.Println("Value error:", err)
+ }
+ handleSettingsUpdate(key, value, u)
+ } else {
+ fmt.Println("Unexpected ChangeType: ", c.ChangeType)
}
- handleSettingsUpdate(key, value, u)
- } else {
- fmt.Println("Unexpected ChangeType: ", c.ChangeType)
}
}
}
@@ -84,6 +85,9 @@
}
}
}
+ if u.CurView == uistate.Discovery {
+ view.LoadDiscoveryView(u)
+ }
}
func UpdateGame(u *uistate.UIState) {
@@ -118,15 +122,15 @@
updateType := strings.Split(valueStr, "|")[0]
switch updateType {
case Deal:
- go onDeal(valueStr, u)
+ onDeal(valueStr, u)
case Pass:
- go onPass(valueStr, u)
+ onPass(valueStr, u)
case Take:
- go onTake(valueStr, u)
+ onTake(valueStr, u)
case Play:
- go onPlay(valueStr, u)
+ onPlay(valueStr, u)
case Ready:
- go onReady(valueStr, u)
+ onReady(valueStr, u)
}
case "players":
switch strings.Split(key, "/")[3] {
@@ -149,9 +153,7 @@
}
func onSettings(key, value string, u *uistate.UIState) {
- joinDone := make(chan bool)
- go JoinSettingsSyncgroup(joinDone, value, u)
- <-joinDone
+ JoinSettingsSyncgroup(value, u)
}
func onDeal(value string, u *uistate.UIState) {
@@ -347,7 +349,7 @@
// UI
if u.CurTable.AllReadyForNewRound() && u.IsOwner {
if u.CurView == uistate.Arrange {
- b := u.Buttons[5]
+ b := u.Buttons["start"]
if !b.GetDisplayingImage() {
u.Eng.SetSubTex(b.GetNode(), b.GetImage())
b.SetDisplayingImage(true)
diff --git a/go/src/hearts/touchhandler/touchhandler.go b/go/src/hearts/touchhandler/touchhandler.go
index 12dce44..65918e7 100644
--- a/go/src/hearts/touchhandler/touchhandler.go
+++ b/go/src/hearts/touchhandler/touchhandler.go
@@ -8,6 +8,8 @@
import (
"fmt"
+ "strconv"
+ "strings"
"golang.org/x/mobile/event/touch"
"golang.org/x/mobile/exp/sprite"
@@ -107,8 +109,8 @@
func beginClickDiscovery(t touch.Event, u *uistate.UIState) {
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- if buttonList[0] == u.Buttons[0] {
+ for _, button := range buttonList {
+ if button == u.Buttons["newGame"] {
logCh := make(chan string)
settingsCh := make(chan string)
go sync.CreateLogSyncgroup(logCh, u)
@@ -126,14 +128,10 @@
}
} else {
for _, b := range u.Buttons {
- if buttonList[0] == b {
+ if button == b {
joinLogDone := make(chan bool)
- joinSettingsDone := make(chan bool)
- settingsAddr := b.GetInfo()[0]
- logAddr := b.GetInfo()[1]
+ logAddr := b.GetInfo()
go sync.JoinLogSyncgroup(joinLogDone, logAddr, u)
- go sync.JoinSettingsSyncgroup(joinSettingsDone, settingsAddr, u)
- <-joinSettingsDone
if success := <-joinLogDone; success {
settingsCh := make(chan string)
go sync.CreateSettingsSyncgroup(settingsCh, u)
@@ -155,27 +153,43 @@
func beginClickArrange(t touch.Event, u *uistate.UIState) {
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- for i, b := range u.Buttons {
- if buttonList[0] == b {
- if i == 5 {
- if b.GetDisplayingImage() {
- successStart := sync.LogGameStart(u)
- for !successStart {
- successStart = sync.LogGameStart(u)
- }
- newHands := u.CurTable.Deal()
- successDeal := sync.LogDeal(u, u.CurPlayerIndex, newHands)
- for !successDeal {
- successDeal = sync.LogDeal(u, u.CurPlayerIndex, newHands)
+ for _, b := range buttonList {
+ if b == u.Buttons["exit"] {
+ if u.SGChan != nil {
+ u.SGChan <- true
+ u.SGChan = nil
+ }
+ u.IsOwner = false
+ u.DiscGroups = make(map[string]*uistate.DiscStruct)
+ u.ScanChan = make(chan bool)
+ go sync.ScanForSG(u.Ctx, u.ScanChan, u)
+ view.LoadDiscoveryView(u)
+ } else if b == u.Buttons["start"] {
+ if b.GetDisplayingImage() {
+ successStart := sync.LogGameStart(u)
+ for !successStart {
+ successStart = sync.LogGameStart(u)
+ }
+ newHands := u.CurTable.Deal()
+ successDeal := sync.LogDeal(u, u.CurPlayerIndex, newHands)
+ for !successDeal {
+ successDeal = sync.LogDeal(u, u.CurPlayerIndex, newHands)
+ }
+ }
+ } else {
+ for key, button := range u.Buttons {
+ if b == button {
+ if key == "joinTable" {
+ u.CurPlayerIndex = 4
+ sync.LogPlayerNum(u)
+ } else {
+ playerNum := strings.Split(key, "-")[1]
+ if u.CurPlayerIndex < 0 {
+ u.CurPlayerIndex, _ = strconv.Atoi(playerNum)
+ sync.LogReady(u)
+ sync.LogPlayerNum(u)
}
}
- } else if u.CurPlayerIndex < 0 {
- u.CurPlayerIndex = i
- if u.CurPlayerIndex >= 0 && u.CurPlayerIndex < u.NumPlayers {
- sync.LogReady(u)
- }
- sync.LogPlayerNum(u)
}
}
}
@@ -195,51 +209,27 @@
reposition.BringNodeToFront(u.CurCard.GetNode(), u)
}
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- if u.Debug {
- if u.Buttons[0] == buttonList[0] {
- pullTab := u.Buttons[0]
- if pullTab.GetDisplayingImage() {
- u.CurImg = u.Buttons[0]
- for _, img := range u.Other {
- u.Eng.SetSubTex(img.GetNode(), img.GetAlt())
- img.SetDisplayingImage(false)
- }
- blueBanner := u.Other[0]
- reposition.BringNodeToFront(u.BackgroundImgs[1].GetNode(), u)
- reposition.BringNodeToFront(pullTab.GetNode(), u)
- for _, d := range u.DropTargets {
- reposition.BringNodeToFront(d.GetCardHere().GetNode(), u)
- }
- if blueBanner.GetNode().Arranger == nil {
- finalX := blueBanner.GetInitial().X
- finalY := pullTab.GetInitial().Y + pullTab.GetDimensions().Y - blueBanner.GetDimensions().Y
- finalPos := coords.MakeVec(finalX, finalY)
- reposition.AnimateImageNoChannel(blueBanner, finalPos, blueBanner.GetDimensions(), u)
- }
- }
- } else if u.Buttons[1] == buttonList[0] {
- view.LoadTableView(u)
- } else if u.Buttons[2] == buttonList[0] {
- view.LoadPassOrTakeOrPlay(u)
- }
- } else {
- pullTab := u.Buttons[0]
- if pullTab.GetDisplayingImage() {
- u.CurImg = u.Buttons[0]
+ for _, b := range buttonList {
+ if b == u.Buttons["table"] {
+ view.LoadTableView(u)
+ } else if b == u.Buttons["hand"] {
+ view.LoadPassOrTakeOrPlay(u)
+ } else if b == u.Buttons["dragPass"] {
+ if b.GetDisplayingImage() {
+ u.CurImg = b
for _, img := range u.Other {
u.Eng.SetSubTex(img.GetNode(), img.GetAlt())
img.SetDisplayingImage(false)
}
blueBanner := u.Other[0]
reposition.BringNodeToFront(u.BackgroundImgs[1].GetNode(), u)
- reposition.BringNodeToFront(pullTab.GetNode(), u)
+ reposition.BringNodeToFront(b.GetNode(), u)
for _, d := range u.DropTargets {
reposition.BringNodeToFront(d.GetCardHere().GetNode(), u)
}
if blueBanner.GetNode().Arranger == nil {
finalX := blueBanner.GetInitial().X
- finalY := pullTab.GetInitial().Y + pullTab.GetDimensions().Y - blueBanner.GetDimensions().Y
+ finalY := b.GetInitial().Y + b.GetDimensions().Y - blueBanner.GetDimensions().Y
finalPos := coords.MakeVec(finalX, finalY)
reposition.AnimateImageNoChannel(blueBanner, finalPos, blueBanner.GetDimensions(), u)
}
@@ -252,7 +242,7 @@
if u.CurImg != nil {
imgs := make([]*staticimg.StaticImg, 0)
cards := make([]*card.Card, 0)
- pullTab := u.Buttons[0]
+ pullTab := u.Buttons["dragPass"]
blueBanner := u.BackgroundImgs[1]
imgs = append(imgs, pullTab)
imgs = append(imgs, blueBanner)
@@ -287,7 +277,7 @@
readyToPass = false
}
}
- pullTab := u.Buttons[0]
+ pullTab := u.Buttons["dragPass"]
if readyToPass {
u.Eng.SetSubTex(pullTab.GetNode(), pullTab.GetImage())
pullTab.SetDisplayingImage(true)
@@ -322,13 +312,11 @@
u.CurCard.GetNode().Arranger = nil
}
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- if u.Debug {
- if u.Buttons[0] == buttonList[0] {
- view.LoadTableView(u)
- } else if u.Buttons[1] == buttonList[0] {
- view.LoadPassOrTakeOrPlay(u)
- }
+ for _, b := range buttonList {
+ if b == u.Buttons["table"] {
+ view.LoadTableView(u)
+ } else if b == u.Buttons["hand"] {
+ view.LoadPassOrTakeOrPlay(u)
}
}
}
@@ -373,17 +361,13 @@
reposition.BringNodeToFront(u.CurCard.GetNode(), u)
}
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- if u.Debug {
- if u.Buttons[0] == buttonList[0] && !u.SwitchingViews {
- view.LoadSplitView(false, u)
- } else if u.Buttons[1] == buttonList[0] {
- view.LoadTableView(u)
- } else if u.Buttons[2] == buttonList[0] {
- view.LoadPassOrTakeOrPlay(u)
- }
- } else if !u.SwitchingViews {
+ for _, b := range buttonList {
+ if b == u.Buttons["toggleSplit"] && !u.SwitchingViews {
view.LoadSplitView(false, u)
+ } else if b == u.Buttons["table"] {
+ view.LoadTableView(u)
+ } else if b == u.Buttons["hand"] {
+ view.LoadPassOrTakeOrPlay(u)
}
}
}
@@ -423,27 +407,8 @@
reposition.BringNodeToFront(u.CurCard.GetNode(), u)
}
buttonList := findClickedButton(t, u)
- if len(buttonList) > 0 {
- if u.Debug {
- if u.Buttons[0] == buttonList[0] && !u.SwitchingViews {
- ch := make(chan bool)
- u.SwitchingViews = true
- reposition.AnimateOutSplit(ch, u)
- quit := make(chan bool)
- u.AnimChans = append(u.AnimChans, quit)
- go func() {
- onDone := func() {
- u.SwitchingViews = false
- view.LoadPlayView(u)
- }
- reposition.SwitchOnChan(ch, quit, onDone, u)
- }()
- } else if u.Buttons[1] == buttonList[0] {
- view.LoadTableView(u)
- } else if u.Buttons[2] == buttonList[0] {
- view.LoadPassOrTakeOrPlay(u)
- }
- } else if !u.SwitchingViews {
+ for _, b := range buttonList {
+ if b == u.Buttons["toggleSplit"] && !u.SwitchingViews {
ch := make(chan bool)
u.SwitchingViews = true
reposition.AnimateOutSplit(ch, u)
@@ -456,6 +421,10 @@
}
reposition.SwitchOnChan(ch, quit, onDone, u)
}()
+ } else if b == u.Buttons["table"] {
+ view.LoadTableView(u)
+ } else if b == u.Buttons["hand"] {
+ view.LoadPassOrTakeOrPlay(u)
}
}
}
@@ -533,7 +502,7 @@
success = sync.LogPass(u, cardsPassed)
}
// UI component
- pullTab := u.Buttons[0]
+ pullTab := u.Buttons["dragPass"]
blueBanner := u.BackgroundImgs[1]
imgs := []*staticimg.StaticImg{pullTab, blueBanner}
for _, d := range dropsToReset {
@@ -672,21 +641,21 @@
}
func updateViewFromTable(b *staticimg.StaticImg, u *uistate.UIState) {
- if u.Buttons[0] == b {
+ if b == u.Buttons["player0"] {
u.CurPlayerIndex = 0
view.LoadPassOrTakeOrPlay(u)
- } else if u.Buttons[1] == b {
+ } else if b == u.Buttons["player1"] {
u.CurPlayerIndex = 1
view.LoadPassOrTakeOrPlay(u)
- } else if u.Buttons[2] == b {
+ } else if b == u.Buttons["player2"] {
u.CurPlayerIndex = 2
view.LoadPassOrTakeOrPlay(u)
- } else if u.Buttons[3] == b {
+ } else if b == u.Buttons["player3"] {
u.CurPlayerIndex = 3
view.LoadPassOrTakeOrPlay(u)
- } else if u.Buttons[4] == b {
+ } else if b == u.Buttons["table"] {
view.LoadTableView(u)
- } else if u.Buttons[5] == b {
+ } else if b == u.Buttons["hand"] {
view.LoadPassOrTakeOrPlay(u)
}
}