Litematica (Forge)

Litematica (Forge)

336k Downloads

Change block types in GUI

rootinchase opened this issue ยท 20 comments

commented

Is your feature request related to a problem? Please describe.
I use a set building block in my testing world, but when I deploy my creations into my actual world, I change what my building material is.

For example I build a sorter using colored wool for the internal redstone, and purpur blocks for the outside design. In my world I want use minecraft:smooth_stone for the internals instead, since it's easier, and oak planks for the outside to fit in with the build.

I would like a way to change all instances of a block type to something else. This would make the pick block better,and help show the play what they're doing.

Describe the solution you'd like
I would like a way to change all instances of a block type to something else. This would probably exist in the Schematic Placement Configuration, or under Material list. To use, you would select the block type in the list, click change, and there would be a field to type in the new block type.

Describe alternatives you've considered
I have tried creating new schematics with the wanted blocks, but it is tedious, and requires changing worlds

  1. A fill command on the OG, (fill ax ay az bx by bz new_block replace old_block)
  2. Create a new schematic like that
  3. Revert the fill command

I've also have ignored it, but it make pick block useless

commented

This worked for me once... changing white concrete to cobble but the problem is I can't change the white stained glass to normal glass!

image

it says that... stuff about sub chunks. what should I do to fix this? been at it now for half an hour.

commented

@aghiuebcuae You just need to select that placement you are working on. Go the the Schematic Placement menu, and click on it so that it has the white outline.

commented

@maruohon
I can change something like concrete to cobble but it simply won't let me change white stained glass to normal glass... i am building the rest of the schematic perfectly fine.

i have already built some of the normal glass where white stained glass is meant to be, is that the problem maybe??

commented

@aghiuebcuae No that doesn't matter "for the most part". The only "restriction" with the replaceAll function (like all schematic edit functions) is that you need to be right clicking on a schematic block. I don't remember for sure if it works if you have already placed that block (ie. does the mod in that case ray trace to the schematic block or the real block). So maybe just try clicking on a position where you haven't placed the block to yet (or temporarily remove it) so that you will be for sure clicking on the schematic block.

commented

Is this still the intended way to replace all of one type of a block? I noticed that schematicRebuildReplaceAll has been updated to schematicEditReplaceAll, and it appears "Rebuild Mode" has been renamed to "Edit Mode". I have tried holding my set hotkey (u) and right-clicking on the desired schematic block, but it seems to just place that block on top of the schematic block. Has something changed, or am I just doing something wrong?

commented

@AD-Wright It is yes, I still haven't had time to work on the GUI-based functionality yet.

Did you get the colored overlay with the white square when you hold the key? If not then the key wasn't recognized (or you have shaders enabled which might break the rendering of that overlay, but that would then also likely break the schematic rendering as well so I assume this isn't the case). If you use the current 1.16.5 Forge version, then the hotkey configs are buggy and they only get applied when you re-log to the world.

commented

I am using a recent version of Fabric, and on 1.18.2. I tried re-logging and disabling shaders, that did not fix anything, but I decided to try disabling every fabric mod except malalib and Litematica, and it works now! So one of the mods in "Fabuously Optimized" apparently conflicts with Litematica. It doesn't contain OptiFine, but perhaps it still messes with it somehow.

Thank you for your help.

commented

Love the mod, performs better than I would have expected.
It would be awesome if it was possible to change the block type in the material list or similar UI.

commented

Like i said i don't know much of a pyton nor the internal structure of file so i just did some quick and dirty way to replace the building blocks of source schematics, feel free to improve if you know the better way. Its not a tool that needs to be fast. And i did it with some python library (litemapy) so i don't actually know how it works internally. It was mostly guesswork so I just iterate over all region and all blocks and replace them all.

EDIT: I just wanted this to replace the decorative/building blocks to what i like/have.

commented

The proposed way to replace the blocks was unfortunately too painful for me so i wrote some mini script for python (which i don't know and don't like) to replace the blocks from source schematic and never have to deal with accidentally removing or replacing wrong blocks or randomly getting my work to be gone after chunk has been unloaded:

requirements:

  • python no idea about the version
  • running in console pip install litemapy

how to run:
save this gist as some file, ex replace.py: https://gist.github.com/pwilkowski/907c677b0e6a3508453019b3836a4a82
edit the section blocksToReplace with your replacements
source which we want to replace as file with name source.litematic
running in console py replace.py

and output output.litematic should be generated

as a companion script i also wrote another script to list all the mats: https://gist.github.com/pwilkowski/40b79d7785cb00cc5f66a8c5147c046e

commented

@pwilkowski If you are replacing a block in the entire schematic region and not only within some given box within the region, then it would be a lot faster (although this would only be noticeable with larger schematics), and also safer (due to not needing container resizes or changes at all) to just replace the block in the palette. This would be done in each region.

So basically there is no need to iterate the entire volume of blocks and replace each of a given ID with another ID, when you can just simply change what that ID maps to.

Another thing that you probably don't want to bother with, is optimizing the material list generation by using lower level access. So you could iterate through the backing long array and count the occurrence of each raw integer ID in there (I mean the bit-packed block IDs, so you still need to iterate through it using bit shifts to get the IDs out), and then finally just map those IDs to actual blocks. This would allow you to use a faster array based storage for the block counts.

