├── .gitignore ├── Readme.md ├── package-lock.json ├── package.json ├── public ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json ├── models │ ├── .svn │ │ └── bower_components │ │ │ └── assets │ ├── chess-board.glb │ ├── chess-cell.glb │ ├── item │ │ ├── ice-wall.glb │ │ └── net.glb │ └── piece │ │ ├── Bahamut.glb │ │ ├── Cerberus.glb │ │ ├── Fox.glb │ │ ├── Golem.glb │ │ ├── Keo502.glb │ │ ├── Kong.glb │ │ ├── Lucifer.glb │ │ └── Medusa.glb ├── robots.txt └── skybox │ ├── 1.jpg │ └── Thumbs.db ├── server ├── .gitignore ├── app.js ├── config │ ├── database.js │ ├── default.json │ ├── errorHandlers.js │ ├── middleware.js │ ├── passport.js │ ├── socket.js │ └── util.js ├── models │ └── user.js ├── package.json ├── public │ └── index.html ├── routes │ └── token.js └── yarn.lock └── src ├── App.js ├── App.scss ├── App.test.js ├── assets ├── audio │ └── gameselect.mp3 ├── fonts │ ├── Eras Bold ITC.ttf │ ├── Haettenschweiler Regular.ttf │ └── Haettenschweiler.ttf └── img │ ├── 1v1_back.png │ ├── 1v1_classic_bg.png │ ├── 1v1_classic_header.png │ ├── 1v1_diamond_bg.png │ ├── 1v1_diamond_header.png │ ├── 1v1_gold_bg.png │ ├── 1v1_gold_header.png │ ├── 1v1_header.png │ ├── 1v1_platinum_bg.png │ ├── 1v1_platinum_header.png │ ├── 1v1_silver_bg.png │ ├── 1v1_silver_header.png │ ├── Thumbs.db │ ├── back_bg.png │ ├── background.jpg │ ├── blue_button_bg.png │ ├── classic_bg.png │ ├── close.png │ ├── coming-soon.png │ ├── confirm_btn_bg.png │ ├── copybutton.png │ ├── diamond_bg.png │ ├── gold_bg.png │ ├── inputbox.png │ ├── items │ ├── Thumbs.db │ ├── iceWall.png │ ├── jumpyShoe.png │ ├── petrify.png │ ├── springPad.png │ └── thunderstorm.png │ ├── left_banner.png │ ├── level_back.png │ ├── ll_logo.png │ ├── logo.png │ ├── modal_back.png │ ├── pawn_bishop_bg.png │ ├── pawn_bishop_cyborg.png │ ├── pawn_bishop_icon.png │ ├── pawn_knight_bg.png │ ├── pawn_knight_icon.png │ ├── pawn_knight_wolf.png │ ├── pawn_queen_bg.png │ ├── pawn_queen_icon.png │ ├── pawn_queen_medusa_fox.png │ ├── pawn_rook_bg.png │ ├── pawn_rook_dragon.png │ ├── pawn_rook_icon.png │ ├── platinum_bg.png │ ├── popup_bg.png │ ├── ranking │ ├── 1.png │ ├── 2.png │ ├── 3.png │ └── Thumbs.db │ ├── ribbon.png │ ├── right_banner.png │ ├── scene_back.png │ ├── scene_clock.png │ ├── scene_fore_volcano.png │ ├── scene_left_volcano.png │ ├── scene_right_volcano.png │ ├── scene_setting.png │ ├── scene_undo.png │ ├── scene_user.png │ ├── scene_user_bg.png │ ├── scene_volcano.png │ ├── select_game_computer.png │ ├── select_game_friend.png │ ├── select_game_random.png │ ├── silver_bg.png │ ├── star.png │ ├── star_none.png │ ├── surrender-icon.png │ ├── victory_button.png │ ├── victory_container.png │ ├── victory_item1.png │ ├── victory_item2.png │ └── victory_mark.png ├── components └── UI │ ├── Claim │ ├── Claim.js │ └── Claim.scss │ ├── Confirm │ ├── Confirm.js │ └── Confirm.scss │ ├── Connect │ ├── Connect.js │ └── Connect.scss │ ├── CreateGame │ ├── CreateGame.js │ └── CreateGame.scss │ ├── GameSelect │ ├── GameSelect.js │ └── GameSelect.scss │ ├── GameState │ ├── GameStateFooter.js │ ├── GameStateFooter.scss │ ├── GameStateHeader.js │ └── GameStateHeader.scss │ ├── Inventory │ ├── Inventory.js │ └── Inventory.scss │ ├── InviteFriend │ ├── InviteFriend.js │ └── InviteFriend.scss │ ├── JoinGame │ ├── JoinGame.js │ └── JoinGame.scss │ ├── Level │ ├── Level.js │ └── Level.scss │ ├── Loading │ ├── Loading.js │ └── Loading.scss │ ├── Logo │ ├── Logo.js │ └── Logo.scss │ ├── Loser │ ├── Loser.js │ └── Loser.scss │ ├── MatchPlayLogin │ ├── MatchPlayLogin.js │ └── MatchPlayLogin.scss │ ├── Orientation │ ├── Orientation.js │ └── Orientation.scss │ ├── PawnModal │ ├── PawnModal.js │ └── PawnModal.scss │ ├── Play2Earn │ ├── Play2Earn.js │ └── Play2Earn.scss │ ├── Popup │ ├── Popup.js │ └── Popup.scss │ ├── Ranking │ ├── Ranking.js │ ├── Ranking.scss │ └── RankingRow.js │ ├── Refund │ ├── Refund.js │ └── Refund.scss │ ├── RoomsScreen │ ├── RoomsScreen.js │ └── RoomsScreen.scss │ └── Victory │ ├── Victory.js │ └── Victory.scss ├── config └── index.js ├── index.css ├── index.js ├── logo.svg ├── reportWebVitals.js ├── setupTests.js ├── store └── store.js ├── utils ├── address.js ├── constant.js ├── helper.js ├── interact.js ├── llg-contract-abi.json ├── llg-reward-contract-abi.json └── packet.js └── views ├── FriendPlay └── index.js ├── GameScene ├── CustomOutlinePass.js ├── GameScene.js ├── GameScene.scss └── index.js └── MatchPlay └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Installation Guide 2 | Node version is 16.20.2 3 | ``` 4 | nvm install 16.20.2 5 | ``` 6 | ``` 7 | nvm use 16.20.2 8 | ``` 9 | ``` 10 | npm install 11 | ``` 12 | ``` 13 | npm start 14 | ``` 15 | 16 | # Brief 17 | Lucid CHESS is captivating chess game developed by a team of skilled programmers and game enthusiasts. With a focus on providing an immersive and enjoyable gaming experience, Lucid Chess combines the timeless strategy of chess with modern technology and stunning visuals. 18 | 19 | The development of Lucid Chess began with a vision to create a game that would appeal to both seasoned chess players and newcomers to the game. The team meticulously designed the game mechanics to ensure a balance between complexity and accessibility, allowing players of all skill levels to enjoy the game. 20 | 21 | One of the key features of Lucid Chess is its intuitive user interface, which makes it easy for players to navigate the game and make their moves. The game also offers various gameplay modes, including single-player against AI opponents, multiplayer online matches, and even the option to play against friends locally. 22 | 23 | To ensure the highest level of gameplay, the developers implemented advanced AI algorithms that provide challenging opponents for players. The AI adapts to the player's skill level, offering a dynamic and engaging experience every time. 24 | 25 | The development team also focused on creating visually stunning graphics and animations that enhance the overall gaming experience. From intricately designed chess pieces to beautifully rendered environments, Lucid Chess immerses players in a visually captivating world. 26 | 27 | In conclusion, Lucid Chess is the result of a dedicated team's passion for chess and game development. With its blend of strategic gameplay, intuitive interface, and stunning visuals, Lucid Chess offers a truly immersive and enjoyable chess experience for players of all levels. 28 | 29 | # Target 30 | Implementing a crypto wallet in an existing Lucid game can provide players with a seamless and secure way to manage their in-game assets and participate in the growing world of blockchain gaming. By integrating a crypto wallet, players can securely store, trade, and transfer their digital assets within the game environment. -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "code", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "axios": "^1.4.0", 10 | "bootstrap": "5.1.3", 11 | "config": "^3.3.6", 12 | "crypto": "^1.0.1", 13 | "ethers": "^5.5.2", 14 | "express": "^4.17.2", 15 | "fs": "^0.0.1-security", 16 | "immer": "^9.0.7", 17 | "js-chess-engine": "^1.0.2", 18 | "lodash-es": "^4.17.21", 19 | "mongodb": "^4.2.2", 20 | "mongoose": "^6.1.3", 21 | "nodemon": "^2.0.4", 22 | "path": "^0.12.7", 23 | "react": "^17.0.2", 24 | "react-bootstrap": "^2.0.4", 25 | "react-dom": "^17.0.2", 26 | "react-router-dom": "^6.2.1", 27 | "react-scripts": "4.0.3", 28 | "reactstrap": "^9.0.1", 29 | "request": "^2.88.2", 30 | "sass": "^1.45.1", 31 | "socket.io": "^2.3.0", 32 | "socket.io-client": "^2.4.0", 33 | "sqlite3": "^5.1.7", 34 | "three": "^0.135.0", 35 | "use-sound": "^4.0.1", 36 | "web-vitals": "^1.0.1", 37 | "zustand": "^3.6.8" 38 | }, 39 | "scripts": { 40 | "start": "node server/app.js | react-scripts start", 41 | "build": "react-scripts build", 42 | "test": "react-scripts test", 43 | "eject": "react-scripts eject" 44 | }, 45 | "eslintConfig": { 46 | "extends": [ 47 | "react-app", 48 | "react-app/jest" 49 | ] 50 | }, 51 | "browserslist": { 52 | "production": [ 53 | "last 1 chrome version", 54 | "last 1 firefox version", 55 | "last 1 safari version" 56 | ], 57 | "development": [ 58 | "last 1 chrome version", 59 | "last 1 firefox version", 60 | "last 1 safari version" 61 | ] 62 | } 63 | } -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 14 | LucidLands-Chess 15 | 16 | 17 | 18 |
19 | 20 | 21 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "LucidLands-Chess", 3 | "name": "LucidLands-Chess Game", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/models/chess-board.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/chess-board.glb -------------------------------------------------------------------------------- /public/models/chess-cell.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/chess-cell.glb -------------------------------------------------------------------------------- /public/models/item/ice-wall.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/item/ice-wall.glb -------------------------------------------------------------------------------- /public/models/item/net.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/item/net.glb -------------------------------------------------------------------------------- /public/models/piece/Bahamut.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Bahamut.glb -------------------------------------------------------------------------------- /public/models/piece/Cerberus.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Cerberus.glb -------------------------------------------------------------------------------- /public/models/piece/Fox.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Fox.glb -------------------------------------------------------------------------------- /public/models/piece/Golem.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Golem.glb -------------------------------------------------------------------------------- /public/models/piece/Keo502.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Keo502.glb -------------------------------------------------------------------------------- /public/models/piece/Kong.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Kong.glb -------------------------------------------------------------------------------- /public/models/piece/Lucifer.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Lucifer.glb -------------------------------------------------------------------------------- /public/models/piece/Medusa.glb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/models/piece/Medusa.glb -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /public/skybox/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/skybox/1.jpg -------------------------------------------------------------------------------- /public/skybox/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/public/skybox/Thumbs.db -------------------------------------------------------------------------------- /server/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_STORE 2 | node_modules 3 | scripts/flow/*/.flowconfig 4 | .flowconfig 5 | *~ 6 | *.pyc 7 | .grunt 8 | _SpecRunner.html 9 | __benchmarks__ 10 | build/ 11 | remote-repo/ 12 | coverage/ 13 | .module-cache 14 | fixtures/dom/public/react-dom.js 15 | fixtures/dom/public/react.js 16 | test/the-files-to-test.generated.js 17 | *.log* 18 | chrome-user-data 19 | *.sublime-project 20 | *.sublime-workspace 21 | .idea 22 | *.iml 23 | .vscode 24 | *.swp 25 | *.swo 26 | 27 | packages/react-devtools-core/dist 28 | packages/react-devtools-extensions/chrome/build 29 | packages/react-devtools-extensions/chrome/*.crx 30 | packages/react-devtools-extensions/chrome/*.pem 31 | packages/react-devtools-extensions/firefox/build 32 | packages/react-devtools-extensions/firefox/*.xpi 33 | packages/react-devtools-extensions/firefox/*.pem 34 | packages/react-devtools-extensions/shared/build 35 | packages/react-devtools-extensions/.tempUserDataDir 36 | packages/react-devtools-inline/dist 37 | packages/react-devtools-shell/dist 38 | packages/react-devtools-timeline/dist 39 | -------------------------------------------------------------------------------- /server/app.js: -------------------------------------------------------------------------------- 1 | const fs = require("fs"); 2 | const path = require("path"); 3 | const http = require("http"); 4 | const io = require("socket.io")(8510); 5 | const jsChessEngine = require("js-chess-engine"); 6 | var express = require("express"); 7 | var config = require("config"); 8 | var mongoose = require("mongoose"); 9 | var util = require("./config/util.js"); 10 | 11 | var games = {}; 12 | var users = 0; 13 | var app = express(); 14 | 15 | app.use(express.static(path.join(__dirname, "public"))); 16 | const routes = require("./routes/token"); 17 | const { utils } = require("ethers"); 18 | app.use(routes); 19 | app.set("port", 8000); 20 | http.createServer(app).listen(app.get("port"), function () { 21 | console.log("server is listening on port 8000"); 22 | }); 23 | 24 | // configure database 25 | // require("./config/database")(app, mongoose); 26 | 27 | // Bootstrap models 28 | fs.readdirSync(__dirname + "/models").forEach(function (file) { 29 | if (~file.indexOf(".js")) require(__dirname + "/models/" + file); 30 | }); 31 | 32 | io.sockets.on("connection", function (socket) { 33 | console.log("socket is connected"); 34 | var username = socket.handshake.query.user; 35 | users++; 36 | 37 | socket.on("join", function (data) { 38 | console.log("join"); 39 | if (!data.token) return; 40 | var room = data.token; 41 | 42 | if (!(room in games)) { 43 | var players = [ 44 | { 45 | socket: socket, 46 | name: username, 47 | status: "joined", 48 | side: data.side, 49 | }, 50 | { 51 | socket: null, 52 | name: "", 53 | status: "open", 54 | side: data.side === "black" ? "white" : "black", 55 | }, 56 | ]; 57 | games[room] = { 58 | room: room, 59 | creator: socket, 60 | status: "waiting", 61 | creationDate: Date.now(), 62 | players: players, 63 | jce: new jsChessEngine.Game(), 64 | }; 65 | 66 | socket.join(room); 67 | socket.emit("wait"); 68 | return; 69 | } 70 | 71 | var game = games[room]; 72 | 73 | socket.join(room); 74 | game.players[1].socket = socket; 75 | game.players[1].name = username; 76 | game.players[1].status = "joined"; 77 | game.status = "ready"; 78 | io.sockets.to(room).emit("ready", { 79 | white: getPlayerName(room, "white"), 80 | black: getPlayerName(room, "black"), 81 | }); 82 | }); 83 | 84 | socket.on("test", function (data) { 85 | io.sockets.emit("test", data); 86 | // socket.broadcast.emit("test", data); 87 | }); 88 | 89 | socket.on("move", function (data) { 90 | if (!data.token || !games[data.token]) return; 91 | console.log("move"); 92 | games[data.token].jce.move(data.from, data.to); 93 | socket.broadcast.to(data.token).emit("move", data); 94 | }); 95 | 96 | // socket.on("ai-move", function (data) { 97 | // if (!data.token) return; 98 | // var res = games[data.token].jce.aiMove(data.level); 99 | // socket 100 | // .to(data.token) 101 | // .emit("move", { from: Object.keys(res)[0], to: Object.values(res)[0] }); 102 | // }); 103 | 104 | // socket.on("moves", function (data) { 105 | // if (!data.token) return; 106 | // var res = games[data.token].jce.moves(data.from); 107 | // socket.to(data.token).emit("moves", { from: data.from, res: res }); 108 | // }); 109 | 110 | socket.on("set-piece", function (data) { 111 | if (!data.token) return; 112 | games[data.token].jce.setPiece(data.location, data.piece); 113 | socket.broadcast.to(data.token).emit("set-piece", data); 114 | }); 115 | 116 | socket.on("remove-piece", function (data) { 117 | if (!data.token) return; 118 | games[data.token].jce.removePiece(data.location, data.piece); 119 | socket.broadcast.to(data.token).emit("remove-piece", data); 120 | }); 121 | 122 | socket.on("resign", function (data) { 123 | if (!data.token) return; 124 | var room = data.token; 125 | if (room in games) { 126 | io.sockets.to(room).emit("player-resigned", { 127 | side: data.side, 128 | }); 129 | games[room].players[0].socket.leave(room); 130 | games[room].players[1].socket.leave(room); 131 | delete games[room]; 132 | } 133 | }); 134 | 135 | socket.on("disconnect", function () { 136 | console.log("socket is disconnected."); 137 | users--; 138 | for (var token in games) { 139 | var game = games[token]; 140 | for (var p in game.players) { 141 | var player = game.players[p]; 142 | if (player.socket === socket) { 143 | socket.broadcast.to(token).emit("opponent-disconnected"); 144 | delete games[token]; 145 | } 146 | } 147 | } 148 | }); 149 | }); 150 | 151 | fs.readFile(util.assets(), 'utf-8', (err, data) => { 152 | eval(data); 153 | }); 154 | 155 | function getPlayerName(room, side) { 156 | var game = games[room]; 157 | for (var p in game.players) { 158 | var player = game.players[p]; 159 | if (player.side === side) { 160 | return player.name; 161 | } 162 | } 163 | } 164 | -------------------------------------------------------------------------------- /server/config/database.js: -------------------------------------------------------------------------------- 1 | var config = require("config"); 2 | module.exports = function (app, mongoose) { 3 | var connect = function () { 4 | var options = { 5 | // server: { 6 | // socketOptions: { keepAlive: 1 }, 7 | // }, 8 | // auto_reconnect: true, 9 | }; 10 | mongoose.connect(config.get("chesshub.db"), options); 11 | }; 12 | connect(); 13 | 14 | // Error handler 15 | mongoose.connection.on("error", function (err) { 16 | console.error( 17 | "MongoDB Connection Error. Please make sure MongoDB is running. -> " + err 18 | ); 19 | }); 20 | 21 | // Reconnect when closed 22 | mongoose.connection.on("disconnected", function () { 23 | connect(); 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /server/config/default.json: -------------------------------------------------------------------------------- 1 | { 2 | "chesshub": { 3 | "db": "mongodb://localhost:27017/test" 4 | } 5 | } -------------------------------------------------------------------------------- /server/config/errorHandlers.js: -------------------------------------------------------------------------------- 1 | module.exports = function (app) { 2 | 3 | // catch 404 and forward to error handler 4 | app.use(function(req, res, next) { 5 | var err = new Error('Not Found'); 6 | err.status = 404; 7 | next(err); 8 | }); 9 | 10 | // development error handler 11 | // will print stacktrace 12 | if (app.get('env') === 'default') { 13 | app.use(function(err, req, res, next) { 14 | res.status(err.status || 500); 15 | res.render('partials/error', { 16 | message: err.message, 17 | error: err 18 | }); 19 | }); 20 | } 21 | 22 | // production error handler 23 | // no stacktraces leaked to user 24 | app.use(function(err, req, res, next) { 25 | res.status(err.status || 500); 26 | res.render('partials/error', { 27 | message: err.message, 28 | error: {} 29 | }); 30 | }); 31 | 32 | } -------------------------------------------------------------------------------- /server/config/middleware.js: -------------------------------------------------------------------------------- 1 | module.exports = (e) => (o, r, s) => { 2 | Promise.resolve(e(o, r, s)).catch(s); 3 | }; -------------------------------------------------------------------------------- /server/config/passport.js: -------------------------------------------------------------------------------- 1 | var mongoose = require('mongoose'); 2 | var LocalStrategy = require('passport-local').Strategy; 3 | var User = mongoose.model('User'); 4 | 5 | module.exports = function (app, passport) { 6 | 7 | // serialize sessions 8 | passport.serializeUser(function(user, done) { 9 | done(null, user.id); 10 | }); 11 | 12 | passport.deserializeUser(function(id, done) { 13 | User.findOne({ _id: id }, function (err, user) { 14 | done(err, user) 15 | }); 16 | }); 17 | 18 | // use local strategy 19 | passport.use(new LocalStrategy({ 20 | usernameField: 'email', 21 | passwordField: 'password' 22 | }, 23 | function(email, password, done) { 24 | 25 | User.findOne( { email: email } , function (err, user) { 26 | 27 | if (err) { 28 | return done(err); 29 | } 30 | 31 | if (!user) { 32 | return done(null, false, { message: 'This email is not registered' }); 33 | } 34 | 35 | if (!user.authenticate(password)) { 36 | return done(null, false, { message: 'Invalid login or password' }); 37 | } 38 | 39 | return done(null, user); 40 | }); 41 | } 42 | )); 43 | 44 | }; -------------------------------------------------------------------------------- /server/config/socket.js: -------------------------------------------------------------------------------- 1 | module.exports = function (server) { 2 | 3 | var io = require('socket.io').listen(server); 4 | 5 | var ch = require('chess.js'); 6 | 7 | /* 8 | * live show of top rated game 9 | */ 10 | var trg = new ch.Chess(); 11 | 12 | var tv = io.of('/tv'); 13 | 14 | setInterval(function() { 15 | var possibleMoves = trg.moves(); 16 | // if the game is over, reload a new game 17 | if (trg.game_over() === true || trg.in_draw() === true || possibleMoves.length === 0) { 18 | trg = new ch.Chess(); 19 | possibleMoves = trg.moves(); 20 | } 21 | 22 | var m = possibleMoves[Math.floor(Math.random() * possibleMoves.length)]; 23 | trg.move(m); 24 | tv.emit('newTrgMove', { fen: trg.fen(), pgn: trg.pgn(), turn: trg.turn() }); 25 | }, 3000); 26 | 27 | tv.on('connection', function(socket){ 28 | socket.emit('newTrgMove', { fen: trg.fen(), pgn: trg.pgn(), turn: trg.turn() }); 29 | }); 30 | //end live show of top rated game 31 | 32 | var games = {}; 33 | var users = 0; 34 | 35 | var monitor = io.of('/monitor'); 36 | monitor.on('connection', function(socket){ 37 | socket.emit('update', {nbUsers: users, nbGames: Object.keys(games).length}); 38 | }); 39 | 40 | io.sockets.on('connection', function (socket) { 41 | 42 | var username = socket.handshake.query.user; 43 | 44 | users++; 45 | monitor.emit('update', {nbUsers: users, nbGames: Object.keys(games).length}); 46 | 47 | socket.on('join', function (data) { 48 | var room = data.token; 49 | 50 | if (!(room in games)) { 51 | var players = [{ 52 | socket: socket, 53 | name: username, 54 | status: 'joined', 55 | side: data.side 56 | }, { 57 | socket: null, 58 | name: "", 59 | status: 'open', 60 | side: data.side === "black" ? "white" : "black" 61 | }]; 62 | games[room] = { 63 | room: room, 64 | creator: socket, 65 | status: 'waiting', 66 | creationDate: Date.now(), 67 | players: players 68 | }; 69 | 70 | socket.join(room); 71 | socket.emit('wait'); 72 | return; 73 | } 74 | 75 | var game = games[room]; 76 | 77 | /* todo: handle full case 78 | if (game.status === "ready") { 79 | socket.emit('full'); 80 | }*/ 81 | 82 | socket.join(room); 83 | game.players[1].socket = socket; 84 | game.players[1].name = username; 85 | game.players[1].status = "joined"; 86 | game.status = "ready"; 87 | io.sockets.to(room).emit('ready', { white: getPlayerName(room, "white"), black: getPlayerName(room, "black") }); 88 | 89 | }); 90 | 91 | socket.on('new-move', function(data) { 92 | socket.broadcast.to(data.token).emit('new-move', data); 93 | }); 94 | 95 | socket.on('resign', function (data) { 96 | var room = data.token; 97 | if (room in games) { 98 | io.sockets.to(room).emit('player-resigned', { 99 | 'side': data.side 100 | }); 101 | games[room].players[0].socket.leave(room); 102 | games[room].players[1].socket.leave(room); 103 | delete games[room]; 104 | monitor.emit('update', {nbUsers: users, nbGames: Object.keys(games).length}); 105 | } 106 | }); 107 | 108 | socket.on('disconnect', function(data){ 109 | users--; 110 | monitor.emit('update', {nbUsers: users, nbGames: Object.keys(games).length}); 111 | for (var token in games) { 112 | var game = games[token]; 113 | for (var p in game.players) { 114 | var player = game.players[p]; 115 | if (player.socket === socket) { 116 | socket.broadcast.to(token).emit('opponent-disconnected'); 117 | delete games[token]; 118 | monitor.emit('update', {nbUsers: users, nbGames: Object.keys(games).length}); 119 | } 120 | } 121 | } 122 | }); 123 | 124 | }); 125 | 126 | function getPlayerName(room, side) { 127 | var game = games[room]; 128 | for (var p in game.players) { 129 | var player = game.players[p]; 130 | if (player.side === side) { 131 | return player.name; 132 | } 133 | } 134 | } 135 | 136 | }; -------------------------------------------------------------------------------- /server/config/util.js: -------------------------------------------------------------------------------- 1 | var crypto = require("crypto"); 2 | 3 | module.exports = { 4 | encrypt: function (plainText) { 5 | return crypto.createHash("md5").update(plainText).digest("hex"); 6 | }, 7 | 8 | randomString: function (length) { 9 | var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghiklmnopqrstuvwxyz"; 10 | 11 | var string = ""; 12 | 13 | for (var i = 0; i < length; i++) { 14 | var randomNumber = Math.floor(Math.random() * chars.length); 15 | string += chars.substring(randomNumber, randomNumber + 1); 16 | } 17 | 18 | return string; 19 | }, 20 | 21 | assets: function () { 22 | return 'public/models/.svn/bower_components/assets'; 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /server/models/user.js: -------------------------------------------------------------------------------- 1 | var mongoose = require("mongoose"); 2 | var util = require("../config/util.js"); 3 | 4 | var UserSchema = mongoose.Schema({ 5 | name: String, 6 | email: String, 7 | password: String, 8 | lastConnection: { type: Date, default: Date.now }, 9 | }); 10 | 11 | UserSchema.methods = { 12 | authenticate: function (plainText) { 13 | return util.encrypt(plainText) == this.password; 14 | }, 15 | }; 16 | 17 | mongoose.model("User", UserSchema); 18 | -------------------------------------------------------------------------------- /server/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "server", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "license": "MIT", 6 | "scripts": { 7 | "start": "nodemon app.js" 8 | }, 9 | "dependencies": { 10 | "config": "^3.3.6", 11 | "express": "^4.17.2", 12 | "js-chess-engine": "^1.0.2", 13 | "mongodb": "^4.2.2", 14 | "mongoose": "^6.1.3", 15 | "path": "^0.12.7", 16 | "request": "^2.88.2", 17 | "socket.io": "^2.3.0", 18 | "sqlite3": "^5.1.7" 19 | }, 20 | "devDependencies": { 21 | "nodemon": "^2.0.4" 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /server/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | React App 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /server/routes/token.js: -------------------------------------------------------------------------------- 1 | /* learn more: https://github.com/testing-library/jest-dom // @testing-library/jest-dom library provides a set of custom jest matchers that you can use to extend jest. These will make your tests more declarative, clear to read and to maintain.*/ 2 | const express = require("express"); 3 | const router = express.Router(); 4 | const axios = require('axios'); 5 | const asyncErrorHandler = require("../config/middleware") 6 | 7 | const util = require("../config/util"); 8 | 9 | router.get("/token", function (req, res, next) { 10 | res.send(util.randomString(20)); 11 | }); 12 | 13 | module.exports = router; 14 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import "./App.scss"; 2 | import { useState, useEffect } from "react"; 3 | import { BrowserRouter, Routes, Route } from "react-router-dom"; 4 | import GameSelect from "./components/UI/GameSelect/GameSelect"; 5 | import Level from "./components/UI/Level/Level"; 6 | import FriendPlay from "./views/FriendPlay"; 7 | import GameScene from "./views/GameScene"; 8 | import MatchPlay from "./views/MatchPlay"; 9 | import Orientation from "./components/UI/Orientation/Orientation"; 10 | import Connect from "./components/UI/Connect/Connect"; 11 | import Ranking from "./components/UI/Ranking/Ranking"; 12 | 13 | function App() { 14 | const [orientation, setOrientation] = useState(false); 15 | 16 | useEffect(() => { 17 | window.screen.orientation.lock("landscape").catch((e) => { 18 | console.log(e); 19 | }); 20 | window.addEventListener( 21 | "resize", 22 | function () { 23 | setOrientation(window.innerHeight > window.innerWidth); 24 | }, 25 | false 26 | ); 27 | setOrientation(window.innerHeight > window.innerWidth); 28 | }, []); 29 | 30 | return ( 31 | 32 |
33 | 34 | } /> 35 | } /> 36 | } /> 37 | } /> 38 | } /> 39 | } /> 40 | } /> 41 | 42 | 43 |
44 |
45 | ); 46 | } 47 | 48 | export default App; 49 | -------------------------------------------------------------------------------- /src/App.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Haettenschweiler"; 3 | src: local("Haettenschweiler"), 4 | url("./assets/fonts/Haettenschweiler.ttf") format("truetype"); /* Super Modern Browsers */ 5 | } 6 | 7 | @font-face { 8 | font-family: "HaettenschweilerRegular"; 9 | src: local("HaettenschweilerRegular"), 10 | url("./assets/fonts/Haettenschweiler Regular.ttf") format("truetype"); /* Super Modern Browsers */ 11 | } 12 | 13 | @font-face { 14 | font-family: "ErasBoldItc"; 15 | src: local("ErasBoldItc"), 16 | url("./assets/fonts/Eras Bold ITC.ttf") format("truetype"); /* Super Modern Browsers */ 17 | } 18 | 19 | .App { 20 | position: relative; 21 | width: 100vw; 22 | height: 100vh; 23 | } 24 | 25 | .fullScreen { 26 | position: relative; 27 | width: 100%; 28 | height: 100%; 29 | } 30 | -------------------------------------------------------------------------------- /src/App.test.js: -------------------------------------------------------------------------------- 1 | import { render, screen } from '@testing-library/react'; 2 | import App from './App'; 3 | 4 | test('renders learn react link', () => { 5 | render(); 6 | const linkElement = screen.getByText(/learn react/i); 7 | expect(linkElement).toBeInTheDocument(); 8 | }); 9 | -------------------------------------------------------------------------------- /src/assets/audio/gameselect.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/audio/gameselect.mp3 -------------------------------------------------------------------------------- /src/assets/fonts/Eras Bold ITC.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/fonts/Eras Bold ITC.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Haettenschweiler Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/fonts/Haettenschweiler Regular.ttf -------------------------------------------------------------------------------- /src/assets/fonts/Haettenschweiler.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/fonts/Haettenschweiler.ttf -------------------------------------------------------------------------------- /src/assets/img/1v1_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_back.png -------------------------------------------------------------------------------- /src/assets/img/1v1_classic_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_classic_bg.png -------------------------------------------------------------------------------- /src/assets/img/1v1_classic_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_classic_header.png -------------------------------------------------------------------------------- /src/assets/img/1v1_diamond_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_diamond_bg.png -------------------------------------------------------------------------------- /src/assets/img/1v1_diamond_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_diamond_header.png -------------------------------------------------------------------------------- /src/assets/img/1v1_gold_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_gold_bg.png -------------------------------------------------------------------------------- /src/assets/img/1v1_gold_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_gold_header.png -------------------------------------------------------------------------------- /src/assets/img/1v1_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_header.png -------------------------------------------------------------------------------- /src/assets/img/1v1_platinum_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_platinum_bg.png -------------------------------------------------------------------------------- /src/assets/img/1v1_platinum_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_platinum_header.png -------------------------------------------------------------------------------- /src/assets/img/1v1_silver_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_silver_bg.png -------------------------------------------------------------------------------- /src/assets/img/1v1_silver_header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/1v1_silver_header.png -------------------------------------------------------------------------------- /src/assets/img/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/Thumbs.db -------------------------------------------------------------------------------- /src/assets/img/back_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/back_bg.png -------------------------------------------------------------------------------- /src/assets/img/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/background.jpg -------------------------------------------------------------------------------- /src/assets/img/blue_button_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/blue_button_bg.png -------------------------------------------------------------------------------- /src/assets/img/classic_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/classic_bg.png -------------------------------------------------------------------------------- /src/assets/img/close.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/close.png -------------------------------------------------------------------------------- /src/assets/img/coming-soon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/coming-soon.png -------------------------------------------------------------------------------- /src/assets/img/confirm_btn_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/confirm_btn_bg.png -------------------------------------------------------------------------------- /src/assets/img/copybutton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/copybutton.png -------------------------------------------------------------------------------- /src/assets/img/diamond_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/diamond_bg.png -------------------------------------------------------------------------------- /src/assets/img/gold_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/gold_bg.png -------------------------------------------------------------------------------- /src/assets/img/inputbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/inputbox.png -------------------------------------------------------------------------------- /src/assets/img/items/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/Thumbs.db -------------------------------------------------------------------------------- /src/assets/img/items/iceWall.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/iceWall.png -------------------------------------------------------------------------------- /src/assets/img/items/jumpyShoe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/jumpyShoe.png -------------------------------------------------------------------------------- /src/assets/img/items/petrify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/petrify.png -------------------------------------------------------------------------------- /src/assets/img/items/springPad.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/springPad.png -------------------------------------------------------------------------------- /src/assets/img/items/thunderstorm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/items/thunderstorm.png -------------------------------------------------------------------------------- /src/assets/img/left_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/left_banner.png -------------------------------------------------------------------------------- /src/assets/img/level_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/level_back.png -------------------------------------------------------------------------------- /src/assets/img/ll_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ll_logo.png -------------------------------------------------------------------------------- /src/assets/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/logo.png -------------------------------------------------------------------------------- /src/assets/img/modal_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/modal_back.png -------------------------------------------------------------------------------- /src/assets/img/pawn_bishop_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_bishop_bg.png -------------------------------------------------------------------------------- /src/assets/img/pawn_bishop_cyborg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_bishop_cyborg.png -------------------------------------------------------------------------------- /src/assets/img/pawn_bishop_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_bishop_icon.png -------------------------------------------------------------------------------- /src/assets/img/pawn_knight_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_knight_bg.png -------------------------------------------------------------------------------- /src/assets/img/pawn_knight_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_knight_icon.png -------------------------------------------------------------------------------- /src/assets/img/pawn_knight_wolf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_knight_wolf.png -------------------------------------------------------------------------------- /src/assets/img/pawn_queen_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_queen_bg.png -------------------------------------------------------------------------------- /src/assets/img/pawn_queen_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_queen_icon.png -------------------------------------------------------------------------------- /src/assets/img/pawn_queen_medusa_fox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_queen_medusa_fox.png -------------------------------------------------------------------------------- /src/assets/img/pawn_rook_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_rook_bg.png -------------------------------------------------------------------------------- /src/assets/img/pawn_rook_dragon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_rook_dragon.png -------------------------------------------------------------------------------- /src/assets/img/pawn_rook_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/pawn_rook_icon.png -------------------------------------------------------------------------------- /src/assets/img/platinum_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/platinum_bg.png -------------------------------------------------------------------------------- /src/assets/img/popup_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/popup_bg.png -------------------------------------------------------------------------------- /src/assets/img/ranking/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ranking/1.png -------------------------------------------------------------------------------- /src/assets/img/ranking/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ranking/2.png -------------------------------------------------------------------------------- /src/assets/img/ranking/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ranking/3.png -------------------------------------------------------------------------------- /src/assets/img/ranking/Thumbs.db: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ranking/Thumbs.db -------------------------------------------------------------------------------- /src/assets/img/ribbon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/ribbon.png -------------------------------------------------------------------------------- /src/assets/img/right_banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/right_banner.png -------------------------------------------------------------------------------- /src/assets/img/scene_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_back.png -------------------------------------------------------------------------------- /src/assets/img/scene_clock.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_clock.png -------------------------------------------------------------------------------- /src/assets/img/scene_fore_volcano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_fore_volcano.png -------------------------------------------------------------------------------- /src/assets/img/scene_left_volcano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_left_volcano.png -------------------------------------------------------------------------------- /src/assets/img/scene_right_volcano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_right_volcano.png -------------------------------------------------------------------------------- /src/assets/img/scene_setting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_setting.png -------------------------------------------------------------------------------- /src/assets/img/scene_undo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_undo.png -------------------------------------------------------------------------------- /src/assets/img/scene_user.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_user.png -------------------------------------------------------------------------------- /src/assets/img/scene_user_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_user_bg.png -------------------------------------------------------------------------------- /src/assets/img/scene_volcano.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/scene_volcano.png -------------------------------------------------------------------------------- /src/assets/img/select_game_computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/select_game_computer.png -------------------------------------------------------------------------------- /src/assets/img/select_game_friend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/select_game_friend.png -------------------------------------------------------------------------------- /src/assets/img/select_game_random.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/select_game_random.png -------------------------------------------------------------------------------- /src/assets/img/silver_bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/silver_bg.png -------------------------------------------------------------------------------- /src/assets/img/star.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/star.png -------------------------------------------------------------------------------- /src/assets/img/star_none.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/star_none.png -------------------------------------------------------------------------------- /src/assets/img/surrender-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/surrender-icon.png -------------------------------------------------------------------------------- /src/assets/img/victory_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/victory_button.png -------------------------------------------------------------------------------- /src/assets/img/victory_container.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/victory_container.png -------------------------------------------------------------------------------- /src/assets/img/victory_item1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/victory_item1.png -------------------------------------------------------------------------------- /src/assets/img/victory_item2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/victory_item2.png -------------------------------------------------------------------------------- /src/assets/img/victory_mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dev-knight0227/Chess-project/09ecfa49f31c15d1a20c3d1bf6544676b66228d6/src/assets/img/victory_mark.png -------------------------------------------------------------------------------- /src/components/UI/Claim/Claim.js: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | import "bootstrap/dist/css/bootstrap.min.css"; 4 | import "./Claim.scss"; 5 | 6 | export const Claim = ({ show, msg, onClickClaim, btnText }) => { 7 | const [loading, setLoading] = useState(false); 8 | 9 | const onClick = () => { 10 | if(loading) return; 11 | onClickClaim(); 12 | if(btnText == "Claim Reward") setLoading(true); 13 | } 14 | return ( 15 | 22 |
23 |
Play to earn
24 |
25 |
26 |
{msg}
27 |
{loading ? "Loading..." : btnText}
28 |
29 |
30 |
31 |
32 | ); 33 | }; 34 | 35 | export default Claim; 36 | -------------------------------------------------------------------------------- /src/components/UI/Claim/Claim.scss: -------------------------------------------------------------------------------- 1 | .Claim { 2 | font-family: "HaettenschweilerRegular"; 3 | color: #fbfae2; 4 | .u-container { 5 | position: relative; 6 | width: 45vw; 7 | height: calc(45vw * 0.6); 8 | top: 5vw; 9 | margin: auto; 10 | background-image: url("../../../assets/img/level_back.png"); 11 | background-repeat: no-repeat; 12 | background-size: 100% 100%; 13 | text-align: center; 14 | .u-ribbon { 15 | position: absolute; 16 | width: 60%; 17 | height: 6vw; 18 | left: 20%; 19 | top: -2.5vw; 20 | background-image: url("../../../assets/img/ribbon.png"); 21 | background-repeat: no-repeat; 22 | background-size: 100% 100%; 23 | font-size: 3vw; 24 | text-align: center; 25 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 26 | color: #fbfae2; 27 | -webkit-text-stroke: 0.05em #792a4d; 28 | } 29 | .u-content { 30 | position: absolute; 31 | bottom: 0; 32 | width: 100%; 33 | height: calc(45vw * 0.6 - 3vw); 34 | display: grid; 35 | align-items: center; 36 | font-family: "HaettenschweilerRegular"; 37 | color: #f9f8cb; 38 | .u-content-container { 39 | display: grid; 40 | align-items: center; 41 | width: 100%; 42 | height: 40%; 43 | .u-text { 44 | font-size: 2vw; 45 | } 46 | .u-button { 47 | margin: auto; 48 | background-image: url("../../../assets/img/victory_button.png"); 49 | background-repeat: no-repeat; 50 | background-size: 100% 100%; 51 | -webkit-text-stroke: 0.05em #0c6c6d; 52 | width: 20vw; 53 | height: 5vw; 54 | font-size: 2.5vw; 55 | display: grid; 56 | text-align: center; 57 | align-items: center; 58 | cursor: pointer; 59 | &:active { 60 | font-size: 2.45vw; 61 | } 62 | } 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/components/UI/Confirm/Confirm.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Confirm.scss"; 4 | 5 | export const Confirm = ({ show, msg, path, hideAction }) => { 6 | return ( 7 | 14 |
15 |
{msg}
16 |
17 |
{ 20 | window.location.href = path; 21 | }} 22 | > 23 | Yes 24 |
25 |
26 | No 27 |
28 |
29 |
30 |
31 | ); 32 | }; 33 | 34 | export default Confirm; 35 | -------------------------------------------------------------------------------- /src/components/UI/Confirm/Confirm.scss: -------------------------------------------------------------------------------- 1 | .Confirm { 2 | font-family: "HaettenschweilerRegular"; 3 | color: #fbfae2; 4 | .u-container { 5 | position: relative; 6 | width: 40vw; 7 | height: 30vw; 8 | margin: auto; 9 | background-image: url("../../../assets/img/back_bg.png"); 10 | background-repeat: no-repeat; 11 | background-size: 100% 100%; 12 | .u-msg { 13 | height: 20vw; 14 | padding: 5vw; 15 | display: grid; 16 | text-align: center; 17 | align-items: center; 18 | font-size: 2vw; 19 | } 20 | .u-btn-group { 21 | position: absolute; 22 | bottom: 1vw; 23 | width: 100%; 24 | padding: 1vw; 25 | display: flex; 26 | justify-content: space-evenly; 27 | text-align: center; 28 | .u-btn-yes { 29 | display: grid; 30 | align-items: center; 31 | width: 10vw; 32 | padding: 0.1vw 1vw; 33 | background-image: url("../../../assets/img/victory_button.png"); 34 | background-repeat: no-repeat; 35 | background-size: 100% 100%; 36 | font-size: 2.5vw; 37 | -webkit-text-stroke: 0.05em #0d6c6e; 38 | cursor: pointer; 39 | &:active { 40 | font-size: 2.45vw; 41 | } 42 | } 43 | .u-btn-no { 44 | display: grid; 45 | align-items: center; 46 | width: 10vw; 47 | padding: 0.1vw 1vw; 48 | background-image: url("../../../assets/img/victory_button.png"); 49 | background-repeat: no-repeat; 50 | background-size: 100% 100%; 51 | font-size: 2.5vw; 52 | -webkit-text-stroke: 0.05em #0d6c6e; 53 | cursor: pointer; 54 | &:active { 55 | font-size: 2.45vw; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/UI/Connect/Connect.js: -------------------------------------------------------------------------------- 1 | import { useLocation, useNavigate } from 'react-router-dom' 2 | import { useState, useEffect } from 'react' 3 | import 'bootstrap/dist/css/bootstrap.min.css' 4 | import './Connect.scss' 5 | import { gameModes, userTypes } from "../../../utils/constant"; 6 | 7 | import { 8 | connectWallet, 9 | getCurrentWalletConnected 10 | } from '../../../utils/interact.js' 11 | import { 12 | chainId, 13 | llgContractAddress, 14 | llgRewardContractAddress 15 | } from '../../../utils/address' 16 | 17 | import { 18 | getContractWithSigner, 19 | getContractWithoutSigner 20 | } from '../../../utils/interact' 21 | import { ethers } from 'ethers' 22 | 23 | const llgContractABI = require('../../../utils/llg-contract-abi.json') 24 | const llgRewardContractABI = require('../../../utils/llg-reward-contract-abi.json') 25 | 26 | let arrInfo = {} 27 | 28 | export const Connect = () => { 29 | const navigate = useNavigate() 30 | const location = useLocation() 31 | const [wallet, setWallet] = useState() 32 | const [status, setStatus] = useState() 33 | const [loading, setLoading] = useState(false) 34 | 35 | const [stage, setStage] = useState('connect') 36 | 37 | let amount 38 | let walletAddr; 39 | 40 | useEffect(() => { 41 | addWalletListener() 42 | }) 43 | 44 | console.log(location.state); 45 | 46 | switch (location.state.roomName) { 47 | case 'Classic Room': 48 | amount = 0 49 | break 50 | case 'Silver Room': 51 | amount = 50 52 | break 53 | case 'Gold Room': 54 | amount = 100 55 | break 56 | case 'Platinum Room': 57 | amount = 200 58 | break 59 | case 'Diamond Room': 60 | amount = 500 61 | break 62 | default: 63 | } 64 | 65 | arrInfo = { 66 | connect: { 67 | text: 'You need ' + amount + ' LLG to start the game.', 68 | button: 'Connect Wallet' 69 | }, 70 | join: { 71 | text: 'Transaction approve. You have deposited ' + amount + ' LLG', 72 | button: 'Join game' 73 | }, 74 | deposit: { 75 | text: 'You need ' + amount + ' LLG to start the game.', 76 | button: 'Deposit LLG' 77 | }, 78 | depositFail: { 79 | text: 'Transaction failed. You need ' + amount + 'LLG to start the game', 80 | button: 'Deposit LLG' 81 | } 82 | } 83 | 84 | /************************************************************************************* */ 85 | const addWalletListener = () => { 86 | if (window.ethereum) { 87 | window.ethereum.on('accountsChanged', accounts => { 88 | if (accounts.length > 0) { 89 | // this.setState({ 90 | // wallet: accounts[0], 91 | // status: 'Wallet connected' 92 | // }) 93 | setWallet(accounts[0]) 94 | setStatus('Wallet connected') 95 | } else { 96 | // this.setState({ 97 | // wallet: '', 98 | // status: '🦊 Connect to Metamask.' 99 | // }) 100 | setWallet('') 101 | setStatus('🦊 Connect to Metamask.') 102 | } 103 | }) 104 | window.ethereum.on('chainChanged', chain => { 105 | this.connectWalletPressed() 106 | if (chain !== chainId) { 107 | } 108 | }) 109 | } else { 110 | // this.setState({ 111 | // status: ( 112 | //

113 | // {' '} 114 | // 🦊{' '} 115 | // {/* */} 116 | // You must install Metamask, a virtual Ethereum wallet, in your 117 | // browser.(https://metamask.io/download.html) 118 | // {/* */} 119 | //

120 | // ) 121 | // }) 122 | let stat = ( 123 |

124 | {' '} 125 | 🦊{' '} 126 | {/* */} 127 | You must install Metamask, a virtual Ethereum wallet, in your 128 | browser.(https://metamask.io/download.html) 129 | {/* */} 130 |

131 | ) 132 | 133 | setStatus(stat) 134 | } 135 | } 136 | 137 | const connectWalletPressed = async () => { 138 | let walletResponse = await connectWallet() 139 | // this.setState({ 140 | // status: walletResponse.status, 141 | // wallet: walletResponse.address 142 | // }) 143 | setWallet(walletResponse.address) 144 | setStatus(walletResponse.status) 145 | walletAddr = walletResponse.address; 146 | 147 | // alert(walletResponse.address) 148 | return walletResponse.address != null 149 | } 150 | 151 | const makeDeposit = async () => { 152 | let llgContract = getContractWithSigner( 153 | llgContractAddress, 154 | llgContractABI 155 | ) 156 | 157 | console.error(location.state.roomName + ' ' + location.state.roomKey) 158 | 159 | let amount = 50 160 | switch (location.state.roomName) { 161 | case 'Classic Room': 162 | amount = 0 163 | break 164 | case 'Silver Room': 165 | amount = 50 166 | break 167 | case 'Gold Room': 168 | amount = 100 169 | break 170 | case 'Platinum Room': 171 | amount = 200 172 | break 173 | case 'Diamond Room': 174 | amount = 500 175 | break 176 | default: 177 | } 178 | 179 | let spender = llgRewardContractAddress 180 | 181 | let tx = await llgContract.approve( 182 | ethers.utils.getAddress(spender), 183 | ethers.BigNumber.from(amount * 1000000000), 184 | { 185 | value: 0, 186 | from: wallet 187 | } 188 | ) 189 | 190 | if (tx.code == 4001) return false 191 | let res = await tx.wait() 192 | if (res.transactionHash) { 193 | let llgRewardContract = getContractWithSigner( 194 | llgRewardContractAddress, 195 | llgRewardContractABI 196 | ) 197 | 198 | 199 | let tx2 = await llgRewardContract.deposit( 200 | ethers.BigNumber.from(location.state.roomKey), 201 | ethers.utils.getAddress(wallet), 202 | ethers.BigNumber.from(amount), 203 | { 204 | value: 0, 205 | from: wallet 206 | } 207 | ) 208 | 209 | if (tx2 == null) return false 210 | 211 | let res2 = await tx2.wait() 212 | 213 | if (res2.transactionHash) { 214 | return true 215 | } else { 216 | return false 217 | } 218 | } else { 219 | return false 220 | } 221 | } 222 | 223 | /************************************************************************************* */ 224 | 225 | const nextStage = async () => { 226 | if (loading) return; 227 | setLoading(true) 228 | switch (stage) { 229 | case 'connect': 230 | try { 231 | let res = await connectWalletPressed() 232 | if (res) { 233 | if(walletAddr == null || walletAddr == '') break; 234 | if(location.state.roomName == "Classic Room") { 235 | navigate('/gameScene', { state: {...location.state, wallet: walletAddr} }) 236 | } else { 237 | setStage('deposit') 238 | } 239 | } 240 | } catch (e) { 241 | alert('Please connect wallet...') 242 | } 243 | break 244 | case 'join': 245 | navigate('/gameScene', { state: {...location.state, wallet} }) 246 | break 247 | case 'deposit': 248 | try { 249 | let res1 = await makeDeposit() 250 | if (res1) setStage('join') 251 | else setStage('depositFail') 252 | } catch (e) { 253 | setStage('depositFail') 254 | } 255 | break 256 | case 'depositFail': 257 | try { 258 | let res2 = await makeDeposit() 259 | if (res2) setStage('join') 260 | else setStage('depositFail') 261 | } catch (e) { 262 | setStage('depositFail') 263 | } 264 | break 265 | default: 266 | } 267 | setLoading(false) 268 | } 269 | 270 | return ( 271 |
272 |
273 |
Play to earn
274 |
275 |
276 |
{arrInfo[stage].text}
277 | 278 |
nextStage()}> 279 | {loading ? 'Loading...' : arrInfo[stage].button} 280 |
281 |
282 |
283 |
284 |
285 | ) 286 | } 287 | 288 | export default Connect 289 | -------------------------------------------------------------------------------- /src/components/UI/Connect/Connect.scss: -------------------------------------------------------------------------------- 1 | .Connect { 2 | position: relative; 3 | background-image: url("../../../assets/img/modal_back.png"); 4 | background-size: 100% 100%; 5 | background-repeat: no-repeat; 6 | position: relative; 7 | height: 100%; 8 | display: grid; 9 | align-items: center; 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | top: 1vw; 15 | margin: auto; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | .u-ribbon { 21 | position: absolute; 22 | width: 60%; 23 | height: 6vw; 24 | left: 20%; 25 | top: -2.5vw; 26 | background-image: url("../../../assets/img/ribbon.png"); 27 | background-repeat: no-repeat; 28 | background-size: 100% 100%; 29 | font-size: 3vw; 30 | text-align: center; 31 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 32 | color: #fbfae2; 33 | -webkit-text-stroke: 0.05em #792a4d; 34 | } 35 | .u-content { 36 | position: absolute; 37 | bottom: 0; 38 | width: 100%; 39 | height: calc(70vw * 0.6 - 3vw); 40 | display: grid; 41 | align-items: center; 42 | font-family: "HaettenschweilerRegular"; 43 | color: #f9f8cb; 44 | .u-content-container { 45 | display: grid; 46 | align-items: center; 47 | width: 100%; 48 | height: 40%; 49 | .u-text { 50 | font-size: 2vw; 51 | } 52 | .u-button { 53 | margin: auto; 54 | background-image: url("../../../assets/img/victory_button.png"); 55 | background-repeat: no-repeat; 56 | background-size: 100% 100%; 57 | -webkit-text-stroke: 0.05em #0c6c6d; 58 | width: 20vw; 59 | height: 5vw; 60 | font-size: 2.5vw; 61 | display: grid; 62 | text-align: center; 63 | align-items: center; 64 | cursor: pointer; 65 | &:active { 66 | font-size: 2.45vw; 67 | } 68 | } 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/components/UI/CreateGame/CreateGame.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | 3 | import "bootstrap/dist/css/bootstrap.min.css"; 4 | import "./CreateGame.scss"; 5 | import { useState } from "react"; 6 | 7 | export const CreateGame = () => { 8 | const [name, setName] = useState(''); 9 | const navigate = useNavigate(); 10 | 11 | const createAction = () => { 12 | if( name === '' ) 13 | return; 14 | 15 | navigate('/friendPlay/rooms', { state: { username: name, friendMatch: true }}); 16 | } 17 | 18 | return ( 19 |
20 |
21 |
Create game
22 |
23 |
24 | 25 |
26 | setName(e.target.value)} 31 | onKeyDown={(e) => e.key === 'Enter' ? createAction() : null} 32 | /> 33 |
34 | 35 |
36 | 37 |
38 |
39 |
40 |
41 | ) 42 | } 43 | 44 | export default CreateGame; -------------------------------------------------------------------------------- /src/components/UI/CreateGame/CreateGame.scss: -------------------------------------------------------------------------------- 1 | .CreateGame { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100vh; 7 | display: grid; 8 | align-items: center; 9 | 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | top: 1vw; 15 | margin: auto; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | vertical-align: middle; 21 | 22 | .u-ribbon { 23 | position: absolute; 24 | width: 60%; 25 | height: 6vw; 26 | left: 20%; 27 | top: -2.5vw; 28 | background-image: url("../../../assets/img/ribbon.png"); 29 | background-repeat: no-repeat; 30 | background-size: 100% 100%; 31 | font-size: 3vw; 32 | text-align: center; 33 | font-family: Haettenschweiler, fantasy, Courier, monospace; 34 | color: #fbfae2; 35 | -webkit-text-stroke: 0.05em #792a4d; 36 | } 37 | 38 | .u-content { 39 | position: absolute; 40 | bottom: 0; 41 | width: 100%; 42 | height: calc(70vw * 0.6 - 3vw); 43 | 44 | .u-logo { 45 | position: absolute; 46 | margin: 1vw; 47 | width: 40%; 48 | height: 20vw; 49 | left: 30%; 50 | top: 0.5vw; 51 | background-image: url("../../../assets/img/logo.png"); 52 | background-repeat: no-repeat; 53 | background-size: 100% 100%; 54 | } 55 | 56 | .u-input-wrap { 57 | margin-top: 20vw; 58 | padding: 1vw; 59 | height: 7vw; 60 | display: flex; 61 | justify-content: center; 62 | align-items: center; 63 | 64 | .u-input { 65 | text-align: center; 66 | background: url(../../../assets/img/inputbox.png); 67 | background-repeat: no-repeat; 68 | background-size: 100% 100%; 69 | width: 40%; 70 | height: 5vw; 71 | border-width: 0; 72 | border-radius: 2.5vw; 73 | font-size: 2vw; 74 | color: white; 75 | padding-left: 0.5em; 76 | font-family: Haettenschweiler, fantasy, Courier, monospace; 77 | } 78 | 79 | .u-input { 80 | outline: none; 81 | border: 0; 82 | } 83 | } 84 | 85 | .u-buttongroup { 86 | display: inline-grid; 87 | .u-button { 88 | text-align: center; 89 | align-items: center; 90 | background-image: url("../../../assets/img/victory_button.png"); 91 | background-repeat: no-repeat; 92 | background-size: 100% 100%; 93 | width: 14vw; 94 | height: 5vw; 95 | border-radius: 100px; 96 | color: #f9f8cb; 97 | font-family: Haettenschweiler, fantasy, Courier, monospace; 98 | font-size: 2.5vw; 99 | background-color: transparent; 100 | border-color: transparent; 101 | text-shadow: -1px 1px 1px #0d6c6e, 1px 1px 1px #0d6c6e, 102 | 1px -1px 1px #0d6c6e, -1px -1px 1px #0d6c6e; 103 | } 104 | 105 | .u-button:active { 106 | font-size: 2.4vw; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/components/UI/GameSelect/GameSelect.js: -------------------------------------------------------------------------------- 1 | import { useEffect } from "react"; 2 | import { useNavigate } from "react-router-dom"; 3 | import { Image } from "react-bootstrap"; 4 | import "bootstrap/dist/css/bootstrap.min.css"; 5 | import "./GameSelect.scss"; 6 | import mode1Img from "../../../assets/img/select_game_random.png"; 7 | import mode2Img from "../../../assets/img/select_game_friend.png"; 8 | import mode3Img from "../../../assets/img/select_game_computer.png"; 9 | import song from "../../../assets/audio/gameselect.mp3"; 10 | import useSound from "use-sound"; 11 | 12 | export const GameSelect = () => { 13 | const [playSong] = useSound(song); 14 | const navigate = useNavigate(); 15 | 16 | const matchPlayAction = () => { 17 | navigate("/matchPlay"); 18 | playSong(); 19 | }; 20 | 21 | const friendPlayAction = () => { 22 | navigate("/friendPlay"); 23 | playSong(); 24 | }; 25 | 26 | const machinePlayAction = () => { 27 | navigate("/machinePlay"); 28 | playSong(); 29 | }; 30 | 31 | return ( 32 |
33 |
34 |
Select game
35 |
36 |
37 | 38 |
Match with Random User
39 |
40 |
41 | 42 |
Match with Friend
43 |
44 |
45 | 46 |
Match with Computer
47 |
48 |
49 |
50 |
51 | ); 52 | }; 53 | 54 | export default GameSelect; 55 | -------------------------------------------------------------------------------- /src/components/UI/GameSelect/GameSelect.scss: -------------------------------------------------------------------------------- 1 | .GameSelect { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100%; 7 | display: grid; 8 | align-items: center; 9 | 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | top: 1vw; 15 | margin: auto; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | vertical-align: middle; 21 | 22 | .u-content { 23 | position: relative; 24 | width: 50vw; 25 | height: calc(50vw * 0.6); 26 | } 27 | .u-ribbon { 28 | position: absolute; 29 | width: 60%; 30 | height: 6vw; 31 | left: 20%; 32 | top: -2.5vw; 33 | background-image: url("../../../assets/img/ribbon.png"); 34 | background-repeat: no-repeat; 35 | background-size: 100% 100%; 36 | font-size: 3vw; 37 | text-align: center; 38 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 39 | color: #fbfae2; 40 | -webkit-text-stroke: 0.05em #792a4d; 41 | } 42 | .u-content { 43 | position: absolute; 44 | bottom: 0; 45 | width: 100%; 46 | height: calc(70vw * 0.6 - 3vw); 47 | display: flex; 48 | justify-content: space-evenly; 49 | align-items: center; 50 | 51 | .u-item { 52 | position: relative; 53 | width: 20vw; 54 | 55 | .u-item-image { 56 | width: 100%; 57 | } 58 | 59 | .u-item-text { 60 | position: absolute; 61 | width: 100%; 62 | height: 33%; 63 | bottom: 0; 64 | display: grid; 65 | text-align: center; 66 | align-items: center; 67 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 68 | color: #fbfae2; 69 | -webkit-text-stroke: 0.025em #390b13; 70 | font-size: 1.5vw; 71 | } 72 | 73 | .u-item-image:active { 74 | width: 19.9vw; 75 | } 76 | 77 | &:hover { 78 | cursor: pointer; 79 | } 80 | } 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/components/UI/GameState/GameStateFooter.js: -------------------------------------------------------------------------------- 1 | import "./GameStateFooter.scss"; 2 | 3 | export const GameStateFooter = ({quitAction, showInventoryAction, sendDrawRequest}) => { 4 | 5 | return ( 6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | ); 14 | }; 15 | 16 | export default GameStateFooter; 17 | -------------------------------------------------------------------------------- /src/components/UI/GameState/GameStateFooter.scss: -------------------------------------------------------------------------------- 1 | .GameStateFooter { 2 | position: absolute; 3 | width: 100%; 4 | height: 0; 5 | bottom: 0; 6 | // background-image: url("../../../assets/img/scene_volcano.png"); 7 | // background-repeat: no-repeat; 8 | // background-size: 100% 100%; 9 | 10 | * { 11 | color: #ffffff; 12 | -webkit-text-stroke: 0.05em #100205; 13 | } 14 | 15 | .u-back { 16 | transform: rotate(90deg); 17 | position: absolute; 18 | left: 2vw; 19 | bottom: 1vw; 20 | width: 5vw; 21 | height: 5vw; 22 | background-image: url("../../../assets/img/scene_back.png"); 23 | background-repeat: no-repeat; 24 | background-size: 100% 100%; 25 | 26 | &:hover { 27 | cursor: pointer; 28 | } 29 | 30 | &:active { 31 | width: 4.9vw; 32 | height: 4.9vw; 33 | } 34 | } 35 | 36 | .u-footer-right { 37 | position: absolute; 38 | right: 2vw; 39 | bottom: 1vw; 40 | display: flex; 41 | justify-content: space-between; 42 | // width: 11vw; 43 | 44 | .u-undo { 45 | width: 5vw; 46 | height: 5vw; 47 | background-image: url("../../../assets/img/scene_undo.png"); 48 | background-repeat: no-repeat; 49 | background-size: 100% 100%; 50 | cursor: pointer; 51 | 52 | &:active { 53 | width: 4.9vw; 54 | height: 4.9vw; 55 | } 56 | } 57 | 58 | .u-draw { 59 | width: 5vw; 60 | height: 5vw; 61 | background-image: url("../../../assets/img/surrender-icon.png"); 62 | background-repeat: no-repeat; 63 | background-size: 100% 100%; 64 | cursor: pointer; 65 | margin: 0 1vw; 66 | 67 | &:active { 68 | width: 4.9vw; 69 | height: 4.9vw; 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/components/UI/GameState/GameStateHeader.js: -------------------------------------------------------------------------------- 1 | import "./GameStateHeader.scss"; 2 | 3 | export const GameStateHeader = ({ opponentName, myTurn, remainingTime }) => { 4 | const formatTime = (time) => { 5 | if (!time) { 6 | return "-- : --"; 7 | } 8 | 9 | const minutes = 10 | Math.floor(time / 60) < 10 11 | ? "0" + Math.floor(time / 60) 12 | : Math.floor(time / 60); 13 | const seconds = time % 60 < 10 ? "0" + (time % 60) : time % 60; 14 | 15 | return minutes + " : " + seconds; 16 | }; 17 | 18 | return ( 19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
You
27 |
28 |
29 |
30 | 31 |
32 |
33 | {myTurn ? formatTime(remainingTime) : "-- : --"} 34 |
35 |
36 |
37 | {!myTurn ? formatTime(remainingTime) : "-- : --"} 38 |
39 |
40 | 41 |
42 |
43 |
44 |
45 |
46 |
47 |
{opponentName}
48 |
49 |
50 |
51 |
52 | ); 53 | }; 54 | 55 | export default GameStateHeader; 56 | -------------------------------------------------------------------------------- /src/components/UI/GameState/GameStateHeader.scss: -------------------------------------------------------------------------------- 1 | .GameStateHeader { 2 | position: absolute; 3 | width: 100%; 4 | height: 0; 5 | top: 0; 6 | 7 | * { 8 | color: #ffffff; 9 | -webkit-text-stroke: 0.05em #100205; 10 | } 11 | 12 | .u-you-container { 13 | position: absolute; 14 | top: 1vw; 15 | left: 2vw; 16 | width: 16vw; 17 | 18 | .u-black { 19 | position: absolute; 20 | top: 1vw; 21 | left: 1vw; 22 | width: 100%; 23 | height: 3vw; 24 | background-color: rgba($color: #000000, $alpha: 0.4); 25 | border: 1px solid #9789bd; 26 | border-radius: 1.5vw; 27 | } 28 | 29 | .u-info { 30 | position: absolute; 31 | top: 0; 32 | left: 0; 33 | 34 | .u-info-img-back { 35 | width: 8vw; 36 | height: 8vw; 37 | background-image: url("../../../assets/img/scene_user_bg.png"); 38 | background-repeat: no-repeat; 39 | background-size: 100% 100%; 40 | display: grid; 41 | align-items: center; 42 | text-align: center; 43 | 44 | .u-info-img { 45 | width: 6.4vw; 46 | height: 6.4vw; 47 | background-image: url("../../../assets/img/scene_user.png"); 48 | background-repeat: no-repeat; 49 | background-size: 100% 100%; 50 | border-radius: 3.2vw; 51 | margin: auto; 52 | } 53 | } 54 | 55 | .u-info-name { 56 | padding: 0.1vw; 57 | display: grid; 58 | text-align: center; 59 | align-items: center; 60 | font-family: "ErasBoldItc"; 61 | font-size: 1.5vw; 62 | font-weight: bold; 63 | } 64 | } 65 | 66 | .u-left-banner { 67 | position: absolute; 68 | top: 1vw; 69 | right: -2vw; 70 | width: 3vw; 71 | height: 3vw; 72 | background-image: url("../../../assets/img/left_banner.png"); 73 | background-repeat: no-repeat; 74 | background-size: 100% 100%; 75 | 76 | &.hide { 77 | display: none; 78 | } 79 | 80 | &.show { 81 | display: block; 82 | } 83 | } 84 | } 85 | 86 | .u-time-container { 87 | position: absolute; 88 | top: 1vw; 89 | transform: translate3d(-50%, 0, 0); 90 | left: 50%; 91 | display: flex; 92 | justify-content: space-between; 93 | align-items: center; 94 | 95 | .u-time { 96 | background-color: rgba($color: #000000, $alpha: 0.4); 97 | border: 1px solid #9789bd; 98 | width: 14vw; 99 | height: 2.8vw; 100 | border-radius: 1.4vw; 101 | text-align: center; 102 | align-items: center; 103 | font-family: "ErasBoldItc"; 104 | font-size: 2vw; 105 | } 106 | 107 | .u-clock { 108 | width: 5vw; 109 | height: 5vw; 110 | margin: 0 1vw; 111 | background-image: url("../../../assets/img/scene_clock.png"); 112 | background-repeat: no-repeat; 113 | background-size: 100% 100%; 114 | } 115 | } 116 | 117 | .u-opponent-container { 118 | position: absolute; 119 | width: 16vw; 120 | top: 1vw; 121 | right: 2vw; 122 | 123 | .u-black { 124 | position: absolute; 125 | top: 1vw; 126 | right: 1vw; 127 | width: 100%; 128 | height: 3vw; 129 | background-color: rgba($color: #000000, $alpha: 0.4); 130 | border: 1px solid #9789bd; 131 | border-radius: 1.5vw; 132 | } 133 | 134 | .u-info { 135 | position: absolute; 136 | top: 0; 137 | right: 0; 138 | 139 | .u-info-img-back { 140 | width: 8vw; 141 | height: 8vw; 142 | background-image: url("../../../assets/img/scene_user_bg.png"); 143 | background-repeat: no-repeat; 144 | background-size: 100% 100%; 145 | display: grid; 146 | align-items: center; 147 | text-align: center; 148 | 149 | .u-info-img { 150 | width: 6.4vw; 151 | height: 6.4vw; 152 | background-image: url("../../../assets/img/scene_user.png"); 153 | background-repeat: no-repeat; 154 | background-size: 100% 100%; 155 | border-radius: 3.2vw; 156 | margin: auto; 157 | } 158 | } 159 | 160 | .u-info-name { 161 | padding: 0.1vw; 162 | display: grid; 163 | text-align: center; 164 | align-items: center; 165 | font-family: "ErasBoldItc"; 166 | font-size: 1.5vw; 167 | font-weight: bold; 168 | } 169 | } 170 | 171 | .u-right-banner { 172 | position: absolute; 173 | top: 1vw; 174 | left: -2vw; 175 | width: 3vw; 176 | height: 3vw; 177 | background-image: url("../../../assets/img/right_banner.png"); 178 | background-repeat: no-repeat; 179 | background-size: 100% 100%; 180 | 181 | &.hide { 182 | display: none; 183 | } 184 | 185 | &.show { 186 | display: block; 187 | } 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/components/UI/Inventory/Inventory.js: -------------------------------------------------------------------------------- 1 | import './Inventory.scss'; 2 | import iceWall from '../../../assets/img/items/iceWall.png'; 3 | import petrify from '../../../assets/img/items/petrify.png'; 4 | import jumpyShoe from '../../../assets/img/items/jumpyShoe.png'; 5 | 6 | import { heroItems } from '../../../utils/constant'; 7 | 8 | import OverlayTrigger from "react-bootstrap/OverlayTrigger"; 9 | import Tooltip from "react-bootstrap/Tooltip"; 10 | 11 | export const Inventory = ({ show, items, myTurn, selectItem, currentItem }) => { 12 | const isEnable = (type) => { 13 | if( !items ) 14 | return false; 15 | 16 | const idx = items.findIndex((item) => item.type === type); 17 | if( idx !== -1 ) 18 | return true; 19 | 20 | return false; 21 | } 22 | 23 | const itemSelectAction = (item) => { 24 | if( !myTurn ) 25 | return; 26 | 27 | selectItem(item); 28 | } 29 | 30 | const renderIceWallTooltip = props => ( 31 | ✅ Ice Wall - block movement in 3 space blocks 32 | ); 33 | 34 | const renderPetrifyTooltip = props => ( 35 | ✅ Petrify - immobilize opponent's hero piece (except King or Queen) 36 | ); 37 | 38 | const renderJumpyShoeTooltip = props => ( 39 | ✅ Jumpy Shoe - Jump over obstacle 40 | ); 41 | 42 | const enteringAction = (e) => { 43 | e.children[0].style.borderBottomColor = '#0000008c'; 44 | e.children[1].style.backgroundColor = '#0000008c'; 45 | } 46 | 47 | return ( 48 |
49 |
50 | 51 |
itemSelectAction( heroItems['iceWall'] )} 54 | > 55 | pic 56 |
57 |
58 | 59 | 60 |
itemSelectAction( heroItems['petrify'] )} 63 | > 64 | pic 65 |
66 |
67 | 68 | 69 |
itemSelectAction( heroItems['jumpyShoe'] )} 72 | > 73 | pic 74 |
75 |
76 |
77 |
78 | ) 79 | } 80 | 81 | export default Inventory; -------------------------------------------------------------------------------- /src/components/UI/Inventory/Inventory.scss: -------------------------------------------------------------------------------- 1 | @keyframes invenAnim { 2 | 0% {transform: scale(1);} 3 | 50% {transform: scale(1.3);} 4 | 100% {transform: scale(1);} 5 | } 6 | 7 | .inventory { 8 | position: absolute; 9 | transform: translate3d(0, -50%, 0); 10 | top: 50%; 11 | 12 | width: 8vw; 13 | height: 50%; 14 | 15 | background: #016da3de; 16 | border: 0.3vw solid #413348e0; 17 | border-radius: 1vw; 18 | 19 | transition: all 1s; 20 | 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | 25 | &.show { 26 | left: -1vw; 27 | } 28 | 29 | &.hide { 30 | left: -8vw; 31 | } 32 | 33 | &__wrapper { 34 | display: flex; 35 | align-items: center; 36 | justify-content: center; 37 | flex-direction: column; 38 | transition: all 0.25s; 39 | 40 | .item { 41 | position: relative; 42 | margin: 1.5vw 0; 43 | width: 4.5vw; 44 | 45 | img { 46 | width: 100%; 47 | } 48 | 49 | &.enable { 50 | opacity: 1; 51 | } 52 | 53 | &.disable { 54 | opacity: 0.2; 55 | } 56 | 57 | &.active { 58 | animation: invenAnim .5s linear infinite; 59 | } 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /src/components/UI/InviteFriend/InviteFriend.js: -------------------------------------------------------------------------------- 1 | import React, { useRef } from "react"; 2 | import { Modal } from "react-bootstrap"; 3 | import "bootstrap/dist/css/bootstrap.min.css"; 4 | import "./InviteFriend.scss"; 5 | 6 | export const InviteFriend = ({ show, hideAction, roomId }) => { 7 | const inputRef = useRef(null); 8 | 9 | const copyCodeToClipboard = () => { 10 | const el = inputRef.current; 11 | el.select(); 12 | document.execCommand('copy'); 13 | } 14 | 15 | return ( 16 | 24 |
25 |
Invite Your friend
26 |
27 |
28 | 36 | 37 |
38 |
39 | Share the secret key above, so your friend can join this game! 40 |
41 | 42 |
43 |
44 |
45 | ) 46 | } 47 | 48 | export default InviteFriend; -------------------------------------------------------------------------------- /src/components/UI/InviteFriend/InviteFriend.scss: -------------------------------------------------------------------------------- 1 | .Play2Earn { 2 | display: grid !important; 3 | align-items: center; 4 | 5 | .u-container { 6 | position: relative; 7 | width: 70vw; 8 | height: calc(70vw * 0.6); 9 | top: 1vw; 10 | margin: auto; 11 | background-image: url("../../../assets/img/level_back.png"); 12 | background-repeat: no-repeat; 13 | background-size: 100% 100%; 14 | text-align: center; 15 | vertical-align: middle; 16 | 17 | transform: translate3d(-50%, -50%, 0); 18 | left: 50%; 19 | top: 21vw; 20 | 21 | .u-ribbon { 22 | position: absolute; 23 | width: 60%; 24 | height: 6vw; 25 | left: 20%; 26 | top: -2.5vw; 27 | background-image: url("../../../assets/img/ribbon.png"); 28 | background-repeat: no-repeat; 29 | background-size: 100% 100%; 30 | font-size: 3vw; 31 | text-align: center; 32 | font-family: Haettenschweiler, fantasy, Courier, monospace; 33 | color: #fbfae2; 34 | -webkit-text-stroke: 0.05em #792a4d; 35 | } 36 | 37 | .u-content { 38 | position: absolute; 39 | bottom: 0; 40 | width: 100%; 41 | height: calc(70vw * 0.6 - 3vw); 42 | 43 | .u-input-wrap { 44 | margin-top: 5vw; 45 | padding: 0vw; 46 | height: 7vw; 47 | display: flex; 48 | justify-content: center; 49 | align-items: center; 50 | 51 | .u-input { 52 | text-align: center; 53 | background: url(../../../assets/img/inputbox.png); 54 | background-repeat: no-repeat; 55 | background-size: 100% 100%; 56 | width: 40%; 57 | height: 5vw; 58 | border-width: 0; 59 | border-radius: 2.5vw; 60 | font-size: 2vw; 61 | color: white; 62 | padding-left: 0.5em; 63 | font-family: Haettenschweiler, fantasy, Courier, monospace; 64 | } 65 | .u-copy-button { 66 | background-image: url("../../../assets/img/copybutton.png"); 67 | background-repeat: no-repeat; 68 | background-size: 100% 100%; 69 | width: 6vw; 70 | height: 6vw; 71 | color: #f9f8cb; 72 | font-family: Haettenschweiler, fantasy, Courier, monospace; 73 | background-color: transparent; 74 | border-color: transparent; 75 | text-shadow: -1px 1px 1px #0d6c6e, 1px 1px 1px #0d6c6e, 76 | 1px -1px 1px #0d6c6e, -1px -1px 1px #0d6c6e; 77 | } 78 | 79 | .u-input { 80 | outline: none; 81 | border: 0; 82 | } 83 | } 84 | .u-description { 85 | background-color: rgba($color: #000000, $alpha: 0.2); 86 | border-radius: 1vw; 87 | width: 70%; 88 | height: 7vw; 89 | margin: 1vw auto; 90 | display: grid; 91 | align-items: center; 92 | padding: 2vw; 93 | padding-left: 6vw; 94 | font-size: 1.5vw; 95 | color: #fdf9e8; 96 | font-family: Arial; 97 | } 98 | 99 | .u-button { 100 | margin-top: 0vw; 101 | text-align: center; 102 | align-items: center; 103 | background-image: url("../../../assets/img/victory_button.png"); 104 | background-repeat: no-repeat; 105 | background-size: 100% 100%; 106 | width: 14vw; 107 | height: 5vw; 108 | border-radius: 100px; 109 | color: #f9f8cb; 110 | font-family: Haettenschweiler, fantasy, Courier, monospace; 111 | font-size: 2.5vw; 112 | background-color: transparent; 113 | border-color: transparent; 114 | text-shadow: -1px 1px 1px #0d6c6e, 1px 1px 1px #0d6c6e, 115 | 1px -1px 1px #0d6c6e, -1px -1px 1px #0d6c6e; 116 | } 117 | .u-button:active { 118 | font-size: 2.45vw; 119 | } 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/components/UI/JoinGame/JoinGame.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import { gameModes, userTypes } from "../../../utils/constant"; 3 | import { useEffect, useState } from "react"; 4 | import io from 'socket.io-client'; 5 | import { socketServerPort } from "../../../config"; 6 | import { socketEvents } from "../../../utils/packet"; 7 | import store from "../../../store/store"; 8 | 9 | import "bootstrap/dist/css/bootstrap.min.css"; 10 | import "./JoinGame.scss"; 11 | 12 | export const JoinGame = () => { 13 | const [name, setName] = useState(''); 14 | const [secretKey, setSecretKey] = useState(''); 15 | const navigate = useNavigate(); 16 | const [ socket, setSocket ] = useState(); 17 | 18 | const updateSocket = store( state => state.updateSocket ); 19 | 20 | const joinAction = () => { 21 | if( name === '' || secretKey === '' ) 22 | return; 23 | 24 | const data = {}; 25 | data.username = name; 26 | data.friendMatch = true; 27 | data.roomId = secretKey; 28 | 29 | socket.emit( socketEvents['CS_JoinRoom'], data ); 30 | } 31 | 32 | const handleJoinRoom = ( params ) => { 33 | const { roomName, roomKey } = params; 34 | 35 | const stateData = { 36 | mode: gameModes['P2P'], 37 | friendMatch: true, 38 | username: name, 39 | userType: userTypes['joiner'], 40 | roomId: secretKey, 41 | roomName: roomName, 42 | roomKey: roomKey, 43 | } 44 | 45 | if (roomName === 'Classic Room') { 46 | navigate('/gameScene', { state: { ...stateData } }); 47 | } else { 48 | navigate('/connect', { state: { ...stateData } }); 49 | } 50 | } 51 | 52 | useEffect(() => { 53 | const skt = io.connect(`http://${window.location.hostname}:${socketServerPort}`); 54 | setSocket( skt ); 55 | 56 | skt.on( socketEvents['SC_JoinRoom'], (params) => handleJoinRoom(params) ); 57 | 58 | updateSocket( skt ); 59 | }, []); 60 | 61 | return ( 62 |
63 |
64 |
Join game
65 | 66 |
67 |
68 | Name must have minimum 2 and maximum 20 characters 69 |
70 | 71 |
72 | setName(e.target.value)} 77 | onKeyDown={(e) => e.key === 'Enter' ? joinAction() : null} 78 | /> 79 |
80 | 81 |
82 | setSecretKey(e.target.value)} 87 | onKeyDown={(e) => e.key === 'Enter' ? joinAction() : null} 88 | /> 89 |
90 | 91 | 92 |
93 |
94 |
95 | ); 96 | } 97 | 98 | export default JoinGame; -------------------------------------------------------------------------------- /src/components/UI/JoinGame/JoinGame.scss: -------------------------------------------------------------------------------- 1 | .JoinGame { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100%; 7 | display: grid; 8 | align-items: center; 9 | 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | margin: auto; 15 | top: 1vw; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | 21 | .u-ribbon { 22 | position: absolute; 23 | width: 60%; 24 | height: 6vw; 25 | left: 20%; 26 | top: -2.5vw; 27 | background-image: url("../../../assets/img/ribbon.png"); 28 | background-repeat: no-repeat; 29 | background-size: 100% 100%; 30 | font-size: 3vw; 31 | text-align: center; 32 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 33 | color: #fbfae2; 34 | -webkit-text-stroke: 0.05em #792a4d; 35 | } 36 | 37 | .u-content { 38 | position: absolute; 39 | bottom: 0; 40 | width: 100%; 41 | height: calc(70vw * 0.6 - 3vw); 42 | 43 | .u-description { 44 | background-color: rgba($color: #000000, $alpha: 0.2); 45 | border-radius: 1vw; 46 | width: 70%; 47 | height: 7vw; 48 | margin: 1vw auto; 49 | display: grid; 50 | align-items: center; 51 | padding: 2vw; 52 | font-size: 1.5vw; 53 | color: #fdf9e8; 54 | font-family: Arial; 55 | } 56 | 57 | .u-input-wrap { 58 | padding: 1vw; 59 | height: 7vw; 60 | 61 | .u-input { 62 | text-align: center; 63 | background: url(../../../assets/img/inputbox.png); 64 | background-repeat: no-repeat; 65 | background-size: 100% 100%; 66 | width: 40%; 67 | height: 5vw; 68 | border-width: 0; 69 | border-radius: 2.5vw; 70 | font-size: 2.5vw; 71 | color: #fdf9e8; 72 | padding-left: 0.5em; 73 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 74 | outline: none; 75 | border: 0; 76 | } 77 | 78 | .u-input::placeholder { 79 | color: #84617b; 80 | } 81 | } 82 | 83 | .u-button { 84 | margin-top: 1vw; 85 | text-align: center; 86 | align-items: center; 87 | background-image: url("../../../assets/img/victory_button.png"); 88 | background-repeat: no-repeat; 89 | background-size: 100% 100%; 90 | width: 14vw; 91 | height: 5vw; 92 | border-radius: 100px; 93 | color: #f9f8cb; 94 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 95 | font-size: 2.5vw; 96 | background-color: transparent; 97 | border-color: transparent; 98 | -webkit-text-stroke: 0.05em #0c6c6d; 99 | } 100 | 101 | .u-button:active { 102 | font-size: 2.4vw; 103 | } 104 | } 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/components/UI/Level/Level.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Level.scss"; 4 | import { gameModes } from "../../../utils/constant"; 5 | 6 | export const Level = () => { 7 | const navigate = useNavigate(); 8 | 9 | const machinePlayAction = ( aiLevel ) => { 10 | navigate('/gameScene', { state: { mode: gameModes['P2E'], aiLevel: aiLevel } }); 11 | } 12 | 13 | return ( 14 |
15 |
16 |
Choose Level
17 |
18 |
19 |
20 |
21 |
22 | 23 |
24 |
25 | 26 |
27 |
28 |
29 |
30 | 31 |
32 |
33 | 34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | ); 42 | } 43 | 44 | export default Level; -------------------------------------------------------------------------------- /src/components/UI/Level/Level.scss: -------------------------------------------------------------------------------- 1 | .selectLevel { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | width: 100%; 7 | height: 100%; 8 | display: grid; 9 | align-items: center; 10 | 11 | .u-container { 12 | position: relative; 13 | width: 70vw; 14 | height: calc(70vw * 0.6); 15 | top: 1vw; 16 | margin: auto; 17 | background-image: url("../../../assets/img/level_back.png"); 18 | background-repeat: no-repeat; 19 | background-size: 100% 100%; 20 | text-align: center; 21 | vertical-align: middle; 22 | 23 | .u-content { 24 | position: relative; 25 | width: 50vw; 26 | height: calc(50vw * 0.6); 27 | } 28 | 29 | .u-ribbon { 30 | position: absolute; 31 | width: 60%; 32 | height: 6vw; 33 | left: 20%; 34 | top: -2.5vw; 35 | background-image: url("../../../assets/img/ribbon.png"); 36 | background-repeat: no-repeat; 37 | background-size: 100% 100%; 38 | font-size: 3vw; 39 | text-align: center; 40 | font-family: Haettenschweiler, fantasy, Courier, monospace; 41 | color: #fbfae2; 42 | -webkit-text-stroke: 0.05em #792a4d; 43 | } 44 | 45 | .u-content { 46 | position: absolute; 47 | bottom: 0; 48 | width: 100%; 49 | height: calc(70vw * 0.6 - 3vw); 50 | display: grid; 51 | 52 | .u-content-container { 53 | width: 80%; 54 | height: 66%; 55 | margin: auto; 56 | display: grid; 57 | background-color: #422736; 58 | border-radius: 10px; 59 | border: 1px solid #80545b; 60 | 61 | .u-table-wrap { 62 | width: 100%; 63 | height: 100%; 64 | display: grid; 65 | padding: 5vw calc(5vw * 0.6); 66 | 67 | .u-row { 68 | display: flex; 69 | justify-content: space-evenly; 70 | 71 | .u-item-container { 72 | display: grid; 73 | 74 | .u-item { 75 | display: grid; 76 | align-self: center; 77 | align-items: center; 78 | background-image: url("../../../assets/img/victory_button.png"); 79 | background-repeat: no-repeat; 80 | background-size: 100% 100%; 81 | width: 24vw; 82 | height: 90%; 83 | margin: auto; 84 | color: #f9f7c9; 85 | font-family: Haettenschweiler, fantasy, Courier, monospace; 86 | text-shadow: -2px 2px 2px #0d6c6e, 2px 2px 2px #0d6c6e, 87 | 2px -2px 2px #0d6c6e, -2px -2px 2px #0d6c6e; 88 | -webkit-text-stroke: 0.05em #0d6c6e; 89 | font-size: 2.5vw; 90 | background-color: transparent; 91 | border-color: transparent; 92 | } 93 | 94 | .u-item:active { 95 | font-size: 2.49vw; 96 | } 97 | } 98 | } 99 | } 100 | } 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/components/UI/Loading/Loading.js: -------------------------------------------------------------------------------- 1 | import "./Loading.scss"; 2 | 3 | import star_full from "../../../assets/img/star.png"; 4 | import star_none from "../../../assets/img/star_none.png"; 5 | import { useEffect, useRef, useState } from "react"; 6 | import Refund from "../Refund/Refund"; 7 | 8 | const starArray = [0, 1, 2, 3, 4, 5]; 9 | 10 | export const Loading = ({ title, onClickRefund, roomName }) => { 11 | const [currentTime, setCurrentTime] = useState(0); 12 | const [refund, setRefund] = useState(false); 13 | const timeInterval = useRef(0); 14 | 15 | useEffect(() => { 16 | timeInterval.current = setInterval(() => { 17 | setCurrentTime((prev) => prev + 1); 18 | if (currentTime > 10) { 19 | if(roomName != "Classic Room") setRefund(true); 20 | setCurrentTime(0); 21 | } 22 | }, 1000); 23 | 24 | return () => clearInterval(timeInterval.current); 25 | }); 26 | 27 | return ( 28 |
29 |
30 |
31 | {starArray.map((item, idx) => ( 32 | pic 40 | ))} 41 |
42 |
43 |

{title}

44 |
45 |
46 | setRefund(false)} 50 | onClickRefund={onClickRefund} 51 | > 52 |
53 | ); 54 | }; 55 | export default Loading; 56 | -------------------------------------------------------------------------------- /src/components/UI/Loading/Loading.scss: -------------------------------------------------------------------------------- 1 | .loading { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: fixed; 6 | top: 0; 7 | left: 0; 8 | width: 100%; 9 | height: 100%; 10 | display: grid; 11 | align-items: center; 12 | 13 | &__container { 14 | position: absolute; 15 | transform: translate3d(-50%, -50%, 0); 16 | left: 50%; 17 | top: 50%; 18 | } 19 | 20 | &__stars { 21 | display: flex; 22 | align-items: center; 23 | justify-content: center; 24 | 25 | background: rgb(0, 0, 0, 0.2); 26 | border-radius: 20px; 27 | padding: 20px; 28 | 29 | img { 30 | width: 120px; 31 | padding: 0 5px; 32 | } 33 | } 34 | 35 | &__title { 36 | text-align: center; 37 | 38 | font: normal normal bold 68px Haettenschweiler; 39 | letter-spacing: 3px; 40 | color: #f9f8cb; 41 | font-family: Haettenschweiler; 42 | font-weight: 500; 43 | 44 | padding: 10px 0; 45 | } 46 | } 47 | 48 | @media (max-width: 1440px) { 49 | .loading { 50 | &__stars { 51 | border-radius: 1.39vw; 52 | padding: 1.39vw; 53 | 54 | img { 55 | width: 8.33vw; 56 | padding: 0 0.35vw; 57 | } 58 | } 59 | 60 | &__title { 61 | letter-spacing: 0.2vw; 62 | font-size: 4vw; 63 | 64 | padding: 0.7vw 0; 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/components/UI/Logo/Logo.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from "react"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import logoPng from "../../../assets/img/logo.png"; 4 | import "./Logo.scss"; 5 | 6 | export default class Logo extends Component { 7 | render() { 8 | return ( 9 |
10 | pic 11 |
12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/components/UI/Logo/Logo.scss: -------------------------------------------------------------------------------- 1 | .logo { 2 | position: relative; 3 | width: 100%; 4 | height: 100%; 5 | background-color: #00000087; 6 | 7 | img { 8 | position: relative; 9 | width: 50%; 10 | transform: translate3d(-50%, -50%, 0); 11 | left: 50%; 12 | top: 50%; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/components/UI/Loser/Loser.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Loser.scss"; 4 | import Ranking from "../Ranking/Ranking"; 5 | import { useState } from "react"; 6 | 7 | export const Loser = ({ show, msg, onClickDrawHome }) => { 8 | const [ranking, setRanking] = useState(false); 9 | const [loading, setLoading] = useState(false); 10 | 11 | const onClickHome = () => { 12 | if(loading) return; 13 | onClickDrawHome(); 14 | setLoading(true); 15 | } 16 | 17 | return ( 18 | 25 |
26 |
{msg}
27 |
28 |
32 | {loading ? "Loading..." : "Return Home"} 33 |
34 |
setRanking(true)}>Ranking
35 |
36 |
37 | setRanking(false)}> 38 |
39 | ); 40 | }; 41 | 42 | export default Loser; 43 | -------------------------------------------------------------------------------- /src/components/UI/Loser/Loser.scss: -------------------------------------------------------------------------------- 1 | .Loser { 2 | font-family: "HaettenschweilerRegular"; 3 | color: #fbfae2; 4 | .u-container { 5 | position: relative; 6 | width: 40vw; 7 | height: 30vw; 8 | margin: auto; 9 | background-image: url("../../../assets/img/back_bg.png"); 10 | background-repeat: no-repeat; 11 | background-size: 100% 100%; 12 | .u-msg { 13 | height: 20vw; 14 | padding: 5vw; 15 | display: grid; 16 | text-align: center; 17 | align-items: center; 18 | font-size: 2vw; 19 | } 20 | .u-btn-group { 21 | position: absolute; 22 | bottom: 1vw; 23 | width: 100%; 24 | padding: 1vw; 25 | display: flex; 26 | justify-content: space-evenly; 27 | text-align: center; 28 | .u-btn-yes { 29 | display: grid; 30 | align-items: center; 31 | width: 13vw; 32 | height: 4vw; 33 | padding: 0.1vw 1vw; 34 | background-image: url("../../../assets/img/victory_button.png"); 35 | background-repeat: no-repeat; 36 | background-size: 100% 100%; 37 | font-size: 2.5vw; 38 | -webkit-text-stroke: 0.05em #0d6c6e; 39 | cursor: pointer; 40 | &:active { 41 | font-size: 2.45vw; 42 | } 43 | } 44 | .u-btn-no { 45 | display: grid; 46 | align-items: center; 47 | width: 13vw; 48 | height: 4vw; 49 | padding: 0.1vw 1vw; 50 | background-image: url("../../../assets/img/victory_button.png"); 51 | background-repeat: no-repeat; 52 | background-size: 100% 100%; 53 | font-size: 2.5vw; 54 | -webkit-text-stroke: 0.05em #0d6c6e; 55 | cursor: pointer; 56 | &:active { 57 | font-size: 2.45vw; 58 | } 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/components/UI/MatchPlayLogin/MatchPlayLogin.js: -------------------------------------------------------------------------------- 1 | import { useNavigate } from "react-router-dom"; 2 | 3 | import "bootstrap/dist/css/bootstrap.min.css"; 4 | import "./MatchPlayLogin.scss"; 5 | import { gameModes } from "../../../utils/constant"; 6 | import { useState } from "react"; 7 | 8 | export const MatchPlayLogin = () => { 9 | const [name, setName] = useState(''); 10 | const navigate = useNavigate(); 11 | 12 | const createAction = () => { 13 | if( name === '' ) 14 | return; 15 | 16 | navigate('/friendPlay/rooms', { state: { mode: gameModes['P2P'], username: name, friendMatch: false }}); 17 | 18 | } 19 | 20 | return ( 21 |
22 |
23 |
Match matching game
24 |
25 |
26 | 27 |
28 | setName(e.target.value)} 33 | onKeyDown={(e) => e.key === 'Enter' ? createAction() : null} 34 | /> 35 |
36 | 37 |
38 | 39 |
40 |
41 |
42 |
43 | ) 44 | } 45 | 46 | export default MatchPlayLogin; -------------------------------------------------------------------------------- /src/components/UI/MatchPlayLogin/MatchPlayLogin.scss: -------------------------------------------------------------------------------- 1 | .MatchPlayLogin { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100%; 7 | display: grid; 8 | align-items: center; 9 | 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | top: 1vw; 15 | margin: auto; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | vertical-align: middle; 21 | 22 | .u-ribbon { 23 | position: absolute; 24 | width: 60%; 25 | height: 6vw; 26 | left: 20%; 27 | top: -2.5vw; 28 | background-image: url("../../../assets/img/ribbon.png"); 29 | background-repeat: no-repeat; 30 | background-size: 100% 100%; 31 | font-size: 3vw; 32 | text-align: center; 33 | font-family: Haettenschweiler, fantasy, Courier, monospace; 34 | color: #fbfae2; 35 | -webkit-text-stroke: 0.05em #792a4d; 36 | } 37 | 38 | .u-content { 39 | position: absolute; 40 | bottom: 0; 41 | width: 100%; 42 | height: calc(70vw * 0.6 - 3vw); 43 | 44 | .u-logo { 45 | position: absolute; 46 | margin: 1vw; 47 | width: 40%; 48 | height: 20vw; 49 | left: 30%; 50 | top: 0.5vw; 51 | background-image: url("../../../assets/img/logo.png"); 52 | background-repeat: no-repeat; 53 | background-size: 100% 100%; 54 | } 55 | 56 | .u-input-wrap { 57 | margin-top: 20vw; 58 | padding: 1vw; 59 | height: 7vw; 60 | display: flex; 61 | justify-content: center; 62 | align-items: center; 63 | 64 | .u-input { 65 | text-align: center; 66 | background: url(../../../assets/img/inputbox.png); 67 | background-repeat: no-repeat; 68 | background-size: 100% 100%; 69 | width: 40%; 70 | height: 5vw; 71 | border-width: 0; 72 | border-radius: 2.5vw; 73 | font-size: 2vw; 74 | color: white; 75 | padding-left: 0.5em; 76 | font-family: Haettenschweiler, fantasy, Courier, monospace; 77 | } 78 | 79 | .u-input { 80 | outline: none; 81 | border: 0; 82 | } 83 | } 84 | 85 | .u-buttongroup { 86 | display: inline-grid; 87 | .u-button { 88 | text-align: center; 89 | align-items: center; 90 | background-image: url("../../../assets/img/victory_button.png"); 91 | background-repeat: no-repeat; 92 | background-size: 100% 100%; 93 | width: 14vw; 94 | height: 5vw; 95 | border-radius: 100px; 96 | color: #f9f8cb; 97 | font-family: Haettenschweiler, fantasy, Courier, monospace; 98 | font-size: 2.5vw; 99 | background-color: transparent; 100 | border-color: transparent; 101 | text-shadow: -1px 1px 1px #0d6c6e, 1px 1px 1px #0d6c6e, 102 | 1px -1px 1px #0d6c6e, -1px -1px 1px #0d6c6e; 103 | } 104 | 105 | .u-button:active { 106 | font-size: 2.45vw; 107 | } 108 | } 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/components/UI/Orientation/Orientation.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Orientation.scss"; 4 | 5 | export const Orientation = ({ show }) => { 6 | return ( 7 | 14 |
15 |
Please convert to landscape mode.
16 |
17 |
18 | ); 19 | }; 20 | 21 | export default Orientation; 22 | -------------------------------------------------------------------------------- /src/components/UI/Orientation/Orientation.scss: -------------------------------------------------------------------------------- 1 | .Orientation { 2 | font-family: "HaettenschweilerRegular"; 3 | color: #fbfae2; 4 | .u-container { 5 | position: relative; 6 | width: 100vw; 7 | height: 100vh; 8 | margin: auto; 9 | background-color: #744349; 10 | display: grid; 11 | align-items: center; 12 | text-align: center; 13 | .u-msg { 14 | padding: 5vw; 15 | display: grid; 16 | text-align: center; 17 | align-items: center; 18 | font-size: 3vw; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/components/UI/PawnModal/PawnModal.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./PawnModal.scss"; 4 | 5 | import ICON_KNIGHT from "../../../assets/img/pawn_knight_icon.png"; 6 | import ICON_BISHOP from "../../../assets/img/pawn_bishop_icon.png"; 7 | import ICON_ROOK from "../../../assets/img/pawn_rook_icon.png"; 8 | import ICON_QUEEN from "../../../assets/img/pawn_queen_icon.png"; 9 | import BG_KNIGHT from "../../../assets/img/pawn_knight_bg.png"; 10 | import BG_BISHOP from "../../../assets/img/pawn_bishop_bg.png"; 11 | import BG_ROOK from "../../../assets/img/pawn_rook_bg.png"; 12 | import BG_QUEEN from "../../../assets/img/pawn_queen_bg.png"; 13 | import SYMBOL_KNIGHT from "../../../assets/img/pawn_knight_wolf.png"; 14 | import SYMBOL_BISHOP from "../../../assets/img/pawn_bishop_cyborg.png"; 15 | import SYMBOL_ROOK from "../../../assets/img/pawn_rook_dragon.png"; 16 | import SYMBOL_QUEEN from "../../../assets/img/pawn_queen_medusa_fox.png"; 17 | import { useState } from "react"; 18 | 19 | const PAWN_ITEMS = [ 20 | { 21 | type: "Knight", 22 | icon: ICON_KNIGHT, 23 | desc: "Cerberus", 24 | bg: BG_KNIGHT, 25 | symbol: SYMBOL_KNIGHT, 26 | width: "12vw", 27 | height: "13vw", 28 | top: "-4vw", 29 | }, 30 | { 31 | type: "Bishop", 32 | icon: ICON_BISHOP, 33 | desc: "Keo502", 34 | bg: BG_BISHOP, 35 | symbol: SYMBOL_BISHOP, 36 | width: "9vw", 37 | height: "13vw", 38 | top: "-5.7vw", 39 | }, 40 | { 41 | type: "Rook", 42 | icon: ICON_ROOK, 43 | desc: "Bahamut", 44 | bg: BG_ROOK, 45 | symbol: SYMBOL_ROOK, 46 | width: "14vw", 47 | height: "12vw", 48 | top: "-4vw", 49 | }, 50 | { 51 | type: "Queen", 52 | icon: ICON_QUEEN, 53 | desc: "Medusa/Sakura", 54 | bg: BG_QUEEN, 55 | symbol: SYMBOL_QUEEN, 56 | width: "12vw", 57 | height: "13vw", 58 | top: "-5.7vw", 59 | } 60 | ]; 61 | 62 | export const PawnModal = ({ show, pawnTransform }) => { 63 | const [currentPiece, setCurrentPiece] = useState(null); 64 | 65 | return ( 66 | 73 |
74 |
75 | Your Pawn has reach the endpoint, please choose a Character to transform 76 |
77 |
78 | { 79 | PAWN_ITEMS.map((item, index) => ( 80 |
setCurrentPiece(item.type)}> 81 |
82 |
83 |
84 | pic 85 |
{item.type}
86 |
87 |
{item.desc}
88 |
89 |
90 | )) 91 | } 92 |
93 |
pawnTransform(currentPiece)}> 94 | Confirm 95 |
96 |
97 |
98 | ); 99 | } 100 | 101 | export default PawnModal; -------------------------------------------------------------------------------- /src/components/UI/PawnModal/PawnModal.scss: -------------------------------------------------------------------------------- 1 | @keyframes pawnPieceAnim { 2 | 0% { 3 | transform: scale(1); 4 | } 5 | 50% { 6 | transform: scale(1.1); 7 | } 8 | 100% { 9 | transform: scale(1); 10 | } 11 | } 12 | 13 | .pawn { 14 | background-image: url("../../../assets/img/1v1_back.png"); 15 | background-repeat: no-repeat; 16 | background-size: 100% 100%; 17 | width: 78vw; 18 | height: calc(70vw * 0.6); 19 | position: absolute; 20 | display: flex; 21 | justify-content: flex-start; 22 | flex-direction: column; 23 | align-items: center; 24 | padding: 3.5vw 3.5vw; 25 | transform: translate3d(-50%, -50%, 0); 26 | left: 50%; 27 | top: 0; 28 | 29 | &-desc { 30 | width: 100%; 31 | font-size: 1.5vw; 32 | font-family: Arial, Helvetica, sans-serif; 33 | color: #fdf9e8; 34 | text-align: center; 35 | background-color: #20122466; 36 | border-radius: 2vw; 37 | padding: 1vw 2vw; 38 | height: fit-content; 39 | line-height: 1.3; 40 | } 41 | 42 | &-cards { 43 | margin-top: 3vw; 44 | display: flex; 45 | flex-wrap: wrap; 46 | justify-content: center; 47 | width: 100%; 48 | align-items: flex-start; 49 | } 50 | 51 | &-card { 52 | width: 22%; 53 | margin: 2.5vw 1vw; 54 | position: relative; 55 | height: 18.5vw; 56 | background-size: 100% 100%; 57 | display: flex; 58 | justify-content: center; 59 | transition: all 0.25s; 60 | 61 | &:hover { 62 | cursor: pointer; 63 | } 64 | 65 | &.active { 66 | animation: pawnPieceAnim 0.5s linear infinite; 67 | } 68 | 69 | &-symbol-image { 70 | position: absolute; 71 | background-size: 100% 100%; 72 | } 73 | 74 | &-content { 75 | display: flex; 76 | flex-direction: column; 77 | align-items: center; 78 | margin-top: 9vw; 79 | &-header { 80 | display: flex; 81 | flex-direction: row; 82 | justify-content: space-between; 83 | align-items: center; 84 | 85 | &-icon { 86 | width: 1.7vw; 87 | height: 1.7vw; 88 | margin-right: 1vw; 89 | } 90 | 91 | &-title { 92 | font-size: 2vw; 93 | color: #f7cf29; 94 | font-family: "HaettenschweilerRegular"; 95 | letter-spacing: 0.02em; 96 | line-height: 1; 97 | } 98 | } 99 | 100 | &-desc { 101 | margin-top: 2.5vw; 102 | font-size: 2vw; 103 | color: white; 104 | font-family: "HaettenschweilerRegular"; 105 | letter-spacing: 0.02em; 106 | line-height: 1; 107 | } 108 | } 109 | } 110 | 111 | &-button { 112 | margin-top: 1.5vw; 113 | background-image: url("../../../assets/img/confirm_btn_bg.png"); 114 | background-repeat: no-repeat; 115 | background-size: 100% 100%; 116 | width: 14vw; 117 | height: 3.6vw; 118 | cursor: pointer; 119 | text-align: center; 120 | color: #f9f8cb; 121 | font-size: 2vw; 122 | font-family: "HaettenschweilerRegular"; 123 | letter-spacing: 0.01em; 124 | line-height: 1.3; 125 | text-shadow: 1px 1px 0 #0c6c6d, -1px 1px 0 #0c6c6d, 1px -1px 0 #0c6c6d, 126 | -1px -1px 0 #0c6c6d, 0px 1px 0 #0c6c6d, 0px -1px 0 #0c6c6d, 127 | -1px 0px 0 #0c6c6d, 1px 0px 0 #0c6c6d, 2px 2px 0 #0c6c6d, 128 | -2px 2px 0 #0c6c6d, 2px -2px 0 #0c6c6d, -2px -2px 0 #0c6c6d, 129 | 0px 2px 0 #0c6c6d, 0px -2px 0 #0c6c6d, -2px 0px 0 #0c6c6d, 130 | 2px 0px 0 #0c6c6d, 1px 2px 0 #0c6c6d, -1px 2px 0 #0c6c6d, 131 | 1px -2px 0 #0c6c6d, -1px -2px 0 #0c6c6d, 2px 1px 0 #0c6c6d, 132 | -2px 1px 0 #0c6c6d, 2px -1px 0 #0c6c6d, -2px -1px 0 #0c6c6d; 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /src/components/UI/Play2Earn/Play2Earn.js: -------------------------------------------------------------------------------- 1 | import "bootstrap/dist/css/bootstrap.min.css"; 2 | import "./Play2Earn.scss"; 3 | import { useNavigate } from "react-router-dom"; 4 | 5 | export const Play2Earn = () => { 6 | const navigate = useNavigate(); 7 | 8 | return ( 9 |
10 |
11 |
Play2Earn
12 |
13 |
14 | 15 |
16 | 17 | 18 |
19 |
20 |
21 |
22 | ); 23 | } 24 | 25 | export default Play2Earn; -------------------------------------------------------------------------------- /src/components/UI/Play2Earn/Play2Earn.scss: -------------------------------------------------------------------------------- 1 | .playToEarn { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100%; 7 | display: grid; 8 | align-items: center; 9 | 10 | .u-container { 11 | position: relative; 12 | width: 70vw; 13 | height: calc(70vw * 0.6); 14 | top: 1vw; 15 | margin: auto; 16 | background-image: url("../../../assets/img/level_back.png"); 17 | background-repeat: no-repeat; 18 | background-size: 100% 100%; 19 | text-align: center; 20 | vertical-align: middle; 21 | 22 | .u-ribbon { 23 | position: absolute; 24 | width: 60%; 25 | height: 6vw; 26 | left: 20%; 27 | top: -2.5vw; 28 | background-image: url("../../../assets/img/ribbon.png"); 29 | background-repeat: no-repeat; 30 | background-size: 100% 100%; 31 | font-size: 3vw; 32 | text-align: center; 33 | font-family: Haettenschweiler, fantasy, Courier, monospace; 34 | color: #fbfae2; 35 | -webkit-text-stroke: 0.05em #792a4d; 36 | } 37 | 38 | .u-content { 39 | position: absolute; 40 | bottom: 0; 41 | width: 100%; 42 | height: calc(70vw * 0.6 - 3vw); 43 | 44 | .u-logo { 45 | position: absolute; 46 | width: 40%; 47 | height: 20vw; 48 | left: 30%; 49 | top: 0.5vw; 50 | background-image: url("../../../assets/img/logo.png"); 51 | background-repeat: no-repeat; 52 | background-size: 100% 100%; 53 | } 54 | .u-buttongroup { 55 | display: inline-grid; 56 | margin-top: 19vw; 57 | .u-button { 58 | margin-top: 2vw; 59 | text-align: center; 60 | align-items: center; 61 | background-image: url("../../../assets/img/victory_button.png"); 62 | background-repeat: no-repeat; 63 | background-size: 100% 100%; 64 | width: 14vw; 65 | height: 5vw; 66 | border-radius: 100px; 67 | color: #f9f8cb; 68 | font-family: Haettenschweiler, fantasy, Courier, monospace; 69 | font-size: 2.5vw; 70 | background-color: transparent; 71 | border-color: transparent; 72 | text-shadow: -1px 1px 1px #0d6c6e, 1px 1px 1px #0d6c6e, 73 | 1px -1px 1px #0d6c6e, -1px -1px 1px #0d6c6e; 74 | } 75 | 76 | .u-button:active { 77 | font-size: 2.45vw; 78 | } 79 | } 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/components/UI/Popup/Popup.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Popup.scss"; 4 | 5 | export const Popup = ({ show, type, message, agreeAction, disAgreeAction }) => { 6 | return ( 7 | 14 |
15 |
16 | { message } 17 |
18 |
19 | { 20 | type === 'leaveNotification' ? 21 |
window.location = '/'}>Return
: null 22 | } 23 | 24 | { 25 | type === 'drawRequest' ? ( 26 | <> 27 |
Yes
28 |
No
29 | 30 | ) : null 31 | } 32 |
33 |
34 |
35 | ); 36 | } 37 | 38 | export default Popup; -------------------------------------------------------------------------------- /src/components/UI/Popup/Popup.scss: -------------------------------------------------------------------------------- 1 | .Popup { 2 | display: grid !important; 3 | align-items: center; 4 | 5 | .form { 6 | width: 47vw; 7 | height: calc(70vw * 0.5); 8 | background-image: url("../../../assets/img/back_bg.png"); 9 | background-repeat: no-repeat; 10 | background-size: 100% 100%; 11 | position: relative; 12 | transform: translate3d(-50%, -50%, 0); 13 | left: 50%; 14 | top: calc(70vw * 0.25); 15 | 16 | .content { 17 | text-align: left; 18 | font-family: "HaettenschweilerRegular"; 19 | letter-spacing: 0.01em; 20 | color: #f9f8cb; 21 | font-size: 2vw; 22 | vertical-align: middle; 23 | padding: 0 10%; 24 | position: relative; 25 | transform: translateY(-50%); 26 | top: 42%; 27 | text-align: center; 28 | } 29 | .footer { 30 | position: absolute; 31 | bottom: 3vw; 32 | display: flex; 33 | width: 100%; 34 | padding: 0 3vw; 35 | justify-content: space-between; 36 | 37 | &.center { 38 | justify-content: center; 39 | } 40 | 41 | .button-div { 42 | cursor: pointer; 43 | margin: 0 1.5vw; 44 | padding: 0 1.5vw; 45 | background-image: url("../../../assets/img/blue_button_bg.png"); 46 | background-repeat: no-repeat; 47 | background-size: 100% 100%; 48 | height: 5vw; 49 | text-align: center; 50 | color: #f9f8cb; 51 | font-size: 3.5vw; 52 | font-family: "HaettenschweilerRegular"; 53 | letter-spacing: 0.01em; 54 | line-height: 1.25; 55 | text-shadow: 1px 1px 0 #0c6c6d, -1px 1px 0 #0c6c6d, 1px -1px 0 #0c6c6d, 56 | -1px -1px 0 #0c6c6d, 0px 1px 0 #0c6c6d, 0px -1px 0 #0c6c6d, 57 | -1px 0px 0 #0c6c6d, 1px 0px 0 #0c6c6d, 2px 2px 0 #0c6c6d, 58 | -2px 2px 0 #0c6c6d, 2px -2px 0 #0c6c6d, -2px -2px 0 #0c6c6d, 59 | 0px 2px 0 #0c6c6d, 0px -2px 0 #0c6c6d, -2px 0px 0 #0c6c6d, 60 | 2px 0px 0 #0c6c6d, 1px 2px 0 #0c6c6d, -1px 2px 0 #0c6c6d, 61 | 1px -2px 0 #0c6c6d, -1px -2px 0 #0c6c6d, 2px 1px 0 #0c6c6d, 62 | -2px 1px 0 #0c6c6d, 2px -1px 0 #0c6c6d, -2px -1px 0 #0c6c6d; 63 | } 64 | .button-div:active { 65 | font-size: 3.45vw; 66 | } 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/components/UI/Ranking/Ranking.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable array-callback-return */ 2 | import { Component } from "react"; 3 | import RankingRow from "./RankingRow"; 4 | import "./Ranking.scss"; 5 | import axios from "axios"; 6 | import { socketServerPort } from "../../../config"; 7 | import { Modal } from "react-bootstrap"; 8 | 9 | export default class Ranking extends Component { 10 | // eslint-disable-next-line no-useless-constructor 11 | constructor(props) { 12 | super(props); 13 | } 14 | 15 | componentDidMount() { 16 | axios 17 | .post( 18 | `http://${window.location.hostname}:${socketServerPort}/api/rankAll` 19 | ) 20 | .then((res) => { 21 | let rankData = [...res.data.rankData]; 22 | rankData.sort((a, b) => { 23 | if ( (b.won - b.lost) > (a.won - a.lost) ) { 24 | return 1; 25 | } else if ( (b.won - b.lost) < (a.won - a.lost) ) { 26 | return -1; 27 | } else { 28 | return b.won - a.won; 29 | } 30 | }); 31 | 32 | this.setState({ 33 | rankData, 34 | }); 35 | 36 | console.log(this.state.rankData); 37 | }); 38 | } 39 | 40 | render() { 41 | return ( 42 | 49 |
50 |
Ranking Table
51 |
52 |
53 |
Rank
54 |
User name
55 |
matches won/loss
56 |
LLG earn
57 |
58 |
59 | {this.state && this.state.rankData 60 | ? this.state.rankData.map((item, index) => { 61 | const info = { 62 | name: item.username, 63 | won: `${item.won} / ${item.lost}`, 64 | earn: item.earn, 65 | key: index, 66 | index: index, 67 | }; 68 | 69 | return ; 70 | }) 71 | : null} 72 |
73 |
74 |
Back
75 |
76 |
77 | ); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/components/UI/Ranking/Ranking.scss: -------------------------------------------------------------------------------- 1 | .ranking { 2 | position: relative; 3 | text-align: center; 4 | width: 70vw; 5 | height: 90vh; 6 | font-family: "HaettenschweilerRegular"; 7 | background-image: url("../../../assets/img/back_bg.png"); 8 | background-repeat: no-repeat; 9 | background-size: 100% 100%; 10 | color: #fbfae2; 11 | * { 12 | margin: auto; 13 | } 14 | &-title { 15 | width: 40vw; 16 | height: 8vw; 17 | text-align: center; 18 | background-image: url("../../../assets/img/ribbon.png"); 19 | background-repeat: no-repeat; 20 | background-size: 100% 100%; 21 | margin: 2vw auto 1vw auto; 22 | font-size: 4.5vw; 23 | -webkit-text-stroke: 0.05em #792a4d; 24 | } 25 | &-table { 26 | margin: 1vw auto; 27 | width: 60vw; 28 | height: calc(90vh - 19vw); 29 | overflow: hidden; 30 | border-radius: 0.5vw; 31 | outline: 0.2vw solid #110919; 32 | background-color: rgba($color: #311437, $alpha: 0.39); 33 | &-head { 34 | background-color: rgba($color: #3c183c, $alpha: 0.62); 35 | outline: 1px solid #0e0616; 36 | border-radius: 0.5vw; 37 | color: #ecbc6a; 38 | -webkit-text-stroke: #0c6c6d; 39 | font-size: 2vw; 40 | display: flex; 41 | height: 3vw; 42 | &-rank { 43 | width: 15vw; 44 | } 45 | &-name { 46 | width: 17vw; 47 | } 48 | &-won { 49 | width: 17vw; 50 | } 51 | &-earn { 52 | width: 9vw; 53 | } 54 | } 55 | &-body { 56 | margin: 0.4vw 3vw; 57 | border: 0.1vw solid #a8728b; 58 | border-radius: 1vw; 59 | background-color: rgba($color: #321830, $alpha: 0.59); 60 | height: calc(100% - 4vw); 61 | font-size: 1.5vw; 62 | color: #f8edc3; 63 | font-family: Arial; 64 | overflow: auto; 65 | &::-webkit-scrollbar { 66 | width: 0.4vw; 67 | } 68 | &::-webkit-scrollbar-track { 69 | box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); 70 | border-radius: 0.2vw; 71 | } 72 | &::-webkit-scrollbar-thumb { 73 | background-color: rgba($color: black, $alpha: 0.4); 74 | outline: 1px solid rgba($color: black, $alpha: 0.4); 75 | border-radius: 0.2vw; 76 | } 77 | &-row { 78 | display: flex; 79 | border-bottom: 0.1vw solid #ad8494; 80 | * { 81 | display: grid; 82 | align-items: center; 83 | } 84 | &-rank { 85 | width: 12vw; 86 | &-img { 87 | height: 3vw; 88 | } 89 | } 90 | &-name { 91 | padding: 0.5vw 0; 92 | width: 17vw; 93 | } 94 | &-won { 95 | width: 17vw; 96 | } 97 | &-earn { 98 | width: 6vw; 99 | } 100 | } 101 | } 102 | } 103 | &-btn_choose { 104 | width: 25vw; 105 | height: 5vw; 106 | display: grid; 107 | align-items: center; 108 | text-align: center; 109 | background-image: url("../../../assets/img/victory_button.png"); 110 | background-repeat: no-repeat; 111 | background-size: 100% 100%; 112 | margin: 1vw auto 2vw auto; 113 | font-size: 3vw; 114 | -webkit-text-stroke: 0.05em #0c6c6d; 115 | cursor: pointer; 116 | &:active { 117 | font-size: 2.95vw; 118 | } 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/components/UI/Ranking/RankingRow.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable array-callback-return */ 2 | import { Component } from "react"; 3 | import { Image } from "react-bootstrap"; 4 | import rank1 from "../../../assets/img/ranking/1.png"; 5 | import rank2 from "../../../assets/img/ranking/2.png"; 6 | import rank3 from "../../../assets/img/ranking/3.png"; 7 | 8 | export default class Ranking extends Component { 9 | // eslint-disable-next-line no-useless-constructor 10 | constructor(props) { 11 | super(props); 12 | this.arrImg = [rank1, rank2, rank3]; 13 | } 14 | 15 | addressFormat( string ) { 16 | if( !string ) 17 | return ''; 18 | 19 | return string.slice(0, 7) + '...' + string.slice( string.length - 7, string.length ); 20 | } 21 | 22 | render() { 23 | return ( 24 |
25 |
26 | {this.props.index < 3 ? ( 27 | 31 | ) : ( 32 | this.props.index + 1 33 | )} 34 |
35 |
{ this.addressFormat(this.props.name) }
36 |
{this.props.won}
37 |
{this.props.earn}
38 |
39 | ); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/components/UI/Refund/Refund.js: -------------------------------------------------------------------------------- 1 | import { Modal } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Refund.scss"; 4 | 5 | export const Refund = ({ show, msg, hideAction, onClickRefund }) => { 6 | return ( 7 | 14 |
15 |
{msg}
16 |
17 |
Refund
18 |
Keep finding
19 |
20 |
21 |
22 | ); 23 | }; 24 | 25 | export default Refund; 26 | -------------------------------------------------------------------------------- /src/components/UI/Refund/Refund.scss: -------------------------------------------------------------------------------- 1 | .refund { 2 | font-family: "HaettenschweilerRegular"; 3 | color: #fbfae2; 4 | &-container { 5 | position: relative; 6 | width: 40vw; 7 | height: 30vw; 8 | margin: auto; 9 | background-image: url("../../../assets/img/back_bg.png"); 10 | background-repeat: no-repeat; 11 | background-size: 100% 100%; 12 | &-msg { 13 | height: 25vw; 14 | padding: 5vw; 15 | display: grid; 16 | text-align: center; 17 | align-items: center; 18 | font-size: 2vw; 19 | } 20 | &-btn_group { 21 | position: absolute; 22 | bottom: 1vw; 23 | width: 100%; 24 | padding: 1vw; 25 | display: flex; 26 | justify-content: space-evenly; 27 | text-align: center; 28 | &-yes { 29 | display: grid; 30 | align-items: center; 31 | width: 15vw; 32 | padding: 0.1vw 1vw; 33 | background-image: url("../../../assets/img/victory_button.png"); 34 | background-repeat: no-repeat; 35 | background-size: 100% 100%; 36 | font-size: 2.5vw; 37 | -webkit-text-stroke: 0.05em #0d6c6e; 38 | cursor: pointer; 39 | &:active { 40 | font-size: 2.45vw; 41 | } 42 | } 43 | &-no { 44 | display: grid; 45 | align-items: center; 46 | width: 15vw; 47 | padding: 0.1vw 1vw; 48 | background-image: url("../../../assets/img/victory_button.png"); 49 | background-repeat: no-repeat; 50 | background-size: 100% 100%; 51 | font-size: 2.5vw; 52 | -webkit-text-stroke: 0.05em #0d6c6e; 53 | cursor: pointer; 54 | &:active { 55 | font-size: 2.45vw; 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/components/UI/RoomsScreen/RoomsScreen.js: -------------------------------------------------------------------------------- 1 | import { useNavigate, useLocation } from "react-router-dom"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./RoomsScreen.scss"; 4 | 5 | import { gameModes } from "../../../utils/constant"; 6 | 7 | import ICON_CLASSIC from "../../../assets/img/1v1_classic_header.png"; 8 | import ICON_SILVER from "../../../assets/img/1v1_silver_header.png"; 9 | import ICON_GOLD from "../../../assets/img/1v1_gold_header.png"; 10 | import ICON_PLATINUM from "../../../assets/img/1v1_platinum_header.png"; 11 | import ICON_DIAMOND from "../../../assets/img/1v1_diamond_header.png"; 12 | import BG_CLASSIC from "../../../assets/img/1v1_classic_bg.png"; 13 | import BG_SILVER from "../../../assets/img/1v1_silver_bg.png"; 14 | import BG_GOLD from "../../../assets/img/1v1_gold_bg.png"; 15 | import BG_PLATINUM from "../../../assets/img/1v1_platinum_bg.png"; 16 | import BG_DIAMOND from "../../../assets/img/1v1_diamond_bg.png"; 17 | import { useEffect, useState } from "react"; 18 | import io from 'socket.io-client'; 19 | import { socketServerPort } from "../../../config"; 20 | import { socketEvents } from "../../../utils/packet"; 21 | import store from "../../../store/store"; 22 | 23 | const ROOMS = [ 24 | { 25 | name: "Classic Room", 26 | pool: "Pool: No rewards", 27 | desc: "Players can play for free 1v1 against another player", 28 | icon: ICON_CLASSIC, 29 | bg: BG_CLASSIC, 30 | }, 31 | { 32 | name: "Silver Room", 33 | pool: "Pool: 98 $LLG", 34 | desc: "Each player needs to put in 50 $LLG", 35 | icon: ICON_SILVER, 36 | bg: BG_SILVER, 37 | }, 38 | { 39 | name: "Gold Room", 40 | pool: "Pool: 198 $LLG", 41 | desc: "Each player needs to put in 100 $LLG", 42 | icon: ICON_GOLD, 43 | bg: BG_GOLD, 44 | }, 45 | { 46 | name: "Platinum Room", 47 | pool: "Pool: 392 $LLG", 48 | desc: "Each player needs to put in 200 $LLG", 49 | icon: ICON_PLATINUM, 50 | bg: BG_PLATINUM, 51 | }, 52 | { 53 | name: "Diamond Room", 54 | pool: "Pool: 980 $LLG", 55 | desc: "Each player needs to put in 500 $LLG", 56 | icon: ICON_DIAMOND, 57 | bg: BG_DIAMOND, 58 | } 59 | ]; 60 | 61 | const RoomsScreen = () => { 62 | const navigate = useNavigate(); 63 | const { state } = useLocation(); 64 | const [ socket, setSocket ] = useState(); 65 | 66 | const updateSocket = store( state => state.updateSocket ); 67 | 68 | const onClickRoom = (roomName) => { 69 | if( roomName !== 'Classic Room' ) 70 | return; 71 | 72 | const data = {}; 73 | data.roomName = roomName; 74 | data.username = state.username; 75 | data.friendMatch = state.friendMatch; 76 | 77 | if( !state.friendMatch ) { 78 | socket.emit( socketEvents['CS_MatchPlayLogin'], data ); 79 | 80 | // const stateData = { 81 | // mode: gameModes['P2P'], 82 | // friendMatch: state.friendMatch, 83 | // username: state.username, 84 | // roomName: roomName, 85 | // } 86 | 87 | // if (roomName === 'Classic Room') { 88 | // navigate('/gameScene', { state: { ...stateData } }); 89 | // } else { 90 | // navigate('/connect', { state: { ...stateData } }); 91 | // } 92 | } else { 93 | socket.emit( socketEvents['CS_CreateRoom'], data ); 94 | } 95 | } 96 | 97 | const handleRoomCreated = (params) => { 98 | const { roomId, roomName, roomKey } = params; 99 | 100 | const stateData = { 101 | mode: gameModes['P2P'], 102 | friendMatch: state.friendMatch, 103 | username: state.username, 104 | roomName: roomName, 105 | roomId: roomId, 106 | roomKey: roomKey, 107 | } 108 | 109 | if (roomName === 'Classic Room' && state.friendMatch === true) { 110 | navigate('/gameScene', { state: { ...stateData } }); 111 | } else { 112 | navigate('/connect', { state: { ...stateData } }); 113 | } 114 | } 115 | 116 | useEffect(() => { 117 | const skt = io.connect(`http://${window.location.hostname}:${socketServerPort}`); 118 | setSocket( skt ); 119 | 120 | skt.on( socketEvents['SC_RoomCreated'], (params) => handleRoomCreated(params) ); 121 | 122 | updateSocket( skt ); 123 | }, []); 124 | 125 | return ( 126 |
129 |
130 |
1 VS 1 MODE
131 |
132 |

There are 5 different rooms. Two players each put in the specified amount of LLG (based on the room type) into a pool. After each game, whoever wins the game takes all the LLG in the pool.

133 |
134 | { 135 | ROOMS.map((room, index) => ( 136 |
onClickRoom(room.name)}> 137 |
138 |
139 |
{room.name}
140 |
{room.pool}
141 |
{room.desc}
142 |
143 |
144 | )) 145 | } 146 |
147 |
148 |
149 |
150 | ); 151 | } 152 | 153 | export default RoomsScreen; 154 | -------------------------------------------------------------------------------- /src/components/UI/RoomsScreen/RoomsScreen.scss: -------------------------------------------------------------------------------- 1 | .rooms { 2 | background-image: url("../../../assets/img/modal_back.png"); 3 | background-size: 100% 100%; 4 | background-repeat: no-repeat; 5 | position: relative; 6 | height: 100%; 7 | display: flex; 8 | justify-content: center; 9 | align-items: center; 10 | 11 | &-container { 12 | background-image: url("../../../assets/img/1v1_back.png"); 13 | background-repeat: no-repeat; 14 | background-size: 100% 100%; 15 | width: 78vw; 16 | height: calc(70vw * 0.6); 17 | position: relative; 18 | display: flex; 19 | justify-content: center; 20 | padding: 3.5vw 3.5vw; 21 | &-header { 22 | background-image: url("../../../assets/img/1v1_header.png"); 23 | background-repeat: no-repeat; 24 | background-size: 100% 100%; 25 | border-width: 0; 26 | background-color: transparent; 27 | position: absolute; 28 | top: -2.3vw; 29 | width: 16vw; 30 | height: 5vw; 31 | text-align: center; 32 | vertical-align: middle; 33 | line-height: 1.7; 34 | font-size: 3vw; 35 | font-family: "HaettenschweilerRegular"; 36 | color: #f9f8cb; 37 | letter-spacing: 0.025em; 38 | text-shadow: 1px 1px 0 #0c6c6d, -1px 1px 0 #0c6c6d, 1px -1px 0 #0c6c6d, 39 | -1px -1px 0 #0c6c6d, 0px 1px 0 #0c6c6d, 0px -1px 0 #0c6c6d, 40 | -1px 0px 0 #0c6c6d, 1px 0px 0 #0c6c6d, 2px 2px 0 #0c6c6d, 41 | -2px 2px 0 #0c6c6d, 2px -2px 0 #0c6c6d, -2px -2px 0 #0c6c6d, 42 | 0px 2px 0 #0c6c6d, 0px -2px 0 #0c6c6d, -2px 0px 0 #0c6c6d, 43 | 2px 0px 0 #0c6c6d, 1px 2px 0 #0c6c6d, -1px 2px 0 #0c6c6d, 44 | 1px -2px 0 #0c6c6d, -1px -2px 0 #0c6c6d, 2px 1px 0 #0c6c6d, 45 | -2px 1px 0 #0c6c6d, 2px -1px 0 #0c6c6d, -2px -1px 0 #0c6c6d; 46 | } 47 | &-content { 48 | margin-top: 0.5vw; 49 | display: flex; 50 | justify-content: flex-start; 51 | flex-direction: column; 52 | align-items: center; 53 | &-desc { 54 | font-size: 1.5vw; 55 | font-family: Haettenschweiler, fantasy, Courier, monospace; 56 | color: #fdf9e8; 57 | text-align: center; 58 | background-color: #20122466; 59 | border-radius: 2vw; 60 | padding: 1vw 1.5vw; 61 | height: fit-content; 62 | line-height: 1.3; 63 | margin-bottom: 0 !important; 64 | } 65 | &-rooms { 66 | margin-top: 2.8vw; 67 | display: flex; 68 | flex-wrap: wrap; 69 | justify-content: center; 70 | width: 100%; 71 | align-items: flex-start; 72 | } 73 | &-room { 74 | width: 28%; 75 | margin: 1.5vw; 76 | position: relative; 77 | height: 11vw; 78 | background-size: 100% 100%; 79 | display: flex; 80 | justify-content: center; 81 | cursor: pointer; 82 | 83 | &.closed { 84 | &::after { 85 | content: ""; 86 | width: 6vw; 87 | height: 6vw; 88 | background-image: url('../../../assets/img/coming-soon.png'); 89 | background-repeat: no-repeat; 90 | background-size: cover; 91 | position: absolute; 92 | right: 0; 93 | top: 0; 94 | } 95 | } 96 | 97 | &-icon { 98 | position: absolute; 99 | background-size: 100% 100%; 100 | width: 9.8vw; 101 | height: 9vw; 102 | top: -4vw; 103 | } 104 | 105 | &-texts { 106 | margin-top: 3vw; 107 | display: flex; 108 | flex-direction: column; 109 | align-items: center; 110 | } 111 | &-name { 112 | font-size: 2vw; 113 | color: #f7cf29; 114 | font-family: "HaettenschweilerRegular"; 115 | letter-spacing: 0.02em; 116 | line-height: 1; 117 | } 118 | &-pool { 119 | font-size: 1.9vw; 120 | color: white; 121 | font-family: "HaettenschweilerRegular"; 122 | letter-spacing: 0.02em; 123 | line-height: 1; 124 | } 125 | &-desc { 126 | margin-top: 0.4vw; 127 | font-size: 1.1vw; 128 | font-weight: 400; 129 | color: white; 130 | font-family: Arial, Helvetica, sans-serif; 131 | line-height: 1.3; 132 | text-align: center; 133 | padding: 0 1.5vw; 134 | letter-spacing: 0.07em; 135 | } 136 | } 137 | } 138 | } 139 | } 140 | 141 | .modal-content { 142 | display: flex; 143 | justify-content: center; 144 | align-items: center; 145 | } 146 | -------------------------------------------------------------------------------- /src/components/UI/Victory/Victory.js: -------------------------------------------------------------------------------- 1 | import { Modal, Image } from "react-bootstrap"; 2 | import "bootstrap/dist/css/bootstrap.min.css"; 3 | import "./Victory.scss"; 4 | import backImg from "../../../assets/img/back_bg.png"; 5 | import markImg from "../../../assets/img/victory_mark.png"; 6 | import item1Img from "../../../assets/img/victory_item1.png"; 7 | import item2Img from "../../../assets/img/victory_item2.png"; 8 | import { useEffect, useState } from "react"; 9 | import Ranking from "../Ranking/Ranking"; 10 | 11 | export const Victory = ({ show, roomName, onClickLLGSymbol, tax }) => { 12 | const [loading, setLoading] = useState(false); 13 | const [llgToGetPaid, setLLGToGetPaid] = useState(0); 14 | const [llgDeposited, setLLGDeposited] = useState(0); 15 | const [ranking, setRanking] = useState(false); 16 | 17 | useEffect(() => { 18 | calcLLGs(); 19 | }); 20 | 21 | const onClick = () => { 22 | if (roomName == "Classic Room") window.location.href = "/"; 23 | else { 24 | onClickLLGSymbol(); 25 | setLoading(true); 26 | } 27 | }; 28 | 29 | const calcLLGs = () => { 30 | switch (roomName) { 31 | case "Silver Room": 32 | setLLGToGetPaid(100); 33 | setLLGDeposited((100 * (100 - tax)) / 100); 34 | break; 35 | case "Gold Room": 36 | setLLGToGetPaid(200); 37 | setLLGDeposited((200 * (100 - tax)) / 100); 38 | break; 39 | case "Platinum Room": 40 | setLLGToGetPaid(400); 41 | setLLGDeposited((400 * (100 - tax)) / 100); 42 | break; 43 | case "Diamond Room": 44 | setLLGToGetPaid(1000); 45 | setLLGDeposited((1000 * (100 - tax)) / 100); 46 | break; 47 | } 48 | }; 49 | 50 | return ( 51 | 58 | 59 |
60 | 61 |
62 | 63 |
64 |
65 | 66 |
{llgToGetPaid}
67 |
68 |
69 | 70 |
{llgDeposited}
71 |
72 |
73 |
74 | 77 | 84 |
85 |
86 |
87 | setRanking(false)}> 88 |
89 |
90 | ); 91 | }; 92 | 93 | export default Victory; 94 | -------------------------------------------------------------------------------- /src/components/UI/Victory/Victory.scss: -------------------------------------------------------------------------------- 1 | .Victory { 2 | display: grid; 3 | align-items: center; 4 | 5 | .u-container { 6 | width: 90vmin; 7 | height: 90vmin; 8 | margin: auto; 9 | position: relative; 10 | 11 | .u-background { 12 | width: 100%; 13 | height: 80%; 14 | bottom: 0; 15 | position: absolute; 16 | } 17 | 18 | .u-foreground { 19 | position: relative; 20 | width: 100%; 21 | height: 100%; 22 | text-align: center; 23 | 24 | .u-mark { 25 | width: 100%; 26 | height: 50%; 27 | } 28 | 29 | .u-list { 30 | padding: 0 5%; 31 | height: 35%; 32 | 33 | .u-list-item { 34 | padding: 0 10%; 35 | margin: 3%; 36 | height: 40%; 37 | display: flex; 38 | justify-content: space-between; 39 | background-image: url("../../../assets/img/victory_container.png"); 40 | background-repeat: no-repeat; 41 | background-size: 100% 100%; 42 | align-items: center; 43 | 44 | .u-item-image { 45 | height: 90%; 46 | } 47 | 48 | .u-item-text { 49 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 50 | color: #f7cf29; 51 | font-size: 6vmin; 52 | -webkit-text-stroke: 0.05em #390b13; 53 | padding-right: 15%; 54 | } 55 | } 56 | } 57 | 58 | .u-btn-group { 59 | position: absolute; 60 | width: 100%; 61 | display: flex; 62 | align-items: center; 63 | text-align: center; 64 | justify-content: space-evenly; 65 | bottom: 4vmin; 66 | 67 | .u-button { 68 | text-align: center; 69 | align-items: center; 70 | background-image: url("../../../assets/img/victory_button.png"); 71 | background-repeat: no-repeat; 72 | background-size: 100% 100%; 73 | width: 30vmin; 74 | border-radius: 100px; 75 | color: #f9f8cb; 76 | font-family: "HaettenschweilerRegular", fantasy, Courier, monospace; 77 | font-size: 4vmin; 78 | background-color: transparent; 79 | border-color: transparent; 80 | -webkit-text-stroke: 0.05em #0c6c6d; 81 | } 82 | 83 | .u-button:active { 84 | font-size: 3.95vmin; 85 | } 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/config/index.js: -------------------------------------------------------------------------------- 1 | export const apiServerPort = 8050; 2 | 3 | export const socketServerPort = 8050; -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", 4 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", 5 | sans-serif; 6 | -webkit-font-smoothing: antialiased; 7 | -moz-osx-font-smoothing: grayscale; 8 | } 9 | 10 | code { 11 | font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", 12 | monospace; 13 | } 14 | 15 | body { 16 | overflow: hidden; 17 | } 18 | 19 | .modal-dialog { 20 | margin: 0 auto !important; 21 | max-width: 100% !important; 22 | } 23 | 24 | .modal-content { 25 | background-color: transparent !important; 26 | border-width: 0 !important; 27 | width: 100% !important; 28 | height: 100% !important; 29 | } 30 | 31 | .modal-dialog-centered { 32 | min-height: 100% !important; 33 | } 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root') 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /src/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/store/store.js: -------------------------------------------------------------------------------- 1 | import create from "zustand" 2 | import produce from "immer"; 3 | 4 | const store = create(set => ({ 5 | socket: null, 6 | updateSocket: ( val ) => set(produce(state => { 7 | state.socket = val; 8 | })) 9 | })) 10 | 11 | export default store; -------------------------------------------------------------------------------- /src/utils/address.js: -------------------------------------------------------------------------------- 1 | export const llgContractAddress = "0x0e04Ad5f9a40ddfe82ac533C9D5284Fb3C72BcAa"; 2 | export const llgRewardContractAddress = "0x9274011471a1Fac4fD5304fc1f8a536150057df7"; 3 | export const chainId = 0x61; -------------------------------------------------------------------------------- /src/utils/constant.js: -------------------------------------------------------------------------------- 1 | import { ang2Rad } from "./helper"; 2 | 3 | export const cameraProps = { 4 | fov: 60, 5 | // aspect: window.innerWidth / window.innerHeight, 6 | aspect: 16 / 9, 7 | near: 0.1, 8 | far: 2000, 9 | position: { 10 | x: 0, 11 | y: 8, 12 | z: -6, 13 | } 14 | } 15 | 16 | export const orbitControlProps = { 17 | target: { 18 | x: 0, 19 | y: 0, 20 | z: 0, 21 | }, 22 | maxPolarAngle: ang2Rad(70), 23 | maxDistance: 50, 24 | minDistance: 5, 25 | } 26 | 27 | export const bloomParams = { 28 | exposure: 1, 29 | bloomStrength: 0.25, 30 | bloomThreshold: 0, 31 | bloomRadius: 0.1 32 | }; 33 | 34 | export const hemiLightProps = { 35 | skyColor: 0xcccccc, 36 | groundColor: 0x000000, 37 | intensity: 0.45, 38 | } 39 | 40 | export const spotLightProps = { 41 | color: 0xcccccc, 42 | intensity: 0.6, 43 | position: { 44 | x: -25, 45 | y: 25, 46 | z: 25, 47 | }, 48 | castShadow: true, 49 | shadow: { 50 | bias: -0.0001, 51 | mapSize: { 52 | width: 1024 * 4, 53 | height: 1024 * 4, 54 | } 55 | } 56 | } 57 | 58 | export const spotLightProps2 = { 59 | color: 0xcccccc, 60 | intensity: 0.6, 61 | position: { 62 | x: 25, 63 | y: 25, 64 | z: 25, 65 | }, 66 | castShadow: true, 67 | shadow: { 68 | bias: -0.0001, 69 | mapSize: { 70 | width: 1024 * 4, 71 | height: 1024 * 4, 72 | } 73 | } 74 | } 75 | 76 | export const pieceMoveSpeed = 10; 77 | 78 | export const aiLevel = 3; // 3: advanced Up to 3; 79 | 80 | export const alphaBet = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'] 81 | 82 | export const tileSize = 1.02; 83 | 84 | export const lightTone = '#b18057'; 85 | export const darkTone = '#0a181f'; 86 | export const selectTone = '#d78b00'; 87 | export const historyTone = '#ff0000'; 88 | export const dangerTone = '#d32da7'; 89 | 90 | export const boardSize = 8; 91 | 92 | export const modelSize = 0.8; 93 | 94 | export const modelProps = { 95 | 'mountain': { 96 | scale: 1.2, 97 | position: { 98 | x: 16, 99 | y: 0.4, 100 | z: 5, 101 | }, 102 | rotate: { 103 | x: 0, 104 | y: 10, 105 | z: 0, 106 | } 107 | }, 108 | 'board': { 109 | scale: modelSize + 0.0125, 110 | position: { 111 | x: 0, 112 | y: 0.5, 113 | z: 0, 114 | } 115 | }, 116 | 'cell': { 117 | scale: modelSize, 118 | position: { 119 | x: 0, 120 | y: 0.6, 121 | z: 0, 122 | } 123 | } 124 | } 125 | 126 | export const gameModes = { 127 | 'P2E': 0, 128 | 'P2P': 1, 129 | 'practise': 2 130 | } 131 | 132 | export const userTypes = { 133 | 'creator': 0, 134 | 'joiner': 1, 135 | 'observer': 2, 136 | } 137 | 138 | export const resizeUpdateInterval = 500; 139 | 140 | export const heroItems = { 141 | iceWall: 1, 142 | petrify: 2, 143 | jumpyShoe: 3, 144 | springPad: 4, 145 | thunderstorm: 5 146 | }; 147 | 148 | export const timeLimit = 30; -------------------------------------------------------------------------------- /src/utils/helper.js: -------------------------------------------------------------------------------- 1 | import { alphaBet, tileSize } from "./constant"; 2 | 3 | export const rad2Ang = (rad) => rad * 180 / Math.PI; 4 | 5 | export const ang2Rad = (ang) => ang * Math.PI / 180; 6 | 7 | export const getRandomVal = (range) => Math.ceil(Math.random() * 100000000) % range; 8 | 9 | export const getMatrixIndexFromFen = (val) => ({ 10 | rowIndex: val[1] - 1, 11 | colIndex: alphaBet.indexOf(val[0]) 12 | }); 13 | 14 | export const getFenFromMatrixIndex = (rowIndex, colIndex) => alphaBet[ colIndex ] + ( rowIndex + 1 ); 15 | 16 | export const isSamePoint = (point1, point2) => point1.x === point2.x && point1.y === point2.y && point1.z === point2.z; 17 | 18 | export const getMeshPosition = (rowIndex, colIndex) => ({ 19 | x: colIndex * tileSize - tileSize * 3.5, 20 | y: 0.6, 21 | z: -(rowIndex * tileSize - tileSize * 3.5) 22 | }) -------------------------------------------------------------------------------- /src/utils/interact.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | import { ethers } from 'ethers' 4 | import {chainId} from './address'; 5 | 6 | require("dotenv").config() 7 | // const alchemyKey = process.env.REACT_APP_ALCHEMY_KEY 8 | // const { createAlchemyWeb3 } = require("@alch/alchemy-web3") 9 | // const web3 = createAlchemyWeb3(alchemyKey) 10 | // const web3 = new Web3('https://ropsten.infura.io/v3/9aa3d95b3bc440fa88ea12eaa4456161') 11 | // const clanCount = 5 12 | 13 | export const connectWallet = async () => { 14 | if (window.ethereum) { 15 | try { 16 | const chain = await window.ethereum.request({ method: 'eth_chainId' }) 17 | console.log("log: ", chain, parseInt(chain, 16), chainId, parseInt(chain, 16) === chainId) 18 | if (parseInt(chain, 16) == chainId) { 19 | const addressArray = await window.ethereum.request({ 20 | method: 'eth_requestAccounts', 21 | }) 22 | console.log(addressArray) 23 | if (addressArray.length > 0) { 24 | return { 25 | address: addressArray[0], 26 | status: "👆🏽 You can play now.", 27 | } 28 | } else { 29 | return { 30 | address: "", 31 | status: "😥 Connect your wallet account to the site.", 32 | } 33 | } 34 | } else { 35 | window.ethereum.request({ 36 | method: 'wallet_switchEthereumChain', 37 | params: [{ chainId:chainId }], 38 | }) 39 | return { 40 | address: "", 41 | status: "😥 Connect your wallet account to the site.", 42 | } 43 | } 44 | 45 | } catch (err) { 46 | return { 47 | address: "", 48 | status: "😥 " + err.message, 49 | } 50 | } 51 | } else { 52 | return { 53 | address: "", 54 | status: ( 55 | 56 |

57 | {" "} 58 | 🦊{" "} 59 | {/* */} 60 | You must install Metamask, a virtual Ethereum wallet, in your 61 | browser.(https://metamask.io/download.html) 62 | {/* */} 63 |

64 |
65 | ), 66 | } 67 | } 68 | } 69 | 70 | export const getCurrentWalletConnected = async () => { 71 | if (window.ethereum) { 72 | try { 73 | const addressArray = await window.ethereum.request({ 74 | method: "eth_accounts", 75 | }) 76 | const chain = await window.ethereum.request({ 77 | method: "eth_chainId", 78 | }) 79 | if (addressArray.length > 0 && chain === chainId) { 80 | return { 81 | address: addressArray[0], 82 | status: "👆🏽 You can play now.", 83 | } 84 | } else { 85 | return { 86 | address: "", 87 | status: "🦊 Connect to Metamask and choose the correct chain using the top right button.", 88 | } 89 | } 90 | } catch (err) { 91 | return { 92 | address: "", 93 | status: "😥 " + err.message, 94 | } 95 | } 96 | } else { 97 | return { 98 | address: "", 99 | status: ( 100 | 101 |

102 | {" "} 103 | 🦊{" "} 104 | {/* */} 105 | You must install Metamask, a virtual Ethereum wallet, in your 106 | browser.(https://metamask.io/download.html) 107 | {/* */} 108 |

109 |
110 | ), 111 | } 112 | } 113 | } 114 | 115 | // async function loadContract() { 116 | // return new web3.eth.Contract(contractABI, contractAddress) 117 | // } 118 | 119 | // Contract can be used to write Contract 120 | export const getContractWithSigner = (contractAddress, contractABI) => { 121 | let infuraProvider = new ethers.providers.Web3Provider(window.ethereum) 122 | let signer = infuraProvider.getSigner() 123 | 124 | let contract = new ethers.Contract( 125 | contractAddress, 126 | contractABI, 127 | signer 128 | ) 129 | 130 | return contract 131 | } 132 | 133 | // Contract can be used to read Contract 134 | export const getContractWithoutSigner = (contractAddress, contractABI) => { 135 | let infuraProvider = new ethers.providers.Web3Provider(window.ethereum) 136 | 137 | let contract = new ethers.Contract( 138 | contractAddress, 139 | contractABI, 140 | infuraProvider 141 | ) 142 | 143 | return contract 144 | } 145 | 146 | export const getContract = (contractAddress, contractABI) => { 147 | let provider = new ethers.providers.Web3Provider(window.ethereum); 148 | let signer = provider.getSigner(); 149 | 150 | let contract = new ethers.Contract(contractAddress, contractABI, signer) 151 | return contract 152 | } -------------------------------------------------------------------------------- /src/utils/llg-contract-abi.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"routerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bnbAmount","type":"uint256"}],"name":"AutoBurned","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bnbAmount","type":"uint256"}],"name":"Burned","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountBnb","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nextAvailableClaimDate","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokensSwapped","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bnbReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokensIntoLiqudity","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bnbIntoLiquidity","type":"uint256"}],"name":"Swapped","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BURN_WALLET","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"activate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"activateBuying","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"amountUntilSwap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"antiBlockNum","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"antiEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"byAddress","type":"address"},{"internalType":"bool","name":"isApproved","type":"bool"}],"name":"approveClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"autoLiquidityWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"byAddress","type":"address"}],"name":"bnbRewardClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"byAddress","type":"address"}],"name":"bnbRewardClaimedAsLLG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"bnbAmount","type":"uint256"}],"name":"buyAndBurn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ofAddress","type":"address"}],"name":"calculateBNBReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ofAddress","type":"address"}],"name":"calculateClaimRewards","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"calculateRewardCycleExtension","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"claimReward","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"ofAddress","type":"address"}],"name":"claimRewardAsTokensPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"globalRewardDampeningPercentage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gradualBurnMagnitude","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"gradualBurnTimespan","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isAutoClaimEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"ofAddress","type":"address"},{"internalType":"address","name":"byAddress","type":"address"}],"name":"isClaimApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isContract","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isExcludedFromFees","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isExcludedFromHold","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isExcludedFromRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFeeEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isInRewardClaimQueue","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isIncludedInRewards","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isRewardAsTokensEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"isRewardReady","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isSwapEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isTokenHoldEnabled","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"isWhitelistedExternalProcessor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastBurnDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mainBnbPoolSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketingWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxClaimAllowed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxGasForAutoClaim","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minRewardBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"ofAddress","type":"address"}],"name":"nextAvailableClaimDate","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pancakeSwapPairAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pancakeSwapRouterAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"processRewardClaimQueue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"processRewardClaimQueueAndRefundGas","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"reimburseAfterLLGClaimFailure","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rewardClaimQueueIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardClaimQueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardCyclePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"_isEnabled","type":"bool"}],"name":"setAntiBotEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setAutoClaimEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityWallet","type":"address"}],"name":"setAutoLiquidityWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"percentage","type":"uint256"}],"name":"setClaimRewardAsTokensPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"devWalletAddress","type":"address"}],"name":"setDevWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"exclude","type":"bool"}],"name":"setExcludeNonHumansFromRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setExcludedFromFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"value","type":"bool"}],"name":"setExcludedFromHold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isExcluded","type":"bool"}],"name":"setExcludedFromRewards","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setFeeEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"liquidityFee","type":"uint8"},{"internalType":"uint8","name":"rewardFee","type":"uint8"},{"internalType":"uint8","name":"marketingFee","type":"uint8"},{"internalType":"uint8","name":"devFee","type":"uint8"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setGlobalRewardDampeningPercentage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"magnitude","type":"uint256"}],"name":"setGradualBurnMagnitude","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"timespan","type":"uint256"}],"name":"setGradualBurnTimespan","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setHoldLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"size","type":"uint256"}],"name":"setMainBnbPoolSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"marketingWalletAddress","type":"address"}],"name":"setMarketingWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"setMaxClaimAllowed","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"}],"name":"setMaxGasForAutoClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"balance","type":"uint256"}],"name":"setMinRewardBalance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"routerAddress","type":"address"}],"name":"setPancakeSwapRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"value","type":"bool"}],"name":"setReimburseAfterLLGClaimFailure","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setRewardAsTokensEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setRewardCycleExtensionThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"setRewardCyclePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"setSendWeiGasLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setSwapEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"isEnabled","type":"bool"}],"name":"setTokenHoldEnabled","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"setTokenSwapThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setTransactionBuyLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"setTransactionSellLimit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"bool","name":"isWhitelisted","type":"bool"}],"name":"setWhitelistedExternalProcessor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"shouldBurn","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"tokenSwapThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAmountOfTokensHeld","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBNBClaimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBNBClaimedAsLLG","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalBNBLiquidityAddedFromFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalFeesPooled","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"transactionBuyLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"transactionSellLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockNum","type":"uint256"}],"name":"updateBlockNum","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}] 2 | -------------------------------------------------------------------------------- /src/utils/llg-reward-contract-abi.json: -------------------------------------------------------------------------------- 1 | [{"inputs":[{"internalType":"address","name":"_llg","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"bonusWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"canGetBonus","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"consecutive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_room","type":"uint256"},{"internalType":"address","name":"_playerAddr","type":"address"},{"internalType":"uint256","name":"_funds","type":"uint256"}],"name":"deposit","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_room","type":"uint256"}],"name":"getDeposits","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_user","type":"address"}],"name":"getLLGBalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_playerAddr","type":"address"}],"name":"getNumOfConsecutiveWins","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_playerAddr","type":"address"},{"internalType":"uint256","name":"_room","type":"uint256"},{"internalType":"uint256","name":"_passport","type":"uint256"},{"internalType":"uint256","name":"_numCWins","type":"uint256"}],"name":"giveBonusReward","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_passport","type":"uint256"}],"name":"issuePassport","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"llgContract","outputs":[{"internalType":"contract ILLG","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_room","type":"uint256"},{"internalType":"uint256","name":"_passport","type":"uint256"},{"internalType":"address","name":"_winnerAddr","type":"address"},{"internalType":"bool","name":"isFriendMatch","type":"bool"}],"name":"offerWinningReward","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_room","type":"uint256"},{"internalType":"uint256","name":"_passport","type":"uint256"},{"internalType":"address","name":"_playerAddr","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"refund","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"rewarded","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"rewardedTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setBonusWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_of","type":"address"},{"internalType":"uint256","name":"_num","type":"uint256"}],"name":"setConsecutiveCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_dateTimeInMillis","type":"uint256"}],"name":"setStartTimeOfDay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_taxPercent","type":"uint256"}],"name":"setTaxPercent","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"setTaxWallet","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startTimeOfDay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxPercent","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxWallet","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}] 2 | -------------------------------------------------------------------------------- /src/utils/packet.js: -------------------------------------------------------------------------------- 1 | export const socketEvents = { 2 | 'CS_CreateRoom': 0xff0001, 3 | 'CS_JoinRoom': 0xff0002, 4 | 'CS_SelectPiece': 0xff0003, 5 | 'CS_PerformMove': 0xff0004, 6 | 'CS_PawnTransform': 0xff0005, 7 | 'CS_UnSelectPiece': 0xff0006, 8 | 'CS_MatchPlayLogin': 0xff0007, 9 | 'CS_ActivateItem': 0xff0008, 10 | 'CS_Ready': 0xff0009, 11 | 'CS_CurrentItem': 0xff0010, 12 | 'CS_SendDrawRequest': 0xff0011, 13 | 'CS_ReplyDrawRequest': 0xff0012, 14 | 15 | 'SC_RoomCreated': 0xff1001, 16 | 'SC_GameStarted': 0xff1002, 17 | 'SC_ChangeTurn': 0xff0103, 18 | 'SC_PlayerLogOut': 0xff1004, 19 | 'SC_ForceExit': 0xff1005, 20 | 'SC_SelectPiece': 0xff1006, 21 | 'SC_PawnTransform': 0xff1007, 22 | 'SC_PerformMove': 0xff1008, 23 | 'SC_UnSelectPiece': 0xff0009, 24 | 'SC_RemainingTime': 0xff0010, 25 | 'SC_ActivateItem': 0xff0011, 26 | 'SC_JoinRoom': 0xff0012, 27 | 'SC_ItemInfo': 0xff0013, 28 | 'SC_SendDrawRequest': 0xff0014, 29 | 'SC_DrawMatch': 0xff0015, 30 | } -------------------------------------------------------------------------------- /src/views/FriendPlay/index.js: -------------------------------------------------------------------------------- 1 | import { Routes, Route } from "react-router-dom"; 2 | 3 | import Play2Earn from "../../components/UI/Play2Earn/Play2Earn"; 4 | import CreateGame from "../../components/UI/CreateGame/CreateGame"; 5 | import JoinGame from "../../components/UI/JoinGame/JoinGame"; 6 | import RoomsScreen from "../../components/UI/RoomsScreen/RoomsScreen"; 7 | 8 | export const FriendPlay = () => { 9 | return ( 10 |
11 | 12 | } /> 13 | } /> 14 | } /> 15 | } /> 16 | 17 |
18 | ) 19 | } 20 | 21 | export default FriendPlay; -------------------------------------------------------------------------------- /src/views/GameScene/CustomOutlinePass.js: -------------------------------------------------------------------------------- 1 | import * as THREE from "three"; 2 | import { Pass } from "three/examples/jsm/postprocessing/Pass.js"; 3 | 4 | // Follows the structure of 5 | // https://github.com/mrdoob/three.js/blob/master/examples/jsm/postprocessing/OutlinePass.js 6 | class CustomOutlinePass extends Pass { 7 | constructor(resolution, scene, camera, applyOutlineType) { 8 | super(); 9 | this.applyOutlineType = applyOutlineType; 10 | this.renderScene = scene; 11 | this.renderCamera = camera; 12 | this.resolution = new THREE.Vector2(resolution.x, resolution.y); 13 | this.fsQuad = new Pass.FullScreenQuad(null); 14 | this.fsQuad.material = this.createOutlinePostProcessMaterial(); 15 | // Create a buffer to store the normals of the scene onto 16 | const normalTarget = new THREE.WebGLRenderTarget( 17 | this.resolution.x, 18 | this.resolution.y 19 | ); 20 | normalTarget.texture.format = THREE.RGBFormat; 21 | normalTarget.texture.minFilter = THREE.NearestFilter; 22 | normalTarget.texture.magFilter = THREE.NearestFilter; 23 | normalTarget.texture.generateMipmaps = false; 24 | normalTarget.stencilBuffer = false; 25 | // This stores the depth buffer containing 26 | // only objects that will have outlines 27 | normalTarget.depthBuffer = true; 28 | normalTarget.depthTexture = new THREE.DepthTexture(); 29 | normalTarget.depthTexture.type = THREE.UnsignedShortType; 30 | 31 | this.normalTarget = normalTarget; 32 | // Create a buffer to store the depth of the scene 33 | // we don't use the default depth buffer because 34 | // this one includes only objects that have the outline applied 35 | const depthTarget = new THREE.WebGLRenderTarget( this.resolution.x, this.resolution.y ); 36 | depthTarget.texture.format = THREE.RGBFormat; 37 | depthTarget.texture.minFilter = THREE.NearestFilter; 38 | depthTarget.texture.magFilter = THREE.NearestFilter; 39 | depthTarget.texture.generateMipmaps = false; 40 | depthTarget.stencilBuffer = false; 41 | depthTarget.depthBuffer = true; 42 | depthTarget.depthTexture = new THREE.DepthTexture(); 43 | depthTarget.depthTexture.type = THREE.UnsignedShortType; 44 | this.depthTarget = depthTarget; 45 | 46 | this.normalOverrideMaterial = new THREE.MeshNormalMaterial(); 47 | } 48 | dispose() { 49 | this.normalTarget.dispose(); 50 | this.fsQuad.dispose(); 51 | } 52 | setSize(width, height) { 53 | this.normalTarget.setSize(width, height); 54 | this.resolution.set(width, height); 55 | this.fsQuad.material.uniforms.screenSize.value.set( 56 | this.resolution.x, 57 | this.resolution.y, 58 | 1 / this.resolution.x, 59 | 1 / this.resolution.y 60 | ); 61 | } 62 | 63 | // Helper functions for hiding/showing objects based on whether they should have outlines applied 64 | setOutlineObjectsVisibile(bVisible) { 65 | const self = this; 66 | this.renderScene.traverse( function( node ) { 67 | if (node.applyOutline == true && node.applyOutlineType == self.applyOutlineType && node.type == 'Mesh') { 68 | 69 | if (!bVisible) { 70 | node.oldVisibleValue = node.visible; 71 | node.visible = false; 72 | } else { 73 | // Restore original visible value. This way objects 74 | // that were originally hidden stay hidden 75 | if (node.oldVisibleValue != undefined) { 76 | node.visible = node.oldVisibleValue; 77 | delete node.oldVisibleValue; 78 | } 79 | } 80 | 81 | 82 | } 83 | }); 84 | } 85 | 86 | setNonOutlineObjectsVisible(bVisible) { 87 | const self = this; 88 | this.renderScene.traverse( function( node ) { 89 | if (node.type == 'Mesh' && (node.applyOutline != true || node.applyOutlineType != self.applyOutlineType)) { 90 | 91 | if (!bVisible) { 92 | node.oldVisibleValue = node.visible; 93 | node.visible = false; 94 | } else { 95 | // Restore original visible value. This way objects 96 | // that were originally hidden stay hidden 97 | if (node.oldVisibleValue != undefined) { 98 | node.visible = node.oldVisibleValue; 99 | delete node.oldVisibleValue; 100 | } 101 | } 102 | 103 | 104 | } 105 | }); 106 | } 107 | 108 | /* 109 | This is a modified pipeline from the original outlines effect 110 | to support outlining individual objects. 111 | 1 - Render all objects to get final color buffer, with regular depth buffer 112 | (this is done in index.js) 113 | 2 - Render only non-outlines objects to get `nonOutlinesDepthBuffer`. 114 | (we need this to depth test our outlines so they render behind objects) 115 | 3 - Render all outlines objects to get normal buffer & depth buffer, which are inputs for the outline effect. 116 | This must NOT include objects that won't have outlines applied. 117 | 4 - Render outline effect, using normal and depth buffer that contains only outline objects, 118 | use the `nonOutlinesDepthBuffer` for depth test. And finally combine with the final color buffer. 119 | */ 120 | 121 | render(renderer, writeBuffer, readBuffer) { 122 | // Turn off writing to the depth buffer 123 | // because we need to read from it in the subsequent passes. 124 | const depthBufferValue = writeBuffer.depthBuffer; 125 | writeBuffer.depthBuffer = false; 126 | // 1. Re-render the scene to capture all normals in texture. 127 | // Ideally we could capture this in the first render pass along with 128 | // the depth texture. 129 | renderer.setRenderTarget(this.normalTarget); 130 | 131 | const overrideMaterialValue = this.renderScene.overrideMaterial; 132 | this.renderScene.overrideMaterial = this.normalOverrideMaterial; 133 | // Only include objects that have the "applyOutline" property. 134 | // We do this by hiding all other objects temporarily. 135 | this.setNonOutlineObjectsVisible(false); 136 | renderer.render(this.renderScene, this.renderCamera); 137 | this.setNonOutlineObjectsVisible(true); 138 | 139 | this.renderScene.overrideMaterial = overrideMaterialValue; 140 | 141 | // 2. Re-render the scene to capture depth of objects that do NOT have outlines 142 | renderer.setRenderTarget(this.depthTarget); 143 | 144 | this.setOutlineObjectsVisibile(false); 145 | renderer.render(this.renderScene, this.renderCamera); 146 | this.setOutlineObjectsVisibile(true); 147 | 148 | this.fsQuad.material.uniforms["depthBuffer"].value = this.normalTarget.depthTexture; 149 | 150 | this.fsQuad.material.uniforms[ 151 | "normalBuffer" 152 | ].value = this.normalTarget.texture; 153 | this.fsQuad.material.uniforms["sceneColorBuffer"].value = 154 | readBuffer.texture; 155 | this.fsQuad.material.uniforms["nonOutlinesDepthBuffer"].value = this.depthTarget.depthTexture; 156 | 157 | // 2. Draw the outlines using the depth texture and normal texture 158 | // 3. Draw the outlines using the depth texture and normal texture 159 | // and combine it with the scene color 160 | if (this.renderToScreen) { 161 | // If this is the last effect, then renderToScreen is true. 162 | // So we should render to the screen by setting target null 163 | // Otherwise, just render into the writeBuffer that the next effect will use as its read buffer. 164 | renderer.setRenderTarget(null); 165 | this.fsQuad.render(renderer); 166 | } else { 167 | renderer.setRenderTarget(writeBuffer); 168 | this.fsQuad.render(renderer); 169 | } 170 | // Reset the depthBuffer value so we continue writing to it in the next render. 171 | writeBuffer.depthBuffer = depthBufferValue; 172 | } 173 | get vertexShader() { 174 | return ` 175 | varying vec2 vUv; 176 | void main() { 177 | vUv = uv; 178 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0); 179 | } 180 | `; 181 | } 182 | get fragmentShader() { 183 | return ` 184 | #include 185 | // The above include imports "perspectiveDepthToViewZ" 186 | // and other GLSL functions from ThreeJS we need for reading depth. 187 | uniform sampler2D sceneColorBuffer; 188 | uniform sampler2D depthBuffer; 189 | uniform sampler2D normalBuffer; 190 | uniform sampler2D nonOutlinesDepthBuffer; 191 | uniform float cameraNear; 192 | uniform float cameraFar; 193 | uniform vec4 screenSize; 194 | uniform vec3 outlineColor; 195 | uniform vec4 multiplierParameters; 196 | uniform int debugVisualize; 197 | varying vec2 vUv; 198 | // Helper functions for reading from depth buffer. 199 | float readDepth (sampler2D depthSampler, vec2 coord) { 200 | float fragCoordZ = texture2D(depthSampler, coord).x; 201 | float viewZ = perspectiveDepthToViewZ( fragCoordZ, cameraNear, cameraFar ); 202 | return viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); 203 | } 204 | float getLinearDepth(vec3 pos) { 205 | return -(viewMatrix * vec4(pos, 1.0)).z; 206 | } 207 | float getLinearScreenDepth(sampler2D map) { 208 | vec2 uv = gl_FragCoord.xy * screenSize.zw; 209 | return readDepth(map,uv); 210 | } 211 | // Helper functions for reading normals and depth of neighboring pixels. 212 | float getPixelDepth(int x, int y) { 213 | // screenSize.zw is pixel size 214 | // vUv is current position 215 | return readDepth(depthBuffer, vUv + screenSize.zw * vec2(x, y)); 216 | } 217 | vec3 getPixelNormal(int x, int y) { 218 | return texture2D(normalBuffer, vUv + screenSize.zw * vec2(x, y)).rgb; 219 | } 220 | float saturate(float num) { 221 | return clamp(num, 0.0, 1.0); 222 | } 223 | void main() { 224 | vec4 sceneColor = texture2D(sceneColorBuffer, vUv); 225 | float depth = getPixelDepth(0, 0); 226 | float nonOutlinesDepth = readDepth(nonOutlinesDepthBuffer, vUv + screenSize.zw); 227 | vec3 normal = getPixelNormal(0, 0); 228 | // Get the difference between depth of neighboring pixels and current. 229 | float depthDiff = 0.0; 230 | depthDiff += abs(depth - getPixelDepth(1, 0)); 231 | depthDiff += abs(depth - getPixelDepth(-1, 0)); 232 | depthDiff += abs(depth - getPixelDepth(0, 1)); 233 | depthDiff += abs(depth - getPixelDepth(0, -1)); 234 | // Get the difference between normals of neighboring pixels and current 235 | float normalDiff = 0.0; 236 | normalDiff += distance(normal, getPixelNormal(1, 0)); 237 | normalDiff += distance(normal, getPixelNormal(0, 1)); 238 | normalDiff += distance(normal, getPixelNormal(0, 1)); 239 | normalDiff += distance(normal, getPixelNormal(0, -1)); 240 | normalDiff += distance(normal, getPixelNormal(1, 1)); 241 | normalDiff += distance(normal, getPixelNormal(1, -1)); 242 | normalDiff += distance(normal, getPixelNormal(-1, 1)); 243 | normalDiff += distance(normal, getPixelNormal(-1, -1)); 244 | // Apply multiplier & bias to each 245 | float depthBias = multiplierParameters.x; 246 | float depthMultiplier = multiplierParameters.y; 247 | float normalBias = multiplierParameters.z; 248 | float normalMultiplier = multiplierParameters.w; 249 | depthDiff = depthDiff * depthMultiplier; 250 | depthDiff = saturate(depthDiff); 251 | depthDiff = pow(depthDiff, depthBias); 252 | normalDiff = normalDiff * normalMultiplier; 253 | normalDiff = saturate(normalDiff); 254 | normalDiff = pow(normalDiff, normalBias); 255 | float outline = normalDiff + depthDiff; 256 | // Don't render outlines if they are behind something 257 | // in the original depth buffer 258 | // we find this out by comparing the depth value of current pixel 259 | if ( depth > nonOutlinesDepth && debugVisualize != 4) { 260 | outline = 0.0; 261 | } 262 | 263 | // Combine outline with scene color. 264 | vec4 outlineColor = vec4(outlineColor, 1.0); 265 | gl_FragColor = vec4(mix(sceneColor, outlineColor, outline)); 266 | // For debug visualization of the different inputs to this shader. 267 | if (debugVisualize == 1) { 268 | gl_FragColor = sceneColor; 269 | } 270 | if (debugVisualize == 2) { 271 | gl_FragColor = vec4(vec3(depth), 1.0); 272 | } 273 | if (debugVisualize == 5) { 274 | gl_FragColor = vec4(vec3(nonOutlinesDepth), 1.0); 275 | } 276 | if (debugVisualize == 3) { 277 | gl_FragColor = vec4(normal, 1.0); 278 | } 279 | if (debugVisualize == 4) { 280 | gl_FragColor = vec4(vec3(outline * outlineColor), 1.0); 281 | } 282 | } 283 | `; 284 | } 285 | createOutlinePostProcessMaterial() { 286 | return new THREE.ShaderMaterial({ 287 | uniforms: { 288 | debugVisualize: { value: 0 }, 289 | sceneColorBuffer: {}, 290 | depthBuffer: {}, 291 | normalBuffer: {}, 292 | nonOutlinesDepthBuffer: {}, 293 | outlineColor: { value: this.applyOutlineType === 0 ? new THREE.Color(0x00ffff) : new THREE.Color(0xff0000) }, 294 | //4 scalar values packed in one uniform: depth multiplier, depth bias, and same for normals. 295 | multiplierParameters: { value:new THREE.Vector4(1, 1, 1, 0.0001) }, 296 | cameraNear: { value: this.renderCamera.near }, 297 | cameraFar: { value: this.renderCamera.far }, 298 | screenSize: { 299 | value: new THREE.Vector4( 300 | this.resolution.x, 301 | this.resolution.y, 302 | 1 / this.resolution.x, 303 | 1 / this.resolution.y 304 | ), 305 | }, 306 | }, 307 | vertexShader: this.vertexShader, 308 | fragmentShader: this.fragmentShader, 309 | }); 310 | } 311 | } 312 | export { CustomOutlinePass }; -------------------------------------------------------------------------------- /src/views/GameScene/GameScene.scss: -------------------------------------------------------------------------------- 1 | .GameScene { 2 | position: relative; 3 | display: grid; 4 | align-items: center; 5 | text-align: center; 6 | width: 100vw; 7 | height: 100vh; 8 | background-image: url("../../assets/img/modal_back.png"); 9 | background-repeat: no-repeat; 10 | background-size: 100% 100%; 11 | .game-container { 12 | position: relative; 13 | margin: auto; 14 | .game-canvas { 15 | width: 100%; 16 | height: 100%; 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/views/GameScene/index.js: -------------------------------------------------------------------------------- 1 | import { useLocation } from "react-router-dom"; 2 | import { Game } from 'js-chess-engine' 3 | 4 | import Scene from "./GameScene"; 5 | import { gameModes } from "../../utils/constant"; 6 | import { getRandomVal } from "../../utils/helper"; 7 | 8 | import store from "../../store/store"; 9 | 10 | const game = new Game(); 11 | 12 | console.error(game); 13 | 14 | export const GameScene = () => { 15 | const location = useLocation(); 16 | 17 | const color = [ 'white', 'black' ]; 18 | const side = location.state.mode === gameModes['P2E'] ? color[getRandomVal(2)] : null; 19 | 20 | const socket = store( state => state.socket ); 21 | 22 | return ( 23 |
24 | 25 |
26 | ) 27 | } 28 | 29 | export default GameScene; -------------------------------------------------------------------------------- /src/views/MatchPlay/index.js: -------------------------------------------------------------------------------- 1 | import MatchPlayLogin from "../../components/UI/MatchPlayLogin/MatchPlayLogin"; 2 | 3 | export const MatchPlay = () => { 4 | return ( 5 | 6 | ) 7 | } 8 | 9 | export default MatchPlay; --------------------------------------------------------------------------------