# Big simplification of slabs combination #1111

Closed
wants to merge 1 commit into from

## Conversation

Projects
None yet
8 participants
Member

### sofar commented May 24, 2016

 Combine slabs if identical based on orientations using a simple lookup table if the nodes are identical. Otherwise relies on place_node() to place the node, which properly handles rotation compared to adjacent nodes already, and can orient based on look_dir as well. Largely based on kilbith's #807 PR. Slab combining and place_node() usage by sofar.
Member Author

### sofar commented May 24, 2016

 Replaces #807
Member Author

### sofar commented May 24, 2016

 Fixes #1109
Member Author

### sofar commented May 24, 2016

 @everamzah @ShadowNinja @paramat @webdesigner97 Please test this, It was somewhat late when I wrote this but I think this is the proper solution with the minimal amount of code.

### Ekdohibs reviewed May 24, 2016

 if n0_is_upside_down and p0.y + 1 ~= p1.y then param2 = 20 -- else attempt to place node with proper param2 minetest.item_place_node(ItemStack(wield_item), clicker, pointed_thing, node.param2)

#### Ekdohibs May 24, 2016

Member

So you can't place upside-down slabs if the node above hasn't a 20-23 param2?

#### sofar May 24, 2016

Author Member

You can place upside down slabs without issues. If you place any slab against the side of an already-upside down slab, it will also be upside-down.

You can also combine an upside down slab from below with another slab.

#### Ekdohibs May 24, 2016

Member

How do you place the first upside-down slab, then?

#### sofar May 24, 2016

Author Member

Can't. Need screwdriver once.

#### sofar May 27, 2016

Author Member

Fixed in a push to allow upside down placement and placement against walls.

Closed

Contributor

### webD97 commented May 24, 2016

 It's working fine for me, this is the behaviour I expected. Thanks for your quick reaction this problem, now I hope we can successfully merge this.

### ghost commented May 24, 2016

 Tested and works as expected. The only concern left is that using `set_node` and `item_place_node` bypasses the `register_on_placenode` callbacks (such as lowering satiation in hunger mod), which is present when using on_place. I think this doesn't matter so much, though, if it is the case. 👍
Contributor

### Fixer-007 commented May 24, 2016

 Will be nice to have this.
Contributor

### PilzAdam commented May 27, 2016

 👎 if it's not possible to place the first slab upside-down without screwdriver.
Member Author

### sofar commented May 27, 2016

 @PilzAdam I'll see if I can add that. Do you expect the player look direction to be the deciding factor for the slab orientation, or the orientation of the selected face?

### 0-afflatus commented May 27, 2016

 Do you expect the player look direction to be the deciding factor for the slab orientation, or the orientation of the selected face? Personally, the orientation of the selected face.
Member Author

### sofar commented May 27, 2016 • edited

 @PilzAdam added placement "to" a face. If under the placement face is an existing slab, the slab is placed the same as the previously placed slab. But if the node pointed under is something else (a normal node), then the slab will be oriented appropriately. This allows upside down placement, or placement against a wall. Without any screwdriver. Tested and slab combining and extending slabs all work fine. Please give it a try.
Member Author

Contributor

### Fixer-007 commented May 29, 2016 • edited

 Hmm, I may have some problems with it: slab on slab (for some reason it is not placing it properly)-> https://i.imgur.com/AohJDvy.png stair on slab (not sure if related but trying to place stair on that slab from different angles, and it stands the same like this -> https://i.imgur.com/TXCEyTx.png Edit: found lua error, hold on a sec: Trying to place any kind of door between those slab-walls: https://i.imgur.com/tdnIbhG.png Error: ``````2016-05-30 01:33:31: ERROR[Main]: ServerError: Lua: Runtime error from mod 'doors' in callback item_OnPlace(): ...minetest\bin\..\games\minetest_game\mods\stairs\init.lua:147: attempt to index local 'pointed_thing' (a nil value) 2016-05-30 01:33:31: ERROR[Main]: stack traceback: 2016-05-30 01:33:31: ERROR[Main]: ...minetest\bin\..\games\minetest_game\mods\stairs\init.lua:147: in function <...minetest\bin\..\games\minetest_game\mods\stairs\init.lua:146> ``````
Member Author

### sofar commented May 29, 2016

 Hmm, I may have some problems with it: slab on slab (for some reason it is not placing it properly)-> https://i.imgur.com/AohJDvy.png on purpose. You're placing an slab on an upside-down slab, so it copies the orientation. I could try and make an exception for this, but it would result in very messy and lengthy code. stair on slab (not sure if related that's basically the same as the above issue. Looking into the door problem atm.
