From 52a9574bb08b3d37eefacdab949360b05feeac4a Mon Sep 17 00:00:00 2001 From: rollrat Date: Sun, 17 Nov 2024 15:11:53 +0900 Subject: [PATCH] Fix nbt position translation --- src/nbt/mod.rs | 80 +++++++++++++++++++----------------- src/transform/placer/mod.rs | 2 +- src/world/position.rs | 2 +- test/alu-export.nbt | Bin 11278 -> 13433 bytes test/and-gate.nbt | Bin 462 -> 454 bytes 5 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/nbt/mod.rs b/src/nbt/mod.rs index ec481dc..33c2806 100644 --- a/src/nbt/mod.rs +++ b/src/nbt/mod.rs @@ -108,30 +108,33 @@ fn nbt_block_name(block: &Block) -> (String, String, Option) let (palette_name, specify_name, property) = match block.kind { BlockKind::Air => ("air", "air".to_owned(), None), BlockKind::Cobble { .. } => ("stone_bricks", "stone_bricks".to_owned(), None), - BlockKind::Switch { is_on } => ( - "lever", - "lever".to_owned(), - Some(NBTPaletteProperty { - face: match block.direction { - Direction::Bottom => Some("floor".to_owned()), - Direction::Top => Some("ceiling".to_owned()), - Direction::East | Direction::West | Direction::South | Direction::North => { - Some("wall".to_owned()) - } - _ => unreachable!(), - }, - facing: match block.direction { - Direction::Bottom | Direction::Top => None, - Direction::East => Some("south".to_owned()), - Direction::West => Some("north".to_owned()), - Direction::South => Some("west".to_owned()), - Direction::North => Some("east".to_owned()), - _ => unreachable!(), - }, - powered: is_on.then(|| "true".to_owned()), - ..Default::default() - }), - ), + BlockKind::Switch { is_on } => { + let facing = match block.direction { + Direction::Bottom | Direction::Top => None, + Direction::East => Some("north".to_owned()), + Direction::West => Some("south".to_owned()), + Direction::South => Some("east".to_owned()), + Direction::North => Some("west".to_owned()), + _ => unreachable!(), + }; + ( + "lever", + format!("lever_{is_on}_{}", facing.clone().unwrap_or_default()), + Some(NBTPaletteProperty { + face: match block.direction { + Direction::Bottom => Some("floor".to_owned()), + Direction::Top => Some("ceiling".to_owned()), + Direction::East | Direction::West | Direction::South | Direction::North => { + Some("wall".to_owned()) + } + _ => unreachable!(), + }, + facing, + powered: is_on.then(|| "true".to_owned()), + ..Default::default() + }), + ) + } BlockKind::Redstone { state, strength, .. } => ( @@ -151,10 +154,10 @@ fn nbt_block_name(block: &Block) -> (String, String, Option) ("redstone_torch", "redstone_torch".to_owned(), None) } else { let facing = match block.direction { - Direction::East => "south", - Direction::West => "north", - Direction::South => "west", - Direction::North => "east", + Direction::East => "north", + Direction::West => "south", + Direction::South => "east", + Direction::North => "west", _ => unreachable!(), } .to_owned(); @@ -176,17 +179,17 @@ fn nbt_block_name(block: &Block) -> (String, String, Option) .. } => { let facing = match block.direction { - Direction::East => "north", - Direction::West => "south", - Direction::South => "east", - Direction::North => "west", + Direction::East => "south", + Direction::West => "north", + Direction::South => "west", + Direction::North => "east", _ => unreachable!(), } .to_owned(); ( "repeater", - "repeater".to_owned(), + format!("repeater_{facing}_{is_on}_{is_locked}_{delay}"), Some(NBTPaletteProperty { facing: Some(facing), delay: Some(delay.to_string()), @@ -224,15 +227,15 @@ fn world3d_to_nbt(world: &World3D) -> NBTRoot { blocks.push(NBTBlock { state: palette_index[&specify_name] as i32, - pos: (pos.2 as i32, pos.0 as i32, pos.1 as i32), + pos: (pos.1 as i32, pos.2 as i32, pos.0 as i32), }); } NBTRoot { size: ( + world.size.1 as i32, world.size.2 as i32, world.size.0 as i32, - world.size.1 as i32, ), blocks, palette, @@ -595,8 +598,11 @@ mod tests { #[test] fn unittest_import_nbt_as_world() -> eyre::Result<()> { let nbt = NBTRoot::load("test/alu.nbt")?; - nbt.save("test/alu-export.nbt"); - let g = WorldGraphBuilder::new(&nbt.to_world()).build(); + let world = nbt.to_world(); + let world_3d = World3D::from(&world); + world_3d.to_nbt().save("test/alu-export.nbt"); + + let g = WorldGraphBuilder::new(&world).build(); println!("{}", g.to_graphviz()); Ok(()) diff --git a/src/transform/placer/mod.rs b/src/transform/placer/mod.rs index 99f2fbc..2ce77de 100644 --- a/src/transform/placer/mod.rs +++ b/src/transform/placer/mod.rs @@ -15,7 +15,7 @@ use crate::{ logic::LogicType, world::{ block::{Block, BlockKind, Direction, RedstoneState}, - position::{self, DimSize, Position}, + position::{DimSize, Position}, world::World3D, }, }; diff --git a/src/world/position.rs b/src/world/position.rs index 80708c6..8008b5d 100644 --- a/src/world/position.rs +++ b/src/world/position.rs @@ -1,6 +1,6 @@ use super::block::{Direction, RedstoneState, RedstoneStateType}; -// 위치 +// 위치 (x, y, z) #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)] pub struct Position(pub usize, pub usize, pub usize); diff --git a/test/alu-export.nbt b/test/alu-export.nbt index 87de2df41ac7af0fe3b197ef075f3f7d37daa263..e20633dd14c04a34b7f2e0af59721925aaf16177 100644 GIT binary patch literal 13433 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 Qr;*mwvE=yPTaFX{4_P!0;s5{u literal 11278 zcmeHNdsI_bx(5VNL>R>mG9auOTUcJI)Cxl|JnpfIK53j8i!g83hd_QIsR)5#R_R4s9*QlCN7!L2Yzjx>N7%3U zZt^gjVl)3-dzb^U3bQR%5*x7;{yBM=P2s_hZ4a|295LI%iP(Vc=EuszY>FLxygh6M z;fmQ7&V&yp;N$Wzn_>-rTYIA&;ego`dOO^iA6ZD+WA2(fJ7NXLubnz7BG+NXnmk8h zGsjP^Uxi2WBjM4j{B80^M`Hb=!hvwX0{OM=jW$IFzgFJ3lK2T`Q|KM>0Dj~Nay1sG z$#Wn)IOXlsk(l(t6q>x1#12lmTsR8T{MHlXTI%S>*na+Dd7~3y zQ%tlst{~hnF5kBB#d7%*@J$|Ry=9AaFEl3$ekYWKejvT1C_cQ=fKPq_-- znbVXOxI&c1$25*(?K!c&8~tAj7)&q7RWjg(P~GE^$*tsXdQBd7a#T}6-b{{li?Qz> zM3DX3Ipf6#>8&l}nA{A$@NuQS2Xk$$h5gkeaKpnmg!}B>v})ly>c2lM*et43RPrOe zd;;NbIgwB(u*YwR+q6A=LG z~cZBYunFM)Gt!C#w z@IG1n7YgnO+^1#|I&x|cL`X{yC>u{1u2Gn$a4jF5=oRN)K3*;C6y7z?%gEIeqp>vf z5zhB1s)s}C%i_EJ4s**7s5u=u2>1%kK%rm-UOl{DiLV_~tR3J5Ym86xUcNv*9t!+* z5`g~``9q)`_9^I&py4kqjk=$e7@{5k??hL|EiFOezqRd%c&0i1K_=l{LwF}R(;ZT; z87LyF^ktdE9h(No%pPxc? zjHN$(n_GXI91CzM#}GV7S9}LYp$Qk0t_G_bU&9H~G#8Q%)`d2rYwrHnlHxMmk}+Nx zbnj8Czz(PHTLM1gmh{;)K8vU&oP_zM~Z0%}W9AjLAyNV5i6Ufrzd; zNy4kwPMCZWCc_w6~` ze2uqW7)+Pk4|Smk0FHR@qj$=vnO~Sc#8N;pn)eCL;P3bIhZ@Md!Nd}|{_*V%w+G7L z;1}Kv&*Vm>A52@H_Bw}PzMB*N94EdmD!xtK`M%;J3XD@j+ zlbDxhkYMx=rkmeW(yTzSK%FEGyzw`M15TJdOY;F5{zAfFlm;uBW5WVi$M3&a8d zf4Y!5)3kvguPI2O>B3SWny3|T<`i=kedFD)e0KBGo1bm@w2>R90k4W9?!k!zZ9`Y^ z$kGCAFMwhx{=tdPC*_%5T8u5%0Wa#xRsfiND+BN^9)A9%fRkZfx8Qdc&R>654LE{N zn1#GpSHb!VCD$?6VTgtB{HYl&H(KLE^@DW*@y-IDEvOC`osm_0@^8R zFbfEqlQUQm$#O)mXV*YB5I17OwK2KQ=h5Y1FDP>wq~B742g#e$`6*h{#-w*8vNFU& z9j$*7BkBOy2MjUVSO`8KtTVoJNJduuwZ4oNJ{FDB-g*SUzm6p3Ep*o*vC}{rJ5|{6 zYW=K?Tz3z2?ocM9f?nX9*CbpwL!uakG6)a_rG${~=@0!ker>V{P{Y0uQQdgL3DgLE zR3n6Ns6uy)swn+alt0ACAzSEI>3d|19*Sm1AD{z(^EyBTh#J<8d0WFC$e?ClFaax4 zH|)N^usBjbEF&CI>Rk+sLZanR_3%X{csAL9fnvTHx5%WeoO+-Y%s0TRr|(nZxr*%* zWpOS7hJO$dOvrVaKfB<;3yFG=Wv!Lq)HhUiDgLbO{-C}zO$jv99#ShSvuXrYZd7MW z*wkK%iP@FH?mpB(6>2KB}R5nzTl^ifl2v23D+6f2uf8O~Y> zC|lh`DJfO%x$Wiz!=K1Rk6(KH!sAyZ|6cM-=B095PSo2`qCR_~TsQo;mjbMmM6YKq zAP`5q2Ok9h+J5U5KvMLpLq5CFC)4_f$*K?P%To9S!PcKQh%{1sH!qVL0NS(Q!(74Z zoN}tU2Fj4kKRKH0f{)<3Kg|w*ar>>?)Gtq~{1#nG-X(oSrnT;e{Q!nKpo{4886RGV zV$2&TC=F)S4_8RjwH8V(3UGS5Fk&C*|Jk#az9^)$|NAB=mG&v3`RGvza5RxX0~87L z&*n@niSJ5|Y6WrQpSdj=<2VB7UdcMCnFG z0nKZ?E^Hir{`ME}+b!}3$s*_t?vdm29hVrrIZz~6gHzq`5l}?;1Z$+b-=tiF#UmgJ zFb-7FzQNWdOoZl8#$l;VKqpIV0x}LuZ2~%BY=X*=FwzpXC75|h78?Z!c%3BWwMf&< zl^+E6`0lU9eZVwkF#Xl#;XYXz@(>P0v^I0&b!?S&F9=-HB&`j#V_aJDu#+Da)&rlN z{0?C9S8A{#0i*!y;)Gx&?!`&fU^WGdWdwmOSlmj%dl#TZ*#<4`qmd~?U(1~j;Sd9q zUp)N9*||yU z{#W-Yz|eOu@c;O_{w;nD-Y*u^qpbe4hbqPaij4TfEa zx*zKO`&o=HW=yc5^Epfx89)EAzbcF21J(`amIt=<(Nkvf8+92gZcuU3a25i76sUh1 z>tYl1#VE?g`n@s${Nmxi?e7K*-Ggnw(N{(Bjt>^!t*b8+Ko(JfZw3B3 zN#2x|rlODs;C~O93fNiO)sS5SL<{&i?RCeH0f08ynIAb89&{}LR|v|4qpA`ea8K=u@5!h^DBzbn^oGgDCDsb`24mbw9Y{z%l|Y9 zrER$!^`SpV0f6d&sSkXZsw?lMxui`%nS(TrVHc7-Tt)skGsT&-$IywwA0+mX^JRjc zG4FUpS@ET*vs4V!b7cZAmh`THuNqI2C!T>Srv|)oSI3Qi0eV-1Y4NQ!HW^TV=$rc# z=!_Qm(dAy7cp(eN=;uQvE)$H<=eJ$a`3$KrCM0Y^QU;;FNK{L9XQ{2_7q+W|mx z)9K9wBlR`m5ny-#+@-yoM!gzrBkUO9-9pY6bpz0PHf|T`f0f|F`;~2xS*na*ru{4p znKkz7P+pg;dP4?uKLk=3LmqT;IUtN^2&Kddtr4vCy_MoeLZ2HIcR%AGXD@0IIyGXv zZG+nc>P;}l&@TZPqV0Y*RQmawQHt51{wDAQds;sUxb#uesSF*0b>nN+h1DyPi@yqeOs{;bIB$M|=R zQ08NPEz%S>Kx7j*()cg}c_;%-P>cthlm;r(zsp2YzqY+GXEHnsw0{~hB|w^Azw*^( zFjv9-{L`0dwEbS*2G%+KM_v@jxoT?YSe;4?YE= zITe!k0C(@o7-UZ=pG#+?jd=yGD-l|Fo7toZlrY*@Wt{jfvli` z4oLI)nb){diQLcv0w9=+&T3}jo9~8yE%EDySp$u{ah&`dSa4(ohBJxTk*S4P^5ZWb zWF2Ng(}`sDQxuoZo^_*st_j+ z!a%QWAPX=+61MamuO1&f#YAizL$dpNJs1>s!$)b(M zye+jw>a*>F3e*$)w%U)Q&G;9`{vZpbVtWS=%00uXriGZNowH{jgh=2j9E7#k#w}C;l@T-kb>2+% zz2pDJzlL%E%1<(_S6J-As-mpCW5OzxT2ANth%Ld6mCj#{HYU?vid`RV%ciZYQ0(4cn1Z&Z1{)vSHSYL-U%N9-W87gi%eDlTxyjb zgt%4u5@7lT2RY?n2hzy^c`e*(u`p%;jF230ydbh4$jAwh0$){HrXE%?l&}lacq8j9S?C+6wI&XHC(~7=Ie>rp6ofmK*Inq}?wS=2i z0~?0<49u5G8VBh8eSffzWd*%eagN=^`ZmAw8c1wnXnwUUwhAUow}Y66_0{Y$_OU#p z6DWSxRInS_UT3M7#|6fQ2w-watz{EKkg#VbHEU$`y+b zs~-(%m&6bdW7>m_Tf_L0MXg`{E`g%}2ogno8I5m0xU_{++xT=xDQdlica<=*WHz^O zVO#Lbs~dQn`ck!;(l7KD7w&A?ui2!up5w@_Ryyli(C2|4$$E{8cD7LwX7xAY-5-2r z{irE1uRF%bdRpJ3!QGq=gvFj-9tv!%wz^J4v|{b4mjWI@haEVkfPRE=uTDU-fRN`f zSKW^6%kcC2W3Jj}mvy|Wnt{mvj+6@}hrryShxk@Dr3Z^En+31D@w5r}p?Ls(;1&M- znymC7j4i2g4mZ32?W01i;1cpm?A%#p(eqZ8Hjd5hZ3-6SHpPDv+Ye3kCi!u-AwLaX z7rZ@qb+84Ii!UC~esX9$BN9l_emdVc~02Anm>M2EzAwQn-KZ6{jYzw`yC<+$M4I zw;+{eebXY?QZYP?8o$L!@7x&VGzg3hk^xGq^!I@9xCgXHe0P0)nNC%FM9Ye5uz;oZ zOk>`m`xNkvxsiZ`2Ab26$A1pj*6b8w!3yFm9eWq0$!g7Hoxd>hn$_7<@xKSw6#a;F zxh-qc5=~95T2C*xVJ$)t%TmYrgZ0LeT(M}`T+!=$g)`bB{UF_JdtJsNl395Hi+DyP z+ZJoBrz|U*E$N`ju-ziT^pB&;gVBl2FbTPdJf+y6) zfd8}0Ga&i>?*FH%)rBrJXl;fm6MQeZ&V{nSB^ifJ(r0_23*PZkEWOZ$j#wjSQ!v3b z6Y()>K)Uoo7dl$zLKi#&VfAv*q=P&bk#xauJWKYdSnAr)$)f9AXiu|l$#t&9dr5Xd zxsuo;0QYg0yVoVui{6gP)tNl~M8-!Yia(qE^t+AcwPw?qO0!mN7&+r7nwwDP8J+!F z=Wa&(i6(nJMKi_P{JEER8WrwQbNA1Ai+;h*4AioJtv?5d=QlYSc$?R25D;7mUY63-V|`Q*V-KPTXc5)g|TSXo5cH z9V+{0leTRk9{gqxix+0k$8I%U%oZ6{aSMH^l^;d@M%$*F+C3erZC&WeFm7)pv)(8- zpyO2t)1{y z&EJ?fo3J+0^ik`x>1N}jhXu2bo@{!2S}~SiZZZTB#>Y1dT66F2$?0q7TNmWT3llfu zA{So$q^-Hd`1p%Nv*%QopSk0Vbm*h`PY(ZHrN2|}+IF5;{$~Zkj!aSH(b1QUcX8Y{c5%$QHrzRWXxa`;%YLiYDi z{YOLbPoHZK+N2E}^eOoH9BDY$H{ayb{3K&qmzdpVN)PQVH<{+&JlxxA$nt!~O`84O zF!Lgj6#ig;zxVN=91qbOrYEZN;VNz0VB7vA^Qp-YH_yC<1!Y-pe3L29L&vFZBY1{y zdb}IgJ<%R3`0M#j-sAO`MC+3t{e0|eZDX@uS*Iy8#t(5T+I9xDB#rXb!j^B0^SWed zqfaX-OZtaMmnn*#Y?9`d8{cWoo%~jGSel=$f0aAvEnGd9(=_6)n!QI3);D_Qoy@K6 zGfu0f-M5Iwh9|DQ-Og-@)JoXAaGTs3h@F9zXE?t$x ztG6iI_$l;_k`U;4`|inTmyL-=WSjC!3=wVLgWabc(O_D+*?TjNqh~|hgd#}%9%q=^ zHSL7{wU<%pjG}yx271hXMjvJr;87{hnH~-F9C*xOMyEVyG789C^5~T3C}UC{o6abp zM+2El9-H!TI-`Id4P-8P7+60Hco^_7;Gu4vk7@ksT`fM8(!|iBm^<{jp?S6kqH5XMi3C_=!NBx6nF4u2lrDy{E wSvTAj#E0*>#KA_|LEm|w==>r5^8f$< literal 462 zcmb2|=3oE;rvFQ)UGzI-AkudGvRGp0N58!vW%qpJ++(zlQSz}ucXI44txo@Z)?*1} zZ~7zT3B%E_{rZtIh}9a%ZwDQfY6HxtbnwtKCh4)8I-vTg|Z29bKyr9qY%hh2&#|v@B zzl(r6YB)Y99%yHf2Ww)GXZ@i8vRmrI#fE;i8lDHq4D!rBW>ieuo%N~9`N90hk4m(@ zc<)Or+^m_c7qgGcU$lPHX_s%Wat`ZFd854L6t`GfXyofhR}x?Bl0M~KzNhy3-LgGj z4qmglKdrBN=CX~^WlnZwjoa@&smpnIs$zrfzkd_F&aKXpTcdq#?;p<+z1QXox4&ur zu{n0mV;i<3hrdr+-oEATqSJf)Q{GMa_c7%0Tla|V{ia(>-)jBKzdzwpjU+!00|Nk2 Cli%n7