From 5a61d563d86d08d0143251ac40c8a08b1885577f Mon Sep 17 00:00:00 2001 From: Joshua Barretto <joshua.s.barretto@gmail.com> Date: Wed, 28 Aug 2019 19:32:44 +0100 Subject: [PATCH] Added modular building generation --- assets/voxygen/shaders/postprocess-frag.glsl | 2 +- assets/voxygen/shaders/terrain-vert.glsl | 2 +- .../world/module/human/balcony_upstairs.vox | Bin 0 -> 1416 bytes assets/world/module/human/base-center.vox | Bin 1760 -> 0 bytes .../world/module/human/base-corner-blank.vox | Bin 2092 -> 0 bytes assets/world/module/human/base-edge-blank.vox | Bin 1940 -> 0 bytes assets/world/module/human/base-edge-door.vox | Bin 1924 -> 0 bytes .../world/module/human/base-edge-window.vox | Bin 1924 -> 0 bytes .../world/module/human/base-inner-blank.vox | Bin 1884 -> 0 bytes assets/world/module/human/chimney_roof.vox | Bin 0 -> 1916 bytes assets/world/module/human/corner_ground.vox | Bin 0 -> 4012 bytes assets/world/module/human/corner_roof.vox | Bin 0 -> 1676 bytes assets/world/module/human/corner_upstairs.vox | Bin 0 -> 4012 bytes assets/world/module/human/door_big.vox | Bin 0 -> 47099 bytes assets/world/module/human/door_ground.vox | Bin 0 -> 3992 bytes assets/world/module/human/example.vox | Bin 8764 -> 0 bytes assets/world/module/human/floor_ground.vox | Bin 0 -> 4012 bytes assets/world/module/human/floor_roof.vox | Bin 0 -> 4012 bytes assets/world/module/human/floor_upstairs.vox | Bin 0 -> 4012 bytes assets/world/module/human/stair_ground.vox | Bin 0 -> 2040 bytes assets/world/module/human/wall_ground.vox | Bin 0 -> 4012 bytes assets/world/module/human/wall_roof.vox | Bin 0 -> 4012 bytes assets/world/module/human/wall_upstairs.vox | Bin 0 -> 4012 bytes assets/world/module/human/window_ground.vox | Bin 0 -> 4012 bytes assets/world/module/human/window_upstairs.vox | Bin 0 -> 4012 bytes server-cli/.gitignore | 1 + world/src/block/natural.rs | 1 + world/src/column/mod.rs | 8 + world/src/generator/mod.rs | 20 + world/src/generator/{town.rs => town/mod.rs} | 623 +++++++++++++++++- world/src/generator/town/util.rs | 42 ++ world/src/generator/town/vol.rs | 203 ++++++ world/src/sim/mod.rs | 7 +- world/src/util/grid.rs | 23 +- 34 files changed, 909 insertions(+), 23 deletions(-) create mode 100644 assets/world/module/human/balcony_upstairs.vox delete mode 100644 assets/world/module/human/base-center.vox delete mode 100644 assets/world/module/human/base-corner-blank.vox delete mode 100644 assets/world/module/human/base-edge-blank.vox delete mode 100644 assets/world/module/human/base-edge-door.vox delete mode 100644 assets/world/module/human/base-edge-window.vox delete mode 100644 assets/world/module/human/base-inner-blank.vox create mode 100644 assets/world/module/human/chimney_roof.vox create mode 100644 assets/world/module/human/corner_ground.vox create mode 100644 assets/world/module/human/corner_roof.vox create mode 100644 assets/world/module/human/corner_upstairs.vox create mode 100644 assets/world/module/human/door_big.vox create mode 100644 assets/world/module/human/door_ground.vox delete mode 100644 assets/world/module/human/example.vox create mode 100644 assets/world/module/human/floor_ground.vox create mode 100644 assets/world/module/human/floor_roof.vox create mode 100644 assets/world/module/human/floor_upstairs.vox create mode 100644 assets/world/module/human/stair_ground.vox create mode 100644 assets/world/module/human/wall_ground.vox create mode 100644 assets/world/module/human/wall_roof.vox create mode 100644 assets/world/module/human/wall_upstairs.vox create mode 100644 assets/world/module/human/window_ground.vox create mode 100644 assets/world/module/human/window_upstairs.vox create mode 100644 server-cli/.gitignore rename world/src/generator/{town.rs => town/mod.rs} (50%) create mode 100644 world/src/generator/town/util.rs create mode 100644 world/src/generator/town/vol.rs diff --git a/assets/voxygen/shaders/postprocess-frag.glsl b/assets/voxygen/shaders/postprocess-frag.glsl index a9316ac993..f653f1d30c 100644 --- a/assets/voxygen/shaders/postprocess-frag.glsl +++ b/assets/voxygen/shaders/postprocess-frag.glsl @@ -170,7 +170,7 @@ void main() { hsva_color.y *= 1.45; hsva_color.z *= 0.85; //hsva_color.z = 1.0 - 1.0 / (1.0 * hsva_color.z + 1.0); - vec4 final_color = fxaa_color; + vec4 final_color = fxaa_color; //vec4 final_color = vec4(hsv2rgb(hsva_color.rgb), hsva_color.a); tgt_color = vec4(final_color.rgb, 1); diff --git a/assets/voxygen/shaders/terrain-vert.glsl b/assets/voxygen/shaders/terrain-vert.glsl index 14fe299613..bbfe953324 100644 --- a/assets/voxygen/shaders/terrain-vert.glsl +++ b/assets/voxygen/shaders/terrain-vert.glsl @@ -47,4 +47,4 @@ void main() { proj_mat * view_mat * vec4(f_pos, 1); -} \ No newline at end of file +} diff --git a/assets/world/module/human/balcony_upstairs.vox b/assets/world/module/human/balcony_upstairs.vox new file mode 100644 index 0000000000000000000000000000000000000000..e06d2de36364167dd23adfc1bec4e406c72f63d9 GIT binary patch literal 1416 zcmeH`J4ysW5QhKmndxc46Bvkrk>U$P5KMO1K_>8lf~=bjOtz7W;1Ns=j06KyFCcgT zy@3~MzgiO$6&KC6;iIa%tNyAfrq7NBOLvkEdd(q5mxXlN4C{H@u;xB7I3G5BH#ycZ zCVJoIQC-Y^o0$#1jb=-A1vZnq9FXh+ln~92mgid!B1hy$r%vd3aR&h+$gJm%*a&5G zZGZw|W?Iz1&%lGTb0fDtumK9&LuNjGSdSjxfm~ZcfC6H$o*i|qe>B0_9!;U=IT!h| ze)&#WZ{&zxL@l8&>WTWIrYDw>anBhw-6R(u&6EAAN8DsN=hCz!*0i~^ypOr>EH0#G zWjT%Zw$r%3`{O+CZ!XgF<8^v@x=nAd4?o7w=KQ<=du?@;HrB^!YxC+)W?NNNs_Xho OEgoU|Pwb6;qpx@PjXo;? literal 0 HcmV?d00001 diff --git a/assets/world/module/human/base-center.vox b/assets/world/module/human/base-center.vox deleted file mode 100644 index 14ed7d12dd4879e4c826f8342006fc708573579a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1760 zcmeIxziU)M5Ww-7o&7O_e?f|1VHGhN1i|u74>?2=5+X_Zyv8ai%s-JLAP6Z0u}zu( zAZe}Ay}xGtPJ-oG9Hz^I4>SAT?!0%id!IM=o_rUPkCXW)g8Z%`Ta&jRatyc>JM)9t z<J*zQBjR6s`v>#WbobyFA*&8r^iW{rp7pS09kS?9iG{I|m&85BhQvK3vUpI|NUSr~ z8Ea6;GcgfWWlS(+6jZdx8}k}9p}a#Ab79CRsA%9<4T*1PjeAgIE({q36)kd}XBbk< z%|sY73Mv|u=dChEffnY%kWo<4V$5?xig}=YBfTDJ=V+k+V*%SSHaOUf(INZ>kKe)f zIfQpRgt`u)o<~i-$01H_Bp5OZDjFP#{wci^)Joqg{UjO^xe_(8w}Ctp4MidB7wZza zQzykZ&VjQI&icx@6nY-@oVwi4DCCvcVjj6OC&&3gA{X{v<1A3$BJ$1#=N%sJV;?K~ z*-$w<4cqUh6MAxcai;pRI@hvmAJ*OV{q^cfpRYabyBll$_}!a+arCNx-CtkW*Yne( z{`1>Ozq&l@H`hNF&U@(Za_9Q_voHO{`f=ZQdGcR+JDpDZY&Kh1i$7t%Pw^l9M}7GN Dt*?sV diff --git a/assets/world/module/human/base-corner-blank.vox b/assets/world/module/human/base-corner-blank.vox deleted file mode 100644 index 7523e5ed3d36fb7907d75ffa5ae7dc9a03b77c2f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2092 zcmeIxy=qiJ6u|MB^D*ZLK7d$=g;m685CqGtF0zOpC`yv<7D*#XZc><+un+{nLa?{= z4fGAH+y}9~{%3<_EP{4k_;F_LoSD6QX6EISt*h@#DUUW6j|t^cmhyD--b3pho{Hy- zo%zL8uapbK-?p}Q7C-cK;3pxZjUsIj)58#_?Spu48*Lk;^|l^1I1CCA9VGgg>^G4E zCmK<SA~HzoV3K34Whqb?91Q_wTqFlk8&hJeLM{{rM?<W{*vN_C9jcNGg~8Dfz0J5m zAwAcKP#7Eyfy#I^`fyYy7Yc);A$p&2h4eg7z9qF@3MlE4`Y#;~0k&nyW-Jqh|Bxtr zU!w5aiNd;x!g|@)<a-h&SsMa{!O;*%NK(6?h7AsbB7^raI`vBSBv*UZYn)@Cv9}3j zzZ-pDy>s3<@7ic^G$h3OS%^Vd&mh|OxYDoedEIw31QOE7F*#^a_f+ei!L{x-VjyXY zljE#obzhAfxRFB)ByBNrnjDCe<8{~IUiTU?khC+&Pv*gC8&M%yhiHs9+QIKAwFu_% zO_H4V<cv1fCCA|8HKGLnS2^Fo7`X;#o@oDHjCrp|&p~omf;-dTFes9H6V$B1jXO|> zO1)|oBB~Nmjfm<*)J8-NB5D%ZW9Ca0aOapK<O{h%o{(egrLlLuV&k(1vrW#|>Z!F( z=QZ)1ckcgrr**$`<?^&xyEeVpSeuUT-<>`m-JV`=ub)}h4{wg9Pw!5quV3Cy-@ko4 sGw*+W&v&kGTz@s)TtA*RZk_y<+RkRPX+EEyxfYjj`j`40{log@7hrX=oB#j- diff --git a/assets/world/module/human/base-edge-blank.vox b/assets/world/module/human/base-edge-blank.vox deleted file mode 100644 index f93dd6e635997a8abc3fef072a383a9dd93b958d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1940 zcmeIxy=oOf6u|L0Uo%JW2`t3IDq=JUf}Oc~2^aALMM+Wyl18F8DNO4FSO|h(A=q2` z2KoSk-9F9u-wl@6B50R|ALq=>+1b5k?!I`uedS{*<>BVy5uv<or99cZ_rS*im*ClA zcYbjim2!dj$M(+d;;x-8{3JB3ONF3mkOz5?JGqlPxxKCkI1CCwQ$4JzuY%}ABPvm* zaV|y5pfETB6%D4zGpIpoBT@^4BT&&MZCR;ljX8)>3xgw2(Z-y0he5|$C&J(eR5S?d ztujVHf?60Hfr>VcSvTld2iiB#>p?+F2l_t*DmaoM!C?%E!f!|v-Y-#jcA~IvqOf0% zd-6VslI#tI!4arvNEDU5q6&i}P|=WkLBEo-$mz_SJUPpxk7Mpj<D4twnC61HV6HA5 zfr^B%kHX*(70y@=4URxXL!y`*2x^l9BRaxlzY-ggyf`&bmwh8Tg1izNlDvfM3pCh= z=m_#kY)JA<>XZ8r<W4l`IA2+>?7_Go8~5=}g?WLpW<*DjS7KpZpwt@C5#-7{2mSGh z(;r_x-I{H3j?*O~{j56IS?@i+@3il?FJJ15wX6O4##%qVf2V&vy4Bz8tgr0rr*}vF z%ZHQx{oDKg>&NGnb?5y(+yDCdwU_<I`f=a5dGb$sJDbh=d_G^f7aw8&pT=+WFZ-9@ Dw$q^S diff --git a/assets/world/module/human/base-edge-door.vox b/assets/world/module/human/base-edge-door.vox deleted file mode 100644 index 951f3b201ecba3e2b8a62416cf057f51fc168417..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 zcmeH`y=oOf6oBXa%^bleun-HYh%rGBEOYfD7x4#0Nm7QJG!osUFfU;t2!e%RZ|NIo zX=k@jGk$x6Wh{brS@@VU-<+M@J!kgilkICCODT`G7LOUq&`No_b?>216E1=0i{1I< z)vT0DjDOhP*<Ebd>B3KjrgcydXd1*p9K=rS#7=B)s@gJD4jUM;;sl!NVO3pLm1Tet ztLkgPyXGKLMg;?hfC>$ab)9k`wK0+l1`Yug+KM(*a$3WI7`b5J5Ky5_G3yQnI^{Ye z7&rt}XdtY&${YeD$OQw3fC_Dzvu>bM9#FoKT8|2pbfo@cKm}SdCeVyAq3{g}h4)J+ zJUgMVZ$e?eoc82>5=yc+C>S^dRA`V;RQ8H07&rt}XpnnBy^>xeeKK|Wm-I5J;}rW~ z8uTrPSh>Ijt}Yz{D&*>HH2Tz7YlDMu26S}}gj{+qLT`oM3cVG+Pxb>8(jnv^D`SI{ zgTMtYaDfY);uNPi#VM{CIE3uC%Ge-f-|>!jyyG43c)<%^@PZe-;48l3E570@zTypU zc*7gs@P;q=f-m@jFZhCg_F%R}-&U81^z+iW&U^30eW!K5bM;DJtX=OfHrM*`{k#3^ z(e3_rXZ_5&etLJ*zkE39-@m=@zkYl^Gw-6l=R4OoZ@lWa){pz<#>qda?QAyd^ZESD Qz4!_H|77|{|FVDi4Vj{!)Bpeg diff --git a/assets/world/module/human/base-edge-window.vox b/assets/world/module/human/base-edge-window.vox deleted file mode 100644 index a96fcb21da86d32f984b56e5f709da66d36130ee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1924 zcmeIxy=qiJ6u|MB^ErY~U?CP(5o3ZNSY~yRMf^Zfl9XYSMxvV(<|QlyL9h_)Eqwzm z?d<N;jQ_jAaxE6^a^c50Gw0mdyEFH`e6oA(V=3j)&g?OvEV7iRJNF*iIN+*yKHHyO zUXDt+MEqlSZ-2I>=Y^kylvoHVQk>k$o!rQc+{pD!h|V1bg)mo<BF7=}+KEO~q7dtH z+!nQ#L7*@=0tuDIZ_tA#Nu(DFgCmejxd?hPnL|~2p)fcCIp)+23K@Hi2!+8BNL1<> zjNzzGFBAqxAjdIvg^Yb*`v&%U5U`~K`#(4W9LdnYVGIq0|Iko)zJ|hYHx$-wD6H4U zHF=(f(pVb;g~1U>G!&@^MFa|iBamnZ&VDt{qH#_tHgD{6B9^%=RD2$ceL3gUow?wQ zgR>55!QA+6B<GaWa$%@aIpcb)FgOB<hNAVTBC;MS(coGSgP3UK#pr=pJyfE>$%B|^ z<i+b@g*fXF4Ne}!L?dsF{>FW9aw95aoDb^38jK5Cav#rBn6D6ON;Eim5DWDRp;w6p zCl{Xi*@MXr=eE3Rt$kgcYu$S<?mOT2J6Est*~az$Vtb>X-oM+wp4{$l_cmAV>!)`o z{mX~5{{7qg{_Dr*m3<fcyWV?!^Tw-wYxA^kZ=L;<y`4-ZeL9`4T#Jve|4-vL`j_>~ EZ$Y1)Q~&?~ diff --git a/assets/world/module/human/base-inner-blank.vox b/assets/world/module/human/base-inner-blank.vox deleted file mode 100644 index ce27fa56d22a873ee452575dd4fcca8eeabb3329..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1884 zcmeIxzlzgA5Ww-7+1=R@d;$xxusZSd5CqFag9h;rigI^dilmX;<*x8v!a@)P3&Gyf zCs5zO?)Nn7cXL?AB4~Gk4>P+vyT4y%lh@DouYDAeC!^_8f;_4s&qwzk=RV-0csV_s zTwaevE)oCOKRBF5I$!ussOBrzSh>WiS|P9Gl{}NPCQhD?-O|jJb?G&%NncOL)okfz zGZ$*qj$9b4E?snKN$09E7!ooH9JS|F=eg=4A*`;{s6|3XfupYRURGzdG6zl6A|a!| zQG3pMMuPR)OhiIPfullMug(|+TBt=rMuDUDG3yD|>p=SkdOa9u=|KO70tZ(z1h|YL zAbf{_@P71v5S|?n&J76XML(1G2}p1@3<((pj*5WMKc#m9cU=^xpTq<sS7MkQ1@|ZG zyx%c*ZFv^lZ|(amX2Cgbg}JhlU>}10Zq6L{&t418Wj>>jJF)gU@+kcromJCiK$0#L z&iRR$QTQ!5u_DMNQv=I7PsEHu?!<~9m%_WiI6o0HN`Dry!UW13u@I9{1A)Sf-U!cu zC=rFZ#5f}{&Uo=~JmNmqA8OjR8lP?VUhF&X``xQo+H~i7d$qUIP9NNBUr+9|w+Fi$ z`}*nKN&E8Qto``*zWw_7d1Kv0f4BQx-@Ngr-P%2Ed$-U2NpHvFahpsg8_(iT*#4*f JAN|Yu@*Cw3nE3zz diff --git a/assets/world/module/human/chimney_roof.vox b/assets/world/module/human/chimney_roof.vox new file mode 100644 index 0000000000000000000000000000000000000000..e8e49926a4339631562d3f6ca7557dda14887b1b GIT binary patch literal 1916 zcmeH`yNZ-S5QV$DZY}r(24Y~OcmojylN}sn0u>Zw-P8$$joidXFflL^3`~6i!3WTw zBNMa#Y1*&G#6%Yt&Gv`G={kL?y1J(4>7)G%?@B2T_BIcp@*+xkvN>3v&4BOBFW7%} zu(>TexqO4Xwb8X~4OY{|RfjrIT}qTuJ1AxJ^tJN5n~iWE4J~>MGh2$|iL!0IY#kIM zc49OKf)>;jk)>DmYNc)+ojTTSbm};DtJM*?7cjBmH@D&GqaP0+Md<}kh|sr=B4t?E z(9qGO4N+ODaW0<H%4qc66urx6y^Wf8Ah*$<X8k-*flw2#82PQz7d7xOBKGJXZq5u~ zaT%WHbGO2L1h%{<d&(>$K@UNGpa-=yk+~t9$854kAb2c$!Kd`1XqNlHfn*F6kE9-L zM8pt!_3lHme<!bVf8(yi!HhdScXB%3o@e7X&hON!l{%o{b2MWuK!Kx0-j_K!?6AQG zE3B}<0yntrVqH{pF(AAl;kOdCMR^-)z8GthgyTbl1(swyvh(1BMe*$XL0;g2EvN%n zOKPl5I{Uynp3WXjEX11N9T-r4Puqc>q~UAiHoUBX0WsFVlC`1%t7t%214*C@+T;7H zJ>KE&<1NpVV)C6d_cZV4+;5#fH#e6q&cnMm=h3}8$IkQpo0s$R$Jg`Ar?>O_*AK_~ rPv`u1@B7N-!+GuM(Y$f})jyf-YPFi{_4>E9_!G|miTscLp?>)R`v$U~ literal 0 HcmV?d00001 diff --git a/assets/world/module/human/corner_ground.vox b/assets/world/module/human/corner_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..ce8b11c4dff312dffd469d33af5822d7814cc04d GIT binary patch literal 4012 zcmeH}yQ(Es5QbOXOBCF(ffyJm-arJwWDXwW1T%tyjFX-Tgn`}LNqhto10&JE)E5wZ z0DS|qb6%$XYMYqo;Go%T_^GPzueG{+t?tGC?Bn~de7DxRd*|vNVSWGNTAyA$xO`y> ze$V|y_dkDd^~LjNyl!+Yk-m0WHzIW{k|>ZPLwemN58F|oM1@)&7QEmEFL=QVp74Yx zTvV<TFYyvD@B%OJ0v_;yi^#R(IiBM=p5r;5!3}P3gB#q2Gq<CdYoJ1nv{0i&fgG7! z+gi6K>(<4Ort8M3W1bsN=n;B_F~WFZeBc*-jdDb9%(%(NW3D1Lyoo8cNz9yfbaEvx z(c>Z-F_2H~>t-3(^>r&Y{jsIQQRm)S2b;A(ff5yJ<dV#hn=&qmMcqi5Lqaz(=I2^c zTq|b&xgR^)<VjwrZ8NSf>6^_xly5%w(SEGC2cAQc$g@cWbD~C(o8(+CHsu+FK4l&C zT<1|{9X&VRs@ruQOTW%|JSFeky4OviNK~w2vKK@nTA^kw@SD2fMJ#yIpVW!x^eDB$ z1z+HcxF(K=1U1jrJZG^sMa)?v_DyH+re>Xb_6G&M!5TPm={#3)&vi<kFT_uVnmsM{ z)bLzt3zXy~g;zXhox~XzC{e+>j>ec~y;Ag4%-84nf;obDSr^xnBzxCHoBi^mxHF%h zBv?P6y?`rgt`q&_(%e^bFU`Eoel&A8b2np~aYSqOi>TB^>^|kPLm^v%9Oc2u^;{dd zlMgTQB+o<O$=O$!!3^fG>1$ZQ3YM@u<hfVi3Rk$n4eqdpHLPF-OYSG&0vEW#73Snk z-t-i89-6+OM^Mt!^dx@a_xZX)K75|Bi8D@!!={$QvN$Y7j?7UWmJB0T@)(cY$<0t5 z7S~+@6PUsjmau>Y%wY~QMNL1P`&j}PxWW})j7hx23%tN{JjXNcjr(5Q^AecA6xNI> z#uQ@`Kk)-U@O{RR^K2a8^wQV#6@5it;w4^8-}vx`7rfv(jJ(Nfa@L=@6FCa*EtsQ* zktey0NABdo^9FM@tY8I8Si%%$FoQYFVZk~C*K2sg3tsSqCtTqQH@Lwa?$b}*)J0v> zN3GOGZQ~PrI8lkg+9q-o>`kz4HH<vTZ9H-(5B4}%uZ9(@U<pf@!VG3GhdC_R|6m;( z-tdAKJmCpfxWWx?aEJT!Q#W-{*Yr^<wNcyn#2!vmV)C983Y5HO$ve=)$cx;^BM<WA zeNFbhshhf}i`wXMn8N}Vu;iU@@+L2GrN`*8nG^2tfG6KW6N{+$if{Oa@9-FZJea}^ z=2H`GA}ZeZMv02=rFfT{*u)r4p5(<h*T`W33s_PY-)JL)JKSd+JYmIm+(_{Z&+r^C z@Dg5p<Bb$g@oeVD3%ndoZPZR3Q<EFHPfoOnDEPh;ISS5%;M=WX<VkMhkvn;CmIU8v z!wOcgge6R21~Zt$92T56!S~wmh8Mix2~W7f6>e~YJKU$Ax~Yr0rjJ^wjoQX1_Hd#S zgL5X4qu`th&X5{Lp5!(jxswOyU2t|ZtY8I8Si%%$FoQYFVZm7#oGA@&c)<&v@PsQ| z;RZLj!+rXxo4TlL`lyxKsBL^=4<{-yIPVfU3eL;mT&rQ^Np9njJ9%&h2j^SE3RbX$ zB}`!kGnm617M#t&8QAcK7rfvJPq@MrZg7J;+^3(qsf)U%k6NjX+QujLaH0}F`RL*f z|NG8A{_E~ftDWD|j(s-n&vk$A<(KxW*IwNpeemx7_`~;~xSl_J^X2}_Phao9{`~F! z`)@x!vH#gR|GW45jn^OTZ@u|=f9LJ5{*$%6xVYFaFE9UgE<VEj|I~b=|1kgh0~`?O AjsO4v literal 0 HcmV?d00001 diff --git a/assets/world/module/human/corner_roof.vox b/assets/world/module/human/corner_roof.vox new file mode 100644 index 0000000000000000000000000000000000000000..dea1a89941406c87b2408b119f59207dd21428cc GIT binary patch literal 1676 zcmeH`J&IL95QXb@*G~(sz(5R)6#qa3!DJpj^aUy?$T+Dlo5)FY2POuZ2nMFJfdLnw zLFI0!{c221ba2pYE*uV3ed=^o-Fu%u*}e2pL>}#I9z*iRMV@W;*5@nWIrj^8U+irj zw&S#XfV{OFDqDlqG+i~-0W2Z83?P!DbWL6kvkdpdB4b1vu{fHLZ5y(6AV%!O<Q#Nz zfnV=E$HLjN;Jf6&$A;y=$MIQg$*8k{i4DEErI(I+4^L5gK@;UwJ$6Y8OAXD|TXyaE za4#BZl8wHbk{><WXt~r3)HeFl@~`_8bUe{^qrNTlg$Ei|#2Nj=&DjCmy{Fgx%qHxo z!&Y;0rtC5b^bphs`M^sHRU7zo-l|8?(OC6@PU%I-S)Bt1y<(tfdgY^KL}aH|AD+GX zcj^Z78?zDzJ0A2rs2ONS-HqP3f8ez&_y9r2r@{{K1`3>9)V%D;VTTPiSYd@b+~Ec{ z`00by4)5jo;oZ*DV)C4}_N?yb-tSzzFgI5&&;5J1=fVBEC+_ppyI1qe;oJH3=>7cu u?emHHvpxUa_kHc^{=9MhVBWg<`k(A}wOY;fdi`53e!}@bQUB;4{N)F6k9-sW literal 0 HcmV?d00001 diff --git a/assets/world/module/human/corner_upstairs.vox b/assets/world/module/human/corner_upstairs.vox new file mode 100644 index 0000000000000000000000000000000000000000..b296e22caf83c4fba65fb40b53af835db69224d3 GIT binary patch literal 4012 zcmeH}y{aWe5P-Y>OB6h@ffyJm{(%UB$u3^x1}Z4Xy6M?KSeQ9(;v<+C7>Nd^zJTBZ z=o^^%G~-vt#6%Yt&AjkYRbTbY?dh5Bdq4T`-V5KXwcfvT`vGBn`|MgD-`>A@W(t0u z`V;p)y?^`J(^tKI)3rp`S)|TlM2CQcf?nsg^`IRB5(;`fD16}yU--foKJkf9{Nnng zm-Lce&<lD&FYtj6yvRB`J*VgNoSxHjdWJW=;SFzi!z=ez=BUh7nX@u?Uo(H%#blEL z*Ihz4N!@v3o--kMHoP>soEN`)k*oHp8N-sC3tIXj&A7B(3dC6t<6gei^hD2jjdqTS z<-5)AFyEyif@@=oaZX;KzAx5$vDP{MIzBd0dL8?k_1C<Jf#)Ux36=DTE*DAJ*Sw=9 zw|PG1<jl|PBEkLV-MMdT-k-7t${3~RMZY$&VqQe0E@Ib3nU69r1BZZwf(8}YT6|B| zswMXzH_=@sw-nn#>|)TOtj&1t1%4gR8W2-_Q?AqN_~QE7oclUaxh7>?>`vdsx!;Vh zOG#{Y{XN0&oqj?vALdD3T%Yud@lD>$qa-hRok!peW~_4G`8`5^o=3Q^FgMny=lwxK zfP;bdMR~Ud4ojQ$=#zn3pK87tqK_kLgZC+^i@K?sI;fr6sEt|+f^oRQ6|QlO3!LK| zXE?)YG8UJ(!WFJ@feW1D9A`6*JjrYN<U#J^rv}wx{>A)@d6N^h!Ryr20gf}A;j|!% zXRXr;J1vKVQ1H{TapX>3(<4vv5Qx)KoZ$@TIL9@vaD_`;;v!E=@QPQw;SKNj#x<^R zg-aZBYUarS2K1Dk(ldI@do^`a7j@3uS%Z1L>oxR*p3<9|HC#>3vo6-id3K+B2yUL6 zcd~Gc^|Toyz}g#gQ10zKLx6$v+|E369C?uI^vI3eSp#Qog-cxG0v9-?R%)X*YG)0a zafL5@;u9ZuC0BAIcb>f&(~K#6;S(QtCEE1yjW6mPKaRX6g7ZED44n7ryvH0z9^^Vb zawB)%r}O>_m$<|QE^tb%)JAR8&ii!UUo*Do6}_aF^nzZ{Q);C)YMZf)YsMA6@QKeE zN7U)#8(-8lHL;1#cNt*de5=m)nB&NUT&G8F<j!~Oe20ZgT;c*3IHgu<qc&>i8*j!H zzVL}peBhN_$&K9k)|)ZSn8Fu6@qt&OO&{O*qR#Q-$ZH}5dndsm*k8dOsd3~<Zqp-o z@?g&e`=W7$D_r6dr#QnI&T)<l_F&^0SGd9@PH~DeoZ%c7?7^mP>Y`3+rB-UA_URLA zJkh3}9D@Cv;1HYv!Je&g<VkMRBX{!PJP7t_;|f=}#3fE~hBKVw92cAkjcZ)t3YR#= zDb8?)b6jv9G<8!Kby6#}QX92TpIGCGHudC?oErrJ$$68U4?T{&$bEX`L7tplP2S{1 zZuFemse?K>!<tw`rDybP?tu$ja%MHLh)PfC89m1ZE;*-~SVYAe-l=2!IBKKz$%!@* zlC!BGAUUg&v#ZC=c~0)rBM<WAyi3lwrf%w@uK63l7{@s-aDhwC%qDO0ntXANKth0n zfr0@4Wip1n3JC!Y1_}ZTda(~6A;7^vL0~~IzBxz;a4=91SkQ}i3JC!Y1_}ZTda<66 z5a3{-Ah4hp&j$$s4h9MW3wrUl77_v+3>0Mbc@aN)@9rJ`x4ZuEKj-nJ9Q-`#wf|rD z$GX4u{By_cOD`S|-+A+R^zPe_UC-~n`uzCmhcAzxfBgFR^_TA-JO2N5{%7C!D=$Ah kUVHV?@y6?4{3~mF_wL=}=H})v@5LrO{!3<${>}Z@?^D~f*#H0l literal 0 HcmV?d00001 diff --git a/assets/world/module/human/door_big.vox b/assets/world/module/human/door_big.vox new file mode 100644 index 0000000000000000000000000000000000000000..a6197d5344945d6c1cf50afd7612752d98307b2d GIT binary patch literal 47099 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 literal 0 HcmV?d00001 diff --git a/assets/world/module/human/door_ground.vox b/assets/world/module/human/door_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..f5465e94b316d9d9eea26dd534df7f7a754fd4e6 GIT binary patch literal 3992 zcmeI!y{c_j6~OU1#+YBC;I1tsg;m5a5J9lXB^S9x6rxB>drlWfj%j=W!N$T$u(0(7 z1Ro&2f!N&hGTYypHa0OBw9A1%bIku3Ypyxw+Iye%i=V#t#vfX1@4WTuCx-T$ueSEH zSMR_4$~E!#rGMkSU%vn9=U+a${Ucl384nFR@~L4*ebl0!+K$H+`)OiF|1frYZqYy5 z)n4xy^6fcRdmY`px92SRD|TI5@fg?q%Fp(C@#~t;_FTq}<eG7-ZPUF*dtKI<{4j3w ze$B5M`4;2DHsWzy^O#TL>}x-DV<9ibb)DKCkLCI>Z`V4Q7+87jS53v^%=Ww%^fJW# z%GvKW-}23UT8o?0a!>mWqnf6+xnE$1^TUqi{MJ*+ZEL1=QXJ}+YxByXV_;&P(Y~C^ zR6ndATsIDDlrdd9#eK_TBDlJqM@xGv^xL}bcib@Fx9*zOrg+`zT1&pWPm04cN)$Q< zCKkf;NEA8-CKkeTNEA8-CKkfECkh<{6AR(I^Li%e7?@ZH=bR{X3{0$x7!NBt>LJ7- z4sk`ljl+ECF&`!hE9PSw!#H9*c1#rV#NF7rGL|vjBgOd`hj>WOvd}TGd^aXW+8+vO z9$2TY-zw@h#dGIvVPNjM?K7`iKTgf=T&Zyl*Tq9T_uxH4WAep!^I<;slpAvM7IG<9 za-AF8+)IASubVHkno@JEKh#V$OU+iZ)ND1SrmGohrkbVZ%3rxIckN-yExF4LZgM_H zXMXKtnP0gjzQ%o9OYbvp+c>Xyh|MR)HSgx!#NhhnisL5+-}&M<KQZ{u7oYs#I#*nB zak=F9;*$@)@trR|`QY2NHkVv*?Wz^GD>lyMj4?2mXR@68ah{8~pPXkRp3Adb&RyL$ zU*^la)O4<MgB#pj&Q`p|OPp#-O`SD8XMUWTtsiGEmvZHrlIwDf4?g(hldt2uoaey> zm&f@%5XXtP^Vb&!=G52J*KyZxhQ3ZtU*b9SHT9)#n=kWaUTQkmxxo!?PJM~Dc!^U@ zsj0K3zW8x!^d*;aDOav3xh~iE;Db*-`8r--TyVkVarzR+iGALNJ}|L{9*2D!w{aY= zU-26H9QJD5#x6J14Y|opZVi2)<hooxYd90R$tPcY@!d6@AAIo1CtrM>_3e`nKKSI5 zFZGRUTyVkVae5WUiJf=X7baHMSJ#(u8^`hb60feWt}o*@cDbQ$$W3l?tLqCT*X8<I zLtk=}Prmr#yK6c>_~4UIzW6%p+dm(C@X04%>KoU%;DXEJ^d*iH+eg_mcImI&|IGC$ z-euqBQ*N3s^Ii7C4Q`xzXTj~#58wID54DqDeDcK?-_M%Pfe$|U<csg>2jBSMgHOKB zJumP7CKp_Cb!zo3&J*kNjQUFZ#ZLP_u^!W&#gkj&o$hHqPK}<;cUqV0+)y*Q#qHDw zUwl97=#O9g_WKobDOYmcHA8O7Ex9Haaw%8mp8AxVC#P3F`EpI?n|YY0d7Zf)#d%^q z8uMK14A1CyHT>qH(EZ;V*v&hRcch6S?#42Dy?hSi_71h0|C!j{Sys!(X&mS%B!b`G zXBH*~Itq!vzTR~(G0;&+1a@<dm>B3NBm&zz(Za+)M<Ef|-j^082099f!1ivnFfp$8 zEEE!fcYpliE$_kSFCy-rm%G2ud+it3{p;L+@b$0VU%mN_`v*Vz{{7>(fB2c_`N!Y= z>i*Y1|MvdLUw(i8```Zbne|_s^MCjG{?<1?xPRx{AK$<C-CzGt&i2KN7x$MhUw-OZ QzJ&MxC)aoMKdj&W3GkEHV*mgE literal 0 HcmV?d00001 diff --git a/assets/world/module/human/example.vox b/assets/world/module/human/example.vox deleted file mode 100644 index 47fd218a963f35128006615d03fee1b30ea89ddf..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8764 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 DrGVB* diff --git a/assets/world/module/human/floor_ground.vox b/assets/world/module/human/floor_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..d231795f22ce605dd21ed1b8d78520988d95beca GIT binary patch literal 4012 zcmeI!zpAfS5r^?v|7KQ*U}_6VVWq?<h#=VH;6YB22nrHYrw~$^#!IlVuo5k7y#c`s z&^xf(`(}QA=A^OFV9+ib9^UoNJm2-MHTxXcKmW;xZ~s0b-hc1a2OjZ<uSWdr)kiPC z(l37A_!mC>#YeAx`R40#Jk5wR;(6?NIuXxj#`B)aiHfJ?eZ}~A;~-JESVJ8LiNeL2 z>NuFC=UKQ|OAiN$!o?oGwLNi=C|s<gj)O$uVmA6ye)hL~d-nNKABlsFg*fhs<-YU8 zQ*7_ccb#$L^jT53h{ba*BYK)<GI}ojX;xt_!#>fo(>KlM?Rl!_6;IdmWISJ->xsJY zl%CsjVYiDi=k%P;I2!jF?ls(NxYuy6@%mozoPIC6_jUH`JcZ>wd+jVoJ^SgL<s8|+ zQ+K`Iue%qv_v|@%mb>hpL*Lyq>{Z;+dv?bCuYH#FHjl-h?hwv9`ibHE;e6qo;k@D8 z;r#w#eH=aap5=81Oe}01BnlVf%(uoy&bPvP_WQC{n_Vw!y@}Pm>0N(fb^m(jOf1fB zXQ=Te7H{){H?eq|ciIbe?!@A5?%^)p<{e)0f;X{vn|FB0+q}a|Uhx)Za}Fmt#W|eh z6z6g_=Wvo!oXbg0ac-YWKlMxh_8xk-zoB00x9jbDzy0pH_i}ceWhToVtf#fw>3Ul0 z9ZbFK{!rr_Ois2}YTSd#O$=_eA9^weQzkKFs&iLQ_F&2;hHN2ZFP8kllur!#Ldah% zdmK!AB!)c-VULR`n;5c%kiD2Pi6K)6ncLsz7J_^Gdz?aWZhLyS`)U_wZL`4MX1UG7 zdRVJv*N?ScV(C@)LyePIoN6!CxQWFrOzy?zCl<dj`L{ErCzn`qg(-J2<d#ff%3O@j zTp78<k}FKPiy;?sQ|4mGgv^#nESbWTxfn9h-{J;$aSD@jF*wmqpF#a%s7Gh5qt~8$ z9rMCIW^~NddRVKSt{-c?gQ=I@4>iug<YarP#yyza#NZYd|6uYHgI}E~J-LG^ml$$| zkh_?2i6K`Ax!c(*D}ONM6GOfb^0&V)R|vU_C37%k5<{jCGPiTwi^)k0P9ZqA_g5=~ z+U>ga#olR-IB8aCR@T#6?Q}h@^$w<9c7LdG4kjntD>d%H<R%8U+7CUMgDI03GS#`O zCwnku6GOHTvKLGKV9F<kd?Dm7mOT!pJrctng|NrPluZoTLdafBnZ%GOgv{;la|^+} z{XI@0IJZ5$+kLf*b;|6J<?dyc*2`LLcfG9jHiq8m{#4^^49;oqs&O|4_aM00{?L=z z7%~STlbCWFL+&8t64klTm)#h$2O*m%*&%lja*2|=a#L<&$Q^`SqU5ez$RtYU$_(y7 za1+J7{SD6TGwCHt?{=@V-fzEq&U4KRdClmWsr9l}TU{?}y@k-*-Jfclh2ZS=t{QhC zxErV4q0V0j{>I@C{zC9K4nNxuJ(-1&**G#O6a0<CPk!+Se<AoAhoAi7A8vAsd%3~e zIK1Q)@A8sYyxV8iPyN!ry^r4Q@2Qvi?Rxv(Z@+u~^v5sW^Y`ZKAAiq1z9<hrUo`t= z?z6dn|Lb3Sy!z%h9-sX1dyh|l^n=fx=O2IjtH)pe{F}$${_?xWKmPuw&-K5Y^MCj6 s`<-un@_6^#pFY0(onQY?X8YpBi^t2CFaPac{u4g_pY;FH|FD1j6C6m#wg3PC literal 0 HcmV?d00001 diff --git a/assets/world/module/human/floor_roof.vox b/assets/world/module/human/floor_roof.vox new file mode 100644 index 0000000000000000000000000000000000000000..e55181a7903775a2f6d21a71eb56384f7bbbbd19 GIT binary patch literal 4012 zcmeI!y~=LY6~*!OG3Qz<M2NLTNMWVq3qn9h<H3WRA_f%1Sf3(b6`Nc_8jDnt6t><# zAQupe)2GYTJo(LKW0QyyJ6{;=ImY<!wdb?X^K#zzfA_&pK5ec2_RVMSxU|3isI~W= zefadHGJbyW6@Bpg51;+vhc|Bj9<80zo}b;G@47ZxW`33L=E~AlzT{bX(2(hue(RS$ z^-=wlVK!!A60<Og3CzT7%)%^8Vgi$xz)VcT3|hFvB`$Ci7r2RQxIrD4xWG(|PxstM zdp>auH>l$RGcgS_s2Ahxh8xuD*_ehI)axw$pk8O`2KDMHGl%Qx`^Bcy_KW436f`S4 z`$dy?^Pp`$!<7~#1vT7s?X)n%^-LVCy4E@FPhHTYlm|`fw2IkO=a@TY$WOSR7G*I@ zURQq9Ij%vIdd<}(Usv}J+2J=W8lKT<Qc%*OO^1f_J535oTD0lVa7L#|K}jq7%PVO0 zm(#q<PqS=SzRkK#p*z(N8D>*pPH{(u-4xhEv)C@jZwmaOiBJ5dz#p3UQGC<6XH&T6 z&~(pmPv8$t{J?j7;x`5U(8LdX$4~6Qc5K52?$E>yT*o!sz;#@!o%KWC^{vj)wR)bs z%Uk8e^R2w=-oyK$GrX_i^O(~tJGA77vhv_{hf<gFsC>$Ghf){1(9P<GPJbx%p`ZGx zAJum~=1^h+Gcf}*Fuj<D!5vCm;3jV1I<DgyZs86kE^re!a2?lh4VU`RPyNt$eba}0 z%7?tmTkRnmvMy_N7T@_+jJeh9y3h2UruQ_>;k}d(KKS%5rYvMBOWE@Ir@YvdFZuF$ zr#$2-Uq08Ag{;n4_MftlrL27L$=96bx-S2Y&ZSLj+hx1|X7(_j+u7B;wq5wZ1)uye zAM-X3-Q*`9x3iaQ$cAjn8sGWOkL#z*K6hTeE6%4yx$LmqcQem4@7vkaoXa!$iJN@z zhu{3>7vK584}RX>zUFOix~}W|xLsxT;rs3FllGxSnf6KN+{`}aeLMS@Gws7q+~k8l z{N^{m_|6Z0@bmWeF>iCzbzSGj?JBbm-*3Ns=bcYU5q1dd%{<e*Zf8$(gy-=CH~7hK ze({S>zVV&!{NNA2`OUA}d%n5f&aUQt^J48YJ(rSVde-%xaWgwk_nL=pnzwnG(;U<D z`F`)SAAk7GFMZzLe&%sIyP4O`>)hh&%sQuL`waU~QVjcC@4TDYXSmNibkn@e%beyI z&f)vL&p!O&H^20Gd;6Hj?d)S-H?MPxuQThMn(fo=LrKx?bG`F!W}ogp^UzK6HZOCU zqdSN1_dfgZhu{3t=k4ud9=EfPdELCuExyjIb87bc+w4F=v)QfTZe|B_-p;P(+1$r> zT;~VB_~et1+xvc)yLs!DZt;0L&y;Q1mMz&aAM?Jmefsen8pmfiKC>$yl})oesLPYO zJgW<xKB()HntqYLIz0=M7+g@tB{kfljoZa63@)hSk{WK&#vR-#ZsV{)9h=m!i#GOP z=fU8DIxeZ<7H!<Y4NOqSBsI*UjX9XEOKQ4BTX*VNvPD~ViZ`E{UEh8C$(#O;yg&Z$ zetcU!{CwMczrXLx_x|f2zw&tY+N+O`e)Frx$8WvyweRz9pZxLhkI(=7_~+mM^7z*m zpM5R={d@jq-|wHk{?X&-Kl}Lc%U}HI|MG61JbChX`t<34J<BiQ<GWP-j{cAH+kXIw Cv%%Q_ literal 0 HcmV?d00001 diff --git a/assets/world/module/human/floor_upstairs.vox b/assets/world/module/human/floor_upstairs.vox new file mode 100644 index 0000000000000000000000000000000000000000..9a4a55bad6c5badeb9f68e0f6c420a35b0c32f59 GIT binary patch literal 4012 zcmeI!zp8EJ6^8LKzP}?Fh;@o!kt)HMfCz$(2M=<JB#=N*>r(`*Vv|cqlOmO9VVfHe zya2s}bh(<9-_XV;O2l+-c$j0p?=$9_>tk=&fBOA9FMSvhzkT!B?_A=epG5re*?Uia z+&6xH^flgj_q}I-e&NeF{yif0jpwW2I$fu0xt8nh`_N(I;G!^7j*Wwh!W?pJ9M3qe z7lk=>*f_YTp8Io_4jTs-g}LR}IJl_3+PVGCM~{tzi^70!`FwDP=M0}Syu<L0zV`F5 zALj6kkVpHRMA%6?(R=#AO*_d?_u2RSY_Fd=^Tjc+^2IdIzE87kcD~KJiO{X?L&lj1 z&T8+-xD&x$*xck!1b1P#d*%Fz;4f_c;RknNb5Fa)<xd2EVe=3F@;CQzFE_ap!Clzg z!@b<%9`5B9H+T!1cX*dq{Y*~vd+Ltv>Z-f`9NCps`{wG|b?)JOaE9|5zK?mDWvlaR z)-9xNcRysDh2-q^O2%DC?nZD=`>C_Dkajl0&cU#^koGph-ofp?(A!-|yBlHm;Mz@l z8)5I@+ADj*-a^{j2zv+DUfByf2iH#7N$y5)4=%U*GdR`nq&v8}>aKU)SKqs?J)ITK zbe_{0nWtH{JHKY##?YPahm5l^IH$dmaW@9{Ai1~w)Y;h>b`H|c#k99E>>Z@Ni?CO{ z8yx!^!~Q|qzX<z<VgDfQUxfX_w7W6v9;Driuv`5Ob}qtBVQ>$UdlB4fpHuyO-9_lC zdvoEO<y>%=b6Vctyv(xOd6{(=OIO`b8Rueg3Y&Mac!k;CkaI5<w=lVjSD3ufUh=pX zi(8o7!JWLp%l3lDy;$7B<PL6f2RFIF-Q0`CEllp<CO5dr4esI;CTDPx6Ycc-$%j1U z(Vyc!-A8-o=-Kt&?c7k?Id0$Iyv?%0kr#I7%e}6!bz8nVpK@Jc>y~cmW_LrUFKqqN zPyN)7?o-bxY|i3L&fpAAwi6s)Ve=Mm@&+$?$qU}$6*h12CU5YP7rfwY{nAhU(5F81 zOFrd8p7QATkPTVNqMzkH-A6m-=-KtwagN7X9cN`eX7`2N_uIX!uw|>WC6gDne933$ zQ?4s)-O^3n=x*rrg{@!usUQ06KJ}c!<}A+S3{G;Qo#5~ao40tAH+abl-r*EBXK^NH zaFP?8ty{XO8@kkmZpo*7$WtEu`LZEPS@d(<r~7Ef96h_9eSL47>w8~kW}ar*?fjZ` z7fV;&4;klTajLzNaW59PFxyQz|6=hAlfU^Fi(i=h(SGRcTr4|<X=m73{KDi9e)2c} zV(|-;KlsU?+`&z*f8v}I2a`8=$qU}#B`^A&^+TWf=;!F7KTn?W=)8UR(f6)rmNUUB z=TgqaoMzeWe4BL_OIO{8jB~L#)!vbDFBZ2jxtn{jxP{s7mGdtazcBfOzqp0T9qksE zf3f(5$shdWPwwC*cXKZmw=lVbo7~_IZgPXWc!kLuyyQhclN0@(x}i&5bl0CFOIfsU zj-Flr@b;58{V)0DkN^1|-<5}-@4EZL-dE@T+RuLac=n5*Ki+@i)yD^Kz5cD|`SIWX z^7!nZe|voX=|3L-`r?ys^?x|$|Lynt<zK%4c;#0gJbv@*zkV-g`{c=!$J3`z|Le2- P5kCH(^xx<=JU{*eX1<5= literal 0 HcmV?d00001 diff --git a/assets/world/module/human/stair_ground.vox b/assets/world/module/human/stair_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..cb742e0dbeeed44471112c1a660a82865ac682bc GIT binary patch literal 2040 zcmeIxJ&F`j5Ww-OSFfs`;0X-Gz)0~6L=a4NaF7X9P>^-AhRrr|6OUkGU?dordI7}) z=nc$zVngrH{%cH3bWt?hh9C7lx?fk-^gMaEf8n)=+~3<gAjsDgdAvDTpREbknV;-G zJ=lD(-LiZmxXM<$%r3I^CfnX*Zh@59n49Qfha->}Fl8N%Kw`ie>u|JWkC+%RV-Jo% zVxTMU>O?pKi2-xg;RqxKT4BHOe5-fy?pFB)`v^EX4C2%Yqu%B+OJ{DpmmE91az$c5 zjQhx|3FwJdU%0=~E1@sSIa0l2pEhng(X;v`^B{W2cEAS_Ib;rECmMR)i=@v%Y~-kg zx|F(<x|F(<x^!2UY=hsW*SX|A$R}aUqsHXotVc!i<P(^qep6~4%m=k6I`gPL5R+PZ z^`UAf3TGwvYMoinQ2*c@W8CS7aet!*Az!TsC4V75Ax|M+A#WjnKCDBjzE>{?HK4)J z;RqxKG}_c)&}0mQhOus}+oaAI2KCOkGwzdi#xQ7i#?IKMh(N^-1Lw9jWsWJ}$Vk?6 z@?9M4+vGi_bk^a{8Ay1o)gHXgM^<c{&$+>~YP=tY4o4uNjXfAT9D#%?doXl30*S`? z9+m5u9^G5*@$K#|zK!K?EnI*5?CEnq`hM&Dxn*<d;&OE7=5l=Z_KE#`^YYp9@!gB% z)B9J;m(Oocy#KV%fA)P}xqP%-yL!Cbxc>Z~^mescE$j9AmuK-OT>hu}kN)O-`3|ZX Br{e$s literal 0 HcmV?d00001 diff --git a/assets/world/module/human/wall_ground.vox b/assets/world/module/human/wall_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..89844fe4851c0ce5e60c65834d61bb6fb88f508b GIT binary patch literal 4012 zcmeI!zpAfC6~^&d^JlFI2HdrUSXd<(6+{qha>yZ^LWKw+rcH`KVDFPOUV=@ER1%A{ z-hhw`h<9Lj_RakAdB?^^LqhDb;bGo+p6{A>X4d<I{q`T;`N>~fYrlK_+3yYQvmdth z$7k<8efgUBd+9&)&Y#|W_Q4O1-Cp$8BHD{+=kc*edyL*5tF^~XsK?&hi#9!Hdy(d0 z?6lNO8kbi%iY?pNrDm8@zsAY8M)3QU6=7TCLr{;rZ?QZt&&%_?kC>k4LyP^q#gGm2 zYwY(u3S+$}d71ZzzT^F%b}71=crU0IpBnXR9^2acz9*j=^&amv3hIkb?UK7_!<_o1 z>6sc0``YQQoMk(EInSnHU)vsvk`_%GwC$lNY0;!X+a8LN7EKzo?V%`X(WG(7zP3FS zB`umXXxnE|(xOS@8l7#>qNJit(_Jju?xrYd(WF5;_Cw0cdDGeQ`abk1^=ij_UV2p5 znXgRWwjK@lzx1SxLw}||En`yAj(T3_4DQUB*sZVW8=2SW8!78#jQbqEHP7>`J09xH z=fgJ6>)mRG_tt8U%f7bSdG@yKV_74;JMUAE(zlsc&wRhdpR{GeIIiC5<+|!=U3>A} zF5mB@aq04{F|o^fla{q6jZ12l-^+BS<vyn0*68bQQm4@;<=r~o<mX+SY|2wMsP2-t zu!}c&lh=5`3ts1S-sqk7UCC0GvL#!xDVws!Z~Wi~zw<kPt0`H@QkJqMTc>8IDSW4k zos`%?*Zw+PYj?WxK_%;S%{%S8Ih=zA&EdSmyN>5<p8Lt%iRU?-b6A6y*yJtV;svks zI&bg>Zw}`h-X$wp$x@cGC0nv43t7mztjmUMoH}RX7r*$)&r{>R_`wf;=l8=qqj{Ov z;oOmVn8(ST`S|X{IF~a`XD}|~Fb?Bf?qbq%hUvZhJe<4YFaF|pem`~Yk3aZ>KbL!) zw7g^LJ+5$R-NYp>aSOL_3%78A3tY!_T*r0Xzzy8M4cuJ%Fr5{@@r5sZ;R~Pm#3w%S z3%~FU-|&GCeBcA$@g3js9Y62`KbQVZcZT2ijo<jf7ryX?PkiDRe&HLw;Tyi;10VRn z2fpJwe&EMhU!Ub$zU3t^dCK#wr{D4>Z}O0byvzHkcNgYmUWa#9^DvK-JHzqq%{WVM zQy-1XIE=$MOV5(ZH<0?p&%@~vfAJT;^ZTjO6aL^2{w#NvRK9_9Pq@ORbrYAk#4X&y zE!@HdE^r;!aUIuj12=F3H*mA;J+J-y2GU)r+v-YPsVjA*F4d*FRF~?Ox}|QZTk4v+ zrY_Wlx=<JDy1K5etLy59x}k2U8|Qs`gx~m$FMQz(U--l)KJj_pqi6VrZ}`9mKJbC> z_>S-Re%9AV`Ic{a$xB}HI_v4Hyvdt9<RK4voO*pW-{$-9`fc9KoB7y!M4iUg^X+bq zr}v)YWcuKFY<=C%!CTnHo4m<uyx;||^Ez*A_rOnn@)v*cC%^F;FL=T0ys_;QU$T;= zEM-eJWzD>qhj~A&UgL^i{N%60xzCg93%~ez{A>MdPuHl2&EBcgXx`tP>3H7fIZozX zo=3ZQXW=dE;!WP<HD2(7*Lj^cT9CcTQkJqMTe2yevc_-x;0M3+JAX92Qdjblr#$6L zzT{Khc#Rjl;Pq4EJHeN%WGPG8I(*>W_u-shUh?AQ$**??U3<Qs_uX4>K6%~$(C5$p zq_=OYo4;>c`+eQN@BP<5{?YB(D?hz`_}gFIK7QjjUwfZ_`{bkB7k~fD?aP0Bdi&Qu zKmS_(`+NRo-}ld6{qXkl*FL`e@)v*pPVV-}lP9;QPoMtRwfqQg|4&`N(f_f2`wHu} B+yVdq literal 0 HcmV?d00001 diff --git a/assets/world/module/human/wall_roof.vox b/assets/world/module/human/wall_roof.vox new file mode 100644 index 0000000000000000000000000000000000000000..de7dbfbc7717eb17568f4dddba11b65dfb4e6fe7 GIT binary patch literal 4012 zcmeI!zpAZC5ys)}>gwte1y5`s21bhiKm@^L4s(zbsGuO@q-O$QlH(*^f{B5VXkh9M z2ws2&D>w6Mwoh*p6CE5hn+-2j^?Tp`zV2RY!T#xw-uu#T#~43&=k*Vj@w?BD@sro@ zzxv!A{C(zM^xn_jfBo~%KI8HCc&?8z=VL@X##)b&`51dYM%81S^N5&ldW=WQv`ovi zOv|)P%Pg5GGi9dCl$kP9X39*NlsPg-=ExkGBXeYq%#qnLB~vmL@xh))em!E=WAF1Q znUdKuTV~GvSaZBdTC%m}WJX{z`J74F@#au@PGvn(X38v?^_*GWIo>p7*he|jea;$h zT#@%r_Yfb%jJN4M`(~EAkqOTk)=dgpGV|U?IG6pM>5TVW%YAmg=x14Hp6PzpcBb+i zcW~F355Bx3>@}QeIr~bw`|{q@=dE~R+Z^t&?me#iK6e}LU!CTuk63RblJ?sj^)_iy z;e{7o_P(FbsD`uBqEq98rlPaynAKMI<@(Z}q{h`&lec-BS6E@koi;6A^71}|w|Rvh z_t_Nu#b5m7Cx7#cH+jJe-r}wMF5bSM1#j{uFL=RQyu2Ph@QF`6@O8O)n5TKR&z*u6 zC2cA?S9`uFYC1(ZU+l~DrEj&>b7;*M$=le*3M;JDR!`3ti=X_w&%rldcwfbQ5&Xqp z{NyKp^Clj6;0s@P;sc-f!~+j}U5*WGViSwY^g};yf8~9-!=A#K!oDcO9x(mV*Y)&U zpNCf1iwqXn!WMS0!V25i#<Iiy<nf6I9{9o=Kls55FMQuTHn53JEN&KS>|h70o6`^d zyuQBm=khz#uH`(-o|gU4Ue1K+Q-7|fFa2)H<xDcz!V*iYv4b6~u)_9Q&LocqzVL-7 z-dJM?J6K^mmUCIdo4nu!Z}F1X=DyFJaxz0^ViOCQC6m0mK0fYRebBCS&UDUnPTJ|5 zm_GIAdiv7urcCFQ!4{TSVvQZ_V1*U7S30LW9{9o+o_J%8otri9NN1GCCmwjnE?)B5 zyr&F*@aOe;i<fv^4_j*7`E2Le_O$JXYC99A-}=6u{^)CO=i!^vyv?oe>*cn8zImCG zx3OB=UU_)n3r~FG1E2WB<31Ztd<PF7mtzY{Y)`X(=~G{{E~D<U&$8cg4!ye7Qd8aP zQuFdE`!QcnzjxUOb~ENQ?<{-3FEgikFYM0x)Gx}Z(xx1Ki^Fey_}=I@E%Sb6?i}9~ zcv0Z>>^aBqxl!<oCVrkh&mYcC!7rNpLxbPXnImHl6mmsV?$8<sKe)S~$vfAde$)0a z)bU*J^XUGD?svr6aldQscE}Ikp>aQ#`?>i{j&;YnR{Od7ZCT&<cV>NC-}n1?KO5`Y z`nJBUZ|jHqnlys$zSOA>cRKGqyW@F3gZtTB#gTOmnv14c9crkd&Ln3Y>bPfCL!H}9 zL9_G})ZTfhy|3-%s7Gz@ZF@QDQQP~^m3I_19s4+*U23VVwtDQPsOflrQPc76qNd~B zb>Dw$wC{U+URy`Aeb+Jl*7x=FM_);!eg9>!#5T6EHn;hhkGXccD_MNui6_4C*0=uX ztJ>Yl%7xtGEnf0Auhpa0Y4<NHH|0Vu<Q6~qo8RhD%l~3SZpcl!DHn2!pZtCQS5wc; z@dtnMgTL^++&s-;UU$|{ecWE1>W{zw@*V$UJpcJ0`RSAD$=@ek`{}xW-urjH_=Ts} zU-|OWhu{15(?{=q_haw#_rLzd)1UwNtEa#G={HY*`|BS*Hvj28|99W-uYL8yr*C}y kqo;3u^OygVyM6ic<<qNIum0_`{0N`^pSr)%|M2|r5Av1RhyVZp literal 0 HcmV?d00001 diff --git a/assets/world/module/human/wall_upstairs.vox b/assets/world/module/human/wall_upstairs.vox new file mode 100644 index 0000000000000000000000000000000000000000..bbcf8d6110ff735beb45801ae19a02e865900439 GIT binary patch literal 4012 zcmeI!zp8ZQ702;st><rukW;4!7FLlY3Lzk*@x_<$7Aiy#V|y$D!knW`F2TmaN=#wv z4FtRZy@PbQn#pI4O`0f*b`C6__4|I;v-j+MX7-%7-+br!Pg`rRzxwPAOZ)6st-bZ^ z-KWo0@cPC7)H{EB_u1cndBg2L*;-_~pV1$qxA$VGsg~O6wD%5v@Pi-x;0NFM#y7t4 zjc<J63txDv%q?!|CpWptO?=`Lk7)OU8{FUqH@LxdyyG43c*i@QRr<t|%i7!8{c$~8 zt=o0QrAJ(ja>e&6`Xyssw%j8hW{ijC+}-t`SP#dHTXMhEtYbtxj@w*bmbrbaei_`c zw_DS(^0v-Pznvo=b}YxMWA4kW<HfMQ&bu$oY;#Quk2+7Cx2`|trPVdaGv>om{kCUb zvhIOnj2PZezqGm+x0(Hr-rsQCal0nRulpMNq1C;)UGH$Lahc9>oMTwKO114hk(aPP z>%G|*&L43eQ#I#r)`<Do<LIZ^dLPvfefM5#uG^E3D~|h_=EJoXuX}$kyUn}ZhFW(= zzizqfhramMFa5fkH<xmkyIlUrTi)`z8@HLj5=*ROLq776x4iDUxzhp*EU}Ia{n2mz zx=S;YAAIMNAAIMN4}S2SPd@n0Cm(#{JD+^;jZZ%Kb~}FPQ(t?Jwf2RzSY_v)-k<7f z47I%HV*07ia{8_xUG2Er*uoYzv55tiSYjRP*hqEUD{ga}TioI%H@U_I7hH15b*|Sw z{NNkk_`+B1!5bcU;E89=%SYbwt~t5MAxC-ZDQ<1nobI~{l|wCmr(*i9Z{_r%&#tz= zH#V?=b*y7eZgR*WXR71#VRmwp8{FVJ*SRJ)IpmPH*=2T_o!sOGH)__}tjEkYv&}3s z%gp3vIsD)o-}u5;arwww-j%J#+NaO0O4Wy2KJUf!Lm%bzsqbBF-wAAD6C2pT8Wvb! zi6z!ko$i|K;TAW!$qjCB4R3hhfhV5$v1fCeTioI%H*1gF<dCCg%^h<a-}u5;%~@M{ z{NP*Om958`!}myq%C4sGT`_&vw{rT>XR76Uiw$gG9qU+=n;de;xjj?NO?=`5A9%-` zzUf1s$8*KpGPlf4ZgPX`T(gGtnAv8wnPp~~ncS$E^4#Gzx4Fg5;_{KVyeeCFt*TGY z6qTwEwLF80>4!eb=~Lgk+Mb!%#3nYdfi*0!z!FQWr#hau+~O8DxycP~a1C#G;DINe z__1emn_JxCCO2!3+~km>X3ZUQ8{hcCSIt>ldHmp8-j%J#+NbBYO4Wy2p83V}Lm%bz zsqbBFzYEyJCN{8vH7u~e5=*S7I?J`&!!2%dlN;RN8s6~015Z5hW6$O`x46YkZq^>T z$stG0nmgt;zVU^xnzOd@_`$clD_f6sOut{Mt1;B_n^sIe^;u5e^`oo3U5goPVH2BJ zV2LHxv5t*Y$L}b&xy>zZag&=|<AMt=x#T+6Yaf2_jc<J6tM=dx4?OV1v*zU^Z+X|8 z+~km>y!8~fHtU+lwfJpTYpCTny_kOMM>+k}udX&PA9>4L?q&uyu!&7<r8?&1BX4=j zX||i~b!={MlbbbbJ=QRjX3|VI)6EQSaE%Ktxa5-STrY<=Jn+C1&*E~ELypSUX8r45 zp1kURyW7kEM%N!&SFazs_vd}z-1k5I=GWI}zkT8Q{-6JN{qVI{zVm+m^WzV$Uw-k? z^{an<a{c$$pMU54&-eNJeZGJ9;``S>{Qkr1%P;-oN4d98o;<leefsqO9?O^T`cqbY JN5AFx?Z1S3qIduR literal 0 HcmV?d00001 diff --git a/assets/world/module/human/window_ground.vox b/assets/world/module/human/window_ground.vox new file mode 100644 index 0000000000000000000000000000000000000000..ebb946a9680d1cf8b48ffc1d5cb6d6489c647265 GIT binary patch literal 4012 zcmeI!KdY_9702;4vu4eVB#>QOh=r9wlRyvxX}shjw@^VrjP1RJAe?h!lb4VtMXHb# zY4ZjIUx2=YbmzXA?Pqoxn<$Z_^T3x`>-$^JpFR6|Hs_=FKYsPE5%KQZPu{b{-+mVH z;ge4u|MWEeUiuav|NfIFpZ?^g<Dp0F)}HPWFLp;#XYK8&;8{b*8oaqY=!dnNNeq2q zo;hs9axB)#(bai+#|>*?o*o-9&7&hRP?%WQh_>#d%we~E->r#(!o<Qx40Gs63=}37 zHX_ZSBQa2zSlG8UUM&03THa@mht|g3^mz)a?Yrso)cH(iqK*5WXLdi2R(Gi`^*GM_ zZgn5lcJ|JGhBfVb_gSXCT0G3=dad6VKaj28&2t{i+j(8nwbHeRx#5_8=Fc2fn|I+H zyUqJ{Tk|f>Z1=s*t(InnweH$>&uGiNpiS#^E$nbTeJv|ICNIX;V<H__T({1MhhZkq z96VVM!#S2UonxV6%eMKgPFZvO(vP#ss?44}unq*azLj&UyLDR^+Sxxe`x3YPwc3~R z9rbgJXJy!<X!H4M>-p9<`xEvc>_NNjPu=x4p7pjo*UK}#o)vmaed<%6&!&F1vJOnF zr(NIGZT3rBsDA0{IQ>?0ar{ur0x9dVK%Ol1@<7UmJY_@HWr36pS;>a1WXTV{_{kSP z`N0=I`NdCu@x@Pm@ta@#<|n`Sef*i#@6%hOyFWzFOTX2r9+y;iuBoHfW$5!ZGq~dB zrMPi(#Z7KqCRaB%xy9|v;^xgQZeO;3>F4b_%XN-RZgA&X%e9UhTyf`Gi$AWo$t~{m zQ-7{|>ZLyG_I<ebLi$|lIQ>*}fzAi=_@$QxQkMKUe)F<G%7$#nO4en8lnq(QN;YN5 z55D-xPk!-(FMjfiU;O5apZwxCzt4HN#qBez-lw)k`93Cw@8Q(Tdiu0-{kW~>JKy-u zC*SzaC*S$x2jBVR2cP`li%)*=b-eFl$VxV4LsqhRvZj}pe9D)+<Ws)nLtf{*l`r|0 zPx+E>dC8Y-pJVxb{OQ$gdA2rYxp&VUx;~C8H6KVmj~g5xNPh6+_~d1Qlnq(QO4en8 zlnq(QrfkZRAAIqXU;H}$Jg2gfP1%xd**;m5$xA-vOTOiUuk$?fi{Iy3+|uvUTif#9 zY|QENdZ*C!aa^hSK=OIq;P^oDgCEByFAJn>$VyhSE(@e=$VxV4Q<nVTi=X`B*YV!7 zAuHLGE!mdslQr3SN99w#<Xb-YI`1mK_<gR$E&V>dwN1YX3*~n}9jD)FE{-2+Ss-Oy z7RZyOULHvKkf&_Ox-5{gAuHLCl`Q$e7eD#pCqMY&C%^c~FTVK6FMjij-~8kkzmGq& z`h9xqnA?4zwrg+quHI@cj~{ATV#+#7o|y7}W|A|PnC3c`xrS-3W0`9xvx#Z8W0`H( zW&_J?!!{e3W;>SIhHW;^yqP%Xl{IWxoLn8Jk9Jv@C=4Vz8Uj1~zGI>=kmzU#?C`sW ziNZjlqam=v?*S$X1Bs4?zz**ZCJF<Ij)uSv&m1NS1Bs4?zz*LZCJF<Ij)uSv`+|wW zK%%3;f7q7~-g)%4|5t8*{{OrFP_F)d=&?T@_wRjw>y?+UPhNlR`q^)Pef|7*zxm$% z{QIB(aQ*V1f4YA4#b2)f`uZQ=JOAT8|98*#8$bW-`inO|zy9i%fBc{9?W0GJu8$u- T{*UMK5?=qGoOkp)&L7_Z3qjZX literal 0 HcmV?d00001 diff --git a/assets/world/module/human/window_upstairs.vox b/assets/world/module/human/window_upstairs.vox new file mode 100644 index 0000000000000000000000000000000000000000..309fc417ec97439b05e71b217abbb99fc70dcfca GIT binary patch literal 4012 zcmeI!yNae+8HVBYZq`N=G&T?eBgGwvAec;JBOS~L3NlVw6$k^}?Ia$8iGh)5VCo47 z9)O;KnMYGzt4vIEaL{ZD9-j5y_qSVL{k8e&kKX_CZ^sz#zVqrmHGcQ`F@EyugO{JX zgRjs0OWyz42d{qq*=Icdo@2xukE6$9$S5u2Xc^owAMV`sk}cfEH@@+WZ+znmU--fU zUpL(1CO5gsO?=|>-p9JR=9=p}bIlcAc;ST?UiTawl6>;XC!d$`nd4zaJ(g~nca|;Z zChF~p{dz>aS+O2wtjCra<Ds6{;~^tnN9;El`|XZ;y}2EYtv4f5w$z&wiA~qJ_e|%z zU*zL<{niof8kcRyPRG`p9qa9SK7TyK^R@0Z?=|9Wc&2dtai8PddcIaVXTCn3sboI) zeg1aLeXek?8_fPf(z9grV|ou6Q<mrJ$7Ma@xX*c;QqnSI$(AEMybGD)qw=sMWQ$MG z!@27nUpTU4FF9s?^t{}9S?`HSV-uU$GVjKv@W%U|hc9dwC&?98Tyv9K_)cDePd@p& z_uwbLxWNS%Tyn)VH?PA79(dw~_vPj=r@8KI9oBi*I&RBeX|HLIX@9cK`sjJN^|IbA z2iHe8H@V3zY+<`NDXzJ`*Wf0%@SVIQUwrY+H$VBs1(#fM#nrtRH@U$D7hH1571!6{ z0}nj##OreNFo!wstmC%qRrX%?UiL2AtdE|TTQBR~a&UcgbCa9g!WOoRlj54|dkt=K z3*X60^2Hb5eDjlETyV)HS6tnDag!TdaKR;)Tyf3K;JLvC7hH11^>x_50!yqevyOXR zIkWA*?N3(Qx7m7IpOW47i(?Dh*v3xEY5V25dC%n*x4F#~*IaXxo800Smt1khHP`n( z+~k5wF1g~0Yp%H&ZNHA;gHJyB;*0O=xxob&Tyn|Pb=bfH3vB42*O{Jqy8pC?X>VrT zm+7@Iy>(%2J+0To_11~kJ;yxFt2w=OaLE<d*u+-xdh5XlpM3F+Pkg0g^wxt9KKbGs zpVwc92cCH0jm^NZz!EF0FEfWZ&2?w%xYv+%miMr{hvhvi@4>A5GQAe2w=S%$r}dh+ z-a7HR=a{E?HK(@@F1g|wo7gH|Z$0?nlP|vUiLZ2w-g@xCCtrNy^ZM)Xz!NXLFEfWZ z&2?w%u+F>Iaa;D<_OR`7+lOqkK6+kmy{vc3!S&J2O>S}vTi7m6ifgX#HMq$wd?zo- z7hiny%};)D!6lbmadq#-O>S_(1(#fM#r1Xgzyl9F@w(hR%wf(u>$oj@9(z6Zc<fJ> zSsy(ww_et}WaIki<|a3}g)MBS99|z?j%mmAy_RF9V-~l#<cce<x#lJ}x!{sZuDH7Q z<C+^>aKR;)Tyb?BKJdT;PdqO-4|AB~&U)M){w7LFNz0TaNA`33n=$;Ik|`}EDIr77 z@Vj1?Olc`e2^n&R-;J_lN=r#f$dEJqyvvd)EhQ--L(cGdl_gVJN>W0GoZ<T_OQy7x zq=XDP!}m&-Olc`e2^sR^AHI0U|Jcu8{<nMjq<Ql7NzeWCynnv;?|$ivPp`iEm8TEC z|DC6ge(=4IeV@Po^)H_O{KsEC{pC-;dHUO5|M0QLfBK&PyU+L6zxLtNH^1@G)3?9% g%m2x{eevSO)617H|LwK>5I+4sbALwv!}Z5M02N%Gf&c&j literal 0 HcmV?d00001 diff --git a/server-cli/.gitignore b/server-cli/.gitignore new file mode 100644 index 0000000000..dc83325b30 --- /dev/null +++ b/server-cli/.gitignore @@ -0,0 +1 @@ +settings.ron diff --git a/world/src/block/natural.rs b/world/src/block/natural.rs index 79fde45685..54c6f27306 100644 --- a/world/src/block/natural.rs +++ b/world/src/block/natural.rs @@ -30,6 +30,7 @@ pub fn structure_gen<'a>( if (st_sample.tree_density as f64) < random_seed || st_sample.alt < st_sample.water_level || st_sample.spawn_rate < 0.5 + || !st_sample.spawn_rules.trees { return None; } diff --git a/world/src/column/mod.rs b/world/src/column/mod.rs index 34bac0c714..04c1903ae0 100644 --- a/world/src/column/mod.rs +++ b/world/src/column/mod.rs @@ -1,6 +1,7 @@ use crate::{ all::ForestKind, block::StructureMeta, + generator::{Generator, SpawnRules, TownGen}, sim::{LocationInfo, SimChunk, WorldSim}, util::{RandomPerm, Sampler, UnitChooser}, World, CONFIG, @@ -518,6 +519,12 @@ impl<'a> Sampler<'a> for ColumnGen<'a> { location: sim_chunk.location.as_ref(), chunk: sim_chunk, + spawn_rules: sim_chunk + .structures + .town + .as_ref() + .map(|town| TownGen.spawn_rules(town, wpos)) + .unwrap_or(SpawnRules::default()), }) } } @@ -547,6 +554,7 @@ pub struct ColumnSample<'a> { pub location: Option<&'a LocationInfo>, pub chunk: &'a SimChunk, + pub spawn_rules: SpawnRules, } #[derive(Copy, Clone)] diff --git a/world/src/generator/mod.rs b/world/src/generator/mod.rs index b24d0b3d84..b658a4b41b 100644 --- a/world/src/generator/mod.rs +++ b/world/src/generator/mod.rs @@ -7,8 +7,28 @@ use crate::{column::ColumnSample, util::Sampler}; use common::terrain::Block; use vek::*; +#[derive(Copy, Clone, Debug)] +pub struct SpawnRules { + pub trees: bool, +} + +impl Default for SpawnRules { + fn default() -> Self { + Self { trees: true } + } +} + +impl SpawnRules { + pub fn and(self, other: Self) -> Self { + Self { + trees: self.trees && other.trees, + } + } +} + pub trait Generator<'a, T: 'a>: Sampler<'a, Index = (&'a T, Vec3<i32>, &'a ColumnSample<'a>, f32), Sample = Option<Block>> { fn get_z_limits(&self, state: &'a T, wpos: Vec2<i32>, sample: &ColumnSample) -> (f32, f32); + fn spawn_rules(&self, town: &'a TownState, wpos: Vec2<i32>) -> SpawnRules; } diff --git a/world/src/generator/town.rs b/world/src/generator/town/mod.rs similarity index 50% rename from world/src/generator/town.rs rename to world/src/generator/town/mod.rs index 73bde112f6..997bfde100 100644 --- a/world/src/generator/town.rs +++ b/world/src/generator/town/mod.rs @@ -1,4 +1,7 @@ -use super::Generator; +mod util; +mod vol; + +use super::{Generator, SpawnRules}; use crate::{ block::block_from_structure, column::{ColumnGen, ColumnSample}, @@ -8,14 +11,617 @@ use crate::{ use common::{ assets, terrain::{Block, BlockKind, Structure}, - vol::{ReadVol, Vox}, + vol::{ReadVol, Vox, WriteVol}, }; +use hashbrown::HashSet; use lazy_static::lazy_static; use rand::prelude::*; use rand_chacha::ChaChaRng; -use std::{collections::HashSet, sync::Arc}; +use std::{ops::Add, sync::Arc}; use vek::*; +use self::vol::{ColumnKind, Module, TownCell, TownColumn, TownVol}; + +const CELL_SIZE: i32 = 9; +const CELL_HEIGHT: i32 = 9; + +pub struct TownGen; + +impl<'a> Sampler<'a> for TownGen { + type Index = (&'a TownState, Vec3<i32>, &'a ColumnSample<'a>, f32); + type Sample = Option<Block>; + + fn get(&self, (town, wpos, sample, height): Self::Index) -> Self::Sample { + let cell_pos = (wpos - town.center) + .map2(Vec3::new(CELL_SIZE, CELL_SIZE, CELL_HEIGHT), |e, sz| { + e.div_euclid(sz) + }) + .add(Vec3::from(town.vol.size() / 2)); + let inner_pos = (wpos - town.center) + .map2(Vec3::new(CELL_SIZE, CELL_SIZE, CELL_HEIGHT), |e, sz| { + e.rem_euclid(sz) + }); + + match town.vol.get(cell_pos).unwrap_or(&TownCell::Empty) { + TownCell::Empty => None, + TownCell::Park => None, + TownCell::Rock => Some(Block::new(BlockKind::Normal, Rgb::broadcast(100))), + TownCell::Wall => Some(Block::new(BlockKind::Normal, Rgb::broadcast(175))), + TownCell::Road => { + if (wpos.z as f32) < height - 1.0 { + Some(Block::new( + BlockKind::Normal, + Lerp::lerp( + Rgb::new(150.0, 140.0, 50.0), + Rgb::new(100.0, 95.0, 30.0), + sample.marble_small, + ) + .map(|e| e as u8), + )) + } else { + Some(Block::empty()) + } + } + TownCell::House { idx, module } => { + if let Some(module) = module { + let transform = [ + (Vec2::new(0, 0), Vec2::unit_x(), Vec2::unit_y()), + (Vec2::new(0, 1), -Vec2::unit_y(), Vec2::unit_x()), + (Vec2::new(1, 1), -Vec2::unit_x(), -Vec2::unit_y()), + (Vec2::new(1, 0), Vec2::unit_y(), -Vec2::unit_x()), + ]; + + MODULES[module.vol_idx] + .0 + .get( + Vec3::from( + transform[module.dir].0 * (CELL_SIZE - 1) + + transform[module.dir].1 * inner_pos.x + + transform[module.dir].2 * inner_pos.y, + ) + Vec3::unit_z() * inner_pos.z, + ) + .ok() + .and_then(|sb| { + block_from_structure( + *sb, + BlockKind::Normal, + wpos, + wpos.into(), + 0, + sample, + ) + }) + } else { + Some(Block::new(BlockKind::Normal, town.houses[*idx].color)) + } + } + } + } +} + +impl<'a> Generator<'a, TownState> for TownGen { + fn get_z_limits( + &self, + town: &'a TownState, + wpos: Vec2<i32>, + sample: &ColumnSample, + ) -> (f32, f32) { + (sample.alt - 32.0, sample.alt + 75.0) + } + + fn spawn_rules(&self, town: &'a TownState, wpos: Vec2<i32>) -> SpawnRules { + SpawnRules { trees: false } + } +} + +struct House { + color: Rgb<u8>, +} + +pub struct TownState { + center: Vec3<i32>, + radius: i32, + vol: TownVol, + houses: Vec<House>, +} + +impl TownState { + pub fn generate(center: Vec2<i32>, gen: &mut ColumnGen, rng: &mut impl Rng) -> Option<Self> { + let radius = rng.gen_range(12, 24) * 9; + let size = Vec2::broadcast(radius * 2 / 9 - 2); + + let alt = gen.get(center).map(|sample| sample.alt).unwrap_or(0.0) as i32; + + let mut vol = TownVol::generate_from( + size, + |pos| { + let wpos = center + (pos - size / 2) * CELL_SIZE + CELL_SIZE / 2; + let rel_alt = gen.get(wpos).map(|sample| sample.alt).unwrap_or(0.0) as i32 + + CELL_HEIGHT / 2 + - alt; + + let col = TownColumn { + ground: rel_alt.div_euclid(CELL_HEIGHT), + kind: None, + }; + + (col.ground, col) + }, + |(col, pos)| { + if pos.z >= col.ground { + TownCell::Empty + } else { + TownCell::Rock + } + }, + ); + + // Generation passes + vol.setup(rng); + vol.gen_roads(rng, 30); + //vol.gen_parks(rng, 8); + vol.emplace_columns(); + let houses = vol.gen_houses(rng, 60); + vol.gen_walls(); + vol.resolve_modules(rng); + + Some(Self { + center: Vec3::new(center.x, center.y, alt), + radius, + vol, + houses, + }) + } + + pub fn center(&self) -> Vec3<i32> { + self.center + } + + pub fn radius(&self) -> i32 { + self.radius + } +} + +impl TownVol { + fn floodfill( + &self, + mut opens: HashSet<Vec2<i32>>, + mut f: impl FnMut(Vec2<i32>, &TownColumn) -> bool, + ) -> HashSet<Vec2<i32>> { + let mut closed = HashSet::new(); + + while opens.len() > 0 { + let mut new_opens = HashSet::new(); + + for open in opens.iter() { + for i in -1..2 { + for j in -1..2 { + let pos = *open + Vec2::new(i, j); + + if let Some(col) = self.col(pos) { + if !closed.contains(&pos) && !opens.contains(&pos) && f(pos, col) { + new_opens.insert(pos); + } + } + } + } + } + + closed = closed.union(&opens).copied().collect(); + opens = new_opens; + } + + closed + } + + fn setup(&mut self, rng: &mut impl Rng) { + // Place a single road tile at first + let root_road = self + .size() + .map(|sz| (sz / 8) * 2 + rng.gen_range(0, sz / 4) * 2); + self.set_col_kind(root_road, Some(ColumnKind::Road)); + } + + fn gen_roads(&mut self, rng: &mut impl Rng, n: usize) { + const ATTEMPTS: usize = 5; + + let mut junctions = HashSet::new(); + junctions.insert(self.choose_column(rng, |_, col| col.is_road()).unwrap()); + + for road in 0..n { + for _ in 0..ATTEMPTS { + let start = *junctions.iter().choose(rng).unwrap(); + //let start = self.choose_column(rng, |pos, col| pos.map(|e| e % 2 == 0).reduce_and() && col.is_road()).unwrap(); + let dir = util::gen_dir(rng); + + // If the direction we want to paint a path in is obstructed, abandon this attempt + if self + .col(start + dir) + .map(|col| !col.is_empty()) + .unwrap_or(true) + { + continue; + } + + // How long should this road be? + let len = rng.gen_range(1, 10) * 2 + 1; + + // Paint the road until we hit an obstacle + let success = (1..len) + .map(|i| start + dir * i) + .try_for_each(|pos| { + if self.col(pos).map(|col| col.is_empty()).unwrap_or(false) { + self.set_col_kind(pos, Some(ColumnKind::Road)); + Ok(()) + } else { + junctions.insert(pos); + Err(()) + } + }) + .is_ok(); + + if success { + junctions.insert(start + dir * (len - 1)); + } + + break; + } + } + } + + fn gen_parks(&mut self, rng: &mut impl Rng, n: usize) { + const ATTEMPTS: usize = 5; + + for _ in 0..n { + for _ in 0..ATTEMPTS { + let start = self + .choose_column(rng, |pos, col| { + col.is_empty() + && (0..4).any(|i| { + self.col(pos + util::dir(i)) + .map(|col| col.is_road()) + .unwrap_or(false) + }) + }) + .unwrap(); + + let mut energy = 50; + let mut park = self.floodfill([start].iter().copied().collect(), |_, col| { + if col.is_empty() && energy > 0 { + energy -= 1; + true + } else { + false + } + }); + + if park.len() < 4 { + continue; + } + + for cell in park { + self.set_col_kind(cell, Some(ColumnKind::Internal)); + let col = self.col(cell).unwrap(); + let ground = col.ground; + for z in 0..2 { + self.set(Vec3::new(cell.x, cell.y, ground + z), TownCell::Park); + } + } + + break; + } + } + } + + fn gen_walls(&mut self) { + let mut outer = HashSet::new(); + for i in 0..self.size().x { + outer.insert(Vec2::new(i, 0)); + outer.insert(Vec2::new(i, self.size().y - 1)); + } + for j in 0..self.size().y { + outer.insert(Vec2::new(0, j)); + outer.insert(Vec2::new(self.size().x - 1, j)); + } + + let mut outer = self.floodfill(outer, |_, col| col.is_empty()); + + let mut walls = HashSet::new(); + self.floodfill([self.size() / 2].iter().copied().collect(), |pos, _| { + if outer.contains(&pos) { + walls.insert(pos); + false + } else { + true + } + }); + + while let Some(wall) = walls + .iter() + .filter(|pos| { + (0..4) + .filter(|i| walls.contains(&(**pos + util::dir(*i)))) + .count() + < 2 + }) + .next() + { + let wall = *wall; + walls.remove(&wall); + } + + for wall in walls.iter() { + let col = self.col(*wall).unwrap(); + let ground = col.ground; + for z in -1..2 { + self.set(Vec3::new(wall.x, wall.y, ground + z), TownCell::Wall); + } + } + } + + fn emplace_columns(&mut self) { + for i in 0..self.size().x { + for j in 0..self.size().y { + let col = self.col(Vec2::new(i, j)).unwrap(); + let ground = col.ground; + + match col.kind { + None => {} + Some(ColumnKind::Internal) => {} + Some(ColumnKind::External) => {} + Some(ColumnKind::Road) => { + for z in -1..2 { + self.set(Vec3::new(i, j, ground + z), TownCell::Road); + } + } + _ => unimplemented!(), + } + } + } + } + + fn gen_houses(&mut self, rng: &mut impl Rng, n: usize) -> Vec<House> { + const ATTEMPTS: usize = 20; + + let mut houses = Vec::new(); + for _ in 0..n { + for _ in 0..ATTEMPTS { + let entrance = { + let start = self.choose_cell(rng, |_, cell| cell.is_road()).unwrap(); + let dir = Vec3::from(util::gen_dir(rng)); + + if self + .get(start + dir) + .map(|col| !col.is_empty()) + .unwrap_or(true) + || self + .get(start + dir - Vec3::unit_z()) + .map(|col| !col.is_foundation()) + .unwrap_or(true) + { + continue; + } else { + start + dir + } + }; + + let mut cells: HashSet<_> = Some(entrance).into_iter().collect(); + + let mut energy = 1000; + while energy > 0 { + energy -= 1; + + let parent = *cells.iter().choose(rng).unwrap(); + let dir = util::UNITS_3D + .choose_weighted(rng, |pos| 1 + pos.z.max(0)) + .unwrap(); + + if self + .get(parent + dir) + .map(|cell| cell.is_empty()) + .unwrap_or(false) + && self + .get(parent + dir - Vec3::unit_z()) + .map(|cell| { + cell.is_foundation() + || cells.contains(&(parent + dir - Vec3::unit_z())) + }) + .unwrap_or(false) + { + cells.insert(parent + dir); + energy -= 10; + } + } + + // Remove cells that are too isolated + loop { + let cells_copy = cells.clone(); + + let mut any_removed = false; + cells.retain(|pos| { + let neighbour_count = (0..6) + .filter(|i| { + let neighbour = pos + util::dir_3d(*i); + cells_copy.contains(&neighbour) + }) + .count(); + + if neighbour_count < 3 { + any_removed = true; + false + } else { + true + } + }); + + if !any_removed { + break; + } + } + + // Get rid of houses that are too small + if cells.len() < 6 { + continue; + } + + for cell in cells { + self.set( + cell, + TownCell::House { + idx: houses.len(), + module: None, + }, + ); + self.set_col_kind(Vec2::from(cell), Some(ColumnKind::Internal)); + } + + houses.push(House { + color: Rgb::new(rng.gen(), rng.gen(), rng.gen()), + }); + } + } + + houses + } + + fn resolve_modules(&mut self, rng: &mut impl Rng) { + fn classify(cell: &TownCell, this_house: usize) -> ModuleKind { + match cell { + TownCell::House { idx, .. } if *idx == this_house => ModuleKind::This, + _ => ModuleKind::That, + } + } + + for x in 0..self.size().x { + for y in 0..self.size().y { + 'cell: for z in self.col_range(Vec2::new(x, y)).unwrap() { + let pos = Vec3::new(x, y, z); + let this_idx = if let Ok(TownCell::House { idx, module }) = self.get(pos) { + idx + } else { + continue; + }; + + let mut signature = [ModuleKind::That; 6]; + for i in 0..6 { + signature[i] = self + .get(pos + util::dir_3d(i)) + .map(|cell| classify(cell, *this_idx)) + .unwrap_or(ModuleKind::That); + } + + let module = MODULES + .iter() + .enumerate() + .filter_map(|(i, module)| { + let perms = [[0, 1, 2, 3], [3, 0, 1, 2], [2, 3, 0, 1], [1, 2, 3, 0]]; + + let mut rotated_signature = [ModuleKind::That; 6]; + for (dir, perm) in perms.iter().enumerate() { + rotated_signature[perm[0]] = signature[0]; + rotated_signature[perm[1]] = signature[1]; + rotated_signature[perm[2]] = signature[2]; + rotated_signature[perm[3]] = signature[3]; + rotated_signature[4] = signature[4]; + rotated_signature[5] = signature[5]; + + if &module.1[0..6] == &rotated_signature[0..6] { + return Some(Module { vol_idx: i, dir }); + } + } + + None + }) + .choose(rng); + + self.set( + pos, + TownCell::House { + idx: *this_idx, + module, + }, + ); + } + } + } + } +} + +#[derive(Copy, Clone, PartialEq)] +pub enum ModuleKind { + This, + That, +} + +lazy_static! { + pub static ref MODULES: Vec<(Arc<Structure>, [ModuleKind; 6])> = { + use ModuleKind::*; + vec![ + ( + assets::load("world.module.human.floor_ground").unwrap(), + [This, This, This, This, This, That], + ), + ( + assets::load("world.module.human.stair_ground").unwrap(), + [This, This, This, This, This, That], + ), + ( + assets::load("world.module.human.corner_ground").unwrap(), + [This, This, That, That, This, That], + ), + ( + assets::load("world.module.human.wall_ground").unwrap(), + [This, This, This, That, This, That], + ), + ( + assets::load("world.module.human.door_ground").unwrap(), + [This, This, This, That, This, That], + ), + ( + assets::load("world.module.human.window_ground").unwrap(), + [This, This, This, That, This, That], + ), + ( + assets::load("world.module.human.floor_roof").unwrap(), + [This, This, This, This, That, This], + ), + ( + assets::load("world.module.human.corner_roof").unwrap(), + [This, This, That, That, That, This], + ), + ( + assets::load("world.module.human.chimney_roof").unwrap(), + [This, This, That, That, That, This], + ), + ( + assets::load("world.module.human.wall_roof").unwrap(), + [This, This, This, That, That, This], + ), + ( + assets::load("world.module.human.floor_upstairs").unwrap(), + [This, This, This, This, This, This], + ), + ( + assets::load("world.module.human.balcony_upstairs").unwrap(), + [This, This, This, This, This, This], + ), + ( + assets::load("world.module.human.corner_upstairs").unwrap(), + [This, This, That, That, This, This], + ), + ( + assets::load("world.module.human.wall_upstairs").unwrap(), + [This, This, This, That, This, This], + ), + ( + assets::load("world.module.human.window_upstairs").unwrap(), + [This, This, This, That, This, This], + ), + ] + }; +} + +/* const CELL_SIZE: i32 = 11; static UNIT_CHOOSER: UnitChooser = UnitChooser::new(0x100F4E37); @@ -113,7 +719,7 @@ impl TownState { return None; } - let radius = 192; + let radius = 200; let mut grid = Grid::new( TownCell::Empty, @@ -144,7 +750,7 @@ impl TownState { let idx = rng.gen_range(0, 4); Vec2::new(dirs[idx], dirs[idx + 1]) }; - let road_len = 2 + rng.gen_range(1, 3) * 2 + 1; + let road_len = 2 + rng.gen_range(1, 5) * 2 + 1; // Make sure we aren't trying to create a road where a road already exists! match grid.get(start_pos + road_dir) { @@ -175,7 +781,7 @@ impl TownState { }; // Create roads - for _ in 0..25 { + for _ in 0..radius.pow(2) / 2000 { create_road(); } @@ -317,7 +923,7 @@ impl TownState { break; }; - for _ in 0..40 { + for _ in 0..radius.pow(2) / 1000 { place_house(); } @@ -467,7 +1073,7 @@ impl TownState { }; for _ in 0..100 { - variate_walls(); + //variate_walls(); } /* @@ -662,3 +1268,4 @@ impl<'a> Generator<'a, TownState> for TownGen { (sample.alt - 32.0, sample.alt + 75.0) } } +*/ diff --git a/world/src/generator/town/util.rs b/world/src/generator/town/util.rs new file mode 100644 index 0000000000..99cce9c784 --- /dev/null +++ b/world/src/generator/town/util.rs @@ -0,0 +1,42 @@ +use rand::prelude::*; +use vek::*; + +pub const UNITS: [Vec2<i32>; 4] = [ + Vec2 { x: 1, y: 0 }, + Vec2 { x: 0, y: 1 }, + Vec2 { x: -1, y: 0 }, + Vec2 { x: 0, y: -1 }, +]; + +pub fn dir(i: usize) -> Vec2<i32> { + UNITS[i % 4] +} + +pub fn unit(i: usize) -> (Vec2<i32>, Vec2<i32>) { + (UNITS[i % 4], UNITS[(i + 1) % 4]) +} + +pub fn gen_unit(rng: &mut impl Rng) -> (Vec2<i32>, Vec2<i32>) { + unit(rng.gen_range(0, 4)) +} + +pub fn gen_dir(rng: &mut impl Rng) -> Vec2<i32> { + UNITS[rng.gen_range(0, 4)] +} + +pub const UNITS_3D: [Vec3<i32>; 6] = [ + Vec3 { x: 1, y: 0, z: 0 }, + Vec3 { x: 0, y: 1, z: 0 }, + Vec3 { x: -1, y: 0, z: 0 }, + Vec3 { x: 0, y: -1, z: 0 }, + Vec3 { x: 0, y: 0, z: 1 }, + Vec3 { x: 0, y: 0, z: -1 }, +]; + +pub fn dir_3d(i: usize) -> Vec3<i32> { + UNITS_3D[i % 6] +} + +pub fn gen_dir_3d(rng: &mut impl Rng) -> Vec3<i32> { + UNITS_3D[rng.gen_range(0, 6)] +} diff --git a/world/src/generator/town/vol.rs b/world/src/generator/town/vol.rs new file mode 100644 index 0000000000..cde6b2fb3f --- /dev/null +++ b/world/src/generator/town/vol.rs @@ -0,0 +1,203 @@ +use crate::util::Grid; +use common::vol::{BaseVol, ReadVol, Vox, WriteVol}; +use rand::prelude::*; +use std::ops::Range; +use vek::*; + +#[derive(Clone)] +pub enum ColumnKind { + Road, + Wall, + Internal, + External, // Outside the boundary wall +} + +#[derive(Clone, Default)] +pub struct TownColumn { + pub ground: i32, + pub kind: Option<ColumnKind>, +} + +impl TownColumn { + pub fn is_empty(&self) -> bool { + self.kind.is_none() + } + + pub fn is_road(&self) -> bool { + self.kind + .as_ref() + .map(|kind| match kind { + ColumnKind::Road => true, + _ => false, + }) + .unwrap_or(false) + } +} + +#[derive(Clone)] +pub struct Module { + pub vol_idx: usize, + pub dir: usize, +} + +#[derive(Clone)] +pub enum TownCell { + Empty, + Park, + Rock, + Road, + Wall, + House { idx: usize, module: Option<Module> }, +} + +impl TownCell { + pub fn is_road(&self) -> bool { + match self { + TownCell::Road => true, + _ => false, + } + } + + pub fn is_foundation(&self) -> bool { + match self { + TownCell::Rock => true, + _ => false, + } + } +} + +impl Vox for TownCell { + fn empty() -> Self { + TownCell::Empty + } + + fn is_empty(&self) -> bool { + match self { + TownCell::Empty => true, + _ => false, + } + } +} + +#[derive(Debug)] +pub enum TownError { + OutOfBounds, +} + +const HEIGHT: usize = 24; +const UNDERGROUND_DEPTH: i32 = 5; + +type GridItem = (i32, TownColumn, Vec<TownCell>); + +pub struct TownVol { + grid: Grid<GridItem>, +} + +impl TownVol { + pub fn generate_from( + size: Vec2<i32>, + mut f: impl FnMut(Vec2<i32>) -> (i32, TownColumn), + mut g: impl FnMut((&TownColumn, Vec3<i32>)) -> TownCell, + ) -> Self { + let mut this = Self { + grid: Grid::new( + (0, TownColumn::default(), vec![TownCell::Empty; HEIGHT]), + size, + ), + }; + + for (pos, (base, col, cells)) in this.grid.iter_mut() { + let column = f(pos); + *base = column.0; + *col = column.1; + for z in 0..HEIGHT { + cells[z] = g(( + col, + Vec3::new(pos.x, pos.y, *base - UNDERGROUND_DEPTH + z as i32), + )); + } + } + + this + } + + pub fn size(&self) -> Vec2<i32> { + self.grid.size() + } + + pub fn set_col_kind(&mut self, pos: Vec2<i32>, kind: Option<ColumnKind>) { + self.grid.get_mut(pos).map(|col| col.1.kind = kind); + } + + pub fn col(&self, pos: Vec2<i32>) -> Option<&TownColumn> { + self.grid.get(pos).map(|col| &col.1) + } + + pub fn col_range(&self, pos: Vec2<i32>) -> Option<Range<i32>> { + self.grid.get(pos).map(|col| { + let lower = col.0 - UNDERGROUND_DEPTH; + lower..lower + HEIGHT as i32 + }) + } + + pub fn choose_column( + &self, + rng: &mut impl Rng, + mut f: impl FnMut(Vec2<i32>, &TownColumn) -> bool, + ) -> Option<Vec2<i32>> { + self.grid + .iter() + .filter(|(pos, col)| f(*pos, &col.1)) + .choose(rng) + .map(|(pos, _)| pos) + } + + pub fn choose_cell( + &self, + rng: &mut impl Rng, + mut f: impl FnMut(Vec3<i32>, &TownCell) -> bool, + ) -> Option<Vec3<i32>> { + self.grid + .iter() + .map(|(pos, (base, _, cells))| { + cells.iter().enumerate().map(move |(i, cell)| { + ( + Vec3::new(pos.x, pos.y, *base - UNDERGROUND_DEPTH + i as i32), + cell, + ) + }) + }) + .flatten() + .filter(|(pos, cell)| f(*pos, *cell)) + .choose(rng) + .map(|(pos, _)| pos) + } +} + +impl BaseVol for TownVol { + type Vox = TownCell; + type Err = TownError; +} + +impl ReadVol for TownVol { + fn get(&self, pos: Vec3<i32>) -> Result<&Self::Vox, Self::Err> { + match self.grid.get(Vec2::from(pos)) { + Some((base, _, cells)) => cells + .get((pos.z + UNDERGROUND_DEPTH - *base) as usize) + .ok_or(TownError::OutOfBounds), + None => Err(TownError::OutOfBounds), + } + } +} + +impl WriteVol for TownVol { + fn set(&mut self, pos: Vec3<i32>, vox: Self::Vox) -> Result<(), Self::Err> { + match self.grid.get_mut(Vec2::from(pos)) { + Some((base, _, cells)) => cells + .get_mut((pos.z + UNDERGROUND_DEPTH - *base) as usize) + .map(|cell| *cell = vox) + .ok_or(TownError::OutOfBounds), + None => Err(TownError::OutOfBounds), + } + } +} diff --git a/world/src/sim/mod.rs b/world/src/sim/mod.rs index 0725fc7b97..5360e000c6 100644 --- a/world/src/sim/mod.rs +++ b/world/src/sim/mod.rs @@ -438,17 +438,18 @@ impl WorldSim { .iter() .min_by_key(|(pos, seed)| wpos.distance_squared(*pos)); - if let Some((pos, seed)) = town { + if let Some((pos, _)) = town { let maybe_town = maybe_towns .entry(*pos) .or_insert_with(|| { - TownState::generate(*pos, *seed, &mut ColumnGen::new(self), &mut rng) + TownState::generate(*pos, &mut ColumnGen::new(self), &mut rng) .map(|t| Arc::new(t)) }) .as_mut() // Only care if we're close to the town .filter(|town| { - town.center.distance_squared(wpos) < town.radius.add(64).pow(2) + Vec2::from(town.center()).distance_squared(wpos) + < town.radius().add(64).pow(2) }) .cloned(); diff --git a/world/src/util/grid.rs b/world/src/util/grid.rs index a30ca989a8..188f96c3ef 100644 --- a/world/src/util/grid.rs +++ b/world/src/util/grid.rs @@ -40,16 +40,19 @@ impl<T: Clone> Grid<T> { } pub fn iter(&self) -> impl Iterator<Item = (Vec2<i32>, &T)> + '_ { - (0..self.size.x) - .map(move |x| { - (0..self.size.y).map(move |y| { - ( - Vec2::new(x, y), - &self.cells[self.idx(Vec2::new(x, y)).unwrap()], - ) - }) - }) - .flatten() + let w = self.size.x; + self.cells + .iter() + .enumerate() + .map(move |(i, cell)| (Vec2::new(i as i32 % w, i as i32 / w), cell)) + } + + pub fn iter_mut(&mut self) -> impl Iterator<Item = (Vec2<i32>, &mut T)> + '_ { + let w = self.size.x; + self.cells + .iter_mut() + .enumerate() + .map(move |(i, cell)| (Vec2::new(i as i32 % w, i as i32 / w), cell)) } pub fn iter_area(