Untitled

 avatar
unknown
plain_text
5 months ago
18 kB
3
Indexable
"use client";
import React, { useState, useEffect, useRef } from "react";
import Web3 from "web3";
import Swal from "sweetalert2";

// or via CommonJS
const Swal = require("sweetalert2");

const Gamebox = () => {
  const [gameResult, setGameResult] = useState("");
  const [videoSrc, setVideoSrc] = useState(null);
  const [isBotTurn, setIsBotTurn] = useState(false);
  const [isVideoPlaying, setIsVideoPlaying] = useState(false);
  const [pendingResult, setPendingResult] = useState(null);
  const [balance, setBalance] = useState(0);
  const [inputDeposit, setInputDeposit] = useState("");
  const [inputWithdraw, setInputWithdraw] = useState("");
  const [isConnected, setIsConnected] = useState(false);
  const [error, setError] = useState(""); // Added for error handling
  const [prizePool, setPrizePool] = useState("0.00");
  const [bulletPositions, setBulletPositions] = useState([]);
  const [loading, setLoading] = useState(false);
  const videoRef = useRef(null);
  const contractAddress = "0x294CB3E5c7F278cDbEC76794FfbA1fC4d3cE2Bf6"; // Replace with your contract address
  const [web3, setWeb3] = useState(null);
  const [account, setAccount] = useState(null);
  const [contract, setContract] = useState(null);
  const contractaddressabi = [
    {
      inputs: [],
      stateMutability: "nonpayable",
      type: "constructor",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: false,
          internalType: "uint256[6]",
          name: "positions",
          type: "uint256[6]",
        },
      ],
      name: "BulletPosition",
      type: "event",
    },
    {
      inputs: [],
      name: "deposit",
      outputs: [],
      stateMutability: "payable",
      type: "function",
    },
    {
      inputs: [],
      name: "depositToPrizePool",
      outputs: [],
      stateMutability: "payable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "player",
          type: "address",
        },
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "distributeReward",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "getBulletPositions",
      outputs: [
        {
          internalType: "uint256[6]",
          name: "",
          type: "uint256[6]",
        },
      ],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "play",
      outputs: [],
      stateMutability: "payable",
      type: "function",
    },
    {
      anonymous: false,
      inputs: [
        {
          indexed: false,
          internalType: "uint256",
          name: "newPrizePool",
          type: "uint256",
        },
      ],
      name: "PrizePoolUpdated",
      type: "event",
    },
    {
      inputs: [
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "withdraw",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "uint256",
          name: "amount",
          type: "uint256",
        },
      ],
      name: "withdrawFromPrizePool",
      outputs: [],
      stateMutability: "nonpayable",
      type: "function",
    },
    {
      inputs: [],
      name: "admin",
      outputs: [
        {
          internalType: "address",
          name: "",
          type: "address",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [
        {
          internalType: "address",
          name: "",
          type: "address",
        },
      ],
      name: "balances",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "checkBalance",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "getPrizePool",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
    {
      inputs: [],
      name: "prizePool",
      outputs: [
        {
          internalType: "uint256",
          name: "",
          type: "uint256",
        },
      ],
      stateMutability: "view",
      type: "function",
    },
  ];
  useEffect(() => {
    const savedAccount = localStorage.getItem("account");
    const savedBalance = localStorage.getItem("balance");

    if (savedAccount) {
      setAccount(savedAccount);
    }

    if (savedBalance && parseFloat(savedBalance) > 0) {
      setBalance(parseFloat(savedBalance));
    }
  }, []);

  useEffect(() => {
    if (account) {
      localStorage.setItem("account", account);
    }
    if (balance !== 0) {
      localStorage.setItem("balance", balance);
    }
  }, [account, balance]);

  useEffect(() => {
    if (window.ethereum) {
      const init = async () => {
        try {
          const _web3 = new Web3(window.ethereum);
          await window.ethereum.request({ method: "eth_requestAccounts" });
          const _accounts = await _web3.eth.getAccounts();
          setWeb3(_web3);
          setAccount(_accounts[0]);

          // เก็บ account ใน localStorage
          localStorage.setItem("account", _accounts[0]);

          // เชื่อมต่อกับ smart contract
          const _contract = new _web3.eth.Contract(
            contractaddressabi,
            contractAddress
          );
          setContract(_contract);
          fetchPrizePool(_contract);

          // ดึงค่า balance จาก smart contract และเก็บไว้
          loadBalance(_contract);

          // ฟังก์ชันที่จะติดตามเหตุการณ์ PrizePoolUpdated
          _contract.events.PrizePoolUpdated({}, (error, event) => {
            if (error) {
              console.error(error);
            } else {
              const newPrizePool = Web3.utils.fromWei(
                event.returnValues.newPrizePool,
                "ether"
              );
              setPrizePool(newPrizePool); // Update prize pool
            }
          });

          // ติดตามเหตุการณ์ BulletPosition
          _contract.events.BulletPosition({}, (error, event) => {
            if (error) {
              console.error(error);
            } else {
              const positions = event.returnValues.positions;
              // ทำบางอย่างกับตำแหน่งกระสุน
            }
          });
        } catch (error) {
          setError("Failed to connect to Ethereum wallet.");
          console.error(error);
        }
      };
      init();
    } else {
      setError(
        "Ethereum is not detected. Please install MetaMask or another Ethereum wallet."
      );
    }
  }, []);

  const fetchPrizePool = async (contract) => {
    try {
      const pool = await contract.methods.prizePool().call();
      setPrizePool(Web3.utils.fromWei(pool, "ether")); // แปลงค่าจาก Wei เป็น Ether
    } catch (error) {
      console.error("Error fetching prize pool:", error);
    }
  };

  const handlePlay = async () => {
    try {
      setLoading(true);

      // เชื่อมต่อ Ethereum
      await window.ethereum.request({ method: "eth_requestAccounts" });

      const accounts = await web3.eth.getAccounts();
      const contract = new web3.eth.Contract(
        contractaddressabi,
        contractAddress
      );

      // ตรวจสอบเงินใน prize pool
      const prizePool = await contract.methods.getPrizePool().call();
      const prizePoolInEth = web3.utils.fromWei(prizePool, "ether");

      if (parseFloat(prizePoolInEth) < 0.002) {
        Swal.fire({
          title: "Error!",
          text: "เงินรางวัลไม่พอ กรุณารอการเติมเงิน",
          icon: "error",
        });
        return;
      }

      // เล่นเกม (เรียก `play`)
      const playAmount = web3.utils.toWei("0.001", "ether");
      await contract.methods
        .play()
        .send({ from: accounts[0], value: playAmount });

      // ดึงตำแหน่ง bullet
      const result = await contract.methods
        .getBulletPositions()
        .send({ from: accounts[0] });
      if (result.events && result.events.BulletPosition) {
        const bulletPositions =
          result.events.BulletPosition.returnValues.positions;
        setBulletPositions(bulletPositions);

        const stopAtIndex = bulletPositions.findIndex((value) => value === 1n);
        const videoArray = bulletPositions
          .map((value, index) => {
            if (stopAtIndex !== -1 && index > stopAtIndex) return null;
            return index % 2 === 0
              ? value === 0n
                ? "/Video/notshootPLAYER.mp4"
                : "/Video/shootPLAYER.mp4"
              : value === 0n
              ? "/Video/notshootAI.mp4"
              : "/Video/shootAI.mp4";
          })
          .filter((video) => video !== null);

        setVideoSrc(videoArray[0]);

        if (videoArray[0] === "/Video/shootPLAYER.mp4") {
          setTimeout(() => window.location.reload(), 12000);
          return;
        }

        let currentIndex = 1;
        const interval = setInterval(() => {
          if (currentIndex < videoArray.length) {
            setVideoSrc(videoArray[currentIndex]);
            currentIndex++;
          } else {
            clearInterval(interval);

            // หลังจากวิดีโอสุดท้าย (AI ยิง)
            if (videoArray[videoArray.length - 1] === "/Video/shootAI.mp4") {
              setTimeout(async () => {
                const rewardAmount = web3.utils.toWei("0.002", "ether");
                await contract.methods
                  .distributeReward(accounts[0], rewardAmount) // เพิ่มเงินใน balances ของผู้เล่น
                  .send({ from: accounts[0] });

                Swal.fire({
                  title: "Congratulations!",
                  text: "เงินรางวัลถูกเพิ่มเข้าสู่บัญชีในเกมของคุณแล้ว!",
                  icon: "success",
                });
                const newBalance = await contract.methods
                  .checkBalance()
                  .call({ from: accounts[0] });
                setBalance(web3.utils.fromWei(newBalance, "ether")); // อัปเดตยอดเงิน
              }, 12000);
            }
          }
        }, 12000);
      }
    } catch (error) {
      console.error("Error calling contract method:", error);
      Swal.fire({
        title: "Error!",
        text: "การเรียกข้อมูลจาก Smart Contract ล้มเหลว",
        icon: "error",
      });
    } finally {
      setLoading(false);
    }
  };

  const loadBalance = async (contract) => {
    if (contract && account) {
      try {
        const balance = await contract.methods
          .checkBalance()
          .call({ from: account });
        const ethBalance = web3.utils.fromWei(balance, "ether");

        if (ethBalance) {
          setBalance(ethBalance); // อัปเดตค่า Balance
          localStorage.setItem("balance", ethBalance); // เก็บ Balance ใน LocalStorage
        }
      } catch (error) {
        setError("Failed to load balance.");
        console.error(error);
      }
    }
  };

  const handleDeposit = async () => {
    if (inputDeposit <= 0) return;
    const depositAmount = web3.utils.toWei(inputDeposit, "ether");
    try {
      await contract.methods
        .deposit()
        .send({ from: account, value: depositAmount });

      // เรียก loadBalance หลังการฝากสำเร็จ
      await loadBalance(contract);
      setInputDeposit("");

      Swal.fire({
        title: "Success!",
        text: `You have successfully deposited ${inputDeposit} ETH.`,
        icon: "success",
      });
    } catch (error) {
      setError("Failed to deposit funds.");
      console.error(error);
    }
  };

  const handleWithdraw = async () => {
    if (!inputWithdraw) {
      alert("Please enter an amount to withdraw");
      return;
    }

    const amount = web3.utils.toWei(inputWithdraw, "ether");

    try {
      // เรียกฟังก์ชัน withdraw จาก Smart Contract
      await contract.methods.withdraw(amount).send({ from: account });

      // อัปเดตยอดคงเหลือหลังการถอน
      const userBalance = await contract.methods
        .checkBalance()
        .call({ from: account });
      setBalance(web3.utils.fromWei(userBalance, "ether"));

      // แปลง amount เป็น Ether เพื่อแสดงผลในข้อความ
      const amountInEth = web3.utils.fromWei(amount, "ether");

      Swal.fire({
        title: "Success!",
        text: `You have successfully withdrawn ${amountInEth} ETH.`,
        icon: "success",
      }).then(() => {
        // รีเฟรชหน้า
        window.location.reload();
      });
    } catch (error) {
      console.error(error);
      Swal.fire({
        title: "Error!",
        text: "Failed to withdraw funds.",
        icon: "error",
      });
      window.location.reload();
    }
  };

  return (
    <div className="flex justify-center items-center p-5 mt-20">
      <div className="container flex justify-center h-screen">
        <div className="info bg-white w-1/5 h-fit mr-5 rounded-2xl text-zinc-950 p-5">
          <p className="text-center mb-3 font-bold text-xl">Details</p>
          <div className="flex justify-center items-center flex-col text-center">
            <div className="mb-3">
              <div className="mb-3 font-bold bg-red-950 text-white p-2 rounded-lg">
                Game prize pool: {prizePool ? prizePool : "Loading..."} ETH
              </div>

              <p className="font-bold">Deposit</p>
              <div className="flex mt-1">
                <input
                  type="text"
                  value={inputDeposit}
                  onChange={(e) => setInputDeposit(e.target.value)}
                  placeholder="Amount"
                  className="input w-full max-w-xs mr-2 bg-zinc-950 text-white text-center"
                />
                <button
                  className="w-fit btn btn-info bg-red-900 hover:bg-red-950 border-none text-white"
                  onClick={handleDeposit}
                >
                  Deposit 📥
                </button>
              </div>
              <p className="mt-5 font-bold">Withdraw</p>
              <div className="flex mt-1">
                <input
                  type="text"
                  value={inputWithdraw}
                  onChange={(e) => setInputWithdraw(e.target.value)}
                  placeholder="Amount"
                  className="input w-full max-w-xs mb-5 mr-2 bg-zinc-950 text-white text-center"
                />
                <button
                  className="btn btn-info bg-success hover:bg-green-950 border-none text-white"
                  onClick={handleWithdraw}
                >
                  Withdraw 📤
                </button>
              </div>
              <p className="mt-5 font-bold bg-zinc-950 text-white py-2 rounded-lg">
                Your balance 💰 {balance === 0 || !balance ? "0.00" : balance}{" "}
                ETH
              </p>
            </div>
          </div>
        </div>

        {/* Game Section */}
        <div className="Gamebox bg-white w-fit h-fit rounded-2xl flex justify-center items-center flex-col">
          <p className="text-black font-bold mt-7 text-xl p-5">
            🔫 Crimson Chamber
          </p>
          {bulletPositions.length > 0 && (
            <p className="text-black font-bold mt-3">
              Bullet positions: {bulletPositions.join(", ")}
            </p>
          )}

          {videoSrc && (
            <video
              ref={videoRef}
              key={videoSrc}
              width="800"
              autoPlay
              muted
              className="p-5 rounded-xl"
              poster="thumbnail2.png"
            >
              <source src={videoSrc} type="video/mp4" />
            </video>
          )}
          <button
            className="btn btn-success text-white mb-5"
            onClick={handlePlay}
          >
            Play (-0.001) 🎮
          </button>

          {gameResult && (
            <p className="mb-4 text-xl font-bold text-center text-red-900">
              {gameResult}
            </p>
          )}
        </div>
      </div>
    </div>
  );
};

export default Gamebox;
Editor is loading...
Leave a Comment