Change Doudizhu message process from websocket to restful api
This commit is contained in:
parent
9de0847a1e
commit
19fafcb832
|
@ -9,53 +9,12 @@ const port = process.env.PORT || 10080;
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
app.use(express.json());
|
app.use(express.json());
|
||||||
|
|
||||||
const server = app.listen(port, () => {
|
app.listen(port, () => {
|
||||||
console.log(`Server is running on port: ${port}`);
|
console.log(`Server is running on port: ${port}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
const socket = require("socket.io");
|
|
||||||
const io = socket(server);
|
|
||||||
|
|
||||||
let testDoudizhuData = null, testLeducHoldemData = null;
|
let testDoudizhuData = null, testLeducHoldemData = null;
|
||||||
|
|
||||||
io.on("connection", socket => {
|
|
||||||
console.log("successfully connected to rlcard showdown frontend");
|
|
||||||
socket.emit("getMessage", "successfully connected to rlcard showdown node server");
|
|
||||||
socket.on("getMessage", message => {
|
|
||||||
let res = null;
|
|
||||||
if(message){
|
|
||||||
switch(message.type){
|
|
||||||
case(0):
|
|
||||||
res = {
|
|
||||||
type: 0,
|
|
||||||
message: {
|
|
||||||
playerInfo: testDoudizhuData.playerInfo,
|
|
||||||
initHands: testDoudizhuData.initHands
|
|
||||||
}
|
|
||||||
};
|
|
||||||
socket.emit("getMessage", res);
|
|
||||||
break;
|
|
||||||
case(1):
|
|
||||||
console.log(message);
|
|
||||||
if(message.message.turn >= testDoudizhuData.moveHistory.length){
|
|
||||||
// todo: process end of game
|
|
||||||
}else{
|
|
||||||
res = {
|
|
||||||
type: 1,
|
|
||||||
message: {
|
|
||||||
turn: message.message.turn,
|
|
||||||
playerIdx: testDoudizhuData.moveHistory[message.message.turn].playerIdx,
|
|
||||||
move: testDoudizhuData.moveHistory[message.message.turn].move
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
socket.emit("getMessage", res);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
router.get('/replay/leduc_holdem/:id', (req, res)=>{
|
router.get('/replay/leduc_holdem/:id', (req, res)=>{
|
||||||
res.json(testLeducHoldemData);
|
res.json(testLeducHoldemData);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
import '../assets/gameview.scss';
|
import '../assets/gameview.scss';
|
||||||
import { DoudizhuGameBoard } from '../components/GameBoard';
|
import { DoudizhuGameBoard } from '../components/GameBoard';
|
||||||
import webSocket from "socket.io-client";
|
import { removeCards, doubleRaf, deepCopy } from "../utils";
|
||||||
import { removeCards, doubleRaf, deepCopy, debounce } from "../utils";
|
|
||||||
|
|
||||||
import { Layout } from 'element-react';
|
import { Layout } from 'element-react';
|
||||||
import Slider from '@material-ui/core/Slider';
|
import Slider from '@material-ui/core/Slider';
|
||||||
|
@ -19,6 +19,8 @@ class DoudizhuGameView extends React.Component {
|
||||||
this.initConsiderationTime = 2000;
|
this.initConsiderationTime = 2000;
|
||||||
this.considerationTimeDeduction = 100;
|
this.considerationTimeDeduction = 100;
|
||||||
this.gameStateTimeout = null;
|
this.gameStateTimeout = null;
|
||||||
|
this.apiUrl = window.g.apiUrl;
|
||||||
|
this.moveHistory = [];
|
||||||
|
|
||||||
this.initGameState = {
|
this.initGameState = {
|
||||||
gameStatus: "ready", // "ready", "playing", "paused", "over"
|
gameStatus: "ready", // "ready", "playing", "paused", "over"
|
||||||
|
@ -32,7 +34,6 @@ class DoudizhuGameView extends React.Component {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
ws: null,
|
|
||||||
gameInfo: this.initGameState,
|
gameInfo: this.initGameState,
|
||||||
gameStateLoop: null,
|
gameStateLoop: null,
|
||||||
gameSpeed: 0
|
gameSpeed: 0
|
||||||
|
@ -42,11 +43,6 @@ class DoudizhuGameView extends React.Component {
|
||||||
gameStateTimer() {
|
gameStateTimer() {
|
||||||
this.gameStateTimeout = setTimeout(()=>{
|
this.gameStateTimeout = setTimeout(()=>{
|
||||||
let currentConsiderationTime = this.state.gameInfo.considerationTime;
|
let currentConsiderationTime = this.state.gameInfo.considerationTime;
|
||||||
// for test use
|
|
||||||
// console.log(currentConsiderationTime);
|
|
||||||
// if(currentConsiderationTime === 1000){
|
|
||||||
// debugger;
|
|
||||||
// }
|
|
||||||
if(currentConsiderationTime > 0) {
|
if(currentConsiderationTime > 0) {
|
||||||
currentConsiderationTime -= this.considerationTimeDeduction * Math.pow(2, this.state.gameSpeed);
|
currentConsiderationTime -= this.considerationTimeDeduction * Math.pow(2, this.state.gameSpeed);
|
||||||
currentConsiderationTime = currentConsiderationTime < 0 ? 0 : currentConsiderationTime;
|
currentConsiderationTime = currentConsiderationTime < 0 ? 0 : currentConsiderationTime;
|
||||||
|
@ -55,83 +51,55 @@ class DoudizhuGameView extends React.Component {
|
||||||
this.setState({gameInfo: gameInfo});
|
this.setState({gameInfo: gameInfo});
|
||||||
this.gameStateTimer();
|
this.gameStateTimer();
|
||||||
}else{
|
}else{
|
||||||
const turn = this.state.gameInfo.turn;
|
let res = this.moveHistory[this.state.gameInfo.turn];
|
||||||
const gameStateReq = {
|
if(res.playerIdx === this.state.gameInfo.currentPlayer){
|
||||||
type: 1,
|
let gameInfo = deepCopy(this.state.gameInfo);
|
||||||
message: {turn: turn}
|
gameInfo.latestAction[res.playerIdx] = res.move === "P" ? "P" : res.move.split(" ");
|
||||||
};
|
gameInfo.turn++;
|
||||||
let gameInfo = deepCopy(this.state.gameInfo);
|
gameInfo.currentPlayer = (gameInfo.currentPlayer+1)%3;
|
||||||
this.setState({gameInfo: gameInfo});
|
// take away played cards from player's hands
|
||||||
this.state.ws.emit("getMessage", gameStateReq);
|
const remainedCards = removeCards(gameInfo.latestAction[res.playerIdx], gameInfo.hands[res.playerIdx]);
|
||||||
|
if(remainedCards !== false){
|
||||||
|
gameInfo.hands[res.playerIdx] = remainedCards;
|
||||||
|
}else{
|
||||||
|
console.log("Cannot find cards in move from player's hand");
|
||||||
|
}
|
||||||
|
gameInfo.considerationTime = this.initConsiderationTime;
|
||||||
|
this.setState({gameInfo: gameInfo});
|
||||||
|
}else{
|
||||||
|
console.log("Mismatched current player index");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
startReplay() {
|
startReplay() {
|
||||||
if(this.state.ws !== null){
|
// for test use
|
||||||
const replayReq = {type: 0};
|
const replayId = 0;
|
||||||
this.state.ws.emit("getMessage", replayReq);
|
|
||||||
// init game state
|
|
||||||
let initGameState = deepCopy(this.initGameState);
|
|
||||||
// set game status to playing
|
|
||||||
initGameState.gameStatus = "playing";
|
|
||||||
this.setState({gameInfo: initGameState});
|
|
||||||
|
|
||||||
if(this.gameStateTimeout){
|
axios.get(`${this.apiUrl}/replay/doudizhu/${replayId}`)
|
||||||
window.clearTimeout(this.gameStateTimeout);
|
.then(res => {
|
||||||
this.gameStateTimeout = null;
|
res = res.data;
|
||||||
}
|
// init replay info
|
||||||
// loop to update game state
|
this.moveHistory = res.moveHistory;
|
||||||
this.gameStateTimer();
|
let gameInfo = deepCopy(this.initGameState);
|
||||||
}else{
|
gameInfo.gameStatus = "playing";
|
||||||
console.log("websocket not connected");
|
gameInfo.playerInfo = res.playerInfo;
|
||||||
}
|
gameInfo.hands = res.initHands.map(element => {
|
||||||
};
|
return element.split(" ");
|
||||||
|
});
|
||||||
|
// the first player should be landlord
|
||||||
|
gameInfo.currentPlayer = res.playerInfo.find(element=>{return element.role === "landlord"}).index;
|
||||||
|
this.setState({gameInfo: gameInfo}, ()=>{
|
||||||
|
if(this.gameStateTimeout){
|
||||||
|
window.clearTimeout(this.gameStateTimeout);
|
||||||
|
this.gameStateTimeout = null;
|
||||||
|
}
|
||||||
|
// loop to update game state
|
||||||
|
this.gameStateTimer();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
connectWebSocket() {
|
|
||||||
let ws = webSocket("http://localhost:10080");
|
|
||||||
ws.on("getMessage", message => {
|
|
||||||
if(message){
|
|
||||||
switch(message.type){
|
|
||||||
case 0:
|
|
||||||
// init replay info
|
|
||||||
let gameInfo = deepCopy(this.state.gameInfo);
|
|
||||||
gameInfo.playerInfo = message.message.playerInfo;
|
|
||||||
gameInfo.hands = message.message.initHands.map(element => {
|
|
||||||
return element.split(" ");
|
|
||||||
});
|
|
||||||
// the first player should be landlord
|
|
||||||
gameInfo.currentPlayer = message.message.playerInfo.find(element=>{return element.role === "landlord"}).index;
|
|
||||||
this.setState({gameInfo: gameInfo});
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
// getting player actions
|
|
||||||
let res = message.message;
|
|
||||||
if(res.turn === this.state.gameInfo.turn && res.playerIdx === this.state.gameInfo.currentPlayer){
|
|
||||||
let gameInfo = deepCopy(this.state.gameInfo);
|
|
||||||
gameInfo.latestAction[res.playerIdx] = res.move === "P" ? "P" : res.move.split(" ");
|
|
||||||
gameInfo.turn++;
|
|
||||||
gameInfo.currentPlayer = (gameInfo.currentPlayer+1)%3;
|
|
||||||
// take away played cards from player's hands
|
|
||||||
const remainedCards = removeCards(gameInfo.latestAction[res.playerIdx], gameInfo.hands[res.playerIdx]);
|
|
||||||
if(remainedCards !== false){
|
|
||||||
gameInfo.hands[res.playerIdx] = remainedCards;
|
|
||||||
}else{
|
|
||||||
console.log("Cannot find cards in move from player's hand");
|
|
||||||
}
|
|
||||||
gameInfo.considerationTime = this.initConsiderationTime;
|
|
||||||
this.setState({gameInfo: gameInfo});
|
|
||||||
}else{
|
|
||||||
console.log("Mismatched game turn or current player index", message);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.log("Wrong message type ", message);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.setState({ws: ws});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
runNewTurn(prevTurn){
|
runNewTurn(prevTurn){
|
||||||
|
@ -175,7 +143,6 @@ class DoudizhuGameView extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
changeGameSpeed(newVal){
|
changeGameSpeed(newVal){
|
||||||
console.log('wdnmd');
|
|
||||||
this.setState({gameSpeed: newVal});
|
this.setState({gameSpeed: newVal});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,11 +155,10 @@ class DoudizhuGameView extends React.Component {
|
||||||
case "paused":
|
case "paused":
|
||||||
return <Button variant={"contained"} startIcon={<PlayArrowRoundedIcon />} color="primary" onClick={()=>{this.resumeReplay()}}>Resume</Button>;
|
return <Button variant={"contained"} startIcon={<PlayArrowRoundedIcon />} color="primary" onClick={()=>{this.resumeReplay()}}>Resume</Button>;
|
||||||
case "over":
|
case "over":
|
||||||
return <Button variant={"contained"} startIcon={<ReplayRoundedIcon />} color="primary" onClick={()=>{this.startReplay()}}>Resume</Button>;
|
return <Button variant={"contained"} startIcon={<ReplayRoundedIcon />} color="primary" onClick={()=>{this.startReplay()}}>Restart</Button>;
|
||||||
default:
|
default:
|
||||||
alert(`undefined game status: ${status}`);
|
alert(`undefined game status: ${status}`);
|
||||||
}
|
}
|
||||||
return ;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
render(){
|
render(){
|
||||||
|
@ -247,14 +213,14 @@ class DoudizhuGameView extends React.Component {
|
||||||
<div className="game-controller">
|
<div className="game-controller">
|
||||||
<Layout.Row>
|
<Layout.Row>
|
||||||
<Layout.Col span="24">
|
<Layout.Col span="24">
|
||||||
<Button variant={"contained"} color="primary" onClick={()=>{this.connectWebSocket()}}>Connect</Button>
|
{/*<Button variant={"contained"} color="primary" onClick={()=>{this.connectWebSocket()}}>Connect</Button>*/}
|
||||||
{ this.gameStatusButton(this.state.gameInfo.gameStatus) }
|
{ this.gameStatusButton(this.state.gameInfo.gameStatus) }
|
||||||
</Layout.Col>
|
</Layout.Col>
|
||||||
</Layout.Row>
|
</Layout.Row>
|
||||||
<Layout.Row style={{height: "31px"}}>
|
<Layout.Row style={{height: "31px"}}>
|
||||||
<Layout.Col span="8" style={{height: "100%"}}>
|
<Layout.Col span="8" style={{height: "100%"}}>
|
||||||
<div style={{display: "table", height: "100%"}}>
|
<div style={{display: "table", height: "100%"}}>
|
||||||
<span style={{display: "table-cell", verticalAlign: "middle"}}>Consideration Time</span>
|
<span style={{display: "table-cell", verticalAlign: "middle"}}>Game Speed</span>
|
||||||
</div>
|
</div>
|
||||||
</Layout.Col>
|
</Layout.Col>
|
||||||
<Layout.Col span="16">
|
<Layout.Col span="16">
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import '../assets/gameview.scss';
|
import '../assets/gameview.scss';
|
||||||
import {LeducHoldemGameBoard} from '../components/GameBoard';
|
import {LeducHoldemGameBoard} from '../components/GameBoard';
|
||||||
import {doubleRaf, deepCopy} from "../utils";
|
import {deepCopy} from "../utils";
|
||||||
|
|
||||||
import { Button, Layout } from 'element-react';
|
import { Button, Layout } from 'element-react';
|
||||||
import Slider from '@material-ui/core/Slider';
|
import Slider from '@material-ui/core/Slider';
|
||||||
|
@ -10,12 +10,14 @@ import Slider from '@material-ui/core/Slider';
|
||||||
class LeducHoldemGameView extends React.Component {
|
class LeducHoldemGameView extends React.Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
const mainViewerId = 0; // Id of the player at the bottom of screen
|
const mainViewerId = 0; // Id of the player at the bottom of screen
|
||||||
this.initConsiderationTime = 2000;
|
this.initConsiderationTime = 2000;
|
||||||
this.considerationTimeDeduction = 100;
|
this.considerationTimeDeduction = 100;
|
||||||
this.gameStateTimeout = null;
|
this.gameStateTimeout = null;
|
||||||
this.apiUrl = window.g.apiUrl;
|
this.apiUrl = window.g.apiUrl;
|
||||||
this.moveHistory = [];
|
this.moveHistory = [];
|
||||||
|
|
||||||
this.initGameState = {
|
this.initGameState = {
|
||||||
playerInfo: [],
|
playerInfo: [],
|
||||||
hands: [],
|
hands: [],
|
||||||
|
|
Loading…
Reference in New Issue