|
#! python version 2.7 |
|
import os |
|
import json |
|
import re |
|
|
|
# The MCEdit 1.0 filter name |
|
displayName = "JER export" |
|
|
|
# filter settings |
|
inputs = ( |
|
# file where worldgen.json should be saved |
|
("Worldgen File", ("file-save", ["*.json"])), |
|
# if drops from an already existing worldgen.json should be preserved |
|
("Keep Drops", True), |
|
# minimum fraction of blocks that has to be found to show up |
|
("Threshold", 0.0001), |
|
# txt file containing a blacklist of blocks that should be ignored |
|
("Resource Blacklist", "file-open"), |
|
# tick if the txt file should be a whitelist instead |
|
("is Whitelist", False), |
|
) |
|
|
|
# dict for mapping from numeric blockids to strings |
|
blockids = {} |
|
|
|
# list containing all blacklisted blocks |
|
blacklist = [] |
|
|
|
# converts the block with the given numeric id and meta to a blockstring |
|
def toBlockString(id, meta): |
|
return blockids[id] + ":" + str(meta); |
|
|
|
# retrieves the blockstring in the given level at the specified coordinates |
|
def blockAt(level, x, y, z): |
|
return toBlockString(level.blockAt(x, y, z), level.blockDataAt(x, y, z)); |
|
|
|
def isBlacklisted(block, isWhitelist): |
|
for s in blacklist: |
|
if block.startswith(s): |
|
return not isWhitelist |
|
return isWhitelist |
|
|
|
# run the filter |
|
def perform(level, box, options): |
|
|
|
# read moedded blockids from level.dat |
|
print("Reading blockids from level.dat...") |
|
for comp in level.root_tag["FML"]["Registries"]["minecraft:blocks"]["ids"]: |
|
key = comp["K"].value |
|
value = comp["V"].value |
|
blockids[value] = key |
|
print(str(len(blockids)) + " blocks found!") |
|
|
|
#Worldgen file |
|
file = options["Worldgen File"] |
|
|
|
# dictionary containing all drops, key is block id, value is a dict |
|
drops = {} |
|
|
|
#dictionary containing all blocks found at certain levels |
|
results = {} |
|
|
|
# load old drops if desired |
|
if options["Keep Drops"]: |
|
if file == None: |
|
raise Exception("Worldgen File not specified") |
|
if os.path.exists(file): |
|
print("Loading old drops") |
|
with open(file) as f: |
|
wg = json.load(f) |
|
for entry in wg: |
|
block = entry["block"] |
|
if "dropsList" in entry: |
|
val = { |
|
"silktouch": entry["silktouch"], |
|
"dropsList": entry["dropsList"] |
|
} |
|
else: |
|
val = { |
|
"silktouch": entry["silktouch"] if "silktouch" in entry else False, |
|
} |
|
drops[block] = val |
|
else: |
|
print("Worldgen File does not exist so drops couldn't be kept") |
|
|
|
#load blacklist |
|
blcklstFile = options["Resource Blacklist"] |
|
if blcklstFile != None: |
|
if not os.path.exists(blcklstFile): |
|
raise Exception("File does not exist: " + blcklstFile) |
|
with open(blcklstFile) as f: |
|
#FIXME for some strange reason blacklist does not work properly |
|
# let's ignore this for now as blacklist is not really needed |
|
blacklist = f.readlines() |
|
|
|
|
|
# count occurrences of blocks, layer by layer |
|
print("Profiling blocks:") |
|
totalblocks = 0.0 |
|
for y in xrange(box.miny, box.maxy): |
|
print(" y=" + str(y) + " (" + str(round((y-box.miny) * 100 / (box.maxy-box.miny), 1)) + "%)") |
|
layerblocks = 0.0 |
|
for x in xrange(box.minx, box.maxx): |
|
for z in xrange(box.minz, box.maxz): |
|
block = blockAt(level, x, y, z) |
|
if block != "minecraft:air:0": |
|
if isBlacklisted(block, options["is Whitelist"]): |
|
#skip blacklisted blocks |
|
continue |
|
layerblocks += 1.0 |
|
if block not in results: |
|
results[block] = {} |
|
if y in results[block]: |
|
results[block][y] += 1.0; |
|
else: |
|
results[block][y] = 1.0; |
|
totalblocks = layerblocks if layerblocks > totalblocks else totalblocks |
|
print("Done!") |
|
|
|
# generate the output dict |
|
print("Generating JSON") |
|
out = [] |
|
for block, spread in results.iteritems(): |
|
distribution = "" |
|
prev = float("nan") |
|
prevY = -1 |
|
for y in xrange(box.miny, box.maxy): |
|
count = spread[y] if y in spread else 0.0 |
|
val = count / totalblocks |
|
val = val if val >= options["Threshold"] else 0.0; |
|
if prev != val: |
|
if prevY != y - 1: |
|
distribution += str(y - 1) + "," + str(prev) + ";" |
|
distribution += str(y) + "," + str(val) + ";" |
|
prev = val |
|
prevY = y |
|
if block in drops: |
|
if "dropsList" in drops[block]: |
|
entry = { |
|
"block": block, |
|
"distrib": distribution, |
|
"silktouch": drops[block]["silktouch"], |
|
"dropsList": drops[block]["dropsList"], |
|
"dim": "Dim 0: overworld", |
|
} |
|
else: |
|
entry = { |
|
"block": block, |
|
"distrib": distribution, |
|
"silktouch": drops[block]["silktouch"], |
|
"dim": "Dim 0: overworld", |
|
} |
|
else: |
|
entry = { |
|
"block": block, |
|
"distrib": distribution, |
|
"silktouch": False, |
|
"dim": "Dim 0: overworld", |
|
} |
|
out.append(entry) |
|
|
|
print("Writing JSON to " + file) |
|
with open(file, 'w') as fp: |
|
json.dump(out, fp, indent = 4, sort_keys = True) |
|
print("Complete!") |