Member Author

### sofar commented May 29, 2016

 Edit: found lua error, hold on a sec: Trying to place any kind of door between those slab-walls: https://i.imgur.com/tdnIbhG.png This is an error in the Door mod. Fixed by #1119
Contributor

### Fixer-007 commented Jun 21, 2016

 Why is this still not reviewed?
Member Author

### sofar commented Jun 21, 2016

 I think the only thing remaining is "placing a slab on top of an upside-down slab". Right now the placement orientation copies the existing stair/slab, while it should just place it normal side up. I think it can be added, it's one more exception case but not too complex.
Member Author

Member Author

### sofar commented Jun 26, 2016

 Investigating... but right now I don't see what's happening there - what slab are you placing against?

### ghost commented Jun 26, 2016 • edited by ghost

 Looks like mossy cobble. Is it touched by xdecor/workbench? Edit: LOL I though that was an inner stair.
Contributor

### Fixer-007 commented Jun 26, 2016 • edited

 @sofar @everamzah Update 2: it seems mossycobble causes lua stop while using this PR, on default it just refuses to transform.
Member Author

### sofar commented Jun 26, 2016

 Seems to crash without this patch too? #1163

Closed

Member Author

### sofar commented Jun 26, 2016

 Ahhh no, #1163 is only an issue for this PR.
Member Author

### sofar commented Jun 26, 2016

 What is happening is that mossy cobble slabs are not craftable. There is no recipe item defined for mossy cobble so it is impossible for the code to combine mossy cobble slabs due to the fact that it has no idea what to combine it to. I'm going to make it so that mossy cobble slabs are just not combinable, since they're an exception case.
Contributor

### Fixer-007 commented Jun 26, 2016 • edited

 Ah yes, mossycobble slab problem is related to this PR. It is fixed for now. I tested this PR and in most cases it was working nice, much simpler to place slabs and panels, very quick. There were some small cases were I put helper blocks to orient properly, but most of the time it just works. 👍
Member Author

### sofar commented Jul 1, 2016

 👍 from myself.

Closed

Contributor

### Fixer-007 commented Jul 26, 2016

 Can you make it work for stairs and full blocks as well? For example, after I rotated some brick block, further blocks should follow its rotation...
Member

### paramat commented Jul 26, 2016 • edited

 I feel that would be overcomplex.

### ghost commented Jul 26, 2016

 It's really great! It's a lot faster, and more combinations are possible. Plus, right now there's this leftover slab that remains for a bit. This doesn't suffer from that.
Contributor

### t4im commented Jul 26, 2016 • edited

 Plus, right now there's this leftover slab that remains for a bit. That could simply be prevented by disabling placement prediction. `on_rightclick` doesn't do that by default, but it can be disabled for `on_place`, too with one more line.
Member

### paramat commented Jul 26, 2016 • edited

 I guess this is a workaround for #1109 as the real issue there is an engine issue detailed in minetest/minetest#4357 Once that is fixed (it will take a while) this code could perhaps be simplified.
Member

Member Author

### sofar commented Aug 9, 2016

 Right, thanks for the comments, I need to address them. Will make some time for this.
Member Author

### sofar commented Aug 26, 2016

 Pushed a fix which addresses all the comments from @t4im (thanks). I want to do a few quick tests on this - will get to that later today.
Contributor

### t4im commented Aug 26, 2016

 The question why this is done in `on_rightclick` is still open. I don't see what could be gained? It certainly has the potential to cause problems.

### t4im reviewed Aug 26, 2016

 return itemstack end if minetest.is_protected(pos, player_name) and not minetest.check_player_privs(clicker, "protection_bypass") then

#### t4im Aug 26, 2016 • edited

Contributor

You should use `minetest.get_player_privs(player_name).protection_bypass` instead in the future, if you just check one priv like this.
It is internally called by `check_player_privs`, too, which does some unnecessary set to list conversation, you don't need here.

