From 1bf1cfa8b6770f448d276e73ad18ce30821b5baa Mon Sep 17 00:00:00 2001 From: David Vierra Date: Wed, 9 Mar 2011 13:05:23 -1000 Subject: [PATCH] expanded block definitions to support blockData for colored wool and varied trees textures are given as a pair of 0-255 pixel coordinates instead of combining them into one byte. the first coordinate of the pair is left-to-right on the terrain.png added flat color definitions for low-detail rendering. color codes borrowed from c10t block defs are now attrs of the MCMaterials objects. fillBlocks now takes Block objects instead of block ID numbers --- materials.py | 666 +++++++++++++++++++++++++++++++++++++-------------- mce.py | 83 ++++--- mclevel.py | 84 ++++--- 3 files changed, 580 insertions(+), 253 deletions(-) diff --git a/materials.py b/materials.py index d5fcb13..1d98856 100644 --- a/materials.py +++ b/materials.py @@ -2,10 +2,11 @@ from materials import classicMaterials, materials ''' from numpy import * -NOTEX = 0xB8 +NOTEX = (0xB0, 0x80) + class Block(object): - def __init__(self, materials, blockID, **kw): + def __init__(self, materials, blockID, blockData = 0, **kw): """ Defines a blocktype. Keyword parameters: @@ -14,28 +15,32 @@ class Block(object): opacity: 0-15 (default 15) aka: Additional keywords to use for searching color: (r, g, b) tuple. 0-255. default (0x77, 0x77, 0x77) + texture: pair of integers 0-255 with pixel coordinates into terrain.png + can be a 6-let of pairs, one pair for each face, + with faces in the order -X +X -Y +Y -Z +Z + """ object.__init__(self) self.materials = materials - materials._objects[blockID] = self; - materials.names[blockID] = kw.pop('name', materials.defaultName) - materials.lightEmission[blockID] = kw.pop('brightness', materials.defaultBrightness) - materials.lightAbsorption[blockID] = kw.pop('opacity', materials.defaultOpacity) - materials.aka[blockID] = kw.pop('aka', "") - color = kw.pop('color', None) - if color: - materials.flatColors[blockID] = color - - texture = kw.pop('texture') - if isinstance(texture, int): - texture = (texture, )*6 - - - materials.blockTextures[blockID] = texture + self.name = kw.pop('name', materials.names[blockID][0]) + + + self.brightness = kw.pop('brightness', materials.defaultBrightness) + self.opacity = kw.pop('opacity', materials.defaultOpacity) + self.aka = kw.pop('aka', "") self.ID = blockID + self.blockData = blockData - + + def __str__(self): + return "".format( + name=self.name,id=self.ID,data=self.blockData,ha=self.hasAlternate) + + def __repr__(self): + return str(self) + hasAlternate = False + class MCMaterials(object): defaultBrightness = 0 defaultOpacity = 15 @@ -44,17 +49,18 @@ class MCMaterials(object): object.__init__(self) self.defaultName = defaultName - self._objects = [None] * 256; - self.blockTextures = zeros((256, 6), dtype='uint8') + self.blockTextures = zeros((256, 16, 6, 2), dtype='uint8') self.blockTextures[:] = defaultTexture - self.names = [defaultName] * 256 + self.names = [[defaultName] * 16 for i in range(256)] self.aka = [""] * 256 + self.blocksByName = {} + self.blocksByID = {} self.lightEmission = zeros(256, dtype='uint8') self.lightAbsorption = zeros(256, dtype='uint8') self.lightAbsorption[:] = self.defaultOpacity - self.flatColors = zeros((256, 4), dtype='uint8') - self.flatColors[:] = (0x77, 0x77, 0x77, 0x255) + self.flatColors = zeros((256, 16, 4), dtype='uint8') + self.flatColors[:] = (0xc9, 0x77, 0xf0, 0x255) #flat colors borrowed from c10t. https://github.com/udoprog/c10t defaultColors = array([ @@ -143,272 +149,374 @@ class MCMaterials(object): (50,89,45,128), (94,167,84,128), ]) - self.flatColors[:len(defaultColors)] = defaultColors + self.flatColors[:len(defaultColors),:,:] = array(defaultColors)[:,newaxis,:] def __repr__(self): return "".format(self.name) - def materialNamed(self, name): - return self.names.index(name); + def blocksMatching(self, name): + return [self.blocksByName[k] for k in self.blocksByName if name in k] - def Block(self, blockID, **kw): - return Block(self, blockID, **kw) - + def blockWithID(self, id, data = 0): + if (id,data) in self.blocksByID: + return self.blocksByID[id,data] + else: + block = self.Block(id, blockData=data) + self.blocksByID[id,data] = block + return block + + def Block(self, blockID, blockData = 0, **kw): + block = Block(self, blockID, blockData, **kw) + + self.lightEmission[blockID] = block.brightness + self.lightAbsorption[blockID] = block.opacity + self.aka[blockID] = block.aka + + color = kw.pop('color', None) + if color: + self.flatColors[blockID, (blockData or slice(None))] = color + + texture = kw.pop('texture', None) + if texture: + self.blockTextures[blockID,(blockData or slice(None))] = texture + + if blockData is 0: + self.names[blockID] = [block.name] * 16 + else: + self.names[blockID][blockData] = block.name + + if block.name is not self.defaultName: + self.blocksByName[block.name] = block + + + if (blockID, 0) in self.blocksByID: + self.blocksByID[blockID, 0].hasAlternate = True + block.hasAlternate = True + + self.blocksByID[blockID, blockData] = block + + return block + + def __cmp__(self, rhs): + return (self.ID, self.blockData).__cmp__( (rhs.ID, rhs.blockData) ) + classicMaterials = MCMaterials(defaultTexture=NOTEX, defaultName = "Not present in Classic"); classicMaterials.name = "Classic" cm = classicMaterials cm.Air = cm.Block(0, name="Air", - texture=0xB8, + texture=(0x80,0xB0), ) + cm.Rock = cm.Block(1, name="Rock", - texture=0x01, + texture=(0x10,0x00), ) + cm.Grass = cm.Block(2, name="Grass", - texture=(0x03, 0x03, 0x00, 0x02, 0x03, 0x03), + texture=((0x30,0x00), (0x30,0x00), (0x00,0x00), (0x20,0x00), (0x30,0x00), (0x30,0x00)), ) + cm.Dirt = cm.Block(3, name="Dirt", - texture=0x02, + texture=(0x20,0x00), ) + cm.Cobblestone = cm.Block(4, name="Cobblestone", - texture=0x10, + texture=(0x00,0x10), ) + cm.WoodPlanks = cm.Block(5, name="Wood Planks", - texture=0x04, + texture=(0x40,0x00), ) + cm.Sapling = cm.Block(6, name="Sapling", - texture=0x0F, + texture=(0xF0,0x00), ) + cm.Adminium = cm.Block(7, name="Adminium", - texture=0x11, + texture=(0x10,0x10), ) + cm.WaterActive = cm.Block(8, name="Water (active)", - texture=0x0E, + texture=(0xE0,0x00), ) + cm.WaterStill = cm.Block(9, name="Water (still)", - texture=0x0E, + texture=(0xE0,0x00), ) + cm.LavaActive = cm.Block(10, name="Lava (active)", - texture=0x1E, + texture=(0xE0,0x10), ) + cm.LavaStill = cm.Block(11, name="Lava (still)", - texture=0x1E, + texture=(0xE0,0x10), ) + cm.Sand = cm.Block(12, name="Sand", - texture=0x12, + texture=(0x20,0x10), ) + cm.Gravel = cm.Block(13, name="Gravel", - texture=0x13, + texture=(0x30,0x10), ) + cm.GoldOre = cm.Block(14, name="Gold Ore", - texture=0x20, + texture=(0x00,0x20), ) + cm.IronOre = cm.Block(15, name="Iron Ore", - texture=0x21, + texture=(0x10,0x20), ) + cm.CoalOre = cm.Block(16, name="Coal Ore", - texture=0x22, + texture=(0x20,0x20), ) + cm.Wood = cm.Block(17, name="Wood", - texture=(0x14, 0x14, 0x15, 0x15, 0x14, 0x14), + texture=((0x40,0x10), (0x40,0x10), (0x50,0x10), (0x50,0x10), (0x40,0x10), (0x40,0x10)), ) + cm.Leaves = cm.Block(18, name="Leaves", - texture=0x34, + texture=(0x40,0x30), ) + cm.Sponge = cm.Block(19, name="Sponge", - texture=0x30, + texture=(0x00,0x30), ) + cm.Glass = cm.Block(20, name="Glass", - texture=0x31, + texture=(0x10,0x30), ) + cm.RedCloth = cm.Block(21, name="Red Cloth", - texture=0x40, + texture=(0x00,0x40), ) + cm.OrangeCloth = cm.Block(22, name="Orange Cloth", - texture=0x41, + texture=(0x10,0x40), ) + cm.YellowCloth = cm.Block(23, name="Yellow Cloth", - texture=0x42, + texture=(0x20,0x40), ) + cm.LightGreenCloth = cm.Block(24, name="Light Green Cloth", - texture=0x43, + texture=(0x30,0x40), ) + cm.GreenCloth = cm.Block(25, name="Green Cloth", - texture=0x44, + texture=(0x40,0x40), ) + cm.AquaCloth = cm.Block(26, name="Aqua Cloth", - texture=0x45, + texture=(0x50,0x40), ) + cm.CyanCloth = cm.Block(27, name="Cyan Cloth", - texture=0x46, + texture=(0x60,0x40), ) + cm.BlueCloth = cm.Block(28, name="Blue Cloth", - texture=0x47, + texture=(0x70,0x40), ) + cm.PurpleCloth = cm.Block(29, name="Purple Cloth", - texture=0x48, + texture=(0x80,0x40), ) + cm.IndigoCloth = cm.Block(30, name="Indigo Cloth", - texture=0x49, + texture=(0x90,0x40), ) + cm.VioletCloth = cm.Block(31, name="Violet Cloth", - texture=0x4A, + texture=(0xA0,0x40), ) + cm.MagentaCloth = cm.Block(32, name="Magenta Cloth", - texture=0x4B, + texture=(0xB0,0x40), ) + cm.PinkCloth = cm.Block(33, name="Pink Cloth", - texture=0x4C, + texture=(0xC0,0x40), ) + cm.BlackCloth = cm.Block(34, name="Black Cloth", - texture=0x4D, + texture=(0xD0,0x40), ) + cm.GrayCloth = cm.Block(35, name="Gray Cloth", - texture=0x4E, + texture=(0xE0,0x40), ) + cm.WhiteCloth = cm.Block(36, name="White Cloth", - texture=0x4F, + texture=(0xF0,0x40), ) + cm.Flower = cm.Block(37, name="Flower", - texture=0x0D, + texture=(0xD0,0x00), ) + cm.Rose = cm.Block(38, name="Rose", - texture=0x0C, + texture=(0xC0,0x00), ) + cm.BrownMushroom = cm.Block(39, name="Brown Mushroom", - texture=0x1D, + texture=(0xD0,0x10), ) + cm.RedMushroom = cm.Block(40, name="Red Mushroom", - texture=0x1C, + texture=(0xC0,0x10), ) + cm.BlockOfGold = cm.Block(41, name="Block of Gold", - texture=(0x27, 0x27, 0x17, 0x37, 0x27, 0x27), + texture=((0x70,0x20), (0x70,0x20), (0x70,0x10), (0x70,0x30), (0x70,0x20), (0x70,0x20)), ) + cm.BlockOfIron = cm.Block(42, name="Block of Iron", - texture=(0x26, 0x26, 0x16, 0x36, 0x26, 0x26), + texture=((0x60,0x20), (0x60,0x20), (0x60,0x10), (0x60,0x30), (0x60,0x20), (0x60,0x20)), ) + cm.DoubleStoneSlab = cm.Block(43, name="Double Stone Slab", - texture=(0x05, 0x05, 0x06, 0x06, 0x05, 0x05), + texture=((0x50,0x00), (0x50,0x00), (0x60,0x00), (0x60,0x00), (0x50,0x00), (0x50,0x00)), ) + cm.SingleStoneSlab = cm.Block(44, name="Stone Slab", - texture=(0x05, 0x05, 0x06, 0x06, 0x05, 0x05), + texture=((0x50,0x00), (0x50,0x00), (0x60,0x00), (0x60,0x00), (0x50,0x00), (0x50,0x00)), ) + cm.Brick = cm.Block(45, name="Brick", - texture=0x07, + texture=(0x70,0x00), ) + cm.TNT = cm.Block(46, name="TNT", - texture=(0x08, 0x08, 0x09, 0x0A, 0x08, 0x08), + texture=((0x80,0x00), (0x80,0x00), (0x90,0x00), (0xA0,0x00), (0x80,0x00), (0x80,0x00)), ) + cm.Bookshelf = cm.Block(47, name="Bookshelf", - texture=(0x23, 0x23, 0x04, 0x04, 0x23, 0x23), + texture=((0x30,0x20), (0x30,0x20), (0x40,0x00), (0x40,0x00), (0x30,0x20), (0x30,0x20)), ) + cm.MossStone = cm.Block(48, name="Moss Stone", - texture=0x24, + texture=(0x40,0x20), ) + cm.Obsidian = cm.Block(49, name="Obsidian", - texture=0x25, + texture=(0x50,0x20), ) + cm.Torch = cm.Block(50, name="Torch", - texture=0x50, + texture=(0x00,0x50), ) + cm.Fire = cm.Block(51, name="Fire", - texture=0x3F, + texture=(0xF0,0x30), ) + cm.InfiniteWaterSource = cm.Block(52, name="Infinite water source", - texture=0x0E, + texture=(0xE0,0x00), ) + cm.InfiniteLavaSource = cm.Block(53, name="Infinite lava source", - texture=0x1E, + texture=(0xE0,0x10), ) + cm.Chest = cm.Block(54, name="Chest", - texture=(0x1A, 0x1A, 0x1A, 0x1B, 0x19, 0x19), + texture=((0xA0,0x10), (0xA0,0x10), (0xA0,0x10), (0xB0,0x10), (0x90,0x10), (0x90,0x10)), ) + cm.Cog = cm.Block(55, name="Cog", - texture=0x3F, + texture=(0xF0,0x30), ) + cm.DiamondOre = cm.Block(56, name="Diamond Ore", - texture=0x32, + texture=(0x20,0x30), ) + cm.BlockOfDiamond = cm.Block(57, name="Block Of Diamond", - texture=(0x28, 0x28, 0x18, 0x38, 0x28, 0x28), + texture=((0x80,0x20), (0x80,0x20), (0x80,0x10), (0x80,0x30), (0x80,0x20), (0x80,0x20)), ) + cm.CraftingTable = cm.Block(58, name="Crafting Table", - texture=(0x3B, 0x3B, 0x2B, 0x14, 0x3C, 0x3C), + texture=((0xB0,0x30), (0xB0,0x30), (0xB0,0x20), (0x40,0x10), (0xC0,0x30), (0xC0,0x30)), ) + cm.Crops = cm.Block(59, name="Crops", - texture=0x5F, + texture=(0xF0,0x50), ) + cm.Farmland = cm.Block(60, name="Farmland", - texture=0x56, + texture=(0x60,0x50), ) + cm.Furnace = cm.Block(61, name="Furnace", - texture=(0x2D, 0x2D, 0x01, 0x01, 0x2C, 0x2C), + texture=((0xD0,0x20), (0xD0,0x20), (0x10,0x00), (0x10,0x00), (0xC0,0x20), (0xC0,0x20)), ) + cm.LitFurnace = cm.Block(62, name="Lit Furnace", - texture=(0x2D, 0x2D, 0x01, 0x01, 0x3D, 0x3D), + texture=((0xD0,0x20), (0xD0,0x20), (0x10,0x00), (0x10,0x00), (0xD0,0x30), (0xD0,0x30)), ) ### @@ -421,379 +529,576 @@ materials.name = "Alpha" am = materials am.Air = am.Block(0, name="Air", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.Stone = am.Block(1, name="Stone", - texture=0x01, + texture=(0x10,0x00), ) + am.Grass = am.Block(2, name="Grass", - texture=(0x03, 0x03, 0x00, 0x02, 0x03, 0x03), + texture=((0x30,0x00), (0x30,0x00), (0x00,0x00), (0x20,0x00), (0x30,0x00), (0x30,0x00)), ) + am.Dirt = am.Block(3, name="Dirt", - texture=0x02, + texture=(0x20,0x00), ) + am.Cobblestone = am.Block(4, name="Cobblestone", - texture=0x10, + texture=(0x00,0x10), ) + am.WoodPlanks = am.Block(5, name="Wood Planks", - texture=0x04, + texture=(0x40,0x00), ) + am.Sapling = am.Block(6, name="Sapling", - texture=0x0F, + texture=(0xF0,0x00), opacity=0, ) + am.Bedrock = am.Block(7, name="Bedrock", - texture=0x11, + texture=(0x10,0x10), ) + am.WaterActive = am.Block(8, name="Water (active)", - texture=0xDF, + texture=(0xF0,0xD0), opacity=3, ) + am.WaterStill = am.Block(9, name="Water (still)", - texture=0xDF, + texture=(0xF0,0xD0), opacity=3, ) + am.LavaActive = am.Block(10, name="Lava (active)", - texture=0xFF, + texture=(0xF0,0xF0), brightness=15, ) + am.LavaStill = am.Block(11, name="Lava (still)", - texture=0xFF, + texture=(0xF0,0xF0), brightness=15, ) + am.Sand = am.Block(12, name="Sand", - texture=0x12, + texture=(0x20,0x10), ) + am.Gravel = am.Block(13, name="Gravel", - texture=0x13, + texture=(0x30,0x10), ) + am.GoldOre = am.Block(14, name="Gold Ore", - texture=0x20, + texture=(0x00,0x20), ) + am.IronOre = am.Block(15, name="Iron Ore", - texture=0x21, + texture=(0x10,0x20), ) + am.CoalOre = am.Block(16, name="Coal Ore", - texture=0x22, + texture=(0x20,0x20), ) + + am.Wood = am.Block(17, name="Wood", - texture=(0x14, 0x14, 0x15, 0x15, 0x14, 0x14), + texture=((0x40,0x10), (0x40,0x10), (0x50,0x10), (0x50,0x10), (0x40,0x10), (0x40,0x10)), ) + +am.Ironwood = am.Block(17, blockData=1, + name="Ironwood", + texture=((0x40,0x70), (0x40,0x70), (0x50,0x10), (0x50,0x10), (0x40,0x70), (0x40,0x70)), + ) + +am.BirchWood = am.Block(17, blockData=2, + name="Birch Wood", + texture=((0x50,0x70), (0x50,0x70), (0x50,0x10), (0x50,0x10), (0x50,0x70), (0x50,0x70)), + ) + + am.Leaves = am.Block(18, name="Leaves", - texture=0x35, + texture=(0x50,0x30), opacity=1, ) + +am.PineLeaves = am.Block(18, blockData=1, + name="Pine Leaves", + texture=(0x50,0x80), + opacity=1, + ) + + am.Sponge = am.Block(19, name="Sponge", - texture=0x30, + texture=(0x00,0x30), ) + am.Glass = am.Block(20, name="Glass", - texture=0x31, + texture=(0x10,0x30), opacity=0, ) + am.LapisLazuliOre = am.Block(21, name="Lapis Lazuli Ore", - texture=0xA0, + texture=(0x00,0xA0), ) + am.LapisLazuliBlock = am.Block(22, name="Lapis Lazuli Block", - texture=0x90, + texture=(0x00,0x90), ) + am.Dispenser = am.Block(23, name="Dispenser", - texture=(0x2E, 0x2E, 0x3E, 0x01, 0x2D, 0x2D), + texture=((0xE0,0x20), (0xE0,0x20), (0xE0,0x30), (0x10,0x00), (0xD0,0x20), (0xD0,0x20)), ) + am.Sandstone = am.Block(24, name="Sandstone", - texture=(0xC0, 0xC0, 0xB0, 0xD0, 0xC0, 0xC0), + texture=((0x00,0xC0), (0x00,0xC0), (0x00,0xB0), (0x00,0xD0), (0x00,0xC0), (0x00,0xC0)), ) + am.NoteBlock = am.Block(25, name="Note Block", - texture=0x4A, + texture=(0xA0,0x40), ) -am.Wool = am.Block(35, - name="Wool", - texture=0x40, + + +am.WhiteWool = am.Block(35, + name="White Wool", + texture=(0x00, 0x40), + color=(0xff, 0xff, 0xff, 0xff) ) + +am.OrangeWool = am.Block(35, blockData = 1, + name="Orange Wool", + texture=(0x20, 0xD0), + color=(0xea, 0x7f, 0x37, 0xff) + ) + +am.MagentaWool = am.Block(35, blockData = 2, + name="Magenta Wool", + texture=(0x20, 0xC0), + color=(0xbf, 0x4b, 0xc9, 0xff) + ) + +am.LightBlueWool = am.Block(35, blockData = 3, + name="Light Blue Wool", + texture=(0x20, 0xB0), + color=(0x68, 0x8b, 0xd4, 0xff) + ) + +am.YellowWool = am.Block(35, blockData = 4, + name="Yellow Wool", + texture=(0x20, 0xA0), + color=(0xc2, 0xb5, 0x1c, 0xff) + ) + +am.LightGreenWool = am.Block(35, blockData = 5, + name="Light Green Wool", + texture=(0x20, 0x90), + color=(0x3b, 0xbd, 0x30, 0xff) + ) + +am.PinkWool = am.Block(35, blockData = 6, + name="Pink Wool", + texture=(0x20, 0x80), + color=(0xd9, 0x83, 0x9b, 0xff) + ) + +am.GrayWool = am.Block(35, blockData = 7, + name="Gray Wool", + texture=(0x20, 0x70), + color=(0x42, 0x42, 0x42, 0xff) + ) + +am.LightGrayWool = am.Block(35, blockData = 8, + name="Light Gray Wool", + texture=(0x10, 0xE0), + color=(0x9e, 0xa6, 0xa6, 0xff) + ) + +am.CyanWool = am.Block(35, blockData = 9, + name="Cyan Wool", + texture=(0x10, 0xD0), + color=(0x27, 0x75, 0x95, 0xff) + ) + +am.PurpleWool = am.Block(35, blockData = 10, + name="Purple Wool", + texture=(0x10, 0xC0), + color=(0x81, 0x36, 0xc4, 0xff) + ) + +am.BlueWool = am.Block(35, blockData = 11, + name="Blue Wool", + texture=(0x10, 0xB0), + color=(0x27, 0x33, 0xa1, 0xff) + ) + +am.BrownWool = am.Block(35, blockData = 12, + name="Brown Wool", + texture=(0x10, 0xA0), + color=(0x56, 0x33, 0x1c, 0xff) + ) + +am.DarkGreenWool = am.Block(35, blockData = 13, + name="Dark Green Wool", + texture=(0x10, 0x90), + color=(0x38, 0x4d, 0x18, 0xff) + ) + +am.RedWool = am.Block(35, blockData = 14, + name="Red Wool", + texture=(0x10, 0x80), + color=(0xa4, 0x2d, 0x29, 0xff) + ) + +am.BlackWool = am.Block(35, blockData = 15, + name="Black Wool", + texture=(0x10, 0x70), + color = (0, 0, 0, 0xff) + ) + + am.Flower = am.Block(37, name="Flower", - texture=0x0D, + texture=(0xD0,0x00), opacity=0, ) + am.Rose = am.Block(38, name="Rose", - texture=0x0C, + texture=(0xC0,0x00), opacity=0, ) + am.BrownMushroom = am.Block(39, name="Brown Mushroom", - texture=0x1D, + texture=(0xD0,0x10), opacity=0, brightness=1, ) + am.RedMushroom = am.Block(40, name="Red Mushroom", - texture=0x1C, + texture=(0xC0,0x10), opacity=0, ) + am.BlockofGold = am.Block(41, name="Block of Gold", - texture=0x17, + texture=(0x70,0x10), ) + am.BlockofIron = am.Block(42, name="Block of Iron", - texture=0x16, + texture=(0x60,0x10), ) + am.DoubleStoneSlab = am.Block(43, name="Double Stone Slab", - texture=(0x05, 0x05, 0x06, 0x06, 0x05, 0x05), + texture=((0x50,0x00), (0x50,0x00), (0x60,0x00), (0x60,0x00), (0x50,0x00), (0x50,0x00)), ) + am.StoneSlab = am.Block(44, name="Stone Slab", - texture=(0x05, 0x05, 0x06, 0x06, 0x05, 0x05), + texture=((0x50,0x00), (0x50,0x00), (0x60,0x00), (0x60,0x00), (0x50,0x00), (0x50,0x00)), ) + am.Brick = am.Block(45, name="Brick", - texture=0x07, + texture=(0x70,0x00), ) + am.TNT = am.Block(46, name="TNT", - texture=(0x08, 0x08, 0x09, 0x0A, 0x08, 0x08), + texture=((0x80,0x00), (0x80,0x00), (0x90,0x00), (0xA0,0x00), (0x80,0x00), (0x80,0x00)), ) + am.Bookshelf = am.Block(47, name="Bookshelf", - texture=(0x23, 0x23, 0x04, 0x04, 0x23, 0x23), + texture=((0x30,0x20), (0x30,0x20), (0x40,0x00), (0x40,0x00), (0x30,0x20), (0x30,0x20)), ) + am.MossStone = am.Block(48, name="Moss Stone", - texture=0x24, + texture=(0x40,0x20), ) + am.Obsidian = am.Block(49, name="Obsidian", - texture=0x25, + texture=(0x50,0x20), ) + am.Torch = am.Block(50, name="Torch", - texture=0x50, + texture=(0x00,0x50), brightness=14, opacity=0, ) + am.Fire = am.Block(51, name="Fire", - texture=0x1F, + texture=(0xF0,0x10), brightness=15, ) + am.MonsterSpawner = am.Block(52, name="Monster Spawner", - texture=0x41, + texture=(0x10,0x40), opacity=0, ) + am.WoodenStairs = am.Block(53, name="Wooden Stairs", - texture=0x04, + texture=(0x40,0x00), opacity=0, ) + am.Chest = am.Block(54, name="Chest", - texture=(0x1A, 0x1A, 0x1A, 0x1B, 0x19, 0x19), + texture=((0xA0,0x10), (0xA0,0x10), (0xA0,0x10), (0xB0,0x10), (0x90,0x10), (0x90,0x10)), ) + am.RedstoneWire = am.Block(55, name="Redstone Wire", - texture=0x64, + texture=(0x40,0x60), opacity=0, ) + am.DiamondOre = am.Block(56, name="Diamond Ore", - texture=0x32, + texture=(0x20,0x30), ) + am.BlockofDiamond = am.Block(57, name="Block of Diamond", - texture=0x18, + texture=(0x80,0x10), ) + am.CraftingTable = am.Block(58, name="Crafting Table", - texture=(0x3B, 0x3B, 0x2B, 0x14, 0x3C, 0x3C), + texture=((0xB0,0x30), (0xB0,0x30), (0xB0,0x20), (0x40,0x10), (0xC0,0x30), (0xC0,0x30)), ) + am.Crops = am.Block(59, name="Crops", - texture=0x5F, + texture=(0xF0,0x50), opacity=0, ) + am.Farmland = am.Block(60, name="Farmland", - texture=0x56, + texture=(0x60,0x50), ) + am.Furnace = am.Block(61, name="Furnace", - texture=(0x2D, 0x2D, 0x01, 0x01, 0x2C, 0x2C), + texture=((0xD0,0x20), (0xD0,0x20), (0x10,0x00), (0x10,0x00), (0xC0,0x20), (0xC0,0x20)), ) + am.LitFurnace = am.Block(62, name="Lit Furnace", - texture=(0x2D, 0x2D, 0x01, 0x01, 0x3D, 0x3D), + texture=((0xD0,0x20), (0xD0,0x20), (0x10,0x00), (0x10,0x00), (0xD0,0x30), (0xD0,0x30)), brightness=14, ) + am.Sign = am.Block(63, name="Sign", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.WoodenDoor = am.Block(64, name="Wooden Door", - texture=0x51, + texture=(0x10,0x50), opacity=0, ) + am.Ladder = am.Block(65, name="Ladder", - texture=0x53, + texture=(0x30,0x50), opacity=0, ) + am.Rail = am.Block(66, name="Rail", - texture=0x80, + texture=(0x00,0x80), opacity=0, ) + am.StoneStairs = am.Block(67, name="Stone Stairs", - texture=0x10, + texture=(0x00,0x10), opacity=0, ) + am.WallSign = am.Block(68, name="Wall Sign", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.Lever = am.Block(69, name="Lever", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.StoneFloorPlate = am.Block(70, name="Stone Floor Plate", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.IronDoor = am.Block(71, name="Iron Door", - texture=0x52, + texture=(0x20,0x50), opacity=0, ) + am.WoodFloorPlate = am.Block(72, name="Wood Floor Plate", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.RedstoneOre = am.Block(73, name="Redstone Ore", - texture=0x33, + texture=(0x30,0x30), ) + am.RedstoneOreGlowing = am.Block(74, name="Redstone Ore (glowing)", - texture=0x33, + texture=(0x30,0x30), brightness=9, ) + am.RedstoneTorchOff = am.Block(75, name="Redstone Torch (off)", - texture=0x73, + texture=(0x30,0x70), opacity=0, ) + am.RedstoneTorchOn = am.Block(76, name="Redstone Torch (on)", - texture=0x63, + texture=(0x30,0x60), opacity=0, brightness=7, ) + am.Button = am.Block(77, name="Button", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.SnowLayer = am.Block(78, name="Snow Layer", - texture=0x42, + texture=(0x20,0x40), opacity=0, ) + am.Ice = am.Block(79, name="Ice", - texture=0x43, + texture=(0x30,0x40), opacity=3, ) + am.Snow = am.Block(80, name="Snow", - texture=0x42, + texture=(0x20,0x40), ) + am.Cactus = am.Block(81, name="Cactus", - texture=(0x46, 0x46, 0x47, 0x45, 0x46, 0x46), + texture=((0x60,0x40), (0x60,0x40), (0x70,0x40), (0x50,0x40), (0x60,0x40), (0x60,0x40)), ) + am.Clay = am.Block(82, name="Clay", - texture=0x48, + texture=(0x80,0x40), ) + am.SugarCane = am.Block(83, name="Sugar Cane", - texture=0x49, + texture=(0x90,0x40), opacity=0, ) + am.Jukebox = am.Block(84, name="Jukebox", - texture=(0x4A, 0x4A, 0x4A, 0x4B, 0x4A, 0x4A), + texture=((0xA0,0x40), (0xA0,0x40), (0xA0,0x40), (0xB0,0x40), (0xA0,0x40), (0xA0,0x40)), ) + am.Fence = am.Block(85, name="Fence", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, ) + am.Pumpkin = am.Block(86, name="Pumpkin", - texture=(0x77, 0x76, 0x66, 0x76, 0x76, 0x76), + texture=((0x70,0x70), (0x60,0x70), (0x60,0x60), (0x60,0x70), (0x60,0x70), (0x60,0x70)), + color=(0xcc, 0x77, 0x18, 0xFF) ) + am.Netherrack = am.Block(87, name="Netherrack", - texture=0x67, + texture=(0x70,0x60), ) + am.SoulSand = am.Block(88, name="Soul Sand", - texture=0x68, + texture=(0x80,0x60), ) + am.Glowstone = am.Block(89, name="Glowstone", - texture=0x69, + texture=(0x90,0x60), brightness=15, + color=(0xFF, 0xEE, 0x00, 0xFF) ) + am.NetherPortal = am.Block(90, name="Nether Portal", - texture=0xB8, + texture=(0x80,0xB0), opacity=0, brightness=11, ) + am.JackOLantern = am.Block(91, name="Jack-o'-Lantern", - texture=(0x78, 0x76, 0x66, 0x76, 0x76, 0x76), + texture=((0x80,0x70), (0x60,0x70), (0x60,0x60), (0x60,0x70), (0x60,0x70), (0x60,0x70)), brightness=15, + color=(0xcc, 0x77, 0x18, 0xFF) ) + am.Cake = am.Block(92, name="Cake", - texture=(0x7A, 0x7A, 0x79, 0x7C, 0x7A, 0x7A), + texture=((0xA0,0x70), (0xA0,0x70), (0x90,0x70), (0xC0,0x70), (0xA0,0x70), (0xA0,0x70)), ) del am @@ -842,12 +1147,5 @@ classicMaterials.conversionTables = { }; -#precalculate coords -def texCoords(idx): - - return ( (idx & 0xf) << 4 , (idx & 0xf0) ) - -materials.blockTextures = array([map(texCoords, faces) for (faces) in materials.blockTextures], dtype='float32') -classicMaterials.blockTextures = array([map(texCoords, faces) for (faces) in classicMaterials.blockTextures], dtype='float32') alphaMaterials = materials; diff --git a/mce.py b/mce.py index d772a97..8589ba6 100755 --- a/mce.py +++ b/mce.py @@ -201,29 +201,23 @@ class mce(object): return (x,y,z) - def readBlockType(self, command): + def readBlockInfo(self, command): keyword = command.pop(0) - def blocksMatching(search): - if search in self.level.materials.names: - #exact match - return [search] - return filter(lambda x:search.lower() in x.lower(), self.level.materials.names) - - matches = blocksMatching(keyword) - blockType = None + matches = self.level.materials.blocksMatching(keyword) + blockInfo = None if len(matches): if len(matches) == 1: - blockType = self.level.materials.materialNamed(matches[0]) + blockInfo = matches[0] #eat up more words that possibly specify a block. stop eating when 0 matching blocks. while len(command): - newMatches = blocksMatching(keyword + " " + command[0]); + newMatches = self.level.materials.blocksMatching(keyword + " " + command[0]); if len(newMatches) == 1: - blockType = self.level.materials.materialNamed(newMatches[0]) + blockInfo = newMatches[0] if len(newMatches) > 0: matches = newMatches keyword = keyword + " " + command.pop(0) @@ -234,23 +228,28 @@ class mce(object): else: try: - blockType = int(keyword); - blockType = blockType & 0xff + data = 0 + if ":" in keyword: + blockID, data = map(int, keyword.split(":")) + else: + blockID = int(keyword) + blockInfo = self.level.materials.blockWithID(blockID, data) + except ValueError: - blockType = None; + blockInfo = None; - if blockType is None: + if blockInfo is None: print "Ambiguous block specifier: ", keyword if len(matches): print "Matches: " for m in matches: - if m == "Future Block!": continue - print "{0:3}: {1}".format(self.level.materials.materialNamed(m),m) + if m == self.level.materials.defaultName: continue + print "{0:3}:{1:<2} : {2}".format(m.ID, m.blockData, m.name) else: print "No blocks matched." raise BlockMatchError - return blockType + return blockInfo def readBlocksToCopy(self, command): blocksToCopy = range(256); @@ -357,17 +356,16 @@ class mce(object): self.printUsage("fill") return; - blockType = self.readBlockType(command) - assert blockType >=0 and blockType < 256 + blockInfo = self.readBlockInfo(command) if len(command): box = self.readBox(command) else: box = None - print "Filling with {0}".format(self.level.materials.names[blockType]) + print "Filling with {0}".format(blockInfo.name) - self.level.fillBlocks(box, blockType) + self.level.fillBlocks(box, blockInfo) self.needsSave = True; @@ -387,12 +385,11 @@ class mce(object): self.printUsage("replace") return; - blockType = self.readBlockType(command) - assert blockType >=0 and blockType < 256 + blockInfo = self.readBlockInfo(command) + if command[0].lower() == "with": command.pop(0) - newBlockType = self.readBlockType(command) - assert newBlockType >=0 and newBlockType < 256 + newBlockInfo = self.readBlockInfo(command) if len(command): box = self.readBox(command) @@ -400,10 +397,9 @@ class mce(object): box = None - print "Replacing {0} with {1}".format(self.level.materials.names[blockType], - self.level.materials.names[newBlockType]) + print "Replacing {0} with {1}".format(blockInfo.name, newBlockInfo.name) - self.level.fillBlocks(box, newBlockType, blockData = 0, blocksToReplace = [blockType]) + self.level.fillBlocks(box, newBlockInfo, blocksToReplace = [blockInfo]) self.needsSave = True; print "Done." @@ -807,12 +803,12 @@ class mce(object): print "Removing grief matter and surface lava above height {0}...".format(box.miny) self.level.fillBlocks(box, - self.level.materials.materialNamed("Air"), - blocksToReplace=[7, - self.level.materials.materialNamed("Obsidian"), - self.level.materials.materialNamed("Fire"), - self.level.materials.materialNamed("Lava (active)"), - self.level.materials.materialNamed("Lava (still)"), + self.level.materials.Air, + blocksToReplace=[self.level.materials.Bedrock, + self.level.materials.Obsidian, + self.level.materials.Fire, + self.level.materials.LavaActive, + self.level.materials.LavaStill, ] ) self.needsSave = True; @@ -1109,16 +1105,19 @@ class mce(object): else: print "{0:3}: {1}".format(searchNumber, self.level.materials.names[searchNumber]) return - - for i in range(len(self.level.materials.names)): - name = self.level.materials.names[i]; - if name == "Future Block!": return; + + matches = [] + for name,b in self.level.materials.blocksByName.iteritems(): + if name is self.level.materials.defaultName: return; if searchName: if not (searchName.lower() in name.lower()): #don't print blocks that don't match the given name or number continue - - print "{0:3}: {1}".format(i, name) + + matches.append(b) + + for b in sorted(matches): + print "{ID:3}:{data:<2} : \"{name}\"".format(ID=b.ID, data=b.blockData, name=b.name) def printUsage(self, command = ""): if command.lower() in self.commands: diff --git a/mclevel.py b/mclevel.py index d6972f2..ae1e051 100644 --- a/mclevel.py +++ b/mclevel.py @@ -29,7 +29,7 @@ level = mclevel.fromFile("server_level.dat"); blocks = level.Blocks # Sand to glass. -blocks[blocks == level.materials.materialNamed("Sand")] = level.materials.materialNamed("Glass") +blocks[blocks == level.materials.Sand.ID] = level.materials.Glass.ID # Save the file with another name. This only works for non-Alpha levels. level.saveToFile("server_level_glassy.dat"); @@ -661,27 +661,45 @@ class MCLevel(object): # end = tuple([o+s for o,s in zip(origin,size)]) return self.Blocks[x:x+w,z:z+l,y:y+h] - def fillBlocks(self, box, blockType, blockData = 0, blocksToReplace = None): + def blockReplaceTable(self, blocksToReplace): + blocktable = zeros( (256, 16), dtype='bool') + for b in blocksToReplace: + if b.hasAlternate: + blocktable[b.ID,b.blockData] = True + else: + blocktable[b.ID] = True + + return blocktable + + def fillBlocks(self, box, blockInfo, blocksToReplace = None): + if box is None: box = self.bounds else: box = box.intersect(self.bounds) - info( u"Filling blocks in {0} with {1}, data={2} replacing{3}".format(box, blockType, blockData, blocksToReplace) ) + info( u"Filling blocks in {0} with {1}, replacing{2}".format(box, blockInfo, blocksToReplace) ) slices = map(slice, box.origin, box.maximum) blocks = self.Blocks[slices[0],slices[2],slices[1]] if blocksToReplace != None: - mask = functools.reduce(operator.or_, (blocks==x for x in blocksToReplace)) - - blocks[mask] = blockType; + blocktable = self.blockReplaceTable(blocksToReplace) + if hasattr(self, "Data"): - self.Data[slices[0],slices[2],slices[1]][mask] = blockData; + data = self.Data[slices[0],slices[2],slices[1]] + mask = blocktable[blocks,data] + + data[mask] = blockInfo.blockData; + else: + mask = blocktable[blocks,0] + + blocks[mask] = blockInfo.ID; + else: - blocks[:] = blockType; + blocks[:] = blockInfo.ID; if hasattr(self, "Data"): - self.Data[slices[0],slices[2],slices[1]] = blockData; + self.Data[slices[0],slices[2],slices[1]] = blockInfo.blockData; #self.saveInPlace(); classicWoolMask = zeros((256,), dtype='bool') @@ -1617,7 +1635,7 @@ class INVEditChest(MCSchematic): Width = 1 Height = 1 Length = 1 - Blocks = array([[[materials.materialNamed("Chest")]]], 'uint8'); + Blocks = array([[[materials.Chest.ID]]], 'uint8'); Data = array([[[0]]], 'uint8'); Entities = TAG_List(); @@ -3426,23 +3444,32 @@ class MCInfdevOldLevel(MCLevel): info( "Removed {0} tile entities".format(count) ) return count; - def fillBlocks(self, box, blockType, blockData = 0, blocksToReplace = None): + def fillBlocks(self, box, blockInfo, blocksToReplace = []): if box is None: chunkIterator = self.getAllChunkSlices() else: chunkIterator = self.getChunkSlices(box) - + + #shouldRetainData = (not blockInfo.hasAlternate and not any([b.hasAlternate for b in blocksToReplace])) + #if shouldRetainData: + # info( "Preserving data bytes" ) + shouldRetainData = False #xxx old behavior overwrote blockdata with 0 when e.g. replacing water with lava + + info("Replacing {0} with {1}".format(blocksToReplace, blockInfo)) + changesLighting = True if blocksToReplace != None: - newAbsorption = self.materials.lightAbsorption[blockType] - oldAbsorptions = map(self.materials.lightAbsorption.__getitem__, blocksToReplace) + blocktable = self.blockReplaceTable(blocksToReplace) + + newAbsorption = self.materials.lightAbsorption[blockInfo.ID] + oldAbsorptions = [self.materials.lightAbsorption[b.ID] for b in blocksToReplace] changesLighting = False for a in oldAbsorptions: if a != newAbsorption: changesLighting = True; - newEmission = self.materials.lightEmission[blockType] - oldEmissions = map(self.materials.lightEmission.__getitem__, blocksToReplace) + newEmission = self.materials.lightEmission[blockInfo.ID] + oldEmissions = [self.materials.lightEmission[b.ID] for b in blocksToReplace] for a in oldEmissions: if a != newEmission: changesLighting = True; @@ -3457,27 +3484,30 @@ class MCInfdevOldLevel(MCLevel): info( u"Chunk {0}...".format(i) ) blocks = chunk.Blocks[slices] - mask = None + data = chunk.Data[slices] + mask = slice(None) needsLighting = changesLighting; if blocksToReplace != None: - mask = functools.reduce(operator.or_, (blocks==x for x in blocksToReplace)) - + mask = blocktable[blocks,data] + blockCount = mask.sum() replaced += blockCount; #don't waste time relighting and copying if the mask is empty if blockCount: - blocks[:][mask] = blockType - chunk.Data[slices][mask] = blockData + blocks[:][mask] = blockInfo.ID + if not shouldRetainData: + data[mask] = blockInfo.blockData else: skipped += 1; needsLighting = False; else: - blocks[:] = blockType - chunk.Data[slices] = blockData + blocks[:] = blockInfo.ID + if not shouldRetainData: + data[:] = blockInfo.blockData chunk.chunkChanged(needsLighting); chunk.compress(); @@ -4102,7 +4132,7 @@ class MCIndevLevel(MCLevel): 8, 9, 10, 11, 12, 13, 14, 15]); - torchIndexes = (self.Blocks == self.materials.materialNamed("Torch")) + torchIndexes = (self.Blocks == self.materials.Torch.ID) info( u"Rotating torches: {0}".format( len(torchIndexes.nonzero()[0]) ) ) self.Data[torchIndexes] = torchRotation[self.Data[torchIndexes]] @@ -4337,7 +4367,7 @@ def testIndevLevels(): indevlevel = MCLevel.fromFile("hueg.mclevel") indevlevel.copyBlocksFrom(srclevel, BoundingBox((0,0,0), (64,64,64,)), (0,0,0) ) assert(all(indevlevel.Blocks[0:64,0:64,0:64] == srclevel.Blocks[0:64,0:64,0:64])) - indevlevel.fillBlocks(BoundingBox((0,0,0), (64,64,64,)), 12, 0, [1,2]) + indevlevel.fillBlocks(BoundingBox((0,0,0), (64,64,64,)), indevlevel.materials.Sand, [indevlevel.materials.Stone, indevlevel.materials.Dirt]) indevlevel.saveInPlace() def testAlphaLevels(): @@ -4366,10 +4396,10 @@ def testAlphaLevels(): except Exception, e: traceback.print_exc(); print e; - level.fillBlocks( BoundingBox((-11, 0, -7), (38, 128, 25)) , 5); + level.fillBlocks( BoundingBox((-11, 0, -7), (38, 128, 25)) , indevlevel.materials.WoodPlanks); c = level.getChunk( 0, 0) assert all(c.Blocks == 5) - level.fillBlocks( BoundingBox((-11, 0, -7), (38, 128, 25)) , 5, 0, [2,3]); + level.fillBlocks( BoundingBox((-11, 0, -7), (38, 128, 25)) , indevlevel.materials.WoodPlanks, [indevlevel.materials.Dirt, indevlevel.materials.Grass]); #print b.shape #raise SystemExit cx, cz = -3,-1;