-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathload.py
177 lines (158 loc) · 4.48 KB
/
load.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
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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import mcpi.minecraft as minecraft
import mcpi.block as block
import mcpi.vec3 as vec3
import sys
import nbt.nbt as nbt
import cStringIO
import binascii
# Block ids that I want to place after all the
# static blocks are in place.
dynamicBlocks = set([
8, #flowing_water
9, #water
10, #flowing_lava
12, #sand
25, #noteblock
27, #golder_rail
28, #detector_rail
29, #sticky_piston
33, #piston
34, #piston_head
36, #piston_extension
50, #torch
41, #fire
55, #redstone_wire
62, #standing_sign
64, #wooden_door
65, #ladder
66, #rail
68, #wall_sign
69, #lever
70, #stone_pressure_plate
71, #iron_door
72, #wooden_pressure_plate
75, #unlit_redstone_torch
76, #redstone_torch
77, #stone_button
93, #unpowered_repeater
94, #powered_repeater
96, #trapdoor
101, #iron_bars
107, #fence_gate
131, #tripwire_hook
132, #tripwire
143, #wooden_button
147, #light_weighted_pressure_plate
148, #heavy_weighted_pressure_plate
149, #unpowered_comparator
150, #powered_comparator
152, #redstone_block
157, #activator_rail
171 #carpet
])
def nbt2hex(item):
file = nbt.NBTFile()
file.name = 'data'
file.tags = item.tags
out = cStringIO.StringIO()
file.write_file(fileobj=out)
return binascii.b2a_hex(bytearray(out.getvalue()))
class Optimizer():
def __init__(self, mc):
self.mc = mc
self.sx = None
self.sy = None
self.sz = None
self.obid = None
self.odatum = None
self.ex = None
self.state = False
def push(self, nx, ny, nz, nbid, ndatum):
if nbid != self.obid or ny != self.sy or nz != self.sz \
or ndatum != self.odatum:
self.flush()
self.sx = nx
self.sy = ny
self.sz = nz
self.obid = nbid
self.odatum = ndatum
self.state = True
# Always set end-x to cur value.
self.ex = nx
def flush(self):
if self.state:
self.mc.setBlocks(self.sx,self.sy,self.sz,self.ex,self.sy,self.sz,
self.obid,self.odatum,2)
self.sx = None
self.sy = None
self.sz = None
self.obid = None
self.odatum = None
self.ex = None
self.state = False
mc = minecraft.Minecraft.create()
if len(sys.argv) != 2:
mc.postToChat('Usage: /py load <schematic>')
exit(0)
nbtfile = nbt.NBTFile(sys.argv[1], 'rb')
w = nbtfile['Width'].value
h = nbtfile['Height'].value
l = nbtfile['Length'].value
tileentities = nbtfile['TileEntities']
blocks = nbtfile['Blocks'].value
data = nbtfile['Data'].value
if len(blocks) != w*h*l:
print "Not matching."
exit(0)
pos = mc.player.getTilePos()
px = pos.x + 1
pz = pos.z + 1
py = mc.getHeight(px, pz)
mc.postToChat('Need to build ' + str(l) + ' levels');
mc.setBlocks(px, py, pz, px+w, py+h, pz+l, block.AIR.id)
opt = Optimizer(mc)
for y in range(0, h):
mc.postToChat('Level '+str(y))
for z in range(0, l):
for x in range(0, w):
idx = (y*l + z)*w +x
blockid = blocks[idx]
if (blockid == 0):
opt.flush()
continue
if (blockid in dynamicBlocks): # skip these the first time.
opt.flush()
continue
datum = data[idx]
#mc.setBlock(px+x,py+y,pz+z,blockid,datum)
opt.push(px+x,py+y,pz+z,blockid,datum)
for y in range(0, h):
mc.postToChat('Level '+str(y))
for z in range(0, l):
for x in range(0, w):
idx = (y*l + z)*w +x
blockid = blocks[idx]
if (blockid == 0):
opt.flush()
continue
if (not (blockid in dynamicBlocks)):
opt.flush()
continue
idx = (y*l + z)*w +x
datum = data[idx]
#mc.setBlock(px+x,py+y,pz+z,blockid,datum)
opt.push(px+x,py+y,pz+z,blockid,datum)
opt.flush()
ntileentities = len(tileentities)
if ntileentities > 0:
mc.postToChat('Updating '+str(ntileentities)+' blocks')
for tileentity in tileentities:
nx = px + tileentity['x'].value
ny = py + tileentity['y'].value
nz = pz + tileentity['z'].value
tileentity['x'].value = nx
tileentity['y'].value = ny
tileentity['z'].value = nz
hex = nbt2hex(tileentity)
mc.conn.send('world.setTileEntityHex', nx, ny, nz, hex)
mc.postToChat('All done')