APE Price: $0.55 (-15.84%)

Contract Diff Checker

Contract Name:
ProjectNineData

Contract Source Code:

File 1 of 1 : ProjectNineData

/**
 *           _          _           _                  _        _             _           _            _
 *          /\ \       /\ \        /\ \               /\ \     /\ \         /\ \         /\ \        / /\
 *         /  \ \     /  \ \      /  \ \              \ \ \   /  \ \       /  \ \        \_\ \      / /  \
 *        / /\ \ \   / /\ \ \    / /\ \ \             /\ \_\ / /\ \ \     / /\ \ \       /\__ \    / / /\ \
 *       / / /\ \_\ / / /\ \_\  / / /\ \ \           / /\/_// / /\ \_\   / / /\ \ \     / /_ \ \  /_/ /\ \ \
 *      / / /_/ / // / /_/ / / / / /  \ \_\ _       / / /  / /_/_ \/_/  / / /  \ \_\   / / /\ \ \ \ \ \_\ \ \
 *     / / /__\/ // / /__\/ / / / /   / / //\ \    / / /  / /____/\    / / /    \/_/  / / /  \/_/  \ \/__\ \ \
 *    / / /_____// / /_____/ / / /   / / / \ \_\  / / /  / /\____\/   / / /          / / /          \_____\ \ \
 *   / / /      / / /\ \ \  / / /___/ / /  / / /_/ / /  / / /______  / / /________  / / /                  \ \ \
 *  / / /      / / /  \ \ \/ / /____\/ /  / / /__\/ /  / / /_______\/ / /_________\/_/ /                    \ \ \
 *  \/_/       \/_/    \_\/\/_________/   \/_______/   \/__________/\/____________/\_\/                      \_\/
 *
 *  On-chain Project-9 NFT, by SoftWave.
 **/

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ProjectNineData {
    address payable internal deployer;
    address payable public nftContract;

    bool private contractLocked = false;
    uint256 private constant CANVAS_SIZE = 24;
    uint256 private constant PIXEL_DATA_SIZE = CANVAS_SIZE * CANVAS_SIZE * 3;
    uint256 public constant MAX_LIMIT = 2222;
    Coordination public updateCoord;

    struct Trait {
        string traitType;
        string value;
    }

    struct Coordination {
        uint256 startX;
        uint256 startY;
        uint256 width;
        uint256 height;
    }

    struct NineData {
        bytes pixelData;
        Trait[] traits;
        bytes  equippedWeapon;
        uint256 xp;
    }

    mapping(uint256 => NineData) private nineData;

    modifier onlyNFTContract() {
        require(msg.sender == nftContract, "Only NFTContract.");
        _;
    }

    modifier onlyDeployer() {
        require(msg.sender == deployer, "Only deployer.");
        _;
    }

    modifier unlocked() {
        require(!contractLocked, "Contract is locked.");
        _;
    }

    constructor() {
        deployer = payable(msg.sender);
    }

    function setNFTContract(address contractAddress) external onlyDeployer {
        nftContract = payable(contractAddress);
    }

    function setUpdateCoordination(
        uint256 startX,
        uint256 startY,
        uint256 width,
        uint256 height
    ) external onlyDeployer {
        require(startX + width <= CANVAS_SIZE, "Width out of bounds");
        require(startY + height <= CANVAS_SIZE, "Height out of bounds");
        updateCoord = Coordination(startX, startY, width, height);
    }

    function lockContract() external onlyDeployer unlocked {
        contractLocked = true;
    }

    function storePixelData(uint256 tokenId, bytes memory pixelData)
        external
        onlyDeployer
        unlocked
    {
        require(tokenId < MAX_LIMIT, "Invalid tokenId");
        require(
            pixelData.length == PIXEL_DATA_SIZE,
            "Invalid pixel data length"
        );
        nineData[tokenId].pixelData = pixelData;
    }

    function batchStorePixelData(
        uint256[] memory tokenIds,
        bytes[] memory pixelDataArray
    ) external onlyDeployer unlocked {
        require(tokenIds.length == pixelDataArray.length, "Mismatched arrays");
        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            bytes memory pixelData = pixelDataArray[i];
            require(tokenId < MAX_LIMIT, "Invalid tokenId");
            require(
                pixelData.length == PIXEL_DATA_SIZE,
                "Invalid pixel data length"
            );
            nineData[tokenId].pixelData = pixelData;
        }
    }

    function storeTraits(uint256 tokenId, Trait[] memory traits)
        external
        onlyDeployer
        unlocked
    {
        require(traits.length > 0, "Traits cannot be empty");
        delete nineData[tokenId].traits;
        for (uint256 i = 0; i < traits.length; i++) {
            nineData[tokenId].traits.push(traits[i]);
        }
    }

    function batchStoreTraits(
        uint256[] memory tokenIds,
        Trait[][] memory traitsArray
    ) external onlyDeployer unlocked {
        require(tokenIds.length == traitsArray.length, "Mismatched arrays");
        for (uint256 i = 0; i < tokenIds.length; i++) {
            uint256 tokenId = tokenIds[i];
            Trait[] memory traits = traitsArray[i];
            delete nineData[tokenId].traits;
            for (uint256 j = 0; j < traits.length; j++) {
                nineData[tokenId].traits.push(traits[j]);
            }
        }
    }

    function getTraits(uint256 tokenId) external view returns (string memory) {
        require(nineData[tokenId].traits.length > 0, "Traits not set");
        string memory jsonTraits = "[";
        for (uint256 i = 0; i < nineData[tokenId].traits.length; i++) {
            jsonTraits = string.concat(
                jsonTraits,
                '{"trait_type": "',
                nineData[tokenId].traits[i].traitType,
                '", "value": "',
                nineData[tokenId].traits[i].value,
                '"}'
            );
            if (i < nineData[tokenId].traits.length - 1) {
                jsonTraits = string.concat(jsonTraits, ",");
            }
        }
        jsonTraits = string.concat(jsonTraits, "]");
        return jsonTraits;
    }

    function getNineData(uint256 tokenId) external view returns (bytes memory) {
        require(tokenId < MAX_LIMIT, "Invalid tokenId");
        require(
            nineData[tokenId].pixelData.length == PIXEL_DATA_SIZE,
            "Pixel data not set"
        );
        return nineData[tokenId].pixelData;
    }

   function updateWeapon(uint256 tokenId, bytes memory colors) external onlyNFTContract {
    uint256 area = updateCoord.width * updateCoord.height;
    require(colors.length == area * 3, "Colors array length mismatch");

    bytes storage weapon = nineData[tokenId].equippedWeapon;
    require(weapon.length == PIXEL_DATA_SIZE, "Invalid pixel data");

    for (uint256 row = 0; row < updateCoord.height; row++) {
        for (uint256 col = 0; col < updateCoord.width; col++) {
            uint256 x = updateCoord.startX + col;
            uint256 y = updateCoord.startY + row;
            uint256 pixelIndex = (y * 24 + x) * 3;
            uint256 colorIndex = (row * updateCoord.width + col) * 3;

            weapon[pixelIndex] = colors[colorIndex];
            weapon[pixelIndex + 1] = colors[colorIndex + 1];
            weapon[pixelIndex + 2] = colors[colorIndex + 2];
        }
    }

     if(nineData[tokenId].xp < 3)
            nineData[tokenId].xp += 1;
}

    function updateTrait(uint256 tokenId, string memory traitType, string memory value) external onlyNFTContract {
        Trait[] storage traits = nineData[tokenId].traits;
        for (uint256 i = 0; i < traits.length; i++) {
            if (keccak256(bytes(traits[i].traitType)) == keccak256(bytes(traitType))) {
                traits[i].value = value;
                return;
            }
        }
        traits.push(Trait(traitType, value));
    }


    function getEquippedWeapon(uint256 tokenId) external view returns (bytes memory) {
        return nineData[tokenId].equippedWeapon;
    }

    function train(uint256 tokenId) external onlyNFTContract {
        if(nineData[tokenId].xp < 3)
            nineData[tokenId].xp += 1;
    }

    function exercise(uint256 tokenId) external onlyNFTContract {
         if(nineData[tokenId].xp < 3)
            nineData[tokenId].xp += 1;
    }

    function getXP(uint256 tokenId) external view returns (uint256) {
        return nineData[tokenId].xp;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):