The Meaning of Life, the Universe, and Everything.
Location:
Kanuckistan
Join Date:
12/16/2010
Posts:
43
Minecraft:
krazeecain
Member Details
I'm currently working on a MCEdit filter that will convert all microblocks from Redpower 2 (which hasn't been updated since 1.4.7, and is officially canned since Eloraam is now working on a game instead.) to Forge microblocks. I'm doing this because my friend and I made quite a large castle/village that utilizes a LOT of microblocks. Moving on simply isn't an option for us (we're not even finished yet >.>) and I'm getting sick of being so far behind on MC updates and other cool mods. After some digging I haven't found any feasible solution from anyone else (if there is one, please let me know!) so I'm taking matters into my own hands. I'll be updating this thread as I progress.
So far I've broken down the NBT structure of RP2 microblocks using a NBT editor filter for MCEdit. My findings are as follows:
sched: I'm not sure what this does, but it always equals -1. I'm assuming it has something to do with updating the blocks in-game. I'll be ignoring this value.
id: This is a string that's always equal to "Covers". I believe I'll have to change this to whatever the id is for forge multiblocks.
cvs: I believe this is an int_array (the editor won't tell me exactly what type of variables they are) that adds a certain number of pairs corresponding to how many different parts are in the block. The first number defines the material (0 being cobble up to 68 being copper), while the second number defines the size. The second number also defines whether a face-type part is hollow or not, depending on what number it is. Here's how it maps out:
Any multiblock part that isn't a hollow face from smallest to largest: 0,1,6,2,7,8,9
Hollow faces: 3,4,10,5,11,12,13
Columns (only 3 sizes available): 0,1,2
EDIT: This wasn't quite right, edges and corners also use slightly different values, from biggest to smallest:
Edges and Corners: 0,1,3,2,4,5,6
cvm: This one is interesting, and threw me through a loop at first. The NBT editor filter in MCEdit shows this as a 32-bit integer, but in reality the way this functions is at a binary level. Each bit from 1-29 corresponds to a certain shape and location of a part (but not the size, that's defined in CVS). As there's only 29 possible parts and locations, and you can't have more than one of each within a block, this system works quite well. I've mapped out each part and location to their corresponding bit as such:
[Face(+Hollow Face)]
1 = Bottom
2 = Top
3 = North
4 = South
5 = west
6 = East
[Corner]
7 = Bottom NW
8 = Bottom SW
9 = Bottom NE
10 = Bottom SE
11 = Top NW
12 = Top SW
13 = Top NE
14 = Top SE
[Strip] 15 = Bottom North
16 = Bottom South
17 = Bottom west
18 = Bottom East
19 = Upright NW
20 = Upright SW
21 = Upright NE
22 = Upright SE
23 = Top North
24 = Top South
25 = Top West
26 = Top East
[Column]
27 = Upright
28 = North to South
29 = West to East
Yeah that took me a while, but it'll hopefully be worth it!
I haven't looked too much into the forge multiblock system yet, as it seems to be much more intuitive. But I'll be looking into it more as I create this script.
from pymclevel import TAG_List
from pymclevel import TAG_Byte
from pymclevel import TAG_Byte_Array
from pymclevel import TAG_Int
from pymclevel import TAG_Compound
from pymclevel import TAG_String
def perform(level, box, options):
for (chunk, slices, point) in level.getChunkSlices(box):
for te in chunk.TileEntities:
x = te["x"].value
y = te["y"].value
z = te["z"].value
if (level.blockAt(x, y, z) == options["RP2 Block ID:"]):
te["parts"] = TAG_List()
c = 0
for i in xrange(0, 29): #Cycle through possible bits in CVM
if testBit(te["cvm"].value, i) != 0: #Add a part
c = c + 1
partsx = TAG_Compound()
partsx["material"] = matMap[te["cvs"].value[(c*2)-2]]
tes = te["cvs"].value[(c*2)-1]
if (0 <= i < 6):
if (2 < tes < 6) or ( 9 < tes < 14):
partsx["id"] = "mcr_hllw"
else:
partsx["id"] = "mcr_face"
sizei = sizeMapFace[tes] << 4
if (6 <= i < 14):
partsx["id"] = "mcr_cnr"
sizei = sizeMapCorner[tes] << 4
if (14 <= i < 26):
partsx["id"] = "mcr_edge"
sizei = sizeMapCorner[tes] << 4
if (i >= 26):
partsx["id"] = "mcr_post"
sizei = 32 * (tes + 1)
By default I mapped out the materials to only use vanilla and ProjectRed textures. The metal blocks simply turn into iron, and pumpkins are replaced by glowstone (since fmp doesn't seem to work on pumpkins for some reason...) If you want to change some of these materials, you'll have to edit the script yourself (you can use notepad or whatever). All the materials are stored in an array under "matMap" near the top of the script.
Another thing to watch out for are the block ID's, FTB modpack Infinity uses block ID 1278 for FMP blocks, while a custom pack that I threw together uses 254 (which is the default in my script), So check on that before using the script!
Aside from those points, the script works fairly simply, just select the chunk of the world you want to save, and run the filter on it. I'm not sure anyone cares about this anymore since redpower 2 is so old at this point, but I hope someone else finds this useful! Feel free to ask any questions.
The Meaning of Life, the Universe, and Everything.
Location:
Kanuckistan
Join Date:
12/16/2010
Posts:
43
Minecraft:
krazeecain
Member Details
I finished mapping out the materials. I arranged the materials in an array, such that I can address the array using the ID number from the old system, and it will return the right string for forge. Here it is:
I also figured out how FMP's system works, it wasn't quite as intuitive as I thought at first. Each part is stored as a TAG_Compound under a TAG_List called "parts", id defines the shape (mcr_face, mcr_edge, mcr_cnr, mcr_hllw, or mcr_post), material stores the material texture type as a string, and shape uses a similar bit manipulation system as RP2, but a bit simpler (or... 24 bits simpler! haha... anyone? *ahem* okay...) It stored an 8-bit... int I think, and the first 4 bits define the size, whilst the last 4 bits define position. This one's easier to work with, as all I have to do is figure out the size of the block, and then shift that 4 bits to the left in the variable. (Not that I actually know how to do that at this moment, but I'll figure it out!)
The Meaning of Life, the Universe, and Everything.
Location:
Kanuckistan
Join Date:
12/16/2010
Posts:
43
Minecraft:
krazeecain
Member Details
Sorry for the late reply. You need to change 254 to the block ID of forge microblocks in your new world. This is because in the new versions of Minecraft/Forge, all of the block ID's are assigned randomly to each block type in a new, or converted world. This means that if you're trying to import your whole world into 1.7.10, the process is a bit clumsy:
-Make a backup copy of your old world (hopefully you've already done this), then open it in your new 1.7.10 pack.
-Your redpower microblocks will get deleted upon opening, don't worry about this for now.
-Place some new forge microblocks in this world.
-Open that world in MCEdit, find those microblocks you placed and take note of their block ID.
-Re-import your world. This part is a little tricky, your best bet is probably to copy all of the .mcr files from your backup, directly into the 1.7.10 world folder. This might not work though. Basically, your goal is to restore all of the redpower microblocks that got deleted. Another way would be to open your backup copy of the world in mcedit, and export each building seperately, then re-import them into your new version of the world.
-Open your new copy of the world in MCEdit, then run my filter, using 751 or 750 as the first block ID, then the new microblock ID you took note of earlier.
Hopefully that should work for you! As for the redpower 2 only microblocks and how they're handled, by default they should convert to project red blocks, if you have it installed. Or you can pick whatever block you want for each by editing the filter in a text editor, all of the blocks are under "matMap". I believe I added #comments for all of the blocks that weren't clear about what they were. Replace each tile.whatever with the block name that you want it to be.
I'm currently working on a MCEdit filter that will convert all microblocks from Redpower 2 (which hasn't been updated since 1.4.7, and is officially canned since Eloraam is now working on a game instead.) to Forge microblocks. I'm doing this because my friend and I made quite a large castle/village that utilizes a LOT of microblocks. Moving on simply isn't an option for us (we're not even finished yet >.>) and I'm getting sick of being so far behind on MC updates and other cool mods. After some digging I haven't found any feasible solution from anyone else (if there is one, please let me know!) so I'm taking matters into my own hands. I'll be updating this thread as I progress.
So far I've broken down the NBT structure of RP2 microblocks using a NBT editor filter for MCEdit. My findings are as follows:
sched: I'm not sure what this does, but it always equals -1. I'm assuming it has something to do with updating the blocks in-game. I'll be ignoring this value.
id: This is a string that's always equal to "Covers". I believe I'll have to change this to whatever the id is for forge multiblocks.
cvs: I believe this is an int_array (the editor won't tell me exactly what type of variables they are) that adds a certain number of pairs corresponding to how many different parts are in the block. The first number defines the material (0 being cobble up to 68 being copper), while the second number defines the size. The second number also defines whether a face-type part is hollow or not, depending on what number it is. Here's how it maps out:
Any multiblock part that isn't a hollow face from smallest to largest: 0,1,6,2,7,8,9
Hollow faces: 3,4,10,5,11,12,13
Columns (only 3 sizes available): 0,1,2
EDIT: This wasn't quite right, edges and corners also use slightly different values, from biggest to smallest:
Edges and Corners: 0,1,3,2,4,5,6
cvm: This one is interesting, and threw me through a loop at first. The NBT editor filter in MCEdit shows this as a 32-bit integer, but in reality the way this functions is at a binary level. Each bit from 1-29 corresponds to a certain shape and location of a part (but not the size, that's defined in CVS). As there's only 29 possible parts and locations, and you can't have more than one of each within a block, this system works quite well. I've mapped out each part and location to their corresponding bit as such:
[Face(+Hollow Face)]
1 = Bottom
2 = Top
3 = North
4 = South
5 = west
6 = East
[Corner]
7 = Bottom NW
8 = Bottom SW
9 = Bottom NE
10 = Bottom SE
11 = Top NW
12 = Top SW
13 = Top NE
14 = Top SE
[Strip] 15 = Bottom North
16 = Bottom South
17 = Bottom west
18 = Bottom East
19 = Upright NW
20 = Upright SW
21 = Upright NE
22 = Upright SE
23 = Top North
24 = Top South
25 = Top West
26 = Top East
[Column]
27 = Upright
28 = North to South
29 = West to East
Yeah that took me a while, but it'll hopefully be worth it!
I haven't looked too much into the forge multiblock system yet, as it seems to be much more intuitive. But I'll be looking into it more as I create this script.
###########################################################
EDIT: And I'm done! Here's the link:
http://sourceforge.net/projects/cainsmceditfilters/files/RP2Conversion.py/download
Here's the raw text in a spoiler just in case the link stops working, just put the following text into a file called "RP2FMP.py":
displayName = "RP2 to FMP Conversion"
from pymclevel import TAG_List
from pymclevel import TAG_Byte
from pymclevel import TAG_Byte_Array
from pymclevel import TAG_Int
from pymclevel import TAG_Compound
from pymclevel import TAG_String
matMap = ['tile.stonebrick',
'tile.stone',
'tile.wood',
'tile.sandStone',
'tile.stoneMoss',
'tile.brick',
'tile.obsidian',
'tile.glass',
'tile.dirt',
'tile.clay',
'tile.bookshelf',
'tile.hellrock',
'tile.log',
'tile.log_1',
'tile.log_2',
'tile.hellsand',
'tile.stone',
'tile.blockIron',
'tile.blockGold',
'tile.blockDiamond',
'tile.blockLapis',
'tile.snow',
'tile.lightgem', #pumpkin
'tile.stonebricksmooth',
'tile.stonebricksmooth_1',
'tile.stonebricksmooth_2',
'tile.netherBrick',
'tile.stonebricksmooth_3',
'tile.wood_1',
'tile.wood_2',
'tile.wood_3',
'tile.sandStone_1',
'tile.cloth',
'tile.cloth_1',
'tile.cloth_2',
'tile.cloth_3',
'tile.cloth_4',
'tile.cloth_5',
'tile.cloth_6',
'tile.cloth_7',
'tile.cloth_8',
'tile.cloth_9',
'tile.cloth_10',
'tile.cloth_11',
'tile.cloth_12',
'tile.cloth_13',
'tile.cloth_14',
'tile.cloth_15',
'tile.projectred.exploration.stone',
'tile.projectred.exploration.stone_3',
'tile.projectred.exploration.stone_1',
'tile.projectred.exploration.stone_2',
'tile.projectred.exploration.stone_4',
'tile.log_3',
'tile.projectred.exploration.stone_5',
'tile.blockEmerald',
'tile.projectred.exploration.stone_6',
'tile.stonebricksmooth_3', #chiselled basalt
'tile.stone', #basalt paver
'tile.stone',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.sandStone_2',
'tile.log_3',
'tile.blockIron', #silver block
'tile.blockIron', #tin block
'tile.blockIron'] #copper block
oriMap = [0,
1,
2,
3,
4,
5,
0,
2,
4,
6,
1,
3,
5,
7,
8,
10,
4,
5,
0,
1,
2,
3,
9,
11,
6,
7,
0,
1,
2,
3]
sizeMapFace = [1,
2,
4,
1,
2,
4,
3,
5,
6,
7,
3,
5,
6,
7,
]
sizeMapCorner = [1,
2,
4,
3,
5,
6,
7]
inputs = (
("RP2 Block ID:", 751),
("FMP Block ID:", 254)
)
def perform(level, box, options):
for (chunk, slices, point) in level.getChunkSlices(box):
for te in chunk.TileEntities:
x = te["x"].value
y = te["y"].value
z = te["z"].value
if (level.blockAt(x, y, z) == options["RP2 Block ID:"]):
te["parts"] = TAG_List()
c = 0
for i in xrange(0, 29): #Cycle through possible bits in CVM
if testBit(te["cvm"].value, i) != 0: #Add a part
c = c + 1
partsx = TAG_Compound()
partsx["material"] = matMap[te["cvs"].value[(c*2)-2]]
tes = te["cvs"].value[(c*2)-1]
if (0 <= i < 6):
if (2 < tes < 6) or ( 9 < tes < 14):
partsx["id"] = "mcr_hllw"
else:
partsx["id"] = "mcr_face"
sizei = sizeMapFace[tes] << 4
if (6 <= i < 14):
partsx["id"] = "mcr_cnr"
sizei = sizeMapCorner[tes] << 4
if (14 <= i < 26):
partsx["id"] = "mcr_edge"
sizei = sizeMapCorner[tes] << 4
if (i >= 26):
partsx["id"] = "mcr_post"
sizei = 32 * (tes + 1)
sizei = sizei + oriMap
partsx["shape"] = TAG_Byte(sizei)
te["parts"].append(partsx)
te["id"]="savedMultipart"
level.setBlockAt(x, y, z, options["FMP Block ID:"])
chunk.dirty = True
def testBit(int_type, offset):
mask = 1 << offset
return(int_type & mask)
By default I mapped out the materials to only use vanilla and ProjectRed textures. The metal blocks simply turn into iron, and pumpkins are replaced by glowstone (since fmp doesn't seem to work on pumpkins for some reason...) If you want to change some of these materials, you'll have to edit the script yourself (you can use notepad or whatever). All the materials are stored in an array under "matMap" near the top of the script.
Another thing to watch out for are the block ID's, FTB modpack Infinity uses block ID 1278 for FMP blocks, while a custom pack that I threw together uses 254 (which is the default in my script), So check on that before using the script!
Aside from those points, the script works fairly simply, just select the chunk of the world you want to save, and run the filter on it. I'm not sure anyone cares about this anymore since redpower 2 is so old at this point, but I hope someone else finds this useful! Feel free to ask any questions.
matMap = [
'tile.stonebrick',
'tile.stone',
'tile.wood',
'tile.sandStone',
'tile.stoneMoss',
'tile.brick',
'tile.obsidian',
'tile.glass',
'tile.dirt',
'tile.clay',
'tile.bookshelf',
'tile.hellrock',
'tile.log',
'tile.log_1',
'tile.log_2',
'tile.hellsand',
'tile.stone',
'tile.blockIron',
'tile.blockGold',
'tile.blockDiamond',
'tile.blockLapis',
'tile.snow',
'tile.lightgem',
'tile.stonebricksmooth',
'tile.stonebricksmooth_1',
'tile.stonebricksmooth_2',
'tile.netherBrick',
'tile.stonebricksmooth_3',
'tile.wood_1',
'tile.wood_2',
'tile.wood_3',
'tile.sandStone_1',
'tile.cloth',
'tile.cloth_1',
'tile.cloth_2',
'tile.cloth_3',
'tile.cloth_4',
'tile.cloth_5',
'tile.cloth_6',
'tile.cloth_7',
'tile.cloth_8',
'tile.cloth_9',
'tile.cloth_10',
'tile.cloth_11',
'tile.cloth_12',
'tile.cloth_13',
'tile.cloth_14',
'tile.cloth_15',
'tile.projectred.exploration.stone',
'tile.projectred.exploration.stone_3',
'tile.projectred.exploration.stone_1',
'tile.projectred.exploration.stone_2',
'tile.projectred.exploration.stone_4',
'tile.log_3',
'tile.projectred.exploration.stone_5',
'tile.blockEmerald',
'tile.projectred.exploration.stone_6',
'tile.stonebricksmooth_3',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.stone',
'tile.sandStone_2',
'tile.log_3',
'tile.thermalfoundation.storage_2"',
'tile.thermalfoundation.storage_1',
'tile.thermalfoundation.storage'
]
I also figured out how FMP's system works, it wasn't quite as intuitive as I thought at first. Each part is stored as a TAG_Compound under a TAG_List called "parts", id defines the shape (mcr_face, mcr_edge, mcr_cnr, mcr_hllw, or mcr_post), material stores the material texture type as a string, and shape uses a similar bit manipulation system as RP2, but a bit simpler (or... 24 bits simpler! haha... anyone? *ahem* okay...) It stored an 8-bit... int I think, and the first 4 bits define the size, whilst the last 4 bits define position. This one's easier to work with, as all I have to do is figure out the size of the block, and then shift that 4 bits to the left in the variable. (Not that I actually know how to do that at this moment, but I'll figure it out!)
I will pm you.. because i have some questions regarding this thread.. i am quite interested. in this.
This is precisely what I've been looking for, thanks!
Sorry for the late reply. You need to change 254 to the block ID of forge microblocks in your new world. This is because in the new versions of Minecraft/Forge, all of the block ID's are assigned randomly to each block type in a new, or converted world. This means that if you're trying to import your whole world into 1.7.10, the process is a bit clumsy:
-Make a backup copy of your old world (hopefully you've already done this), then open it in your new 1.7.10 pack.
-Your redpower microblocks will get deleted upon opening, don't worry about this for now.
-Place some new forge microblocks in this world.
-Open that world in MCEdit, find those microblocks you placed and take note of their block ID.
-Re-import your world. This part is a little tricky, your best bet is probably to copy all of the .mcr files from your backup, directly into the 1.7.10 world folder. This might not work though. Basically, your goal is to restore all of the redpower microblocks that got deleted. Another way would be to open your backup copy of the world in mcedit, and export each building seperately, then re-import them into your new version of the world.
-Open your new copy of the world in MCEdit, then run my filter, using 751 or 750 as the first block ID, then the new microblock ID you took note of earlier.
Hopefully that should work for you! As for the redpower 2 only microblocks and how they're handled, by default they should convert to project red blocks, if you have it installed. Or you can pick whatever block you want for each by editing the filter in a text editor, all of the blocks are under "matMap". I believe I added #comments for all of the blocks that weren't clear about what they were. Replace each tile.whatever with the block name that you want it to be.
Good luck!