plant.lua looks like exactly what I need to simulate tree chopping. I was worried that I'd just have to ignore trees entirely if I couldn't figure it out!
I don't understand everything that's going on in the script, but it doesn't look like it will cause items to fall out of the removed tree, or water to recalculate. In other words, it's equivalent to using a ballista bolt.
dfhack.items.makeProjectile can be used to cause an item to fall, and liquids plugin probably has the proper way to update fluids. Should be simple enough to implement.
I've been preparing to disassemble the exact code for tree chopping by starting with understanding the less complex function for finding a plant at a tile (that the tree chopping function calls.) Knowing I'm probably seeing:
y_column = math.floor(base.y/16)
y_column-y_column%3
when I'm looking at
movsx r12d, r8w ; y coord into r12
mov eax, 2AAAAAABh
imul r12d
mov edi, r12d
movzx ecx, r12w
sar edx, 3
mov eax, edx
shr eax, 1Fh
add edx, eax
lea eax, [rdx+rdx*2]
shl eax, 4
sub edi, eax
sub cx, di
mov [rsp+30h+arg_8], edi
is very helpful!
Edit: Actually, looks like the above assembly calculates
math.floor(base.x / 48) * 48 and
base.y%48 (which it later uses with
dim_y to completely avoid using
extent_north, etc.)
The optimized code used by DF is:
map_block_column = df.global.world.map.column_index[(math.floor(base.x / 48) * 48) / 16][(math.floor(base.y / 48) * 48) / 16]
which avoids %3.