diff --git a/packages/client/src/components/Fog/styles.scss b/packages/client/src/components/Fog/styles.scss index 0848cbb5..8e6b9a01 100644 --- a/packages/client/src/components/Fog/styles.scss +++ b/packages/client/src/components/Fog/styles.scss @@ -1,10 +1,10 @@ .mi-map-fog { position: absolute; z-index: 10; - left: 0; - right: 0; - top: 0; - bottom: 0; - background: radial-gradient(circle closest-side at 50% 50%, #00000000 200px, #000000ff 80%); + left: -150vw; + top: -150vh; + width: 300vw; + height: 300vh; + background: radial-gradient(circle closest-side at 50% 50%, #00000000 200px, #000000ff 24%); pointer-events: none; } \ No newline at end of file diff --git a/packages/client/src/components/Map/index.tsx b/packages/client/src/components/Map/index.tsx index 7193b0a2..53caf9df 100644 --- a/packages/client/src/components/Map/index.tsx +++ b/packages/client/src/components/Map/index.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useRef } from 'react'; +import React, { useMemo, useRef, useState } from 'react'; import { IPlayer } from '../Player'; import MapCell, { ICellClassCache, ICoordinate } from '../MapCell'; import './styles.scss'; @@ -22,6 +22,8 @@ const Map = (props: IProps) => { const { width, height, vertexCoordinate, data = [], players, curId, onPlayerMove } = props; const { x: startX, y: startY } = vertexCoordinate; + const [prevActionCoordinate, setPrevActionCoordinate] = useState({ x: -1, y: -1}); + const staticData = useMemo(() => { return Array(height).fill(0).map(() => Array(width).fill(0)); }, [width, height]); @@ -35,7 +37,11 @@ const Map = (props: IProps) => { const playerData = useMemo(() => { const obj = {}; players.forEach((player) => { - obj[`${player.x}-${player.y}`] = player; + if (obj[`${player.x}-${player.y}`]) { + obj[`${player.x}-${player.y}`].push(player) + } else { + obj[`${player.x}-${player.y}`] = [player]; + } }); return obj; }, [players]); @@ -71,9 +77,11 @@ const Map = (props: IProps) => { x, y }} + prevActionCoordinate={prevActionCoordinate} + onExeAction={setPrevActionCoordinate} mapData={data} cellClassCache={cellClassCache.current} - player={playerData[`${x}-${y}`]} + players={playerData[`${x}-${y}`]} onMoveTo={onMoveTo} /> ) diff --git a/packages/client/src/components/Map/styles.scss b/packages/client/src/components/Map/styles.scss index d83d4621..46a88032 100644 --- a/packages/client/src/components/Map/styles.scss +++ b/packages/client/src/components/Map/styles.scss @@ -7,7 +7,6 @@ height: 100%; .mi-map-content { - border: 1px solid; width: $cellSize * 24; } diff --git a/packages/client/src/components/MapCell/index.tsx b/packages/client/src/components/MapCell/index.tsx index 16409276..b3ace795 100644 --- a/packages/client/src/components/MapCell/index.tsx +++ b/packages/client/src/components/MapCell/index.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useEffect, useState } from 'react'; import { CellType } from '../../constants'; import { getCellClass, isMovable } from '@/utils'; import './styles.scss'; @@ -27,12 +27,18 @@ interface IProps { coordinate: ICoordinate, mapData: number[][]; cellClassCache: ICellClassCache; - player?: IPlayer; + players?: IPlayer[]; onMoveTo: (ICoordinate) => void; + prevActionCoordinate: ICoordinate; + onExeAction: (ICoordinate) => void; } const MapCell = (props: IProps) => { - const { coordinate: { x, y}, mapData, cellClassCache, player, onMoveTo } = props; + const { coordinate: { x, y}, mapData, cellClassCache, players, onMoveTo, onExeAction, prevActionCoordinate } = props; + + const [menuVisible, setMenuVisible] = useState(false); + const [activePlayerId, setActivePlayerId] = useState(-1); + if (!cellClassCache[`${y}-${x}`]) { cellClassCache[`${y}-${x}`] = getCellClass(mapData, { x, y}); } @@ -40,16 +46,49 @@ const MapCell = (props: IProps) => { const { transforms, classList } = cellClassCache[`${y}-${x}`]; const onContextMenu = (e) => { + onExeAction({ x, y}); e.preventDefault(); const curMapDataType = mapData[y][x]; - if (isMovable(curMapDataType) && !player) { + if (isMovable(curMapDataType)) { onMoveTo({ x, y}); } + } + + const onClick = () => { + onExeAction({ x, y}); + if (!players || players?.length === 0) { + return; + } + setMenuVisible(true); + setActivePlayerId(players[0].id) + } + const exeAction = (e, action) => { + e.stopPropagation(); + setMenuVisible(false); + switch (action) { + case 'move': + onMoveTo({x, y}); + break; + case 'info': + break; + case 'attack': + break; + } } + useEffect(() => { + if (prevActionCoordinate.x !== x || prevActionCoordinate.y !== y) { + setMenuVisible(false); + } + }, [prevActionCoordinate.x, prevActionCoordinate.y]) + return ( -
+
{ classList.map((item, index) => { @@ -67,8 +106,47 @@ const MapCell = (props: IProps) => { }) }
+ + { + players && players.map((player) => ) + } { - player && + menuVisible && ( +
+ { + players?.length > 1 && ( +
    + { + players?.slice(0, 3).map((player) => { + return ( +
  • { + setActivePlayerId(player.id); + e.stopPropagation(); + }} + >{player.username}
  • + ) + }) + } +
+ ) + } + +
    +
  • + +
  • +
  • + +
  • +
  • + +
  • +
+
+ ) }
); diff --git a/packages/client/src/components/MapCell/styles.scss b/packages/client/src/components/MapCell/styles.scss index 312a34a9..7df77bae 100644 --- a/packages/client/src/components/MapCell/styles.scss +++ b/packages/client/src/components/MapCell/styles.scss @@ -13,4 +13,43 @@ background: url("/src/assets/wall/wall_#{$i}.png") no-repeat center 100% / cover; } } + + .mi-cell-user-menu { + position: absolute; + z-index: 20; + left: 100%; + top: 0; + display: flex; + + li { + margin-bottom: 4px; + } + + .mi-cell-username-list { + margin-right: 10px; + + li { + padding-left: 10px; + width: 144px; + height: 44px; + font-size: 24px; + line-height: 42px; + color: #fff; + background: rgba(0, 0, 0, 0.8); + border-radius: 5px; + + &.active { + text-shadow: #000 1px 0 0, #000 0 1px 0, #000 -1px 0 0, #000 0 -1px 0; + border: 1px solid #000; + background: #FED982; + } + } + } + + .mi-btn { + font-size: 24px; + width: 136px; + height: 46px; + } + } } \ No newline at end of file diff --git a/packages/client/src/components/Player/index.tsx b/packages/client/src/components/Player/index.tsx index d1bfa875..a82df1d7 100644 --- a/packages/client/src/components/Player/index.tsx +++ b/packages/client/src/components/Player/index.tsx @@ -1,5 +1,7 @@ import React from 'react'; import './styles.scss'; +import { CurIdMockData } from '@/mock/data'; +import Fog from '@/components/Fog'; export interface IPlayer { x: number; @@ -13,6 +15,9 @@ const Player = (props: IPlayer) => {
{props.username}
+ { + props.id === CurIdMockData && + }
); }; diff --git a/packages/client/src/config/index.ts b/packages/client/src/config/index.ts index 9d7aad61..3f2f7bad 100644 --- a/packages/client/src/config/index.ts +++ b/packages/client/src/config/index.ts @@ -1,4 +1,9 @@ export const MapConfig = { visualWidth: 24, visualHeight: 16, +} + +export const LimitSpace = { + x: ~~(MapConfig.visualWidth / 2), + y: ~~(MapConfig.visualHeight / 2) } \ No newline at end of file diff --git a/packages/client/src/mock/data.ts b/packages/client/src/mock/data.ts index 2ec559a2..8302e53c 100644 --- a/packages/client/src/mock/data.ts +++ b/packages/client/src/mock/data.ts @@ -36,7 +36,19 @@ export const PlayersMockData: IPlayer[] = [ username: 'other', x: 18, y: 10, - } + }, + { + id: 6, + username: 'other2', + x: 18, + y: 13, + }, + { + id: 8, + username: 'other3', + x: 18, + y: 13, + }, ]; export const CurIdMockData = 3; \ No newline at end of file diff --git a/packages/client/src/pages/game/index.tsx b/packages/client/src/pages/game/index.tsx index 61dee144..ff14ad4d 100644 --- a/packages/client/src/pages/game/index.tsx +++ b/packages/client/src/pages/game/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef, useState } from "react"; import { useComponentValue } from "@latticexyz/react"; -import { MapConfig } from "@/config"; +import { LimitSpace, MapConfig } from "@/config"; import { loadMapData } from "@/utils"; import Map from "@/components/Map"; import UserAvatar from "@/components/UserAvatar"; @@ -12,7 +12,6 @@ import { IPlayer } from "@/components/Player"; import { uploadUserMove } from "@/service/user"; import { useMUD } from "@/mud/MUDContext"; import { getComponentValue } from "@latticexyz/recs"; -import Fog from "@/components/Fog"; import Battle from "@/components/Battle"; const Game = () => { @@ -43,35 +42,29 @@ const Game = () => { roomId = "000000", } = location.state ?? {}; - const onKeyDown = (e) => { - const mapData = mapDataRef.current; - if (mapData.length === 0 || e.keyCode < 37 || e.keyCode > 40) { - return; - } - switch (e.keyCode) { - case 37: - vertexCoordinate.x = Math.max(0, vertexCoordinate.x - 1); - break; - case 38: - vertexCoordinate.y = Math.max(0, vertexCoordinate.y - 1); - break; - case 39: - vertexCoordinate.x = Math.min( - mapData[0].length - 1 - MapConfig.visualWidth, - vertexCoordinate.x + 1 - ); - break; - case 40: - vertexCoordinate.y = Math.min( - mapData.length - 1 - MapConfig.visualHeight, - vertexCoordinate.y + 1 - ); - break; - } - setVertexCoordinate({ - ...vertexCoordinate, - }); - }; + // const onKeyDown = (e) => { + // const mapData = mapDataRef.current; + // if (mapData.length === 0 || e.keyCode < 37 || e.keyCode > 40) { + // return; + // } + // switch (e.keyCode) { + // case 37: + // vertexCoordinate.x = Math.max(0, vertexCoordinate.x - 1); + // break; + // case 38: + // vertexCoordinate.y = Math.max(0, vertexCoordinate.y - 1); + // break; + // case 39: + // vertexCoordinate.x = Math.min(mapData[0].length - 1 - MapConfig.visualWidth, vertexCoordinate.x + 1); + // break; + // case 40: + // vertexCoordinate.y = Math.min(mapData.length - 1 - MapConfig.visualHeight, vertexCoordinate.y + 1); + // break; + // } + // setVertexCoordinate({ + // ...vertexCoordinate + // }); + // }; const movePlayer = (paths, merkelData) => { let pathIndex = 0; @@ -79,6 +72,7 @@ const Game = () => { (item) => item.id === curPlayer!.id ); const interval = setInterval(() => { + triggerVertexUpdate(paths[pathIndex], players[curPlayerIndex]); Object.assign(players[curPlayerIndex], paths[pathIndex]); pathIndex++; setPlayers([...players]); @@ -89,6 +83,43 @@ const Game = () => { // move(merkelData); }; + const triggerVertexUpdate = (cur, before) => { + const xDegree = cur.x - before.x; + const yDegree = cur.y - before.y; + const mapData = mapDataRef.current; + if (xDegree === 1) { + const limitExceeded = cur.x - vertexCoordinate.x > LimitSpace.x; + const lessBoundary = + vertexCoordinate.x + MapConfig.visualWidth < mapData[0].length - 1; + if (limitExceeded && lessBoundary) { + vertexCoordinate.x++; + } + } else if (xDegree === -1) { + const limitExceeded = cur.x - vertexCoordinate.x < LimitSpace.x; + const lessBoundary = vertexCoordinate.x > 0; + if (limitExceeded && lessBoundary) { + vertexCoordinate.x--; + } + } else if (yDegree === 1) { + const limitExceeded = cur.y - vertexCoordinate.y > LimitSpace.y; + const lessBoundary = + vertexCoordinate.y + MapConfig.visualHeight < mapData.length - 1; + if (limitExceeded && lessBoundary) { + vertexCoordinate.y++; + } + } else if (yDegree === -1) { + const limitExceeded = cur.y - vertexCoordinate.y < LimitSpace.y; + const lessBoundary = vertexCoordinate.y > 0; + if (limitExceeded && lessBoundary) { + vertexCoordinate.y--; + } + } + + setVertexCoordinate({ + ...vertexCoordinate, + }); + }; + useEffect(() => { loadMapData().then((csv) => { setRenderMapData(csv); @@ -101,7 +132,7 @@ const Game = () => { }, []); return ( -
+
{
- + {/**/} { const [hasInit, setHasInit] = useState(false); const [walletAddress, setWalletAddress] = useState(''); - const [step, setStep] = useState('mint'); + const [step, setStep] = useState('play'); const { Modal, open, close, setContent } = useModal({ title: '', }); diff --git a/packages/contracts/script/BattleConfigInit.sol b/packages/contracts/script/BattleConfigInit.sol index ba4803a2..6751b7c0 100644 --- a/packages/contracts/script/BattleConfigInit.sol +++ b/packages/contracts/script/BattleConfigInit.sol @@ -7,7 +7,7 @@ import {BattleConfig} from "../src/codegen/Tables.sol"; import { BATTLE_CONFIG_KEY } from "../src/Constants.sol"; library BattleConfigInit { - function initGameConfig(IWorld _world) internal { + function initBattleConfig(IWorld _world) internal { address[] memory players; BattleConfig.set( _world, diff --git a/packages/contracts/script/GlobalConfigInit.sol b/packages/contracts/script/GlobalConfigInit.sol new file mode 100644 index 00000000..9d1e759a --- /dev/null +++ b/packages/contracts/script/GlobalConfigInit.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.0; + +import {console} from "forge-std/console.sol"; +import {IWorld} from "../src/codegen/world/IWorld.sol"; +import {GlobalConfig} from "../src/codegen/Tables.sol"; +import { GLOBAL_CONFIG_KEY } from "../src/Constants.sol"; + +library GlobalConfigInit { + function initGlobalConfig(IWorld _world) internal { + address userContract = 0x09aDeA780C664D100374fcdE48dF82290270f4D2; + GlobalConfig.setUserContract( + _world, + GLOBAL_CONFIG_KEY, //key + userContract + ); + } +} \ No newline at end of file diff --git a/packages/contracts/script/PostDeploy.s.sol b/packages/contracts/script/PostDeploy.s.sol index b2b4262a..7c61b6dd 100644 --- a/packages/contracts/script/PostDeploy.s.sol +++ b/packages/contracts/script/PostDeploy.s.sol @@ -6,6 +6,7 @@ import { console } from "forge-std/console.sol"; import { IWorld } from "../src/codegen/world/IWorld.sol"; import { GameConfigInit } from "./GameConfigInit.sol"; import { BattleConfigInit } from "./BattleConfigInit.sol"; +import { GlobalConfigInit } from "./GlobalConfigInit.sol"; import { console } from "forge-std/console.sol"; contract PostDeploy is Script { @@ -20,7 +21,8 @@ contract PostDeploy is Script { // ------------------ INIT ------------------ GameConfigInit.initGameConfig(IWorld(worldAddress)); - BattleConfigInit.initGameConfig(IWorld(worldAddress)); + BattleConfigInit.initBattleConfig(IWorld(worldAddress)); + GlobalConfigInit.initGlobalConfig(IWorld(worldAddress)); vm.stopBroadcast(); diff --git a/packages/contracts/src/systems/BattlePrepareSystem.sol b/packages/contracts/src/systems/BattlePrepareSystem.sol index 538dfc33..e8133d18 100644 --- a/packages/contracts/src/systems/BattlePrepareSystem.sol +++ b/packages/contracts/src/systems/BattlePrepareSystem.sol @@ -41,7 +41,7 @@ contract BattlePrepareSystem is System { moveList.length > 0 && moveList.length <= BattleConfig.getMaxAttackzDistance(BATTLE_CONFIG_KEY), "invalid attack distance" ); - require(moveList.length <= Player.getSpace(_msgSender()), "exceed player space"); + // require(moveList.length <= Player.getSpace(_msgSender()), "exceed player space"); //Todo: temp remove require( Player.getState(_msgSender()) == PlayerState.Exploring && @@ -78,7 +78,7 @@ contract BattlePrepareSystem is System { //是否已超时 BattleListData memory battle = BattleList.get(_battleId); - BattleUtils.checkBattlePlayer(battle, _msgSender(), BattleState.Confirmed); + BattleUtils.checkBattlePlayer(battle, _msgSender(), BattleState.Inited); require(block.timestamp - battle.timestamp < BattleConfig.getMaxTimeLimit(BATTLE_CONFIG_KEY), "Battle is timeout"); // 战斗是否已经选择buff diff --git a/packages/contracts/src/systems/BattleSystem.sol b/packages/contracts/src/systems/BattleSystem.sol index f77f68a1..66bf12f8 100644 --- a/packages/contracts/src/systems/BattleSystem.sol +++ b/packages/contracts/src/systems/BattleSystem.sol @@ -10,6 +10,7 @@ import { GAME_CONFIG_KEY, BATTLE_CONFIG_KEY } from "../Constants.sol"; contract BattleSystem is System { function revealBattle(uint256 _battleId, bytes32 _action, uint256 _arg, bytes32 _nonce) external { // check battle + // TODO 揭示后全局event提示已经揭示(battle_id,address) BattleListData memory battle = BattleList.get(_battleId); BattleUtils.checkBattlePlayer(battle, _msgSender(), BattleState.Confirmed); @@ -37,7 +38,9 @@ contract BattleSystem is System { } function revealWinner(uint256 _battleId) public { - // 结算战斗 + // 结算战斗TODO revealWinner之后event + // TODO 战斗全局结束后有event + // TODO 战斗结束后如果没有人战败,也发一个event,表示当前局战斗结束了,但是整场战斗没有结束 BattleListData memory battle = BattleList.get(_battleId); BattleUtils.checkBattlePlayer(battle, _msgSender(), BattleState.Revealed); diff --git a/packages/contracts/src/systems/BoxSystem.sol b/packages/contracts/src/systems/BoxSystem.sol index 7d753f51..4332b4db 100644 --- a/packages/contracts/src/systems/BoxSystem.sol +++ b/packages/contracts/src/systems/BoxSystem.sol @@ -23,6 +23,7 @@ contract BoxSystem is System { function openBox(uint256 _boxId) external { // 宝箱打开时init内容物,根据自带randomId来实现随机 + // TODO开宝箱的时候用户定身 uint256 roomId = GameConfig.getRoomId(GAME_CONFIG_KEY); uint256 boxId = GameConfig.getBoxId(GAME_CONFIG_KEY); require(BoxList.getDropTime(roomId, _boxId) != 0, "Invalid box"); diff --git a/packages/contracts/src/systems/GMSystem.sol b/packages/contracts/src/systems/GMSystem.sol index 06274122..8c194140 100644 --- a/packages/contracts/src/systems/GMSystem.sol +++ b/packages/contracts/src/systems/GMSystem.sol @@ -13,7 +13,6 @@ contract GMSystem is System { uint256 start = Season.getStart(MAP_KEY); uint256 end = Season.getEnd(MAP_KEY); uint256 no = Season.getNo(MAP_KEY); - return (start, end, no); } diff --git a/packages/contracts/src/systems/GameSystem.sol b/packages/contracts/src/systems/GameSystem.sol index 5585cc65..315312d3 100644 --- a/packages/contracts/src/systems/GameSystem.sol +++ b/packages/contracts/src/systems/GameSystem.sol @@ -21,12 +21,4 @@ contract GameSystem is System { function dropLoot() external {} - //------非战区空间部分 - - - - - - - } diff --git a/packages/contracts/src/systems/MoveSystem.sol b/packages/contracts/src/systems/MoveSystem.sol index 66d21942..8248637e 100644 --- a/packages/contracts/src/systems/MoveSystem.sol +++ b/packages/contracts/src/systems/MoveSystem.sol @@ -31,7 +31,7 @@ contract MoveSystem is System { moveList.length > 0 && moveList.length <= BattleConfig.getMaxMoveDistance(BATTLE_CONFIG_KEY), "invalid move distance" ); - require(moveList.length <= Player.getSpeed(_msgSender()), "exceed player speed"); + // require(moveList.length <= Player.getSpeed(_msgSender()), "exceed player speed"); // check player lock require(PlayerLocationLock.get(_msgSender()) == 0, "You are locked"); // check continuity diff --git a/packages/contracts/src/systems/library/MRandom.sol b/packages/contracts/src/systems/library/MRandom.sol index a1d33eaa..19ae1844 100644 --- a/packages/contracts/src/systems/library/MRandom.sol +++ b/packages/contracts/src/systems/library/MRandom.sol @@ -37,7 +37,6 @@ library MRandom { function choice(uint8 rand, string[] memory sourceArray) internal pure returns (string memory) { string memory output = sourceArray[rand % sourceArray.length]; - return output; } } diff --git a/packages/contracts/worlds.json b/packages/contracts/worlds.json index 98e6e3d2..367411a2 100644 --- a/packages/contracts/worlds.json +++ b/packages/contracts/worlds.json @@ -1,7 +1,7 @@ { "4242": { - "address": "0x480f891A7b1AA7018Bb0cCb5Af558d82FA4A5501", - "blockNumber": 27830588 + "address": "0x037451EB237700458Af435ffF1CeFcac037247aD", + "blockNumber": 27950347 }, "31337": { "address": "0x74Df809b1dfC099E8cdBc98f6a8D1F5c2C3f66f8"