Skip to content

Commit cd54ed4

Browse files
committed
Fix View for DSL-TTT
1 parent c756e33 commit cd54ed4

File tree

9 files changed

+242
-18
lines changed

9 files changed

+242
-18
lines changed

games-core/src/main/kotlin/net/zomis/games/dsl/impl/DslImpl.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ class GameViewContext<T : Any>(val model: T, override val viewer: PlayerIndex) :
134134
gridSpec.apply(grid as GameGridBuilder<T, P>.() -> Unit)
135135
val context = GameViewContext2D<T, P>(model)
136136
view(context)
137-
viewResult[name] = (0 until gridSpec.sizeY(model)).flatMap {y ->
137+
viewResult[name] = (0 until gridSpec.sizeY(model)).map {y ->
138138
(0 until gridSpec.sizeX(model)).map {x ->
139139
val p = gridSpec.get(model, x, y)
140140
val tileMap = mutableMapOf<String, Any?>()

games-server/src/test/kotlin/net/zomis/games/server2/DslGameTest.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import net.zomis.games.server2.clients.ur.WSClient
88
import net.zomis.games.server2.clients.ur.getInt
99
import net.zomis.games.server2.clients.ur.getText
1010
import org.junit.jupiter.api.AfterEach
11+
import org.junit.jupiter.api.Assertions
1112
import org.junit.jupiter.api.BeforeEach
1213
import org.junit.jupiter.api.Test
1314
import java.net.URI
@@ -57,7 +58,11 @@ class DslGameTest {
5758
}
5859

5960
p1.sendAndExpectResponse("""{ "gameType": "$dslGame", "gameId": "1", "type": "ViewRequest" }""")
60-
p1.expectJsonObject { it.getText("type") == "GameView" }
61+
val viewResponse = p1.expectJsonObject { it.getText("type") == "GameView" }
62+
Assertions.assertEquals(3, viewResponse["view"]["board"].size())
63+
Assertions.assertEquals(3, viewResponse["view"]["board"][0].size())
64+
Assertions.assertEquals(3, viewResponse["view"]["board"][1].size())
65+
Assertions.assertEquals(3, viewResponse["view"]["board"][2].size())
6166
p2.sendAndExpectResponse("""{ "gameType": "$dslGame", "gameId": "1", "type": "ViewRequest" }""")
6267
p2.expectJsonObject { it.getText("type") == "GameView" }
6368

games-vue-client/src/components/Invites.vue

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,15 +136,14 @@ export default {
136136
this.$set(this.inviteWaiting, "declined", []);
137137
},
138138
gameStartedMessage: function(e) {
139-
let games = {
139+
let routeNames = {
140140
UR: "RoyalGameOfUR",
141-
UTTT: "UTTT",
142-
"UTTT-ECS": "ECSGame",
143-
Connect4: "Connect4"
141+
"UTTT-ECS": "ECSGame"
144142
};
143+
let routeName = routeNames[e.gameType] ? routeNames[e.gameType] : e.gameType;
145144
this.inviteWaiting = emptyInvite();
146145
this.$router.push({
147-
name: games[e.gameType],
146+
name: routeName,
148147
params: {
149148
gameId: e.gameId, // needed for route URL
150149
gameInfo: {

games-vue-client/src/components/StartScreen.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ import Invites from "./Invites";
7575
import RoyalGameOfUR from "@/components/RoyalGameOfUR";
7676
import Connect4 from "@/components/games/Connect4";
7777
import UTTT from "@/components/games/UTTT";
78+
import DSLTTT from "@/components/games/DSLTTT";
7879
import { mapState } from "vuex";
7980
/*
8081
let gameTypes = {
@@ -97,6 +98,7 @@ export default {
9798
RoyalGameOfUR,
9899
Connect4,
99100
UTTT,
101+
DSLTTT,
100102
Invites
101103
},
102104
methods: {
@@ -154,7 +156,7 @@ export default {
154156
}
155157
Socket.$on("type:GameList", this.gameListMessage);
156158
Socket.send(
157-
`{ "type": "ClientGames", "gameTypes": ["UR", "Connect4", "UTTT", "UTTT-ECS"], "maxGames": 1 }`
159+
`{ "type": "ClientGames", "gameTypes": ["UR", "Connect4", "UTTT", "DSL-TTT", "UTTT-ECS"], "maxGames": 1 }`
158160
);
159161
Socket.send(`{ "type": "ListRequest" }`);
160162
},
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<template>
2+
<div class="board-parent">
3+
<div class="board" :style="{width: width*64 + 'px', height: height*64 + 'px'}">
4+
<div class="pieces pieces-bg" :style="{ 'grid-template-columns': `repeat(${width}, 1fr)`, 'grid-template-rows': `repeat(${height}, 1fr)` }">
5+
<!-- :class="{ 'moveable': moveableIndex[idx - 1] && movesMade % 2 == gameInfo.yourIndex }" -->
6+
<div v-for="idx in width*height" :key="idx" class="piece piece-bg"
7+
@click="onClick({ x: (idx - 1) % width, y: Math.floor((idx - 1) / width) })">
8+
</div>
9+
</div>
10+
<div class="pieces player-pieces">
11+
<template v-for="piece in gridTiles">
12+
<slot :tile="piece" />
13+
</template>
14+
</div>
15+
</div>
16+
</div>
17+
</template>
18+
<script>
19+
export default {
20+
name: "Map2D",
21+
props: ["width", "height", "grid", "clickHandler"],
22+
methods: {
23+
doNothing() {},
24+
onClick(data) {
25+
console.log(`Click at background ${data.x}, ${data.y}. Handler ${this.clickHandler}`)
26+
if (this.clickHandler) {
27+
this.clickHandler(data.x, data.y)
28+
}
29+
}
30+
},
31+
computed: {
32+
gridTiles() {
33+
console.log("Grid is " + JSON.stringify(this.grid));
34+
if (typeof this.grid === 'undefined') {
35+
console.log("Grid is apparently undefined");
36+
return []
37+
}
38+
let gridTiles = []
39+
console.log("not undefined, checking rows...")
40+
this.grid.forEach((row, y) => {
41+
console.log("Found row", row, y)
42+
row.forEach((tile, x) => {
43+
console.log(x, y, tile, "equals", this.grid[y][x])
44+
if (this.grid[y][x]) {
45+
gridTiles.push({ key: `tile-${x}-${y}`, x: x, y: y, tile: tile })
46+
}
47+
})
48+
})
49+
return gridTiles
50+
}
51+
}
52+
}
53+
</script>
54+
<!--<style>
55+
@import "../../assets/games-style.css";
56+
57+
</style>-->
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<template>
2+
<div class="game-dsl">
3+
<GameHead :gameInfo="gameInfo"></GameHead>
4+
<Map2D :width="3" :height="3" :grid="view.board" :clickHandler="onClick">
5+
<template v-slot:default="slotProps">
6+
<UrPiece
7+
:key="slotProps.key"
8+
:mouseover="doNothing" :mouseleave="doNothing"
9+
class="piece"
10+
:class="'piece-' + slotProps.tile.tile.owner"
11+
:onclick="pieceClick"
12+
:piece="slotProps.tile">
13+
</UrPiece>
14+
</template>
15+
</Map2D>
16+
<GameResult :gameInfo="gameInfo"></GameResult>
17+
</div>
18+
</template>
19+
<script>
20+
import Map2D from "../common/Map2D";
21+
import Socket from "../../socket";
22+
import UrPiece from "../ur/UrPiece";
23+
import GameHead from "./common/GameHead";
24+
import GameResult from "./common/GameResult";
25+
import { mapState } from "vuex";
26+
27+
export default {
28+
name: "DSLTTT",
29+
props: ["gameInfo", "showRules"],
30+
created() {
31+
Socket.$on("type:IllegalMove", this.messageIllegal); // TODO: Is this used?
32+
},
33+
beforeDestroy() {
34+
Socket.$off("type:IllegalMove", this.messageIllegal);
35+
},
36+
mounted() {
37+
Socket.send(
38+
`{ "type": "ViewRequest", "gameType": "${
39+
this.gameInfo.gameType
40+
}", "gameId": "${this.gameInfo.gameId}" }`
41+
);
42+
},
43+
components: {
44+
Map2D,
45+
GameHead,
46+
GameResult,
47+
UrPiece
48+
},
49+
methods: {
50+
doNothing: function() {},
51+
action: function(name, data) {
52+
if (Socket.isConnected()) {
53+
let json = `{ "gameType": "${this.gameInfo.gameType}", "gameId": "${
54+
this.gameInfo.gameId
55+
}", "type": "move", "moveType": "${name}", "move": ${JSON.stringify(
56+
data
57+
)} }`;
58+
Socket.send(json);
59+
}
60+
},
61+
pieceClick(data) {
62+
console.log(`onClick on DSLTTT pieceClick invoked: ${data.x}, ${data.y}`)
63+
this.action("play", { x: data.x, y: data.y });
64+
},
65+
onClick: function(x, y) {
66+
console.log(`onClick on DSLTTT invoked: ${x}, ${y}`)
67+
this.action("play", { x: x, y: y });
68+
},
69+
messageIllegal(e) {
70+
console.log("IllegalMove: " + JSON.stringify(e));
71+
}
72+
},
73+
computed: {
74+
...mapState("DslGameState", {
75+
view(state) {
76+
return state.games[this.gameInfo.gameId].gameData.view;
77+
}
78+
})
79+
}
80+
};
81+
</script>
82+
<style>
83+
@import "../../assets/games-style.css";
84+
85+
.connect4-board {
86+
width: 448px;
87+
height: 384px;
88+
}
89+
90+
.game-connect4 .pieces {
91+
grid-template-columns: repeat(7, 1fr);
92+
grid-template-rows: repeat(6, 1fr);
93+
}
94+
</style>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import Vue from "vue";
2+
3+
import Socket from "../../socket";
4+
5+
const gameStore = {
6+
namespaced: true,
7+
state: {
8+
games: {}
9+
},
10+
getters: {},
11+
mutations: {
12+
createGame(state, data) {
13+
Vue.set(state.games, data.gameId, {
14+
component: "DSLTTT", // TODO: Support other types
15+
gameInfo: {
16+
gameType: data.gameType,
17+
gameId: data.gameId,
18+
yourIndex: data.yourIndex,
19+
players: data.players
20+
},
21+
gameData: {
22+
view: {}
23+
}
24+
});
25+
},
26+
updateView(state, data) {
27+
let game = state.games[data.gameId].gameData;
28+
game.view = data.view
29+
}
30+
},
31+
actions: {
32+
onSocketMessage(context, data) {
33+
if (data.type === "GameStarted") {
34+
context.commit("createGame", data);
35+
}
36+
if (data.type === "GameView") {
37+
context.commit("updateView", data);
38+
}
39+
if (data.type === "GameMove") {
40+
console.log(`Recieved move: ${data.moveType}: ${data.move}. DSL Game. Sending request for view update`);
41+
Socket.send(`{ "type": "ViewRequest", "gameType": "${data.gameType}", "gameId": "${data.gameId}" }`);
42+
}
43+
}
44+
}
45+
};
46+
47+
export default gameStore;

games-vue-client/src/router/index.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import Connect4 from "@/components/games/Connect4";
99
import UTTT from "@/components/games/UTTT";
1010
import ECSGame from "@/components/ecs/ECSGame";
1111
import InviteByURL from "@/components/InviteByURL";
12+
import DSLTTT from "@/components/games/DSLTTT";
1213

1314
import VueAxios from "vue-axios";
1415
import VueAuthenticate from "vue-authenticate";
@@ -93,6 +94,15 @@ export default new Router({
9394
showRules: true
9495
})
9596
},
97+
{
98+
path: "/games/DSL-TTT/:gameId/",
99+
name: "DSL-TTT",
100+
component: DSLTTT,
101+
props: route => ({
102+
gameInfo: route.params.gameInfo,
103+
showRules: true
104+
})
105+
},
96106
{
97107
path: "/games/UTTT/:gameId/",
98108
name: "UTTT",

games-vue-client/src/store.js

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,21 +3,29 @@ import Vuex from "vuex";
33
import Connect4state from "./components/games/Connect4state";
44
import URstate from "./components/RoyalGameOfURstate";
55
import UTTTstate from "./components/games/UTTTstate";
6+
import DslGameState from "./components/games/DslGameState";
67

78
// const debug = process.env.NODE_ENV !== "production";
89
Vue.use(Vuex);
910

11+
let dslGames = { "DSL-TTT": true };
12+
1013
const store = new Vuex.Store({
1114
state: {
1215
loginName: null,
1316
lobby: {}, // key: gameType, value: array of players (names)
1417
invites: [],
1518
games: [] // includes both playing and observing
1619
},
17-
modules: { Connect4: Connect4state, UR: URstate, UTTT: UTTTstate },
20+
modules: {
21+
Connect4: Connect4state,
22+
UR: URstate,
23+
UTTT: UTTTstate,
24+
DslGameState: DslGameState
25+
},
1826
getters: {
1927
activeGames: state => {
20-
let modules = [state.Connect4, state.UR, state.UTTT];
28+
let modules = [state.Connect4, state.UR, state.UTTT, state.DslGameState];
2129
return modules
2230
.flatMap(m => m.games)
2331
.map(i => Object.values(i))
@@ -72,14 +80,16 @@ const store = new Vuex.Store({
7280
if (data.type === "LobbyChange") {
7381
context.commit("changeLobby", data);
7482
}
75-
if (data.gameType === "Connect4") {
76-
context.dispatch("Connect4/onSocketMessage", data);
77-
}
78-
if (data.gameType === "UTTT") {
79-
context.dispatch("UTTT/onSocketMessage", data);
80-
}
81-
if (data.gameType === "UR") {
82-
context.dispatch("UR/onSocketMessage", data);
83+
if (data.gameType) {
84+
if (data.gameType === "Connect4") {
85+
context.dispatch("Connect4/onSocketMessage", data);
86+
} else if (data.gameType === "UTTT") {
87+
context.dispatch("UTTT/onSocketMessage", data);
88+
} else if (data.gameType === "UR") {
89+
context.dispatch("UR/onSocketMessage", data);
90+
} else if (dslGames[data.gameType]) {
91+
context.dispatch("DslGameState/onSocketMessage", data);
92+
}
8393
}
8494
}
8595
}

0 commit comments

Comments
 (0)