`check_player_privs` also has a broken signature of 2nd return values (set expected and either string or list returned, which means you can't really use that anyway without lots of checking) and should probably be deprecated one day.

#### paramat Sep 10, 2016

Member

in the future

Why in the future, can this be corrected now?

#### t4im Sep 14, 2016

Contributor

Can, just didn't seem important enough to stale for it.

Member Author

### sofar commented Aug 26, 2016

 Had to think about that for a bit, since it's been a while since I dove into this problem and patch myself. If we'd rely on `on_place` entirely for slabs, placement prediction would place the second slab in the adjacent node, and so visually it would look very weird to begin with, since the new slab would be placed first, then the server would remove it and modify the target slab to a block. I can't remember whether that was the only reason, though. Only thing left would be to convert it to `on_place` entirely and see whether it all still works.
Member

### paramat commented Sep 10, 2016 • edited

 👎 Thinking on this i now would prefer this to be done in 'on place' so that extra code is not run on every rightclick performed in-game, even if 'on place' placement prediction makes something appear and disappear.
Member Author

### sofar commented Sep 10, 2016

 I'll redo this and see if that can be done. The original code uses both as well, so when I wrote this patch originally I just didn't consider it to begin with. Give me some more time on this and I think I can work it out.

Member Author

### sofar commented Sep 12, 2016

 Updated to entirely use `on_place()`. Needs a little bit more testing. All the basic behavior is the same, with one exception: Due to this now entirely relying on `on_place()`, this means that slab combining only works if `pointed_thing.above()` is either `empty` or is `buildable_to`. This is because we can not avoid the mandatory check to see if `pointed_thing.above()` is empty. If it isn't empty, `on_place()` will never get called. (test case: place slab in bottom half of node. Place full dirt node above slab. Place slab pointing to top of slab placed in first step - this last step does nothing) I find this somewhat awkward, but not prohibitive for the patch. Most people combing slabs will not run into this corner case.

Member

### paramat commented Sep 13, 2016 • edited

 (test case: place slab in bottom half of node. Place full dirt node above slab. Place slab pointing to top of slab placed in first step - this last step does nothing) No problem i wouldn't expect this to work. This makes some assumptons about how a player wants to build but i find how it behaves fairly intuitive and better than current behaviour. It's also very clever. Just one thing, placing on 2 sides of a column produces horizontal and then vertical lines, perhaps better to always have horizontal? As horizontal is usually wanted more and this also matches the horizontal lines of the column sides. I'm not too bothered though, only if this is simple to do.

### paramat reviewed Sep 13, 2016

 local n0 = minetest.get_node(p0) local n1 = minetest.get_node(p1) local param2 = 0 if wield_item == under.name then

#### paramat Sep 13, 2016 • edited

Member

`if under and wield_item == uunder.name then`
in case an unknown node is 'under'? Pedantic i know but might avoid a crash (?).

#### sofar Sep 13, 2016

Author Member

no, it's entirely possible (pointing at an unknown node). So, I'll fix.

Member

### paramat commented Sep 13, 2016

 Line comment.

Closed

Member

### paramat commented Sep 13, 2016

 Otherwise looks good.
Contributor

### t4im commented Sep 13, 2016 • edited

 This is because we can not avoid the mandatory check to see if pointed_thing.above() is empty. If it isn't empty, on_place() will never get called. Ah, that explains a few things. That underlying behavior also prevents for example combining homedecor-style fences or handrails to corners or catwalks on placement, because you usually point pass the nodebox during placement at the nodes beneath them (Contrary to when placing slabs, so this is probably indeed a smaller issue here.) Perhaps an item definition flag might help improve this in the future some time? To have `on_place` not ignore placement of certain items. (Although i don't think this needs to delay this PR)
``` Big simplification of slabs combination ```
```Combine slabs if identical based on orientations using a simple lookup
table if the nodes are identical.

Otherwise relies on place_node() to place the node, which properly
based on look_dir as well.

Initial slabs placed are oriented based on (1) the orientation of
the pointed "face" (assumes nodes are cubic, of course), and uses
the player look direction to orient the node n/e/w/s if the slab
is horizontal or upside-down. If placed against a vertical face,
the slab is placed against the face without rotation around the axis
perpendicular to that vertical face. This allows upside down placement
and vertical placement without screwdriver.

If a slab is placed on top of an upside down slab, or below a normally
placed slab, the rotation is inverted so that no "floating" slab
is created.

Largely based on kilbith's #807 PR. Slab combining and place_node()
usage by sofar.

Since this relies entirely on `on_place` mechanics, this fails to
combine slabs into a plain node if the space *above* is occupied.
This is unavoidable due to the fact that on_place() happens after
the checks required to see if pointed_thing.above is empty or not.```
``` 4b4dff1 ```
Member Author

### sofar commented Sep 13, 2016

 Fixed up one comment by @paramat.
Member

 👍

Member