def __init__(self, cmd="", hover="", block="I", d="u", cond=False, redstone=False, time=0, first=False): name = "minecraft:" + self.nameMap[block] dv = self.dMap[d] if cond: dv += 8 nbtData = nbt.TAG_Compound("", []) nbtData.add(nbt.TAG_Byte("auto", int(not redstone))) nbtData.add(nbt.TAG_String("Command", cmd)) nbtData.add(nbt.TAG_String("CustomName", hover)) nbtData.add(nbt.TAG_Byte("powered", int(block == "R" and not redstone))) if time == 0 and not first: nbtData.add(nbt.TAG_Int("Version", 8)) else: nbtData.add(nbt.TAG_Int("Version", 9)) nbtData.add(nbt.TAG_Byte("ExecuteOnFirstTick", int(first))) nbtData.add(nbt.TAG_Int("TickDelay", time)) nbtData.add(nbt.TAG_Byte("conditionMet", 0)) nbtData.add(nbt.TAG_String("id", "CommandBlock")) nbtData.add(nbt.TAG_Byte("isMovable", 1)) nbtData.add(nbt.TAG_Int("LPCommandMode", 0)) # Not sure what these LPModes do. This works. nbtData.add(nbt.TAG_Byte("LPConditionalMode", 0)) nbtData.add(nbt.TAG_Byte("LPRedstoneMode", 0)) nbtData.add(nbt.TAG_Long("LastExecution", 0)) nbtData.add(nbt.TAG_String("LastOutput", "")) nbtData.add(nbt.TAG_List("LastOutputParams", [])) nbtData.add(nbt.TAG_Int("SuccessCount", 0)) nbtData.add(nbt.TAG_Byte("TrackOutput", 1)) super().__init__(name, dv, nbtData)
def copyWithOffset(cls, entity, copyOffset, regenerateUUID=False): eTag = deepcopy(entity) # Need to check the content of the copy to regenerate the possible sub entities UUIDs. # A simple fix for the 1.9+ minecarts is proposed. positionTags = map(lambda p, co: nbt.TAG_Double(p.value + co), eTag["Pos"], copyOffset) eTag["Pos"] = nbt.TAG_List(positionTags) # Also match the 'minecraft:XXX' names # if eTag["id"].value in ("Painting", "ItemFrame", u'minecraft:painting', u'minecraft:item_frame'): # print "#" * 40 # print eTag # eTag["TileX"].value += copyOffset[0] # eTag["TileY"].value += copyOffset[1] # eTag["TileZ"].value += copyOffset[2] # Trying more agnostic way if eTag.get('TileX') and eTag.get('TileY') and eTag.get('TileZ'): eTag["TileX"].value += copyOffset[0] eTag["TileY"].value += copyOffset[1] eTag["TileZ"].value += copyOffset[2] if "Riding" in eTag: eTag["Riding"] = Entity.copyWithOffset(eTag["Riding"], copyOffset) # # Fix for 1.9+ minecarts if "Passengers" in eTag: passengers = nbt.TAG_List() for passenger in eTag["Passengers"]: passengers.append( Entity.copyWithOffset(passenger, copyOffset, regenerateUUID)) eTag["Passengers"] = passengers # # if regenerateUUID: # Courtesy of SethBling eTag["UUIDMost"] = nbt.TAG_Long((random.getrandbits(47) << 16) | (1 << 12) | random.getrandbits(12)) eTag["UUIDLeast"] = nbt.TAG_Long(-( (7 << 60) | random.getrandbits(60))) return eTag
def copyWithOffset(cls, entity, copyOffset, regenerateUUID=False): eTag = deepcopy(entity) positionTags = map(lambda p, co: nbt.TAG_Double(p.value + co), eTag["Pos"], copyOffset) eTag["Pos"] = nbt.TAG_List(positionTags) if eTag["id"].value in ("Painting", "ItemFrame"): eTag["TileX"].value += copyOffset[0] eTag["TileY"].value += copyOffset[1] eTag["TileZ"].value += copyOffset[2] if "Riding" in eTag: eTag["Riding"] = Entity.copyWithOffset(eTag["Riding"], copyOffset) if regenerateUUID: # Courtesy of SethBling eTag["UUIDMost"] = nbt.TAG_Long((random.getrandbits(47) << 16) | (1 << 12) | random.getrandbits(12)) eTag["UUIDLeast"] = nbt.TAG_Long(-((7 << 60) | random.getrandbits(60))) return eTag
def copyWithOffset(cls, tileEntity, copyOffset, staticCommands, moveSpawnerPos, regenerateUUID, first): #You'll need to use this function twice #The first time with first equals to True #The second time with first equals to False eTag = deepcopy(tileEntity) eTag['x'] = nbt.TAG_Int(tileEntity['x'].value + copyOffset[0]) eTag['y'] = nbt.TAG_Int(tileEntity['y'].value + copyOffset[1]) eTag['z'] = nbt.TAG_Int(tileEntity['z'].value + copyOffset[2]) if regenerateUUID: # Courtesy of SethBling eTag["UUIDMost"] = nbt.TAG_Long((random.getrandbits(47) << 16) | (1 << 12) | random.getrandbits(12)) eTag["UUIDLeast"] = nbt.TAG_Long(-( (7 << 60) | random.getrandbits(60))) def num(x): try: return int(x) except ValueError: return float(x) def coordX(x, argument): if first == True: x = str(num(x)) + '!' + str(num(x) + copyOffset[0]) elif argument == True and x.find("!") >= 0: x = x[x.index("!") + 1:] x = str(num(x) + copyOffset[0]) elif argument == False and x.find("!") >= 0: x = x[:x.index("!")] return x def coordY(y, argument): if first == True: y = str(num(y)) + '!' + str(num(y) + copyOffset[1]) elif argument == True and y.find("!") >= 0: y = y[y.index("!") + 1:] y = str(num(y) + copyOffset[1]) elif argument == False and y.find("!") >= 0: y = y[:y.index("!")] return y def coordZ(z, argument): if first == True: z = str(num(z)) + '!' + str(num(z) + copyOffset[2]) elif argument == True and z.find("!") >= 0: z = z[z.index("!") + 1:] z = str(num(z) + copyOffset[2]) elif argument == False and z.find("!") >= 0: z = z[:z.index("!")] return z def coords(x, y, z, argument): if x[0] != "~": x = coordX(x, argument) if y[0] != "~": y = coordY(y, argument) if z[0] != "~": z = coordZ(z, argument) return x, y, z if eTag['id'].value == 'MobSpawner': mobs = [] mob = eTag.get('SpawnData') if mob: mobs.append(mob) potentials = eTag.get('SpawnPotentials') if potentials: mobs.extend(p["Properties"] for p in potentials) for mob in mobs: if "Pos" in mob: if first == True: pos = Entity.pos(mob) x, y, z = [str(part) for part in pos] x, y, z = coords(x, y, z, moveSpawnerPos) mob['Temp1'] = nbt.TAG_String(x) mob['Temp2'] = nbt.TAG_String(y) mob['Temp3'] = nbt.TAG_String(z) elif 'Temp1' in mob and 'Temp2' in mob and 'Temp3' in mob: x = mob['Temp1'] y = mob['Temp2'] z = mob['Temp3'] del mob['Temp1'] del mob['Temp2'] del mob['Temp3'] parts = [] for part in (x, y, z): part = str(part) part = part[13:len(part) - 2] parts.append(part) x, y, z = parts pos = [ float(p) for p in coords(x, y, z, moveSpawnerPos) ] Entity.setpos(mob, pos) if eTag['id'].value == "Control": command = eTag['Command'].value oldCommand = command def selectorCoords(selector): old_selector = selector try: char_num = 0 x = "" y = "" z = "" new_selector = "" dont_copy = 0 if len(selector) > 4: if selector[3] >= '0' and selector[3] <= '9': new_selector = selector[:3] end_char_x = selector.find(',', 4, len(selector) - 1) if end_char_x == -1: end_char_x = len(selector) - 1 x = selector[3:end_char_x] x = coordX(x, staticCommands) new_selector += x + ',' end_char_y = selector.find(',', end_char_x + 1, len(selector) - 1) if end_char_y == -1: end_char_y = len(selector) - 1 y = selector[end_char_x + 1:end_char_y] y = coordY(y, staticCommands) new_selector += y + ',' end_char_z = selector.find(',', end_char_y + 1, len(selector) - 1) if end_char_z == -1: end_char_z = len(selector) - 1 z = selector[end_char_y + 1:end_char_z] z = coordZ(z, staticCommands) new_selector += z + ',' + selector[end_char_z + 1:] else: for char in selector: if dont_copy != 0: dont_copy -= 1 else: if (char != 'x' and char != 'y' and char != 'z') or letter == True: new_selector += char if char == '[' or char == ',': letter = False else: letter = True elif char == 'x' and letter == False: new_selector += selector[ char_num:char_num + 2] char_x = char_num + 2 end_char_x = selector.find( ',', char_num + 3, len(selector) - 1) if end_char_x == -1: end_char_x = len(selector) - 1 x = selector[char_x:end_char_x] dont_copy = len(x) + 1 x = coordX(x, staticCommands) new_selector += x elif char == 'y' and letter == False: new_selector += selector[ char_num:char_num + 2] char_y = char_num + 2 end_char_y = selector.find( ',', char_num + 3, len(selector) - 1) if end_char_y == -1: end_char_y = len(selector) - 1 y = selector[char_y:end_char_y] dont_copy = len(y) + 1 y = coordY(y, staticCommands) new_selector += y elif char == 'z' and letter == False: new_selector += selector[ char_num:char_num + 2] char_z = char_num + 2 end_char_z = selector.find( ',', char_num + 3, len(selector) - 1) if end_char_z == -1: end_char_z = len(selector) - 1 z = selector[char_z:end_char_z] dont_copy = len(z) + 1 z = coordZ(z, staticCommands) new_selector += z char_num += 1 else: new_selector = old_selector except: new_selector = old_selector finally: return new_selector try: execute = False Slash = False if command[0] == "/": command = command.replace("/", "", 1) Slash = True # Adjust command coordinates. words = command.split(' ') i = 0 for word in words: if word[0] == '@': words[i] = selectorCoords(word) i += 1 if command.startswith('execute'): stillExecuting = True execute = True saving_command = "" while stillExecuting == True: if Slash == True: saving_command += '/' x, y, z = words[2:5] words[2:5] = coords(x, y, z, staticCommands) if words[5] == 'detect': x, y, z = words[6:9] words[6:9] = coords(x, y, z, staticCommands) saving_command += ' '.join(words[:9]) words = words[9:] else: saving_command += ' '.join(words[:5]) words = words[5:] command = ' '.join(words) saving_command += ' ' Slash = False if command[0] == "/": command = command.replace("/", "", 1) Slash = True words = command.split(' ') if not command.startswith('execute'): stillExecuting = False if (command.startswith('tp') and len(words) == 5 ) or command.startswith('particle') or command.startswith( 'replaceitem block') or ( command.startswith('spawnpoint') and len(words) == 5) or command.startswith('stats block') or ( command.startswith('summon') and len(words) >= 5): x, y, z = words[2:5] words[2:5] = coords(x, y, z, staticCommands) elif command.startswith('blockdata') or command.startswith( 'setblock') or (command.startswith('setworldspawn') and len(words) == 4): x, y, z = words[1:4] words[1:4] = coords(x, y, z, staticCommands) elif command.startswith('playsound') and len(words) >= 6: x, y, z = words[3:6] words[3:6] = coords(x, y, z, staticCommands) elif command.startswith('clone'): x1, y1, z1, x2, y2, z2, x, y, z = words[1:10] x1, y1, z1 = coords(x1, y1, z1, staticCommands) x2, y2, z2 = coords(x2, y2, z2, staticCommands) x, y, z = coords(x, y, z, staticCommands) words[1:10] = x1, y1, z1, x2, y2, z2, x, y, z elif command.startswith('fill'): x1, y1, z1, x2, y2, z2 = words[1:7] x1, y1, z1 = coords(x1, y1, z1, staticCommands) x2, y2, z2 = coords(x2, y2, z2, staticCommands) words[1:7] = x1, y1, z1, x2, y2, z2 elif command.startswith('spreadplayers'): x, z = words[1:3] if x[0] != "~": x = coordX(x, staticCommands) if z[0] != "~": z = coordZ(z, staticCommands) words[1:3] = x, z elif command.startswith('worldborder center') and len( words) == 4: x, z = words[2:4] if x[0] != "~": x = coordX(x, staticCommands) if z[0] != "~": z = coordZ(z, staticCommands) words[2:4] = x, z if Slash == True: command = '/' else: command = "" command += ' '.join(words) if execute == True: command = saving_command + command eTag['Command'].value = command except: eTag['Command'].value = oldCommand return eTag
def testCreate(self): "Create an indev level." # The root of an NBT file is always a TAG_Compound. level = nbt.TAG_Compound(name="MinecraftLevel") # Subtags of a TAG_Compound are automatically named when you use the [] operator. level["About"] = nbt.TAG_Compound() level["About"]["Author"] = nbt.TAG_String("codewarrior") level["About"]["CreatedOn"] = nbt.TAG_Long(time.time()) level["Environment"] = nbt.TAG_Compound() level["Environment"]["SkyBrightness"] = nbt.TAG_Byte(16) level["Environment"]["SurroundingWaterHeight"] = nbt.TAG_Short(32) level["Environment"]["FogColor"] = nbt.TAG_Int(0xcccccc) entity = nbt.TAG_Compound() entity["id"] = nbt.TAG_String("Creeper") entity["Pos"] = nbt.TAG_List( [nbt.TAG_Float(d) for d in (32.5, 64.0, 33.3)]) level["Entities"] = nbt.TAG_List([entity]) # You can also create and name a tag before adding it to the compound. spawn = nbt.TAG_List( (nbt.TAG_Short(100), nbt.TAG_Short(45), nbt.TAG_Short(55))) spawn.name = "Spawn" mapTag = nbt.TAG_Compound() mapTag.add(spawn) mapTag.name = "Map" level.add(mapTag) mapTag2 = nbt.TAG_Compound([spawn]) mapTag2.name = "Map" # I think it looks more familiar with [] syntax. l, w, h = 128, 128, 128 mapTag["Height"] = nbt.TAG_Short(h) # y dimension mapTag["Length"] = nbt.TAG_Short(l) # z dimension mapTag["Width"] = nbt.TAG_Short(w) # x dimension # Byte arrays are stored as numpy.uint8 arrays. mapTag["Blocks"] = nbt.TAG_Byte_Array() mapTag["Blocks"].value = numpy.zeros( l * w * h, dtype=numpy.uint8) # create lots of air! # The blocks array is indexed (y,z,x) for indev levels, so reshape the blocks mapTag["Blocks"].value.shape = (h, l, w) # Replace the bottom layer of the indev level with wood mapTag["Blocks"].value[0, :, :] = 5 # This is a great way to learn the power of numpy array slicing and indexing. mapTag["Data"] = nbt.TAG_Byte_Array() mapTag["Data"].value = numpy.zeros(l * w * h, dtype=numpy.uint8) # Save a few more tag types for completeness level["ShortArray"] = nbt.TAG_Short_Array( numpy.zeros((16, 16), dtype='uint16')) level["IntArray"] = nbt.TAG_Int_Array( numpy.zeros((16, 16), dtype='uint32')) level["Float"] = nbt.TAG_Float(0.3) return level