-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathOreReduce.py
More file actions
155 lines (136 loc) · 5.5 KB
/
Copy pathOreReduce.py
File metadata and controls
155 lines (136 loc) · 5.5 KB
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
# Version 2
"""This takes a MineCraft level and changes the amount of materials present.
It is designed to shrink the amount of ore underground, but you can use it for
replacing any block type with any other block type.
"""
# The following is an interface class for .mclevel data for minecraft savefiles.
import mcInterface
from random import random
# Here are the variables you can edit.
# This is the name of the map to edit.
# Make a backup if you are experimenting!
LOADNAME = "TestB"
# the search will be around the player
# How large an area do you want to search?
# size is in chunks:
# 0 is just the chunk that the player is in
# 1 is the player's chunk + and - 1 chunk (so 9 total)
# 2 is 25 chunks centered on the player, etc
SEARCHSIZE = 1
# What block types do you want to affect, and by how much?
# This is a tuple or list of block types
# Default: mcInterface.blocktype_extractable
# which is all the ores
ALTER = mcInterface.blocktype_extractable
# What fraction of blocks do you want to replace?
# 1 will replace everything
# 0.5 will replace half
# Default: 0.4
FRACTION = 0.4
# What block type is the environment of the altered blocks?
# If an increase is indicated, only these types of blocks will be replaced
# if a decrease is indicated, these blocks will replace them.
# Default: mcInterface.blocktype_stones
# the script will attempt to use existing block types where they are already present
ENVIRONMENT = mcInterface.blocktype_stones
##############################################################
# Don't edit below here unless you know what you are doing #
##############################################################
# input filtering
if SEARCHSIZE < 0:
print("SEARCHSIZE was less than zero, setting to 0 and continuing on")
SEARCHSIZE = 0
if len(ALTER) < 1:
print("There is nothing in ALTER, aborting!")
raise IOError("ALTER empty, not looking for anything")
if FRACTION <= 0:
print("Please replace at least something!")
raise IOError("FRACTION zero or less, not replacing anything")
if FRACTION > 1:
print("FRACTION greater than 1, setting to 1 and continuing on")
FRACTION = 1
# Now, on to the actual code.
def get_chunks(the_map):
all_chunks = []
px,py,pz = the_map.get_player_block()
locations = [(px,pz),]
if SEARCHSIZE > 0:
for i in range(SEARCHSIZE+1):
xoff = i * 16
for j in range(SEARCHSIZE+1):
zoff = j * 16
if xoff == zoff == 0:
continue
locations += [(px+xoff,pz+zoff),]
if xoff > 0:
locations += [(px - xoff, pz + zoff), ]
if zoff > 0:
locations += [(px + xoff, pz - zoff), ]
if xoff > 0 and zoff > 0:
locations += [(px - xoff, pz - zoff), ]
for x,z in locations:
possible_chunk = the_map.get_chunk_from_cord(x,z)
if possible_chunk is None: continue
all_chunks.append(possible_chunk)
return all_chunks
def replace_section_materials(section, find, replace, fraction = 1):
if 'block_states' not in section: return
block_states = section['block_states'].payload
palette = block_states['palette'].payload
if 'data' in block_states:
data = block_states['data']
else:
data = mcInterface.SaveFile.new_block_data()
block_states['data'] = data
# and unpack the block states if necessary
if not hasattr(data, "unpacked"):
mcInterface.SaveFile.unpack_block_states(data, palette)
#search the pallete for the find values and make a list of indicies
# search the pallete for the replace values, use the first one found
find_indicies = []
replaceidx = -1
for i in range(len(palette)):
block_name = palette[i].payload["Name"].payload.replace("minecraft:",'')
if block_name in find:
find_indicies.append(i)
if replaceidx == -1 and block_name in replace:
replaceidx = i
# abort if there is nothing to find and replace
if len(find_indicies) == 0: return
if replaceidx == -1:
# if no replacement material is found, add a new pallete entry
mcInterface.SaveFile.add_block_data(mcInterface.SaveFile,palette, {'B':'minecraft:'+replace[0]})
replaceidx = len(palette) - 1
if fraction == 1:
# if fraction is 1, do a pallete swap
newpalletdata = palette[replaceidx]
for i in find_indicies:
palette[i] = newpalletdata
else:
# list comprehension find and replace and clobber the section block list
data.unpacked = [replaceidx if (idx in find_indicies and random() < fraction)
else idx for idx in data.unpacked]
def replace_chunk_materials(chunk, find, replace, fraction):
sections = chunk.tags[0].payload['sections'].payload
for section in sections:
replace_section_materials(section.payload, find, replace, fraction)
def main():
"""Load the file, do the stuff, and save the new file.
"""
print("Importing the map")
try:
the_map = mcInterface.SaveFile(LOADNAME)
except IOError:
print('File name invalid or save file otherwise corrupted. Aborting')
return None
print("Finding the chunks")
all_chunks = get_chunks(the_map)
print("Replacing the materials")
for c in all_chunks:
replace_chunk_materials(c, ALTER, ENVIRONMENT, FRACTION)
# print("Saving the map (takes a bit)")
the_map.write()
print("finished")
return None
if __name__ == '__main__':
main()