EngineHub / WorldEdit

🗺️ Minecraft map editor and mod
https://enginehub.org/worldedit/
Other
3.06k stars 828 forks source link

Place axis-aware blocks: Optimize for density of block at the axis-pointing surface #2380

Open mk-pmb opened 12 months ago

mk-pmb commented 12 months ago

The Problem

I'm building grids of oak logs and chains in water or air. It's tedious to select lots of small regions in order to set the correct orientation.

A Solution

My concept of block density is: void < air < non-air liquid < partial block < transparent full block < opaque full block.

I'd like to give my preference for whether the axis-aligned sides (oak log rings, chain ends) should prefer higher or lower density, and a priority list of fixed directions that decides in the case the density preference can be satisfied equally by multiple axes. The measurement of neighboring blocks' density shall compare the block that would be the neighbor after placement. Example: When placing a straight line of chain floating in air, it would compare to the to-be-placed chains and thus a preference for higher density would connect all of them.

The syntax could be something like //replace glass oak_log[axis=Dxz] where D means high density (d = low density). If multiple axes will achieve it: If one of them is the X axis, use [axis=x]. Otherwise, if the Z axis is one of the equally-good axes, use [axis=z]. If there's still ambiguity, pick any of the good axes. (In this example, there should only be one remaining choice anyway.)

Alternatives

No response

Anything Else?

No response

octylFractal commented 12 months ago

You're going to have to clarify this more, maybe with some pictures. It's not clear how your definition of density applies to an axis.

Moreover, this sounds incredibly specific and complex, and might be better suited as an expression mask.

mk-pmb commented 12 months ago

What kind of picture would help? I assume, a screenshot of my glass construction that shall be converted?

I made a simplified version of just the framework without surroundings and without the interiors of the rooms:

We'll need numerical values for the densities. I have no experience what would be good numbers, but for the explanation in this post, these will work well enough:

Density Block category Relevant examples
0 void
1 air air, cave_air
2 non-air liquid water, lava
4 partial block chain, oak_fence
8 transparent full block glass, glowstone
16 opaque full block oak_log

Some users will probably want an easy way to configure their own values, but that's not part of this feature request, because for me it's easy to patch and recompile.

Now assume I have a cuboid selection that includes the blocks that are marked with letters, and I issue the suggested command: //replace glass oak_log[axis=Dxz]

WE would need to replace block A. To do so, it assesses a score for each possible axis value.

Block B: Same except the X neighbors are A and C, which will both become oak logs (16), sum = 32, winning with even more of a margin. B will become oak_log[axis=x].

Block K: For both X and Z axis, the neighbors are air (1) so their sum is 2. Y axis is the same situation as A but rotated: The neighbors are the corner glowstone (8) and block L which will become oak log (16), sum = 24. K will become oak_log[axis=y].

Block L: For both X and Z axis, the neighbors are air (1) so their sum is 2. Y axis neighbors (K and M) will become oak log (16) so their sum is 32. Y axis wins, L will become oak_log[axis=y].

Block P: Like A but rotated, will become oak_log[axis=z].

Block Q: Like B but rotated, will become oak_log[axis=z].

If I were to add glowstone to the //replace pattern, WE would have to also replace the corner glowstone.

I haven't checked inner corners yet, but I'm very optimistic that with this algorithm, selecting the entire structure and applying //replace glass,glowstone oak_log[axis=Dxz] (Edit: probably rather Dyx) will place solid oak pillars and connect them horizontally using oak trunk segments of length 9, giving a result that would perfectly //rotate 90 into itself.