Skip to content

Commit

Permalink
buy me a ceptor world adaptation
Browse files Browse the repository at this point in the history
  • Loading branch information
tippi-fifestarr committed May 14, 2024
1 parent 34b754c commit aa89bab
Show file tree
Hide file tree
Showing 11 changed files with 2,065 additions and 196 deletions.
137 changes: 137 additions & 0 deletions packages/hardhat/contracts/BuyMeACeptor.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;

/**
* @title World
* @dev World struct
*/
struct World {
string vibe;
string gameMasterName;
string gameMasterTwitterHandle;
string description;
uint256 time;
address gameMasterAddress;
}

/**
* @title BuyMeACeptorWorld
* @dev BuyMeACeptorWorld contract to accept donations and for our users to create a world for us
*/
contract BuyMeACeptor{
address payable public owner;
uint256 public price;
World[] public worlds;

error InsufficientFunds();
error InvalidArguments(string message);
error OnlyOwner();

event BuyMeACeptorWorldEvent(address indexed buyer, uint256 price);
event NewWorld(address indexed gameMasterAddress, uint256 time, string vibe, string gameMasterName, string gameMasterTwitterHandle, string description);

constructor() {
owner = payable(msg.sender);
price = 0.0001 ether;
}

/**
* WRITE FUNCTIONS *************
*/

/**
* @dev Function to buy a world
* @param gameMasterName The name of the game master
* @param gameMasterTwitterHandle The Twitter handle of the game master
* @param description The description of the world
* (Note: Using calldata for gas efficiency)
*/
function buyWorld(string calldata vibe, string calldata gameMasterName, string calldata gameMasterTwitterHandle, string calldata description) public payable {
if (msg.value < price) {
revert InsufficientFunds();
}

emit BuyMeACeptorWorldEvent(msg.sender, msg.value);

if (bytes(gameMasterName).length == 0 && bytes(description).length == 0) {
revert InvalidArguments("Invalid gameMasterName or description");
}

worlds.push(World(vibe, gameMasterName, gameMasterTwitterHandle, description, block.timestamp, msg.sender));

emit NewWorld(msg.sender, block.timestamp, vibe, gameMasterName, gameMasterTwitterHandle, description);
}

/**
* @dev Function to remove a world
* @param index The index of the world
*/
function removeWorld(uint256 index) public {
if (index >= worlds.length) {
revert InvalidArguments("Invalid index");
}

World memory world = worlds[index];

// if operation isnt sent from the same game master or the owner, then not allowed
if (world.gameMasterAddress != msg.sender && msg.sender != owner) {
revert InvalidArguments("Operation not allowed");
}

World memory indexWorld = worlds[index];
worlds[index] = worlds[worlds.length - 1];
worlds[worlds.length - 1] = indexWorld;
worlds.pop();
}

/**
* @dev Function to modify a world description
* @param index The index of the world
* @param description The description of the world
*/
function modifyWorldDescription(uint256 index, string memory description) public {
if (index >= worlds.length) {
revert InvalidArguments("Invalid index");
}

World memory world = worlds[index];

if (world.gameMasterAddress != msg.sender || msg.sender != owner) {
revert InvalidArguments("Operation not allowed");
}

worlds[index].description = description;
}

/**
* @dev Function to withdraw the balance
*/
function withdrawTips() public {
if (msg.sender != owner) {
revert OnlyOwner();
}

if (address(this).balance == 0) {
revert InsufficientFunds();
}

(bool sent,) = owner.call{value: address(this).balance}("");
require(sent, "Failed to send Ether");
}

/**
* READ FUNCTIONS *************
*/

/**
* @dev Function to get the worlds
*/
function getWorlds() public view returns (World[] memory) {
return worlds;
}

/**
* @dev Recieve function to accept ether
*/
receive() external payable {}
}
156 changes: 0 additions & 156 deletions packages/hardhat/contracts/BuyMeACoffee.sol

This file was deleted.

90 changes: 90 additions & 0 deletions packages/hardhat/contracts/CeptorCS.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";

contract CeptorCharacterSheets is ERC721URIStorage, VRFConsumerBaseV2, Ownable {
struct Stats {
uint8 strength;
uint8 dexterity;
uint8 constitution;
uint8 intelligence;
uint8 wisdom;
uint8 charisma;
uint8 luck;
}

struct Character {
Stats stats;
string name;
uint swapsLeft;
}

mapping(address => uint256) public ownerToTokenId;
mapping(uint256 => Character) public tokenIdToCharacter;

uint256 public tokenIdCounter;
bytes32 public keyHash;
uint256 public fee;
uint64 public subscriptionId;

event CharacterCreated(uint256 indexed tokenId, address owner);
event StatsSwapped(uint256 indexed tokenId, address owner);

constructor(
address vrfCoordinator,
address linkToken,
bytes32 _keyHash,
uint64 _subscriptionId
)
VRFConsumerBaseV2(vrfCoordinator)
ERC721("CeptorCharacterSheets", "CCS")
{
keyHash = _keyHash;
fee = 0.1 * 10**18; // Chainlink VRF fee
subscriptionId = _subscriptionId;
tokenIdCounter = 1;
}

function createCharacter(string memory name) external {
require(ownerToTokenId[msg.sender] == 0, "Owner already has a character");
uint256 tokenId = tokenIdCounter++;
ownerToTokenId[msg.sender] = tokenId;
tokenIdToCharacter[tokenId] = Character({
name: name,
stats: Stats(0, 0, 0, 0, 0, 0, 0),
swapsLeft: 3
});
_safeMint(msg.sender, tokenId);
emit CharacterCreated(tokenId, msg.sender);
requestStats(tokenId);
}

function requestStats(uint256 tokenId) internal {
require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK");
requestRandomWords(keyHash, subscriptionId, 3, fee, 1);
}

function fulfillRandomWords(uint256, uint256[] memory randomWords) internal override {
uint256 tokenId = ownerToTokenId[msg.sender];
Character storage character = tokenIdToCharacter[tokenId];
character.stats.strength = uint8(randomWords[0] % 16 + 3);
character.stats.dexterity = uint8(randomWords[1] % 16 + 3);
character.stats.constitution = uint8(randomWords[2] % 16 + 3);
character.stats.intelligence = uint8(randomWords[3] % 16 + 3);
character.stats.wisdom = uint8(randomWords[4] % 16 + 3);
character.stats.charisma = uint8(randomWords[5] % 16 + 3);
character.stats.luck = uint8(randomWords[6] % 16 + 3);
}

function swapStats(uint256 tokenId) external {
require(ownerOf(tokenId) == msg.sender, "Not the owner");
Character storage character = tokenIdToCharacter[tokenId];
require(character.swapsLeft > 0, "No swaps left");
character.swapsLeft--;
requestStats(tokenId);
emit StatsSwapped(tokenId, msg.sender);
}
}
Loading

0 comments on commit aa89bab

Please sign in to comment.