1# This file allows you to programmatically create blocks in Craft. 2# Please use this wisely. Test on your own server first. Do not abuse it. 3 4import requests 5import socket 6import sqlite3 7import sys 8 9DEFAULT_HOST = '127.0.0.1' 10DEFAULT_PORT = 4080 11 12EMPTY = 0 13GRASS = 1 14SAND = 2 15STONE = 3 16BRICK = 4 17WOOD = 5 18CEMENT = 6 19DIRT = 7 20PLANK = 8 21SNOW = 9 22GLASS = 10 23COBBLE = 11 24LIGHT_STONE = 12 25DARK_STONE = 13 26CHEST = 14 27LEAVES = 15 28CLOUD = 16 29TALL_GRASS = 17 30YELLOW_FLOWER = 18 31RED_FLOWER = 19 32PURPLE_FLOWER = 20 33SUN_FLOWER = 21 34WHITE_FLOWER = 22 35BLUE_FLOWER = 23 36 37OFFSETS = [ 38 (-0.5, -0.5, -0.5), 39 (-0.5, -0.5, 0.5), 40 (-0.5, 0.5, -0.5), 41 (-0.5, 0.5, 0.5), 42 (0.5, -0.5, -0.5), 43 (0.5, -0.5, 0.5), 44 (0.5, 0.5, -0.5), 45 (0.5, 0.5, 0.5), 46] 47 48def sphere(cx, cy, cz, r, fill=False, fx=False, fy=False, fz=False): 49 result = set() 50 for x in range(cx - r, cx + r + 1): 51 if fx and x != cx: 52 continue 53 for y in range(cy - r, cy + r + 1): 54 # if y < cy: 55 # continue # top hemisphere only 56 if fy and y != cy: 57 continue 58 for z in range(cz - r, cz + r + 1): 59 if fz and z != cz: 60 continue 61 inside = False 62 outside = fill 63 for dx, dy, dz in OFFSETS: 64 ox, oy, oz = x + dx, y + dy, z + dz 65 d2 = (ox - cx) ** 2 + (oy - cy) ** 2 + (oz - cz) ** 2 66 d = d2 ** 0.5 67 if d < r: 68 inside = True 69 else: 70 outside = True 71 if inside and outside: 72 result.add((x, y, z)) 73 return result 74 75def circle_x(x, y, z, r, fill=False): 76 return sphere(x, y, z, r, fill, fx=True) 77 78def circle_y(x, y, z, r, fill=False): 79 return sphere(x, y, z, r, fill, fy=True) 80 81def circle_z(x, y, z, r, fill=False): 82 return sphere(x, y, z, r, fill, fz=True) 83 84def cylinder_x(x1, x2, y, z, r, fill=False): 85 x1, x2 = sorted((x1, x2)) 86 result = set() 87 for x in range(x1, x2 + 1): 88 result |= circle_x(x, y, z, r, fill) 89 return result 90 91def cylinder_y(x, y1, y2, z, r, fill=False): 92 y1, y2 = sorted((y1, y2)) 93 result = set() 94 for y in range(y1, y2 + 1): 95 result |= circle_y(x, y, z, r, fill) 96 return result 97 98def cylinder_z(x, y, z1, z2, r, fill=False): 99 z1, z2 = sorted((z1, z2)) 100 result = set() 101 for z in range(z1, z2 + 1): 102 result |= circle_z(x, y, z, r, fill) 103 return result 104 105def cuboid(x1, x2, y1, y2, z1, z2, fill=True): 106 x1, x2 = sorted((x1, x2)) 107 y1, y2 = sorted((y1, y2)) 108 z1, z2 = sorted((z1, z2)) 109 result = set() 110 a = (x1 == x2) + (y1 == y2) + (z1 == z2) 111 for x in range(x1, x2 + 1): 112 for y in range(y1, y2 + 1): 113 for z in range(z1, z2 + 1): 114 n = 0 115 n += x in (x1, x2) 116 n += y in (y1, y2) 117 n += z in (z1, z2) 118 if not fill and n <= a: 119 continue 120 result.add((x, y, z)) 121 return result 122 123def pyramid(x1, x2, y, z1, z2, fill=False): 124 x1, x2 = sorted((x1, x2)) 125 z1, z2 = sorted((z1, z2)) 126 result = set() 127 while x2 >= x1 and z2 >= z2: 128 result |= cuboid(x1, x2, y, y, z1, z2, fill) 129 y, x1, x2, z1, z2 = y + 1, x1 + 1, x2 - 1, z1 + 1, z2 - 1 130 return result 131 132def get_identity(): 133 query = ( 134 'select username, token from identity_token where selected = 1;' 135 ) 136 conn = sqlite3.connect('auth.db') 137 rows = conn.execute(query) 138 for row in rows: 139 return row 140 raise Exception('No identities found.') 141 142class Client(object): 143 def __init__(self, host, port): 144 self.conn = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 145 self.conn.connect((host, port)) 146 self.authenticate() 147 def authenticate(self): 148 username, identity_token = get_identity() 149 url = 'https://craft.michaelfogleman.com/api/1/identity' 150 payload = { 151 'username': username, 152 'identity_token': identity_token, 153 } 154 response = requests.post(url, data=payload) 155 if response.status_code == 200 and response.text.isalnum(): 156 access_token = response.text 157 self.conn.sendall('A,%s,%s\n' % (username, access_token)) 158 else: 159 raise Exception('Failed to authenticate.') 160 def set_block(self, x, y, z, w): 161 self.conn.sendall('B,%d,%d,%d,%d\n' % (x, y, z, w)) 162 def set_blocks(self, blocks, w): 163 key = lambda block: (block[1], block[0], block[2]) 164 for x, y, z in sorted(blocks, key=key): 165 self.set_block(x, y, z, w) 166 def bitmap(self, sx, sy, sz, d1, d2, data, lookup): 167 x, y, z = sx, sy, sz 168 dx1, dy1, dz1 = d1 169 dx2, dy2, dz2 = d2 170 for row in data: 171 x = sx if dx1 else x 172 y = sy if dy1 else y 173 z = sz if dz1 else z 174 for c in row: 175 w = lookup.get(c) 176 if w is not None: 177 self.set_block(x, y, z, w) 178 x, y, z = x + dx1, y + dy1, z + dz1 179 x, y, z = x + dx2, y + dy2, z + dz2 180 181def get_client(): 182 default_args = [DEFAULT_HOST, DEFAULT_PORT] 183 args = sys.argv[1:] + [None] * len(default_args) 184 host, port = [a or b for a, b in zip(args, default_args)] 185 client = Client(host, int(port)) 186 return client 187 188def main(): 189 client = get_client() 190 set_block = client.set_block 191 set_blocks = client.set_blocks 192 # set_blocks(circle_y(0, 32, 0, 16, True), STONE) 193 # set_blocks(circle_y(0, 33, 0, 16), BRICK) 194 # set_blocks(cuboid(-1, 1, 1, 31, -1, 1), CEMENT) 195 # set_blocks(cuboid(-1024, 1024, 32, 32, -3, 3), STONE) 196 # set_blocks(cuboid(-3, 3, 32, 32, -1024, 1024), STONE) 197 # set_blocks(cuboid(-1024, 1024, 33, 33, -3, -3), BRICK) 198 # set_blocks(cuboid(-1024, 1024, 33, 33, 3, 3), BRICK) 199 # set_blocks(cuboid(-3, -3, 33, 33, -1024, 1024), BRICK) 200 # set_blocks(cuboid(3, 3, 33, 33, -1024, 1024), BRICK) 201 # set_blocks(sphere(0, 32, 0, 16), GLASS) 202 # for y in range(1, 32): 203 # set_blocks(circle_y(0, y, 0, 4, True), CEMENT) 204 # set_blocks(circle_x(16, 33, 0, 3), BRICK) 205 # set_blocks(circle_x(-16, 33, 0, 3), BRICK) 206 # set_blocks(circle_z(0, 33, 16, 3), BRICK) 207 # set_blocks(circle_z(0, 33, -16, 3), BRICK) 208 # for x in range(0, 1024, 32): 209 # set_blocks(cuboid(x - 1, x + 1, 31, 32, -1, 1), CEMENT) 210 # set_blocks(cuboid(-x - 1, -x + 1, 31, 32, -1, 1), CEMENT) 211 # set_blocks(cuboid(x, x, 1, 32, -1, 1), CEMENT) 212 # set_blocks(cuboid(-x, -x, 1, 32, -1, 1), CEMENT) 213 # for z in range(0, 1024, 32): 214 # set_blocks(cuboid(-1, 1, 31, 32, z - 1, z + 1), CEMENT) 215 # set_blocks(cuboid(-1, 1, 31, 32, -z - 1, -z + 1), CEMENT) 216 # set_blocks(cuboid(-1, 1, 1, 32, z, z), CEMENT) 217 # set_blocks(cuboid(-1, 1, 1, 32, -z, -z), CEMENT) 218 # for x in range(0, 1024, 8): 219 # set_block(x, 32, 0, CEMENT) 220 # set_block(-x, 32, 0, CEMENT) 221 # for z in range(0, 1024, 8): 222 # set_block(0, 32, z, CEMENT) 223 # set_block(0, 32, -z, CEMENT) 224 # set_blocks(pyramid(32, 32+64-1, 12, 32, 32+64-1), COBBLE) 225 # outer = circle_y(0, 11, 0, 176 + 3, True) 226 # inner = circle_y(0, 11, 0, 176 - 3, True) 227 # set_blocks(outer - inner, STONE) 228 # a = sphere(-32, 48, -32, 24, True) 229 # b = sphere(-24, 40, -24, 24, True) 230 # set_blocks(a - b, PLANK) 231 # set_blocks(cylinder_x(-64, 64, 32, 0, 8), STONE) 232 # data = [ 233 # '...............................', 234 # '..xxx..xxxx...xxx..xxxxx.xxxxx.', 235 # '.x...x.x...x.x...x.x.......x...', 236 # '.x.....xxxx..xxxxx.xxx.....x...', 237 # '.x...x.x..x..x...x.x.......x...', 238 # '..xxx..x...x.x...x.x.......x...', 239 # '...............................', 240 # ] 241 # lookup = { 242 # 'x': STONE, 243 # '.': PLANK, 244 # } 245 # client.bitmap(0, 32, 32, (1, 0, 0), (0, -1, 0), data, lookup) 246 247if __name__ == '__main__': 248 main() 249