Skip to content

Commit

Permalink
Update:新增loot合约与user合约,并自动部署
Browse files Browse the repository at this point in the history
  • Loading branch information
LidamaoHub committed Oct 28, 2023
1 parent 8145a1d commit ba29bcd
Show file tree
Hide file tree
Showing 8 changed files with 825 additions and 5 deletions.
10 changes: 7 additions & 3 deletions packages/contracts/script/GlobalConfigInit.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@ import {GlobalConfig} from "../src/codegen/Tables.sol";
import { GLOBAL_CONFIG_KEY } from "../src/Constants.sol";

library GlobalConfigInit {
function initGlobalConfig(IWorld _world) internal {
address userContract = 0x5FbDB2315678afecb367f032d93F642f64180aa3;
function initGlobalConfig(IWorld _world,address _userContract,address _lootContract) internal {
GlobalConfig.setUserContract(
_world,
GLOBAL_CONFIG_KEY, //key
userContract
_userContract
);
GlobalConfig.setLootContract(
_world,
GLOBAL_CONFIG_KEY, //key
_lootContract
);
}
}
6 changes: 5 additions & 1 deletion packages/contracts/script/PostDeploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import { GameConfigInit } from "./GameConfigInit.sol";
import { BattleConfigInit } from "./BattleConfigInit.sol";
import { GlobalConfigInit } from "./GlobalConfigInit.sol";
import { console } from "forge-std/console.sol";
import "../src/other/User.sol";
import "../src/other/Loot.sol";

contract PostDeploy is Script {
function run(address worldAddress) external {
Expand All @@ -18,11 +20,13 @@ contract PostDeploy is Script {
vm.startBroadcast(deployerPrivateKey);

console.log(" ========== PostDeploy ========== ");
MUser muser = new MUser(2, "MUser", "MUser", "", "");
MLoot mloot = new MLoot("", "MLOOT", "MLOOT", "", 2);

// ------------------ INIT ------------------
GameConfigInit.initGameConfig(IWorld(worldAddress));
BattleConfigInit.initBattleConfig(IWorld(worldAddress));
GlobalConfigInit.initGlobalConfig(IWorld(worldAddress));
GlobalConfigInit.initGlobalConfig(IWorld(worldAddress), address(muser),address(mloot));

vm.stopBroadcast();

Expand Down
62 changes: 62 additions & 0 deletions packages/contracts/src/other/Base64.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
/// [MIT License]
/// @title Base64
/// @notice Provides a function for encoding some bytes in base64
/// @author Brecht Devos <[email protected]>
library Base64 {
bytes internal constant TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

/// @notice Encodes some bytes to the base64 representation
function encode(bytes memory data) internal pure returns (string memory) {
uint256 len = data.length;
if (len == 0) return "";

// multiply by 4/3 rounded up
uint256 encodedLen = 4 * ((len + 2) / 3);

// Add some extra buffer at the end
bytes memory result = new bytes(encodedLen + 32);

bytes memory table = TABLE;

assembly {
let tablePtr := add(table, 1)
let resultPtr := add(result, 32)

for {
let i := 0
} lt(i, len) {

} {
i := add(i, 3)
let input := and(mload(add(data, i)), 0xffffff)

let out := mload(add(tablePtr, and(shr(18, input), 0x3F)))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(12, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(shr(6, input), 0x3F))), 0xFF))
out := shl(8, out)
out := add(out, and(mload(add(tablePtr, and(input, 0x3F))), 0xFF))
out := shl(224, out)

mstore(resultPtr, out)

resultPtr := add(resultPtr, 4)
}

switch mod(len, 3)
case 1 {
mstore(sub(resultPtr, 2), shl(240, 0x3d3d))
}
case 2 {
mstore(sub(resultPtr, 1), shl(248, 0x3d))
}

mstore(result, encodedLen)
}

return string(result);
}
}
253 changes: 253 additions & 0 deletions packages/contracts/src/other/Loot.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,253 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import "./LootSuit.sol";
import "./Base64.sol";
import './MRandom.sol';
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

contract MLoot is Suit, ERC721,MRandom {
using Strings for uint256;

constructor(
string memory _desc,
string memory symbol,
string memory name,
string memory _notRevealedInfo,
uint256 _waitBlockCount
) ERC721(symbol, name) {
desc = _desc;
owner = msg.sender;
waitBlockCount = _waitBlockCount;
notRevealedInfo = _notRevealedInfo;
}





struct Loot {
uint256 randomId;
address owner;
string Weapon;
string Chest;
string Head;
string Waist;
string Foot;
string Hand;
string Neck;
string Ring;
RandomState state;
}

uint256 public tokenId;
uint256 public waitBlockCount;


address owner;
string desc;
string notRevealedInfo;

mapping(uint256 => Loot) public lootList;

modifier onlyOwner() {
require(msg.sender == owner);
_;
}


function tokenURI(
uint256 _tokenId
) public view override returns (string memory) {
string[17] memory parts;
Loot memory loot = lootList[_tokenId];
if(loot.state == RandomState.Pending){
string memory r = string(
abi.encodePacked(
"data:application/json;base64,",
notRevealedInfo
)
);
return r;
}
require(loot.state != RandomState.Inited, "Box not existed");

parts[
0
] = '<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMinYMin meet" viewBox="0 0 350 350"><style>.base { fill: white; font-family: serif; font-size: 14px; }</style><rect width="100%" height="100%" fill="black" /><text x="10" y="20" class="base">';

parts[1] = loot.Weapon;

parts[2] = '</text><text x="10" y="40" class="base">';

parts[3] = loot.Chest;

parts[4] = '</text><text x="10" y="60" class="base">';

parts[5] = loot.Head;

parts[6] = '</text><text x="10" y="80" class="base">';

parts[7] = loot.Waist;

parts[8] = '</text><text x="10" y="100" class="base">';

parts[9] = loot.Foot;

parts[10] = '</text><text x="10" y="120" class="base">';

parts[11] = loot.Hand;

parts[12] = '</text><text x="10" y="140" class="base">';

parts[13] = loot.Neck;

parts[14] = '</text><text x="10" y="160" class="base">';

parts[15] = loot.Ring;

parts[16] = "</text></svg>";

string memory output = string(
abi.encodePacked(
parts[0],
parts[1],
parts[2],
parts[3],
parts[4],
parts[5],
parts[6],
parts[7],
parts[8]
)
);
output = string(
abi.encodePacked(
output,
parts[9],
parts[10],
parts[11],
parts[12],
parts[13],
parts[14],
parts[15],
parts[16]
)
);

string memory json = Base64.encode(
bytes(
string(
abi.encodePacked(
'{"name": "MLoot #',
_tokenId.toString(),
'", "description":"',
desc,
'","image": "data:image/svg+xml;base64,',
Base64.encode(bytes(output)),
'"}'
)
)
)
);
output = string(
abi.encodePacked("data:application/json;base64,", json)
);

return output;
}

function luck(
uint8 rand,
string[] memory sourceArray
) internal view returns (string memory) {
string memory output = sourceArray[rand % sourceArray.length];

uint256 greatness = rand % 21;
if (greatness > 14) {
output = string(
abi.encodePacked(output, " ", suffixes[rand % suffixes.length])
);
}
if (greatness >= 19) {
string[2] memory name;
name[0] = namePrefixes[rand % namePrefixes.length];
name[1] = nameSuffixes[rand % nameSuffixes.length];
if (greatness == 19) {
output = string(
abi.encodePacked('"', name[0], " ", name[1], '" ', output)
);
} else {
output = string(
abi.encodePacked(
'"',
name[0],
" ",
name[1],
'" ',
output,
" +1"
)
);
}
}
return output;
}

function revealNFT(uint256 _tokenId) external {
Loot storage loot = lootList[_tokenId];
require(loot.owner == msg.sender, "only owner can reveal the box");
uint8[] memory random_numbers = getRandom(loot.randomId, 8,waitBlockCount);
loot.Weapon = luck(random_numbers[0], weapons);
loot.Chest = luck(random_numbers[1], chestArmor);
loot.Head = luck(random_numbers[2], headArmor);
loot.Waist = luck(random_numbers[3], waistArmor);
loot.Foot = luck(random_numbers[4], footArmor);
loot.Hand = luck(random_numbers[5], handArmor);
loot.Neck = luck(random_numbers[6], necklaces);
loot.Ring = luck(random_numbers[7], rings);
loot.state = RandomState.Confirmed;
}

function mint() external {
// init loot box
Loot storage loot = lootList[tokenId];
loot.owner = msg.sender;
loot.state = RandomState.Pending;
loot.randomId = randomId;
requestRandom(randomId);
_mint(msg.sender, tokenId);
tokenId++;
randomId++;
}




function withdraw(address to) public onlyOwner {
uint256 balance = address(this).balance;
require(balance > 0, "sufficient funds");
payable(to).transfer(balance);
}

function withdrawErc20(
address _targetAddress,
address _contractAddress,
uint256 _amount
) external onlyOwner {
IERC20(_contractAddress).transfer(_targetAddress, _amount);
}
function getStructInfo(uint256 _tokenId) external view returns(string memory,string memory,string memory,string memory,string memory,string memory,string memory,string memory){
Loot memory loot = lootList[_tokenId];
require(loot.state == RandomState.Confirmed,"User not exists");
return(loot.Weapon,
loot.Chest,
loot.Head,
loot.Waist,
loot.Foot,
loot.Hand,
loot.Neck,
loot.Ring);
}
}
Loading

0 comments on commit ba29bcd

Please sign in to comment.