commented

Hello, Litemapy developer here.
Sorry for necro-ing the discussion, I just came across it and I wanted to added some precisions and insight on how you can do block replacement with Litemapy.

@pwilkowski If you want to keep the loop version, you can use Region.allblockpos() to get an iterator over the positions in the schematics, that avoids the nested for loops, and you can use BlockState.with_block_id() to change the ID without having to access the internal property array.

That would look something like this:

for reg in regions:
    for x, y, z in reg.allblockpos():
        b = reg.getblock(x, y, z)
        if b.blockid in blocksToReplace:
            newBlock = b.with_blockid(blocksToReplace[b.blockid])
            reg.setblock(x, y, z, newBlock)

Now, as @maruohon pointed out, unless you need the blocks' position, it's faster to work with the palette. You can do that with Region.filter().

def replace(b: BlockState) -> BlockState:
    if b.blockid in blocksToReplace:
        return b.with_blockid(blocksToReplace[b.blockid])
    else:
        return b

for reg in regions:
    reg.filter(replace)

Depending on the size of the litematic, that could be faster by several orders of magnitude.

commented

Did you try rebuild mode?

commented

Rebuild mode is exactly for this purpose. But there will likely also be a GUI alternative like you described, where you can just pick a replacement block for a given block from a list.

commented

And here is how to use the Rebuild mode:

Litematica's Rebuild mode for changing schematic blocks (= editing schematics) quick howto:

- Change all identical blocks of one type to another type:

  1. Set a hotkey for schematicRebuildReplaceAll
  2. Change to Schematic Rebuild mode (Litematica menu bottom left)
  3. Hold that hotkey and right click on one of the blocks you want to replace, while holding the new block in your hand
  4. Change out of Schematic Rebuild mode

- Change or remove or add individual blocks:

  1. Change to Schematic Rebuild mode (Litematica menu bottom left)
  2. To remove blocks, just punch them out like in creative mode
  3. To add blocks, just place them against other existing schematic blocks
  4. To change individual blocks or blocks in continuous lines, set a hotkey for schematicRebuildReplaceDirection, and then again hold that key while right clicking on the old block with the new block

- Remove all blocks of one type:

  1. Change to Schematic Rebuild mode (Litematica menu bottom left)
  2. Set a hotkey for schematicRebuildBreakPlaceAll
  3. Hold that hotkey while punching out one of the blocks you want to remove all of.
  4. If you want to fill all air spaces in the schematic with a block, then place that new block against an existing schematic block while holding that hotkey.
  5. Similarly if you want to break or place blocks in continuous lines (through a single continuous line of identical blocks), then use the schematicRebuildBreakPlaceDirection hotkey while punching or placing the block.

- Tips:

  • You can use the Render Layers to limit the range in which the blocks get removed/replaced.
  • The block state that is used when right clicking is the state that would be normally placed to the position where you click. So for example top/bottom slabs happen like they would be placed in vanilla.
  • You can also "store" block states from the world, by default by left Alt + middle clicking, and then you can do the Rebuild operation with an empty main hand to use that "stored" state. This allows using things like open trap doors or water logged blocks etc. (basically anything) that you can't do when just directly "placing" a block.
  • If you want to keep the changes, save the schematic again from the Loaded Schematics list.
  • Don't override the original file when saving, as there is a bug currently in the block handling that can corrupt the rebuilt schematic in certain cases when it's reloaded from file (depends on the number of unique block states before and after the Rebuild operation).
commented

It's finally my days off and I was able to try it, and it works easily.

I would like to see it in the GUI, so I've changed the name, so this can be used to track when it gets added (and yes, I will be looking into adding it)

commented

@maruohon Tried the approach you mentioned, it's useful, but being able to do it from the GUI would be so much more amazing.

Current problems:

  • Often I forget to change away from "Rebuild" mode after I replaced a block. Then right clicking will replace that single block. And there's no undo that I was able to find.
  • Changes are not applied to everything. Ie. changing bottom half slabs does not apply to top half slabs/double slabs.
  • The fact Render Layers limits the range is more of a hindrance than a useful thing IMHO. Especially while building in survival, sometimes it is very difficult to access a certain block (like a carpet on top of hoppers, surrounded by blocks. I have to switch to Single Layer, but then the change doesn't apply globally.

I'm still a noob at using Litematica, so some of it could be attributed to that of course.

commented

Yep all of those are valid concerns and quite common issues with the current Rebuild mode. There are various changes and improvements planned for it, mostly via a new GUI that would allow you to do the replacement, and probably also on option in that GUI for selecting whether or not the replacement should be limited to the current render layers, and/or also to within an area selection (this will be a new feature), or done to the entire schematic regardless of the render layers setting.

commented

Yep all of those are valid concerns and quite common issues with the current Rebuild mode. There are various changes and improvements planned for it, mostly via a new GUI that would allow you to do the replacement, and probably also on option in that GUI for selecting whether or not the replacement should be limited to the current render layers, and/or also to within an area selection (this will be a new feature), or done to the entire schematic regardless of the render layers setting.

any updates?

commented

No updates yet. I haven't had time to do much of anything for Litematica in the past year. Most of my modding time in recent months has gone to rewriting malilib. Litematica rewrites will start once malilib is completely done first.