Advertisement
Guest User

Untitled

a guest
Aug 17th, 2017
467
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 22.75 KB | None | 0 0
  1. # This filter is for casting Worlds from the raw potential of code
  2. # abrightmoore@yahoo.com.au
  3. # http://brightmoore.net
  4. # My filters may include code and inspiration from PYMCLEVEL/MCEDIT mentors @Texelelf, @Sethbling, @CodeWarrior0, @Podshot_
  5.  
  6. from pymclevel import TAG_String # @Texelelf
  7. from pymclevel import TileEntity # @Texelelf
  8.  
  9. import time # for timing
  10. from math import sqrt, tan, sin, cos, pi, ceil, floor, acos, atan, asin, degrees, radians, log, atan2
  11. from random import *
  12. from numpy import *
  13. from pymclevel import alphaMaterials, MCSchematic, MCLevel, BoundingBox, MCMaterials
  14. from mcplatform import *
  15. from os import listdir
  16. from os.path import isfile, join
  17. import glob
  18. from pymclevel import TAG_List, TAG_Byte, TAG_Int, TAG_Compound, TAG_Short, TAG_Float, TAG_Double, TAG_String, TAG_Long
  19. # import from @Texelelf
  20. from copy import deepcopy
  21. import bresenham # @Codewarrior0
  22. from random import Random # @Codewarrior0
  23. import inspect # @Texelelf
  24. from PIL import Image
  25. import png
  26.  
  27. # GLOBAL
  28. CHUNKSIZE = 16
  29.  
  30. # Filter pseudocode:
  31. #
  32.  
  33. inputs = (
  34. ("World Foundry", "label"),
  35. ("Divisions:", 30),
  36. ("Radius:",50),
  37. ("Wiggle:",6),
  38. ("Operation:", (
  39. "Surface",
  40. "Wireframe"
  41. )),
  42. ("Palette:", ( "Random",
  43. "Stone",
  44. "Earth",
  45. "Lava",
  46. "prismarine",
  47. "ice",
  48. "redstone",
  49. "sand",
  50. "redsand",
  51. "wood",
  52. "metals",
  53. "Custom"
  54. )),
  55. ("Custom Blocks:", ("string","value=95:3 22:0 24:2 19:0 18:0 3:0 1:0 80:0") ),
  56. ("Seed:", 1),
  57. ("Ocean:", False),
  58. ("Core:", False),
  59. ("Clouds:", False),
  60. ("Cloud Material:", alphaMaterials.WhiteWool),
  61. ("Transparency Threshold", 128),
  62. ("Filename:", ("string","value=")),
  63. ("abrightmoore@yahoo.com.au", "label"),
  64. ("http://brightmoore.net", "label"),
  65. )
  66.  
  67. def createSign(level, x, y, z, text): #abrightmoore - convenience method. Due to Jigarbov - this is not a Sign.
  68. ALIASKEY = "WORLD NUMBER"
  69. COMMANDBLOCK = 137
  70. CHUNKSIZE = 16
  71. STANDING_SIGN = 63
  72.  
  73. setBlock(level, (STANDING_SIGN,8), x, y, z)
  74. setBlock(level, (1,0), x, y-1, z)
  75. control = TAG_Compound()
  76. control["id"] = TAG_String("Sign")
  77. control["Text1"] = TAG_String(ALIASKEY)
  78. control["Text2"] = TAG_String(text)
  79. control["Text3"] = TAG_String("Generated by")
  80. control["Text4"] = TAG_String("@abrightmoore")
  81.  
  82. control["x"] = TAG_Int(x)
  83. control["y"] = TAG_Int(y)
  84. control["z"] = TAG_Int(z)
  85. chunka = level.getChunk((int)(x/CHUNKSIZE), (int)(z/CHUNKSIZE))
  86. chunka.TileEntities.append(control)
  87. chunka.dirty = True
  88.  
  89. def worldGeometry(RAND, BASERADIUS, DIVISIONS, WIGGLE):
  90. ANGLEDELTA = 2*pi/(DIVISIONS+1)
  91. OFFSETANGLELAT = pi/DIVISIONS
  92. ANGLEDELTALAT = (pi-OFFSETANGLELAT*2)/DIVISIONS
  93. aWorld = [[BASERADIUS+RAND.randint(-WIGGLE,WIGGLE) for x in range(DIVISIONS)] for x in range(DIVISIONS)]
  94.  
  95. for i in range(RAND.randint(0,DIVISIONS)):
  96. x = RAND.randint(0,DIVISIONS-1)
  97. y = RAND.randint(0,DIVISIONS-1)
  98. w0 = 0
  99. if WIGGLE > 0:
  100. w0 = RAND.randint(1,WIGGLE)
  101. aWorld[x][y] = aWorld[x][y]-w0
  102.  
  103. return aWorld
  104.  
  105. def worldBuilder(level,box,options):
  106. method = "worldBuilder"
  107. (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(level,box,options,method)
  108. print "Seed:"
  109. PARAM = int(options["Seed:"])
  110. if PARAM == 0:
  111. PARAM = randint(0,99999999999)
  112. print PARAM
  113. RAND = Random(PARAM)
  114.  
  115. # MAXWIGGLE = 8
  116.  
  117. R = centreWidth
  118. if centreHeight < R:
  119. R= centreHeight
  120. if centreDepth < R:
  121. R= centreDepth
  122.  
  123.  
  124. DIVISIONS = options["Divisions:"]
  125. if DIVISIONS < 3:
  126. DIVISIONS = RAND.randint(20,60)
  127. BASERADIUS = options["Radius:"] # R-MAXWIGGLE-RAND.randint(0,int(R/3))
  128. if BASERADIUS < 1:
  129. BASERADIUS = R-MAXWIGGLE-RAND.randint(0,int(R/3))
  130. WIGGLE = options["Wiggle:"]
  131. if WIGGLE < 1:
  132. WIGGLE = RAND.randint(2,MAXWIGGLE)
  133. OPERATION = options["Operation:"]
  134.  
  135. if OPERATION == "Wireframe":
  136. materialFill = (0,0) # AIR
  137.  
  138. # A world is a planet spheroid defined by a bunch of altitudes from the centre
  139. aWorld = worldGeometry(RAND, BASERADIUS, DIVISIONS, WIGGLE)
  140.  
  141. # plot the world in the selection box
  142. cx = centreWidth
  143. cy = centreHeight
  144. cz = centreDepth
  145.  
  146. ANGLEDELTA = 2*pi/(DIVISIONS+1)
  147. OFFSETANGLELAT = pi/DIVISIONS
  148. ANGLEDELTALAT = (pi-OFFSETANGLELAT*2)/DIVISIONS
  149. aWorldWiggle = [[RAND.randint(-1,1)*ANGLEDELTALAT/3 for x in range(DIVISIONS)] for x in range(DIVISIONS)]
  150.  
  151. print 'Pallette Selection'
  152. palette = []
  153. palette.append( [ (1,0),(1,1), (1,2), (1,3), (1,4), (1,5), (1,6), (16,0) ] ) # Stone
  154. palette.append( [ (9,0),(9,0), (12,0), (2,0), (18,0), (17,0), (1,0), (13,0) ] ) # Earth
  155. palette.append( [ (11,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # Lava
  156. palette.append( [ (1,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # prismarine
  157. palette.append( [ (2,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # ice
  158. palette.append( [ (3,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # redstone
  159. palette.append( [ (4,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # sand
  160. palette.append( [ (5,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # redsand
  161. palette.append( [ (6,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # wood
  162. palette.append( [ (7,0),(11,0), (87,0), (88,0), (89,0), (153,0), (213,0), (214,0) ] ) # metals
  163. palette.append( [ (49,0),(11,0), (11,0), (11,0), (11,0), (11,0), (11,0), (11,0) ] ) # Lava with Obsidian base
  164. colours = "15 7 8 0 6 2 10 11 3 9 13 5 4 1 14 12".split() # I like this sequence
  165. coloursList = map(int, colours)
  166. coloursListLen = len(coloursList)
  167. RAND2 = Random(42)
  168. # Choose a colour pallette
  169. for i in range(128): # Stained hardened clay variant
  170. gap = RAND2.randint(1,4)
  171. newCols = []
  172. baseIndex = RAND2.randint(0,coloursListLen)
  173. for j in range(8):
  174. newCols.append( (159, (int)(coloursList[(baseIndex+j*gap)%coloursListLen]) ) )
  175. palette.append(newCols)
  176.  
  177. for i in range(8): # Stained glass variants
  178. gap = RAND2.randint(1,4)
  179. newCols = []
  180. baseIndex = RAND2.randint(0,coloursListLen)
  181. for j in range(8):
  182. newCols.append( (95, (int)(coloursList[(baseIndex+j*gap)%coloursListLen]) ) )
  183. palette.append(newCols)
  184.  
  185. for i in range(64): # Wool variants
  186. gap = RAND2.randint(1,4)
  187. newCols = []
  188. baseIndex = RAND2.randint(0,coloursListLen)
  189. for j in range(8):
  190. newCols.append( (35, (int)(coloursList[(baseIndex+j*gap)%coloursListLen]) ) )
  191. palette.append(newCols)
  192. blocks = palette[PARAM%len(palette)]
  193.  
  194. PALETTESELECTED = options["Palette:"]
  195. if PALETTESELECTED == "Stone":
  196. blocks = palette[0]
  197. elif PALETTESELECTED == "Earth":
  198. blocks = palette[1]
  199. elif PALETTESELECTED == "Lava":
  200. blocks = palette[2]
  201. elif PALETTESELECTED == "prismarine":
  202. blocks = palette[3]
  203. elif PALETTESELECTED == "ice":
  204. blocks = palette[4]
  205. elif PALETTESELECTED == "redstone":
  206. blocks = palette[5]
  207. elif PALETTESELECTED == "sand":
  208. blocks = palette[6]
  209. elif PALETTESELECTED == "redsand":
  210. blocks = palette[7]
  211. elif PALETTESELECTED == "wood":
  212. blocks = palette[8]
  213. elif PALETTESELECTED == "metals":
  214. blocks = palette[9]
  215. elif PALETTESELECTED == "Custom":
  216. BLOCKS = options["Custom Blocks:"]
  217. b1 = BLOCKS.split()
  218. plt = []
  219. for i in b1:
  220. bd = i.split(':')
  221. bd1= map(int, bd)
  222. plt.append( (bd1[0],bd1[1]) )
  223.  
  224. if len(plt) >= 8:
  225. blocks = plt
  226. print 'Custom palette blocks loaded.'
  227. else:
  228. print 'Custom palette blocks ignored: it has less than 8 blocks.'
  229.  
  230. print blocks
  231. print 'Pallette Selection complete'
  232.  
  233. print "Forging the planet..."
  234.  
  235. # do the top and bottom bit
  236. NorthPole = BASERADIUS+RAND.randint(-WIGGLE,WIGGLE)
  237. SouthPole = BASERADIUS+RAND.randint(-WIGGLE,WIGGLE)
  238.  
  239. RENDERWORLD = True
  240. if RENDERWORLD == True:
  241. for longitude in xrange(0,DIVISIONS+1): # http://www.bbc.co.uk/staticarchive/e344e73982934a546e4c9909087547478672e9ad.png
  242. if longitude%10 == 0:
  243. print longitude
  244.  
  245. for latitude in xrange(0,DIVISIONS):
  246. longAngle1 = ANGLEDELTA * longitude + aWorldWiggle[longitude%DIVISIONS][(latitude)%DIVISIONS]
  247. latAngle1 = -pi/2+OFFSETANGLELAT+ANGLEDELTALAT * latitude + aWorldWiggle[longitude%DIVISIONS][(latitude)%DIVISIONS]
  248. longAngle2 = ANGLEDELTA * (longitude+1) + aWorldWiggle[(longitude+1)%DIVISIONS][(latitude)]
  249. latAngle2 = -pi/2+OFFSETANGLELAT+ANGLEDELTALAT * (latitude+1) + aWorldWiggle[longitude%DIVISIONS][(latitude+1)%DIVISIONS]
  250.  
  251.  
  252. (x1,z1,y1) = ((aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * cos(longAngle1) * cos(latAngle1) ),
  253. (aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * sin(longAngle1) * cos(latAngle1) ),
  254. (aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * sin(latAngle1) ))
  255. (x2,z2,y2) = ((aWorld[(longitude)%DIVISIONS][(latitude+1)%DIVISIONS] * cos(longAngle1) * cos(latAngle2) ),
  256. (aWorld[(longitude)%DIVISIONS][(latitude+1)%DIVISIONS] * sin(longAngle1) * cos(latAngle2) ),
  257. (aWorld[(longitude)%DIVISIONS][(latitude+1)%DIVISIONS] * sin(latAngle2) ))
  258. (x3,z3,y3) = ((aWorld[(longitude+1)%DIVISIONS][(latitude+1)%DIVISIONS] * cos(longAngle2) * cos(latAngle2) ),
  259. (aWorld[(longitude+1)%DIVISIONS][(latitude+1)%DIVISIONS] * sin(longAngle2) * cos(latAngle2) ),
  260. (aWorld[(longitude+1)%DIVISIONS][(latitude+1)%DIVISIONS] * sin(latAngle2) ))
  261. (x4,z4,y4) = ((aWorld[(longitude+1)%DIVISIONS][(latitude)%DIVISIONS] * cos(longAngle2) * cos(latAngle1) ),
  262. (aWorld[(longitude+1)%DIVISIONS][(latitude)%DIVISIONS] * sin(longAngle2) * cos(latAngle1) ),
  263. (aWorld[(longitude+1)%DIVISIONS][(latitude)%DIVISIONS] * sin(latAngle1) ))
  264. (x0,z0,y0) = ((x1+x2+x3+x4)/4,(z1+z2+z3+z4)/4,(y1+y2+y3+y4)/4)
  265.  
  266. if OPERATION == "Wireframe":
  267. drawTriangleEdge(level, box, options, (cx+x1,cy+y1,cz+z1),(cx+x2,cy+y2,cz+z2),(cx+x0,cy+y0,cz+z0), blocks[PARAM%len(blocks)])
  268. drawTriangleEdge(level, box, options, (cx+x2,cy+y2,cz+z2),(cx+x3,cy+y3,cz+z3),(cx+x0,cy+y0,cz+z0), blocks[PARAM%len(blocks)])
  269. drawTriangleEdge(level, box, options, (cx+x3,cy+y3,cz+z3),(cx+x4,cy+y4,cz+z4),(cx+x0,cy+y0,cz+z0), blocks[PARAM%len(blocks)])
  270. drawTriangleEdge(level, box, options, (cx+x4,cy+y4,cz+z4),(cx+x1,cy+y1,cz+z1),(cx+x0,cy+y0,cz+z0), blocks[PARAM%len(blocks)])
  271.  
  272. else:
  273. drawTriangleColour(level, box, options, (0,0,0), (cx+x1,cy+y1,cz+z1),(cx+x2,cy+y2,cz+z2),(cx+x0,cy+y0,cz+z0), blocks, (cx,cy,cz), BASERADIUS)
  274. drawTriangleColour(level, box, options, (0,0,0), (cx+x2,cy+y2,cz+z2),(cx+x3,cy+y3,cz+z3),(cx+x0,cy+y0,cz+z0), blocks, (cx,cy,cz), BASERADIUS)
  275. drawTriangleColour(level, box, options, (0,0,0), (cx+x3,cy+y3,cz+z3),(cx+x4,cy+y4,cz+z4),(cx+x0,cy+y0,cz+z0), blocks, (cx,cy,cz), BASERADIUS)
  276. drawTriangleColour(level, box, options, (0,0,0), (cx+x4,cy+y4,cz+z4),(cx+x1,cy+y1,cz+z1),(cx+x0,cy+y0,cz+z0), blocks, (cx,cy,cz), BASERADIUS)
  277.  
  278. if latitude == 0: # South pole
  279. latAngle3 = -pi/2
  280. R2 = SouthPole
  281. (x5,z5,y5) = ((R2 * cos(longAngle1) * cos(latAngle3) ),
  282. (R2 * sin(longAngle1) * cos(latAngle3) ),
  283. (R2 * sin(latAngle3) ))
  284. drawTriangleColour(level, box, options, (0,0,0),(cx+x2,cy+y2,cz+z2),(cx+x3,cy+y3,cz+z3),(cx+x5,cy+y5,cz+z5), blocks, (cx,cy,cz), BASERADIUS)
  285.  
  286. if latitude == DIVISIONS-1:
  287. latAngle3 = pi/2
  288. R2 = NorthPole
  289. (x5,z5,y5) = ((R2 * cos(longAngle2) * cos(latAngle3) ),
  290. (R2 * sin(longAngle2) * cos(latAngle3) ),
  291. (R2 * sin(latAngle3) ))
  292. drawTriangleColour(level, box, options, (0,0,0),(cx+x1,cy+y1,cz+z1),(cx+x4,cy+y4,cz+z4),(cx+x5,cy+y5,cz+z5), blocks, (cx,cy,cz), BASERADIUS)
  293.  
  294. if options["Ocean:"] == True:
  295. print "Ocean..."
  296. for y in xrange(0,height):
  297. if y%10 == 0:
  298. print y
  299. for z in xrange(0,depth):
  300. for x in xrange(0,width):
  301. dx = x-cx
  302. dy = y-cy
  303. dz = z-cz
  304. dist = sqrt(dx*dx+dy*dy+dz*dz)
  305. if dist < BASERADIUS and dist >= BASERADIUS-WIGGLE:
  306. block = getBlock(level,x,y,z)
  307. if block == (0,0): # AIR
  308. setBlock(level,blocks[0],x,y,z)
  309.  
  310. if options["Core:"] == True:
  311. print "Core..."
  312. for y in xrange(0,height):
  313. if y%10 == 0:
  314. print y
  315. for z in xrange(0,depth):
  316. for x in xrange(0,width):
  317. dx = x-cx
  318. dy = y-cy
  319. dz = z-cz
  320. dist = sqrt(dx*dx+dy*dy+dz*dz)
  321. if dist <= BASERADIUS-WIGGLE:
  322. block = getBlock(level,x,y,z)
  323. if block == (0,0): # AIR
  324. if RAND.randint(0,100) < 10:
  325. setBlock(level,blocks[RAND.randint(0,len(blocks)-1)],x,y,z)
  326. else:
  327. setBlock(level,blocks[int(dist)%len(blocks)],x,y,z)
  328.  
  329. if options["Clouds:"] == True:
  330. print "Clouds..."
  331. tempDiv = DIVISIONS
  332. tempWorld = aWorld
  333.  
  334. TRANSPARENCY_T = options["Transparency Threshold"]
  335. CLOUDMATERIALID = options["Cloud Material:"].ID
  336. filenameTop = options["Filename:"]
  337. filenameTop = filenameTop.strip()
  338. if filenameTop == "":
  339. filenameTop = askOpenFile("Select a Cloud image...", False)
  340. f = open(filenameTop, "rb")
  341. data = f.read()
  342. f.close()
  343. reader = png.Reader(bytes=data) # @Sethbling
  344. (w, h, pixels1, metadata) = reader.asRGBA8() # @Sethbling
  345. pixels = list(pixels1) # @Sethbling
  346.  
  347. DIVISIONS = w
  348. aWorld = worldGeometry(RAND, BASERADIUS+9, DIVISIONS, 0)
  349. ANGLEDELTA = 2*pi/(DIVISIONS+1)
  350. OFFSETANGLELAT = pi/DIVISIONS
  351. ANGLEDELTALAT = (pi-OFFSETANGLELAT*2)/DIVISIONS
  352. aWorldWiggle = [[RAND.randint(-1,1)*ANGLEDELTALAT/3 for x in range(DIVISIONS)] for x in range(DIVISIONS)]
  353. cloudLayer = [[(0.1,0.1,0.1) for x in range(DIVISIONS)] for x in range(DIVISIONS)]
  354.  
  355. p = 0
  356. q = 0
  357. (px,py,pz) = (0,0,0) # Init
  358. for longitude in xrange(0,DIVISIONS):
  359. if longitude%100 == 0:
  360. print longitude
  361. for latitude in xrange(0,DIVISIONS):
  362. longAngle1 = ANGLEDELTA * longitude + aWorldWiggle[longitude%DIVISIONS][(latitude)%DIVISIONS]
  363. latAngle1 = -pi/2+OFFSETANGLELAT+ANGLEDELTALAT * latitude + aWorldWiggle[longitude%DIVISIONS][(latitude)%DIVISIONS]
  364.  
  365. (x1,z1,y1) = ((aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * cos(longAngle1) * cos(latAngle1) ),
  366. (aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * sin(longAngle1) * cos(latAngle1) ),
  367. (aWorld[(longitude)%DIVISIONS][(latitude)%DIVISIONS] * sin(latAngle1) ))
  368. cloudLayer[longitude][latitude] = (cx+x1,cy+y1,cz+z1)
  369.  
  370. colour = getPixel(pixels, longitude%h, latitude%w) # after @Sethbling
  371. if opaque(colour, TRANSPARENCY_T): # @Sethbling
  372. (theBlock, theBlockData) = closestMaterial(colour) # @Sethbling
  373. (r,g,b,a) = colour
  374. (x_,y_,z_) = cloudLayer[int(longitude)%DIVISIONS][int(latitude)%DIVISIONS]
  375. setBlock(level, (CLOUDMATERIALID,theBlockData), x_,y_,z_ )
  376.  
  377.  
  378. # Cloud swirly shapes- \\\insert sekrit text here
  379. # p = 0
  380. # q = 0
  381. # (px,py,pz) = (0,0,0) # Init
  382. # for i in xrange(0,1000):
  383. # p = 4*DIVISIONS * sin(i*pi/180)
  384. # q = 5*DIVISIONS * cos(i*pi/180)
  385.  
  386. # (px,py,pz) = cloudLayer[int(p)%DIVISIONS][int(q)%DIVISIONS]
  387. # if i > 0:
  388. # c = 0
  389. # for qx, qy, qz in bresenham.bresenham((int(p),0,int(q)),(int(r),0,int(s))):
  390. # if c > 0:
  391. # drawLine(level, blocks[len(blocks)-1], cloudLayer[int(qx)%DIVISIONS][int(qz)%DIVISIONS], cloudLayer[int(px1)%DIVISIONS][int(pz1)%DIVISIONS])
  392. # (px1,py1,pz1) = (qx,qy,qz)
  393. # c = c+1
  394.  
  395. # (r,s) = (p,q)
  396.  
  397. # c = 0
  398. # for qx, qy, qz in bresenham.bresenham((int(DIVISIONS/2),0,int(DIVISIONS/2)),(int(DIVISIONS/2),0,int(0))):
  399. # if c > 0:
  400. # drawLine(level, blocks[len(blocks)-4], cloudLayer[int(qx)][int(qz)], cloudLayer[int(px1)][int(pz1)])
  401. # (px1,py1,pz1) = (qx,qy,qz)
  402. # c = c+1
  403.  
  404. DIVISIONS = tempDiv
  405. aWorld = tempWorld
  406.  
  407. createSign(level, cx, cy, cz, str(PARAM))
  408.  
  409. FuncEnd(level,box,options,method)
  410.  
  411. def getPixel(pixels, x, y): # @Sethbling
  412. idx = x*4
  413. return (pixels[y][idx], pixels[y][idx+1], pixels[y][idx+2], pixels[y][idx+3])
  414.  
  415. def transparent((r, g, b, a)):
  416. return a < 128
  417.  
  418. def opaque((r, g, b, a), threshold):
  419. return a >= threshold
  420.  
  421. def closestMaterial((r, g, b, a)): # @Sethbling
  422. closest = 255*255*3
  423. best = (35, 0)
  424. for (mat, dat, mr, mg, mb) in materials:
  425. (dr, dg, db) = (r-mr, g-mg, b-mb)
  426. dist = dr*dr+dg*dg+db*db
  427. if dist < closest:
  428. closest = dist
  429. best = (mat, dat)
  430. return best
  431.  
  432. # Map fragment originally by @Sethbling - this needs some work to decouple the colour from the intensity.
  433. materials = [
  434. (35, 0, 221, 221, 221),
  435. (35, 1, 219, 125, 62),
  436. (35, 2, 179, 80, 188),
  437. (35, 3, 107, 138, 201),
  438. (35, 4, 177, 166, 39),
  439. (35, 5, 65, 174, 56),
  440. (35, 6, 208, 132, 153),
  441. (35, 7, 64, 64, 64),
  442. (35, 8, 154, 161, 161),
  443. (35, 9, 46, 110, 137),
  444. (35, 10, 126, 61, 181),
  445. (35, 11, 46, 56, 141),
  446. (35, 12, 79, 50, 31),
  447. (35, 13, 53, 70, 27),
  448. (35, 14, 150, 52, 48),
  449. (35, 15, 25, 22, 22),
  450. ]
  451.  
  452. def drawTriangleColour(level, box, options, (ox, oy, oz), (p1x, p1y, p1z), (p2x, p2y, p2z), (p3x, p3y, p3z), blocks, centre, radius):
  453. # for each step along the 'base' draw a line from the apex
  454. dx = p3x - p2x
  455. dy = p3y - p2y
  456. dz = p3z - p2z
  457.  
  458. distHoriz = dx*dx + dz*dz
  459. distance = sqrt(dy*dy + distHoriz)
  460.  
  461. phi = atan2(dy, sqrt(distHoriz))
  462. theta = atan2(dz, dx)
  463.  
  464. iter = 0
  465. while iter <= distance:
  466. (px, py, pz) = ((int)(p2x+iter*cos(theta)*cos(phi)), (int)(p2y+iter*sin(phi)), (int)(p2z+iter*sin(theta)*cos(phi)))
  467. iter = iter+0.5 # slightly oversample because I lack faith.
  468. drawLineColour(level, (ox+px, oy+py, oz+pz), (ox+p1x, oy+p1y, oz+p1z), blocks, centre, radius )
  469.  
  470. def drawTriangleEdge(level, box, options, (p1x, p1y, p1z), (p2x, p2y, p2z), (p3x, p3y, p3z), materialEdge):
  471. drawLine(level, materialEdge, (p1x, p1y, p1z), (p2x, p2y, p2z) )
  472. drawLine(level, materialEdge, (p1x, p1y, p1z), (p3x, p3y, p3z) )
  473. drawLine(level, materialEdge, (p2x, p2y, p2z), (p3x, p3y, p3z) )
  474.  
  475. def perform(originalLevel,originalBox, options):
  476. ''' Feedback to abrightmoore@yahoo.com.au '''
  477. # Local variables
  478. method = "Perform"
  479. (method, (width, height, depth), (centreWidth, centreHeight, centreDepth)) = FuncStart(originalLevel,originalBox,options,method) # Log start
  480. SUCCESS = True
  481. level = originalLevel.extractSchematic(originalBox) # Working set
  482. box = BoundingBox((0,0,0),(width,height,depth))
  483. # Operations go here - switch to the function based on selected operation
  484. worldBuilder(level, box, options)
  485.  
  486. # Conditionally copy back the working area into the world
  487. if SUCCESS == True: # Copy from work area back into the world
  488. b=range(4096); b.remove(0) # @CodeWarrior0 and @Wout12345 explained how to merge schematics
  489. originalLevel.copyBlocksFrom(level, box, (originalBox.minx, originalBox.miny, originalBox.minz ),b)
  490. originalLevel.markDirtyBox(originalBox)
  491.  
  492. FuncEnd(originalLevel,box,options,method) # Log end
  493.  
  494.  
  495.  
  496. ####################################### CLASSES
  497.  
  498.  
  499.  
  500.  
  501. ####################################### LIBS
  502.  
  503. def FuncStart(level, box, options, method):
  504. # abrightmoore -> shim to prepare a function.
  505. print '%s: Started at %s' % (method, time.ctime())
  506. (width, height, depth) = (box.maxx - box.minx, box.maxy - box.miny, box.maxz - box.minz)
  507. centreWidth = math.floor(width / 2)
  508. centreHeight = math.floor(height / 2)
  509. centreDepth = math.floor(depth / 2)
  510. # other initialisation methods go here
  511. return (method, (width, height, depth), (centreWidth, centreHeight, centreDepth))
  512.  
  513. def FuncEnd(level, box, options, method):
  514. print '%s: Ended at %s' % (method, time.ctime())
  515.  
  516. def getBoxSize(box):
  517. return (box.maxx - box.minx, box.maxy - box.miny, box.maxz - box.minz)
  518.  
  519. def getBlock(level,x,y,z):
  520. return (level.blockAt(x,y,z), level.blockDataAt(x,y,z))
  521.  
  522. def setBlock(level, (block, data), x, y, z):
  523. level.setBlockAt(int(x), int(y), int(z), block)
  524. level.setBlockDataAt(int(x), int(y), int(z), data)
  525.  
  526. # Ye Olde GFX Libraries
  527. def drawLine(scratchpad, (blockID, blockData), (x,y,z), (x1,y1,z1) ):
  528. drawLineConstrained(scratchpad, (blockID, blockData), (x,y,z), (x1,y1,z1), 0 )
  529.  
  530. def drawLineColour(scratchpad, (x,y,z), (x1,y1,z1), blocks, centre, radius ):
  531. drawLineConstrainedColour(scratchpad, (x,y,z), (x1,y1,z1), 0, blocks, centre, radius )
  532.  
  533. def drawLineBresenham(scratchpad, (blockID, blockData), (x,y,z), (x1,y1,z1) ):
  534. for px, py, pz in bresenham.bresenham((x,y,z),(x1,y1,z1)):
  535. setBlock(scratchpad,(blockID, blockData),px,py,pz)
  536. setBlock(scratchpad,(blockID, blockData),x1,y1,z1)
  537.  
  538. def drawLineConstrainedColour(level, (x,y,z), (x1,y1,z1), maxLength, blocks, (cx,cy,cz), BASERADIUS ):
  539. dx = x1 - x
  540. dy = y1 - y
  541. dz = z1 - z
  542.  
  543. distHoriz = dx*dx + dz*dz
  544. distance = sqrt(dy*dy + distHoriz)
  545.  
  546. if distance < maxLength or maxLength < 1:
  547. phi = atan2(dy, sqrt(distHoriz))
  548. theta = atan2(dz, dx)
  549. px = 0
  550. py = 0
  551. pz = 0
  552. ddx = 0
  553. ddy = 0
  554. ddz = 0
  555.  
  556. iter = 0
  557. while iter <= distance:
  558. ix = (int)(x+iter*cos(theta)*cos(phi))
  559. iy = (int)(y+iter*sin(phi))
  560. iz = (int)(z+iter*sin(theta)*cos(phi))
  561.  
  562. ddx = ix-cx
  563. ddy = iy-cy
  564. ddz = iz-cz
  565.  
  566. dist = sqrt(ddx*ddx+ddy*ddy+ddz*ddz)
  567. if dist < BASERADIUS-1:
  568. setBlock(level,blocks[0],ix,iy,iz) # Sea
  569. elif dist < BASERADIUS:
  570. setBlock(level,blocks[1],ix,iy,iz) # Lapis
  571. elif dist < BASERADIUS+1:
  572. setBlock(level,blocks[2],ix,iy,iz) # Sand
  573. elif dist < BASERADIUS+2:
  574. setBlock(level,blocks[3],ix,iy,iz) # Plain
  575. elif dist < BASERADIUS+3:
  576. setBlock(level,blocks[4],ix,iy,iz) # Forest
  577. elif dist < BASERADIUS+4:
  578. setBlock(level,blocks[5],ix,iy,iz) # Mt
  579. elif dist < BASERADIUS+5:
  580. setBlock(level,blocks[6],ix,iy,iz) # Snow
  581. elif dist >= BASERADIUS+5:
  582. setBlock(level,blocks[7],ix,iy,iz) # Snow
  583. iter = iter+0.5 # slightly oversample because I lack faith.
  584.  
  585. def drawLineConstrained(scratchpad, (blockID, blockData), (x,y,z), (x1,y1,z1), maxLength ):
  586. dx = x1 - x
  587. dy = y1 - y
  588. dz = z1 - z
  589.  
  590. distHoriz = dx*dx + dz*dz
  591. distance = sqrt(dy*dy + distHoriz)
  592.  
  593. if distance < maxLength or maxLength < 1:
  594. phi = atan2(dy, sqrt(distHoriz))
  595. theta = atan2(dz, dx)
  596.  
  597. iter = 0
  598. while iter <= distance:
  599. scratchpad.setBlockAt((int)(x+iter*cos(theta)*cos(phi)), (int)(y+iter*sin(phi)), (int)(z+iter*sin(theta)*cos(phi)), blockID)
  600. scratchpad.setBlockDataAt((int)(x+iter*cos(theta)*cos(phi)), (int)(y+iter*sin(phi)), (int)(z+iter*sin(theta)*cos(phi)), blockData)
  601. iter = iter+0.5 # slightly oversample because I lack faith.
  602.  
  603.  
  604. def drawLineConstrainedRandom(scratchpad, (blockID, blockData), (x,y,z), (x1,y1,z1), frequency ):
  605. dx = x1 - x
  606. dy = y1 - y
  607. dz = z1 - z
  608.  
  609. distHoriz = dx*dx + dz*dz
  610. distance = sqrt(dy*dy + distHoriz)
  611.  
  612.  
  613. phi = atan2(dy, sqrt(distHoriz))
  614. theta = atan2(dz, dx)
  615.  
  616. iter = 0
  617. while iter <= distance:
  618. if randint(0,99) < frequency:
  619. scratchpad.setBlockAt((int)(x+iter*cos(theta)*cos(phi)), (int)(y+iter*sin(phi)), (int)(z+iter*sin(theta)*cos(phi)), blockID)
  620. scratchpad.setBlockDataAt((int)(x+iter*cos(theta)*cos(phi)), (int)(y+iter*sin(phi)), (int)(z+iter*sin(theta)*cos(phi)), blockData)
  621. iter = iter+0.5 # slightly oversample because I lack faith.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement