forked from SethBling/SetBiome
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathImageToBiome.py
116 lines (97 loc) · 4.91 KB
/
ImageToBiome.py
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
# WizardCM's Image to Biome Map Filter
# Heavily based on SethBling's beautifully simple SetBiome filter
from pymclevel import MCSchematic
from pymclevel import TAG_Compound
from pymclevel import TAG_Short
from pymclevel import TAG_Byte
from pymclevel import TAG_Byte_Array
from pymclevel import TAG_String
from numpy import zeros
from PIL import Image
import json
import time
from datetime import datetime
from pprint import pprint
displayName = "Image to Biome Map"
timeFormat = "[%H:%M:%S]"
# input = image filename (relative path probably best)
inputs = (
("Created by WizardCM, based on SethBling's SetBiome", "label"),
("Full Image Path", ("string", "value=C:/image.png")),
("Full Colour Mappings Path", ("string", "value=C:/mappings.json")),
("If your client freezes, the script is running perfectly fine. The larger your world/image, the longer it takes. Check MCEdit's console for progress if you're worried.", "label"),
)
def perform(level, box, options):
imageFile = options["Full Image Path"]
colorMapFile = options["Full Colour Mappings Path"]
image = Image.open(imageFile)
with open(colorMapFile) as data_file:
colorMap = json.load(data_file)
# We need the Minecraft coords of the top left corner of the selection to determine
# the offset so we can safely determine the coordinates of the image's top left corner
minx = int(box.minx / 16) * 16
minz = int(box.minz / 16) * 16
# compare the width and height of the image to the selection
# warn and confirm with the user that it's fine if they don't match
# displaying the values would be helpful
selectionWidth = box.maxx - box.minx
selectionHeight = box.maxz - box.minz
totalBlocks = selectionWidth * selectionHeight
currentPercent = 0
currentBlocks = 0
imageWidth,imageHeight = image.size
print('=====================================')
print('= Starting Image to Biome filter... =');
print('=====================================')
startTime = time.strftime(timeFormat);
if selectionWidth == imageWidth and selectionHeight == imageHeight:
print('Image and selection size match! Starting..');
# loop through the x axis of the user's selection (of chunks?)
for x in xrange(minx, box.maxx, 16):
# loop through the z axis of the user's selection (of chunks?)
for z in xrange(minz, box.maxz, 16):
# get the top corner coords of the chunk, or the chunk id
chunk = level.getChunk(x / 16, z / 16)
# mark the chunk as 'modified'
chunk.dirty = True
# get the current biome IDs of the chunk (I think)
# this is probably so if a biome of a column/block within a chunk
# does not get replaced, the original data is kept
array = chunk.root_tag["Level"]["Biomes"].value
# store the chunk's coordinates, again why / then *
chunkx = int(x / 16) * 16
chunkz = int(z / 16) * 16
# loop through the x axis of the selected blocks within the chunk
for bx in xrange(max(box.minx, chunkx), min(box.maxx, chunkx + 16)):
xcoord = minx;
# loop through z axis of selected blocks within chunk
for bz in xrange(max(box.minz, chunkz), min(box.maxz, chunkz + 16)):
# get the ID of the column/block within the chunk (I think)
idx = 16 * (bz - chunkz) + (bx - chunkx)
# set the biome of the column/block to the biome in the image
progress = int(100 * float(currentBlocks + 1)/float(totalBlocks))
# originally we were going to show a progress bar IN MCEdit - turns out just rendering it slows down this task
if progress > currentPercent:
currentTime = time.strftime(timeFormat);
print(currentTime + " Completed " + str(progress) + '%')
if progress%10 == 0:
timeDifference = datetime.strptime(currentTime, timeFormat) - datetime.strptime(startTime, timeFormat)
print (" Time Elapsed: " + str(timeDifference))
currentPercent = progress
currentBlocks = currentBlocks + 1
loc = str(image.getpixel((bx - minx, bz - minz))).strip('()')
if loc.count(',') == 3:
loc = loc[:-5]
try:
array[idx] = colorMap[loc]
except KeyError, e:
raise Exception("The colour rgb" + str(e) + " at " + str(1+bx-minx) + "," + str(1+bz-minz) + " (image coordinates) doesn't exist. Please update your mappings.json or change the colour of the pixel.")
# save the biome data in the array to the chunk itself
chunk.root_tag["Level"]["Biomes"].value = array
elif selectionWidth > imageWidth or selectionHeight > imageHeight:
raise Exception("Image size (" + str(imageWidth) + "x" + str(imageHeight) + ") is smaller than the selection (" + str(selectionWidth) + "x" + str(selectionHeight) + "). Please make your selection smaller or make your image larger.")
return None
else:
# TODO Show a dialog asking if we should continue anyway.
raise Exception("Image size (" + str(imageWidth) + "x" + str(imageHeight) + ") & selection size (" + str(selectionWidth) + "x" + str(selectionHeight) + ") don't match. ")
return None