Files
Sequence/Source/Game.js
2026-04-15 11:51:49 -07:00

217 lines
12 KiB
JavaScript

import React from "react";
import io from "socket.io-client"
import pako from "pako";
import * as Act from "./interface/Actions";
import Store from "./interface/Store";
import Players from "./Players"
import WinStats from "./WinStats"
import SerStats from "./SeriesStats";
import settings from "../settings";
import retImg from "./Images/goback.png"
import bp1Img from "./Images/spkron.png"
import bp2Img from "./Images/spkroff.png"
export default class Game extends React.Component {
constructor() {
super()
this.state = {
auth: Store.getToken(),
players: [], hand: [], turn: [], status: 0, atr: 0,
live: false, msg: '', noise: true,
myturn: false, coin: 0, avail: [],
}
this.color = ['grey', 'red', 'green', 'blue']
this.card = []
this.hand = []
this.connect = this.connect.bind(this)
this.boardCard = this.boardCard.bind(this)
this.dealtCard = this.dealtCard.bind(this)
this.player = this.player.bind(this)
this.status = this.status.bind(this)
this.myturn = this.myturn.bind(this)
this.onDragStart = this.onDragStart.bind(this)
this.onDragOver = this.onDragOver.bind(this)
this.onDrop = this.onDrop.bind(this)
}
componentDidMount() {
this.socket = io.connect(settings.server.baseSite,
{ query: 'token=' + this.state.auth + '&game=' + this.props.game })
this.socket.on('connect', this.connect)
this.socket.on('boardCard', this.boardCard)
this.socket.on('dealtCard', this.dealtCard)
this.socket.on('player', this.player)
this.socket.on('status', this.status)
this.socket.on('myturn', this.myturn)
this.socket.emit('reqBoardCards', { id: 'BRDCRD' })
}
componentWillUnmount() {
this.socket.emit('disconnect', { id: 'PLYERS', act: 0, soc: '' })
this.socket.disconnect()
}
connect() {
this.socket.emit('reqPlayers', { id: 'PLYERS', act: 1 })
}
boardCard(data) {
const binData = new Uint8Array(data);
const obj = JSON.parse(pako.inflate(binData, { to: 'string' }));
const node = this.card[obj.crd]
node.innerHTML = obj.img;
}
dealtCard(data) {
const binData = new Uint8Array(data);
const obj = JSON.parse(pako.inflate(binData, { to: 'string' }));
const node = this.hand[obj.inx]
node.innerHTML = obj.img;
let hand = this.state.hand
hand[obj.inx] = { dlr: obj.dlr }
this.setState({ hand: hand })
}
player(data) {
let obj = data
this.setState({ players: obj.players, live: obj.live })
if (obj.live === true) {
this.socket.emit('reqDealtHand', { id: 'DLTHND' })
} else {
for (let i = 0; i < this.hand.length; i++) {
const node = this.hand[i]
while (node.firstChild) node.removeChild(node.firstChild);
}
}
}
status(data) {
let obj = data
this.setState({ turn: obj.turn, msg: obj.msg, atr: obj.atr, status: Number(obj.typ) })
if (obj.typ === 1) {
Act.apiCall('service', 'GMSTAT', { match: this.props.game })
this.setState({ myturn: false, coin: 0 })
} else if (obj.typ === 2) {
this.socket.emit('reqDealtHand', { id: 'DLTHND' })
this.setState({status: 0})
}
}
myturn(data) {
let obj = data
this.setState({ myturn: true, coin: obj.coin, avail: obj.avail })
if (this.state.noise) this.beep()
}
newgame() {
this.socket.emit('reqNewGame', { id: 'GAMREQ' })
}
leave() {
this.props.xout()
}
beep() {
var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");
snd.play();
}
onDragStart(ev, id) {
ev.dataTransfer.setData("id", id);
let inx = Number(id.substr(1));
let dlr = this.state.hand[inx].dlr
for (let i = 0; i < this.state.avail.length; i++) {
if (this.state.avail[i].dlr === dlr) {
this.state.avail[i].p.map((x) => {
const node = this.card[x]
node.addEventListener('dragover', this.onDragOver);
// console.log("d:" + dlr + " i:" + i + " c:" + x)
})
}
}
}
onDragOver(ev) {
ev.preventDefault();
}
onDrop(ev, msg) {
let id = ev.dataTransfer.getData("id");
let inx = Number(id.substr(1));
//console.log("I:" + inx + " B:" + msg.substr(1) + " D:" + this.state.hand[inx].dlr)
this.socket.emit('PlayCard', { id: 'CRDPLY', crd: msg.substr(1), inx: inx, dlr: this.state.hand[inx].dlr })
this.setState({ myturn: false, coin: 0 })
for (let i = 0; i < this.card.length; i++) {
const node = this.card[i]
node.removeEventListener('dragover', this.onDragOver);
}
}
render() {
let dec = []
for (let i = 0; i < 100; i++) {
dec.push(<div className="card"
onDrop={(e) => this.onDrop(e, 'X' + i)}
ref={(component) => { this.card[i] = component; }} >
</div>)
}
let hnd = []
for (let i = 0; i < this.props.deal; i++) {
hnd.push(<div id="dealt" className="dealt">
{this.state.live && this.state.myturn === true
? <div className="coin"
draggable onDragStart={(e) => this.onDragStart(e, 'I' + i)}
style={{
backgroundColor: this.color[this.state.coin], backgroundClip: "content-box",
opacity: "0.7", border: "solid 3px " + this.color[this.state.coin]
}}>
</div>
: <div className="coin"
style={{ backgroundColor: "#f0f0f0", opacity: "0.7", border: "solid 3px grey" }}>
</div>
}
{this.state.status === 0
? <div className="card" style={{ backgroundImage: "url('FC.svg')", backgroundSize: "100%" }}
ref={(component) => { this.hand[i] = component; }} >
</div>
: null
}
</div>)
}
return (
<div className="flexCol">
<div className="flexRow flexSpace msg">
<div className="flexRow" onClick={this.leave.bind(this)}>
<img src={retImg} />return
</div>
<div style={{ color: this.color[this.state.atr] }}>
{this.state.msg}
</div>
<div className="flexRow">
<SerStats />
<img src={this.state.noise ? bp1Img : bp2Img}
onClick={(e) => this.setState({ noise: !this.state.noise })}
style={{ width: "16px", height: "16px", margin: "2px 7px" }} />
</div>
</div>
<div className="flexRow">
<Players players={this.state.players} turn={this.state.turn} live={this.state.live} />
<div id="board" className={this.state.myturn ? "flash" : ""}>
{dec}
</div>
{this.state.status === 1
? <WinStats newgame={this.newgame.bind(this)} game={this.props.game} />
: <div className="flexCol" style={{ marginTop: "8px" }}>
{hnd}
</div>
}
</div>
</div>
);
}
}