-
Notifications
You must be signed in to change notification settings - Fork 1
/
Map.sol
185 lines (165 loc) · 5.33 KB
/
Map.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
// import "solmate/tokens/ERC721.sol";
import "openzeppelin/token/ERC721/ERC721.sol";
// import "solmate/tokens/ERC1155.sol";
import "openzeppelin/token/ERC1155/IERC1155.sol";
import "solmate/utils/LibString.sol";
// import "solmate/auth/Owned.sol";
import {ERC1155TokenReceiver} from "solmate/tokens/ERC1155.sol";
import "openzeppelin/metatx/ERC2771Context.sol";
error ZeroSize();
error ZeroPerSize();
error SizeNotDivisibleByPerSize();
error InvalidXIndex();
error InvalidYIndex();
error LandAlreadyOwned();
error NotOwner();
error InvalidLength();
contract Map is ERC2771Context, ERC721 {
// // rectangular land with coordinates of corners as (x,y), (x,y+perSize), (x+perSize,y), (x+perSize,y+perSize)
struct Land {
uint256 xIndex;
uint256 yIndex;
}
uint256 public size;
uint256 public perSize;
uint256 public landCount;
string public baseUri;
uint256 public utilCount;
address public utilsAddress;
// x/perSize,y/perSize to LandId
// [ (x/perSize,y/perSize) to LandId ] of rectangular land with coordinates of corners as (x,y), (x,y+perSize), (x+perSize,y), (x+perSize,y+perSize)
mapping(uint256 => mapping(uint256 => uint256)) public landIds;
// mapping of LandId to Land (xIndex, yIndex)
mapping(uint256 => Land) public land;
// x,y to utilId
mapping(uint256 => mapping(uint256 => uint256)) public map;
constructor(
uint256 _size,
uint256 _perSize,
string memory _baseUri,
address _utilsAddress,
address trustedForwarder
) ERC2771Context(trustedForwarder) ERC721("Map", "MAP") {
if (_size == 0) revert ZeroSize();
if (_perSize == 0) revert ZeroPerSize();
size = _size;
perSize = _perSize;
if (_size % perSize != 0) revert SizeNotDivisibleByPerSize();
baseUri = _baseUri;
utilsAddress = _utilsAddress;
}
function mint(uint256 xIndex, uint256 yIndex) public returns (uint256) {
if (xIndex >= size / perSize) revert InvalidXIndex();
if (yIndex >= size / perSize) revert InvalidYIndex();
if (landIds[xIndex][yIndex] != 0) revert LandAlreadyOwned();
landCount += 1;
// land[id] = Land(x, y);
landIds[xIndex][yIndex] = landCount;
land[landCount] = Land(xIndex, yIndex);
_mint(_msgSender(), landCount);
return landCount;
}
function placeItem(uint256 x, uint256 y, uint256 utilId) public {
if (_msgSender() != ownerOf(landIds[x / perSize][y / perSize]))
revert NotOwner();
IERC1155 utils = IERC1155(utilsAddress);
if (map[x][y] != 0) {
utils.safeTransferFrom(
address(this),
_msgSender(),
map[x][y],
1,
""
);
}
utils.safeTransferFrom(_msgSender(), address(this), utilId, 1, "");
map[x][y] = utilId;
}
function removeItem(uint256 x, uint256 y) public {
if (_msgSender() != ownerOf(landIds[x / perSize][y / perSize]))
revert NotOwner();
IERC1155 utils = IERC1155(utilsAddress);
if (map[x][y] != 0) {
utils.safeTransferFrom(
address(this),
_msgSender(),
map[x][y],
1,
""
);
}
map[x][y] = 0;
}
function updateItem(uint256 x, uint256 y, uint256 utilId) public {
if (utilId == 0) {
removeItem(x, y);
} else {
placeItem(x, y, utilId);
}
}
function placeItems(
uint256[] memory x,
uint256[] memory y,
uint256[] memory utilId
) public {
if (x.length != y.length) revert InvalidLength();
if (x.length != utilId.length) revert InvalidLength();
for (uint256 i = 0; i < x.length; i++) {
placeItem(x[i], y[i], utilId[i]);
}
}
function updateItems(
uint256[] memory x,
uint256[] memory y,
uint256[] memory utilId
) public {
if (x.length != y.length) revert InvalidLength();
if (x.length != utilId.length) revert InvalidLength();
for (uint256 i = 0; i < x.length; i++) {
updateItem(x[i], y[i], utilId[i]);
}
}
function tokenURI(
uint256 id
) public view virtual override returns (string memory) {
return string.concat(baseUri, LibString.toString(id));
}
function onERC1155Received(
address,
address,
uint256,
uint256,
bytes memory
) public virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155Received.selector;
}
function onERC1155BatchReceived(
address,
address,
uint256[] memory,
uint256[] memory,
bytes memory
) public virtual returns (bytes4) {
return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
}
function _msgSender()
internal
view
virtual
override(Context, ERC2771Context)
returns (address sender)
{
return ERC2771Context._msgSender();
}
function _msgData()
internal
view
virtual
override(Context, ERC2771Context)
returns (bytes calldata)
{
return ERC2771Context._msgData();
}
}