From 3d0754f06087c20b4b20f7388117b7e7d01b2f43 Mon Sep 17 00:00:00 2001 From: Ivory Date: Tue, 10 Jan 2023 21:51:11 -0500 Subject: [PATCH] context aware walls --- res/textures.png | Bin 13384 -> 29168 bytes .../xyz/valnet/engine/graphics/Tile16.java | 104 ++++++++++ .../designation/CutTreesDesignation.java | 1 - .../valnet/hadean/gameobjects/Terrain.java | 2 + .../xyz/valnet/hadean/gameobjects/Tile.java | 38 ++++ .../hadean/gameobjects/ui/tabs/BuildTab.java | 5 +- .../gameobjects/worldobjects/WorldObject.java | 1 - .../worldobjects/{ => constructions}/Bed.java | 3 +- .../worldobjects/constructions/Wall.java | 187 ++++++++++++++++++ .../worldobjects/items/Boulder.java | 3 + .../hadean/interfaces/BuildableMetadata.java | 1 + .../valnet/hadean/interfaces/IPingable.java | 7 + .../java/xyz/valnet/hadean/util/Assets.java | 6 +- 13 files changed, 353 insertions(+), 5 deletions(-) create mode 100644 src/main/java/xyz/valnet/engine/graphics/Tile16.java rename src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/{ => constructions}/Bed.java (96%) create mode 100644 src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Wall.java create mode 100644 src/main/java/xyz/valnet/hadean/interfaces/IPingable.java diff --git a/res/textures.png b/res/textures.png index f1acfaaafbd886864bb01819cec97da2cc7138dc..e7b56410bf26b4cfde576e07a8005a23e4965784 100644 GIT binary patch literal 29168 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

ED5E%e7s*ilsCFS#HBBz%U6LC_j$9Uz`pn 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 literal 13384 zcmeHucT|(z((jXmCQ=op6Qn2>dJlwvG*POcARR)BKxm=203uQ(Dgx3GP(W!)?;s)~ zy+{vL1f=&GxWTu4=d5+UbQIS*I)yW3sU=09#U9r#Mx0Oly7@5?Ne8QxMF#2bumgoi)$J zJ08zq_=wWfs|L3@EeUGa4QyAbw|2e1q22vpQc80w_ zzR&SpHB;B8lXqqvMpSFzpIvNTNvxBtx4(6C9={S@^dj$E+Ig*4{haIEgBNfUQj8`S zy=*?WXU&Ckf42M(5=&#ltIM5wIr?3q=KjqAWbEce+x)x8e7XIzP2T?235z8v&l$>18>`1J$!n%LI@=n-u|*T6M(4Ied&GZb}F zoh?jsBczG$E&FmF$v@9b29gzQmDP^`HVC!C^3r*Fp(1Ky<8pCp+KMsI<5a5QmnN-R zcla2vyP^kg*@V2#ZsmKs*{95GfxdRbi!W z)zb7N#^sFjtp{!ZKvRGE2a+PyAjp4Mkwnd@gT&vafT%0H?IG4V-hLDD{qO~3BmXE8ou8*c3(#IYtZN-I}||*}(29sr;#g*n@M~VKB}xK|xPXPXSL+0Vh{mL1AfWX+a?oK@kytA_u>l zHyUH%#gBI5{zJ*1YLu+qkgh0a49W@3d8*dJ(#ahI=OWtihk=gH8XA9VN4x!r0}&BH zFAHZuVF4jQN5@mEe{;KGls$;Tf7`GdCEux1E%DJbU(F6O$p9*Iw;J_35l|T{chSwNLolpOW5#>i&;wZ zi&-K?_@#t|g!n}yk(Q$3NGl6zNr}JosG;337HFjPsUD(c0TfY*xQLCFh?tZVzo>+j zBvIblieE}f)P~;*i4+zl(nZC^t^ShNazznS&%)s!?K#zBMbsl9Wnm*_Whu-rC1GK~ zFD4}|!Y?f$A;yoCw6?OcloS;gv$Ejgv_isEoLn6(h#^BcTG(0(I-_m5I8TvB8f z$^v7dWP!0J>JkzWg$W76gv9iO#9$)QFkvBnA#s?{U(8NcC>!tp9qaFj#7TU~{t?w% zC^zEh-hY$-oF2N?F8@IKljwlr{GI7A3*;XzxLJ5u6XWs+5ou?EwzVcM1;i};gM#`O zk(RWP7PFBSNAlYcv*a{F()`k*l2-iUqDZ8;kfpG+goWf^@@`Hx7*7jVYXw^(YD92| zN%tEZPQKsKxcV2Lr=9gF)I!7=FD$|@BCaPa3=F-W>VNb_R`7J``o~zw z3jV9G{=xSTOWtoh{-6@qQ(})O_tz4A+WUK%w?-2K>PlS1ZE}k=0N{p(nv#N^m+5lK znU}`;2^012eks@5mGaz)i>fj5+GUcZDx0FKA@P%?;u(4-YD<$U9HVF{q~0m4ju zyi(INk0J+?`MQcc`an(d%wrc-+Q2v$K^*2b@{T$>Fj4i1? z$rdg9R@<}U4z+~a1I}2_w(s8_ov1DEj!x^oFKnCb8G3Tff!)D=`)HIOcQQr@(lZTi zYdNPo-rKlw>}?RG`HpLhmkFd~0!$8sip}9~<2R@og@+8XKBAHMjVQBmQKRYTG_sS5 zfK-=z$#FYw&%fPr_RSn&cZVHUy7@jlFh?pRZW^1Fw+S-rjWzWxN{=m?#M6`q94h+P ztw1p4D1>~ytaG27DMV@d8)R^7Y27y=%RY63dqHgsXC;8(kh^FmGcM8hxa4qpGxCti zB0{)}9B%}%`+kNu%wy{8D?NfAX;9Wq`5hcyzH}4g@}engw>M!#Rc9avGlM{sE8y#*X}+y znMPg?&yC*C!f$G2;O*)3X&mQvTJVas5x&brJz7^+Sdy{rWWX`-CMNC9i)g6ript@7 zV|H!Y{tzC6rAagGTU*c6bP*^}DBjaRm7!`*{LBsox@*O;9!}Wv9~eO>_H;(A!dUxg z5&Ti!5w^)_g1M5~#SzsU#EoM_o4hC>CEBR;;@cH>tdRH59S9cFbj5^(uCH@wL#}pc zhNq`ZW4U?p>+bE|T5kMN0CRo8{rLgjPo++C2UlXlT1Bsr1LatwAm4nGD?iBkF^yli zV%=G9q+s>NTM%^^?$1-u!49{3UpEAFmgAi}(CjIn5W9xe51A$MJh^WY=!M zz{Dw$36j@=k;0ImT`U^*B5*3>)}{sD@F#aU=z{6O^TR7%l#}FhRb>fL(Aq^7 zCx-xU?NMHJrGe)evhf!L6ZJW&oyS*JVx4lXw;#Iq=d`uQk(bfL*v9HxFYiTRINZ0H z!}HqsSfZ(;I&}u^N@e>?MN|^`yQFOB1)#{;acExYlv>);iI%wKdg#@xAn_zz>Z z6^}O1P?UNl^-OjBf7DWxb>qys9z1w1t6FZhbiO7bj|;vOnq5%j5^jhQSfcV!aj zo4s5XiXj-x2B5n;TDwvug;K-+af_u|`T zK!b*8fHyQZ>QS}PH?Fvn!^ zE9^g^MKoOR8XhTtcOM&6Y1gf=+*sN~tPcXt$7+M}I=!EE@4lGer_($F8lW#(DPV-D zN_e1y(@2Q3Z%|U4bH|x#0Ve0v0&J8NqC1VGZ{zpo&=qcC3We;PTcOCjV93A7QI413 zyTZT%T%;_3NJdsv)^y7i()EM{Ou-03WCiyhT^XcBmtr9)c8HzrX3_`uD^U%HDyQjH zQ|;d7CL;EoeFA=&djV^P!(klGyuzCl1&(Yki);3Kg#EC;(g01}x>V*Cog?t;u?uSZ z=E3r=n(xtl7hD(E5DuM8J^SwYJIfSbb(P-cDKo{~<nwO@$pN2JFf0`{7)ax1uvdJAhydEVpow(5;v8wxp7YAn zxj1Y8{FG>=OYEa?{;T}#6ZsIEa<(L6lXIHxWo#P-Xn|XO=v~8hUa10}bI0Blhoz${ z6*C^;op9307#s|g^8g!|f5cjUKaI0Nu!|9g6ZB`wn}%UWS8_JAD|=C6$U7~zSvyyz z;!$s+Jy1Vixy%U$5i%Yr^tMX;==)@Sv^gmO*{$f9F88I$p#@gL#UPSZu^W6dlzq2N zT$KF1u281fo%p55KqWhB@k_No#%1b+Zo!5h%gUq*3M9L?RaUfYw(STl(TFU@(^n-k^6$`KhCcWyWLP zq8(+gBT2XcG^RfcC_Q|=?~VOgn?nBHXNh6EO}FjT0j-*CF(*z8MZu%@XqaMH$_IFo&Fqc zz;J6*N=-7gY@HLA`qkT;{iMKH$Dlx0-!6@Q;z2@Cg?}3UV`v<|k&2?C;y_QA?56ri zmHYdS_}jcmEgqJZ!PjCbH8eHvelRHUAPL&ePQ50BD0+Hpt1-^m-hUaADfWyt%lHl5 zLv`J6O0?q@i1r7cA9DhEEDPB^$Ffhm^zvv>4c?4p!pCw21WDBh3*bpLS%u9*+~v_7 zL!d#x`50%a_uBL1(Y&o_w~E`$MtU#AW-~;wjIzz)8UQlKSGkwXnSHPfUEcRx9#OU* zEGX@yX;H=D#FFdk>nGx5W?$+q4T!XG1O0m=hZl8U7s`vyp1XI&O-xqS3e2Em{r0wK z%N;Se>D#-^lo`Exp#kg9XA~?76)1pgLDrJa5w!|UYT%($3mO8nJDEw}&YV4Su$Gqp zHgLPgf1tuoOp8^WRHlY9ju~H%h@3Z?@z;ZyzP|G18s>vbyBQO?vQWdNgp{{~g7Ix- zo?)9!J@GdlSh7PGnj;zejtPe-E340B*n|XT8Lpusi;xtsgVeHE-%VX4KgFX9gHPn7 zrBl{Fwmcl=(;ltgJGjfzPTRM&E^^^YL|HlXf$**7^%r>LL)VCReKs=aj31a( z%6`?*AlZAaygt(*9=A;G8E^oNdVBZASu@A3WidBR!J4&Te1Tbgs>jM0YB#i?u(0db z5RFhU%=O2U?aqex#ak=1YpHv3j z8c7)q$iuj2l5tSl0%@n$O>z`K4b-7Rpuz({O=?|WcyqzIOMk+BL+$5JxRRuq_M7^l z7ujwDTRl26L(u9v`B|jWVu8%?il5!0g`w~FhX>!`g5AS`ek{v=&b0p1$6T|!u?x(7 zcg8J_mhR#DCkRZS$+w}pnX2_mAKUC49NJ-WLm!Y~wZkr(T3TA83m_HBim4A?6|S@2 ziegnh0h1s7&sXPDC7+Z`$u1X=+G!h+X#P3qKR!OPC1_XadT7weB)bCxPo-8!Wu z2y0EWgDT*enVB8KN)$=Z^}?FopC4{T{o~Pa+ReG0TBWqW+}kIFTs9L~rL9Iu z{tR5b#j}95wt#DlA*_C@O^2w1NvaF9?cEI<0VC_%CR-nz80U9b5A43Z1f}_K4ON-n z3jCFuZI~^$m{*+Fgk+);Iw!B)kOOqm3V|m{HQX`XJ?)zPl#-PVqRq# z0^UhV$m^FzG@bQkn=h(cA9L$^5JXce+w1I1BA1osx1q*LF|^M-f8mYpkPFY@Aidkf zP9b~x>>Pil6S}i!kR#!B{g8yZ(@}%P!Hm;RA2|nemgmu6rUdnHKtI)cvz*?Cx*pqh z(VEPcecrgR?5?P4;qLiMRj~K6?ktbmLO_rADQM;wgzjNyAS>+rIZ?de!S%u_PqkN+ z*y5)31jI?BM76T{+Ev|f8V+eY8`j1P34Xas(xTMYH16k0-OtEvx=g_k9+$`T=8b(= z$Fb<;V6yFY_1IjYTbOm#cI77&4_=X3z_!{&yM{Qin||Nln_9aA(RIGN=%mLpNJp%1 zfH8L#y$}P@ziP(1?aoO^&Q~A2GE9OpogM({y-a&6SOPp3$AsBx7O zvx!VyqN)Ep&-Eqy`rS&MYntk#7xpk$H5LGu`fCu_Gv)!kNF}}HbCGl50XEC_-|omgtCHDiHjY-& zzrPTY6qe_fZELLz;jy*BM8Eb8fnb*J!pR3sVy6(JixaeymtOG5_Z9z75X@a%mG$WyBMT60|&NtUePoRzaFh{$@G_fa%s6I zQx(;dq3kh^GY?AQ$ONPs%M_av9S|alU2Mr2wq}&Q)h#S$_pzB;HDbz5cNjwxeKMAK zMO#{Katz#9lefaOQt-2wDmBlD>WS#CO;3qvbViMO%Z-!1l8Yv|mDrV5KKq{RFQP3T z{}gIiQB<6dKM zcN?SVzP*XSAMgx=9us0`E^{Sv_*-c}siSGS`?p*YIV7XeZ_ifNBwS>wral+*c21CK z&MdZEi~L)RlCA-_l;sXwV32mQfdVX>+(H4QdxjNn+5w#>^O?929T1Lz$rRGvg1vnu z2e14-3bM*VVd}0Sb40F%=I=?>I9zyKY+Rm3+WFKQ;Uiu%2D#Fr%>Ykt?Qjgys zFa{a#J?Cg}P7B*|_LGunxCvDOdqDxz&b4HN9SNZV=WXqBvt3S(dp$7kq>1@sm#4ZeOHa*QU=8VHRu%Bz106myXzM zpaA;FI1531x9$7E07rK$E*90aTA2M>eB&_ra@tMWHyJ>%d2S^8+pjSY8t}8( zv}@g#qIrm#-5is>q%&!<<~g|d0EuygJnhjpvY1; zP=L5WG$a)QD@X<91(H%h$P^sQ>qR^Hi7mhW;mh&kT+AXcmntEDvi^>l#n&>iZqqoF zLqvCSH8F#Ya^)cGOZw!-?CPU%3Xc7|uk3=~ubN$u?swuT>nnILVa3I68o?$3mm8p8 zR}qfmtUEBS*{n7rt6HO$9N}P7^ihXk58nx5o47loaXkPS984;|CVRA{Rihtt;f?r1 zZfp#tV#(;(9q6&z_qw&|0tiDKt-+L7#o+-ZeC_zn*2?oUBWpk1F=q2e*W*Ye3l{02 zeygm?7O8uO)EP=3a?h!n!c`IqvuA;00Wa?-Es8kQ1U^src0?G+4DVcp*tW27bawRt z*eSRQDILc~)4DL_WF-PeC3F|q)&g}u;`_IEmw(!k zXcs3JD@=yb=4DqG3iPH3LW}o($Hg>uYf5k1p0u{vtty7)h&*`hIZ+qWP20F%@9I2u zT!1~1Dq{C*iSzNS*=su3stt6b+G4bOPCrT@FTq5};=)8Tcjt5f=WGzuRr4WS1C}4h zLaYKR@D%tm*H;6HG;@j*f<1}X^>r8MddjLjv`b%Q;*M{q1|G~ZAMC|PZY4OW_xVc_ z5;+3iDS0k&yg6o9KIpgj*h#y_3O-rvkQk`QPOl^?C!vmfyaTvLGtFj)B(&6_}051M|S zSTP0Y%x`T-!O_8=QU*yRWq<9rBlH%39txc7_f33^#OiDkCcH6sHLFZ;8vWZnghf?C z@~ST(k`H??Ns4vXZD)Kh2|%sQa<1iS2$G$t?7p#=5!4XbMS_?h)vTQqJ{a(y8{J}c z8nG-d=3$rD@rnNdOma)Zp7eLYn6lTz%^CeRH7qxOc351S958Y!9X(Lgv+q1v(2&VJ zc)ELcg;vh7WXe>{Hl7Q>W|yaDJMsfHd+n=YS1y%b0=D17SxU>1w3o9`^6Y4M zGOpKGp0s5*rJi}EYEj_&&Fza)_0{AOHBXUC*o&#F+UTI=Vl!} zos+xCTXIa}Kjy&h4+ z+$NiHh0olBopWV6>5rUDv1C9!)#ng7e+O zyx-NI)Axxb6$d|YJ1WhD4D3(sMUo#hBc__OmI+D9DP{}ez2rc>>YU%pfM|<3+vp3n z?9gBY-=|L6QNn2SfOv6|TVQ%;;TG4bK;*?GyE$dX*{ryofIoIN8XWlG&nQZPwBVLvqzPwT|Ht{KKHKId@uQWc&e{d zyHqGGoWVignB9T@X|qWcJAhq08V$HuayX_>R{t@Q6Wc=Q>4g4R+561C6@)m!YE+Ny zq>g^lvp?ES31olE@MhO88Qids=Wpty9V=G*(V;JTf&?<0T(!8Z!JvD;pE1C z$LcF~1x`*OE%>(H9g(xab}#=2Cxd@FO_2980cCLY%DDiCa_X&oS|vaehnOV|2Xli~ zN{t$c$X@E)Z)}k}7Cvl|S|N=3I&yTbl0S+RsQP+4QEcwQo59vWZ{=47{t9b^LfSGk z&Wtjk*N}xY&!l?bnAE%>6X^dD7?d5$IT?Rub5BEYag6DgTUQr1=yKd%{^v@sGQjowEPOqBh||(2vAg)E1WSPBZx;r;hzEn$5~o`&?@mM4Hcu+%+2 z{QM{X%ufQQh|FBjio`BuBvZ#%a=94P;2B`vmT+t$;_3o$U|3q%PvCVweO+}c~4iVN}rBh3@EKIn)d~63yK~lVF!lU(mmXhaU&uD zscP4tr5aJr+p_if$JQJqMCU|1Q~V27gMsc&Iz&O9CJ0M(J(V`O9TZLOq88)n9x$$Y zZQ`<#T;TiVZDuJs8HBT=O9ScwlUg?4S>bjlj zk!Miwm~1Z-yWg?NprH}NSmq&IW+OkEf#HpQ>!6QWIit$R_i71fD@QrPZgAy!Qr?N^ zq_c-dK&NP7{c=8LkiU@HZJ}q}?7bU01;YgzDGN> zE{$83T-`G&K3Rg&YeeoGf4ga=aKw2lS4M*`e-Du@lnjKz( z>%@D>X=p_CY{c9T<+aZEc><%ej2g$sI|C>Pp3z zILxy6EUl;YteURFe0~j^^>$BR*a}H=D&;Mx*<$k<4Ltjn%59TLoA`6647kFl$x^2` z7!h#hIn%GUKKV;dpUj=z zlAH*5QMXl_ZFjWi0-H(RoL_M|NfrofzP@mFVlQxO-t7=|awlx5ZZ54X@vZGO3I0Y! zf6ofRg+#@NlK;^y#y_o9e{}pg_h%W2w^EzWednnI-J$r6*|2<0YIX;gNi8E@g7OT*cjN=zv$_^n9F1(>SMY}7F|8+}2$0v4#rJ>4w@spmv;U`bOqovZr zzCi)!X2ekv0`iQjv4FgV~@8I zH|Mi@ERvus4=l^YDqaobNw;1W1`idP9_yTcTRU#5qsg|RFS|v@UUBT>^K+>fWyW_) zkvs{vxVL9tzG7Ar+h82HJRLNm3;*%qBDV6xD%X;oUBUdV@mp&}f4w*6UeW$z?m<$w z-*9S=`4F17LdnzKtmkHQKu0!Ns|owXT}inLMYJkFbE|Mt+?sEo@`JDaD!@urMTyGF z&cR-|{eo=)ezM`^w|k?-g4cfJZz6s33^HnG`UchmeI34ZZsWb{t2v%MzJorwMrbW% z)Cnh>pGc&ae_fb{4#2CxP|GL`KGc5x*PX8P-hLM!yfy1GW^%&sXP8B+O3AMNN2L{R zrSJCY;MLy!=#%v4^c(I<>{r9f)5Rig9%p~SA-l@2;xVaKq58JAtGr;o?1_9u>25LJg5Sg zTUWrD(B34IGrPwE0dx(%z^krJx4?1myvflnsKHipl~y+*1H)2H2DF4twjv%u6wcLc zLINEDH^27TwB{KE_t)YzwzLrNMG_Dgqym;@q2Mz3Ki;MPzW)qklny%C5^0xyrJ`{DKs(&I2(-3 z1{YN-V8c#`N1lS6mEpw`p(h!930zb_E$i$40^;V@WqKB1loL9%t!?OYI&)mYsQ=6g z_f~W^Q>S|5JBLP1?JUqOzydIpzV|;~Ds90=WLVLrfOGIqMlv4^d6Sy1?61!UlAQ zkbfLq=&)7$cs)Yoq#ul3%+jIhz%&)`eH+WvJ^ks|0%*7idNd`w`16~{^pDQ3w%kgzZyN_aYQI#PgV~a8uf?fQa zFNOI-l05<3@Y, Sprite> cache = new HashMap, Sprite>(); + + public Tile16(Texture base, Vector4i area) { + this.area = area; + solo = new Sprite(base, getPixelCoords(0, 0)); + + n = new Sprite(base, getPixelCoords(0, 3)); + e = new Sprite(base, getPixelCoords(3, 0)); + s = new Sprite(base, getPixelCoords(0, 1)); + w = new Sprite(base, getPixelCoords(1, 0)); + + h = new Sprite(base, getPixelCoords(0, 2)); + v = new Sprite(base, getPixelCoords(2, 0)); + + cne = new Sprite(base, getPixelCoords(3, 3)); + cnw = new Sprite(base, getPixelCoords(1, 3)); + cse = new Sprite(base, getPixelCoords(3, 1)); + csw = new Sprite(base, getPixelCoords(1, 1)); + + tn = new Sprite(base, getPixelCoords(2, 3)); + te = new Sprite(base, getPixelCoords(3, 2)); + ts = new Sprite(base, getPixelCoords(2, 1)); + tw = new Sprite(base, getPixelCoords(1, 2)); + + all = new Sprite(base, getPixelCoords(2, 2)); + + cache.put(EnumSet.noneOf(Direction.class), solo); + + cache.put(EnumSet.of(Direction.NORTH), n); + cache.put(EnumSet.of(Direction.EAST), e); + cache.put(EnumSet.of(Direction.SOUTH), s); + cache.put(EnumSet.of(Direction.WEST), w); + + cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH), h); + cache.put(EnumSet.of(Direction.EAST, Direction.WEST), v); + + cache.put(EnumSet.of(Direction.NORTH, Direction.EAST), cne); + cache.put(EnumSet.of(Direction.NORTH, Direction.WEST), cnw); + cache.put(EnumSet.of(Direction.SOUTH, Direction.EAST), cse); + cache.put(EnumSet.of(Direction.SOUTH, Direction.WEST), csw); + + cache.put(EnumSet.of(Direction.NORTH, Direction.EAST, Direction.WEST), tn); + cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH, Direction.EAST), te); + cache.put(EnumSet.of(Direction.SOUTH, Direction.EAST, Direction.WEST), ts); + cache.put(EnumSet.of(Direction.NORTH, Direction.SOUTH, Direction.WEST), tw); + + cache.put(EnumSet.allOf(Direction.class), all); + } + + private Vector4i getPixelCoords(int x, int y) { + int tileWidth = area.z / 4; + int tileHeight = area.w / 4; + return new Vector4i( + area.x + x * tileWidth, + area.y + y * tileHeight, + tileWidth, + tileHeight + ); + } + + public Sprite getTextureFor(EnumSet directions) { + return cache.get(directions); + } +} diff --git a/src/main/java/xyz/valnet/hadean/designation/CutTreesDesignation.java b/src/main/java/xyz/valnet/hadean/designation/CutTreesDesignation.java index c3e2ea8..b1fd994 100644 --- a/src/main/java/xyz/valnet/hadean/designation/CutTreesDesignation.java +++ b/src/main/java/xyz/valnet/hadean/designation/CutTreesDesignation.java @@ -15,5 +15,4 @@ public class CutTreesDesignation extends Designation { protected void designate(Tree thing) { thing.runAction(Tree.ACTION_CHOP); } - } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java index 12e2ba9..53220f5 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Terrain.java @@ -45,6 +45,8 @@ public class Terrain extends GameObject implements IPathable, IWorldBoundsAdapte } public Tile getTile(int x, int y) { + if(x < 0 || y < 0) return null; + if(x >= WORLD_SIZE || y >= WORLD_SIZE) return null; return tiles[x][y]; } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/Tile.java b/src/main/java/xyz/valnet/hadean/gameobjects/Tile.java index ac3bf91..1f16f5e 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/Tile.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/Tile.java @@ -15,6 +15,7 @@ import xyz.valnet.hadean.gameobjects.worldobjects.WorldObject; import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; import xyz.valnet.hadean.interfaces.IItemPredicate; +import xyz.valnet.hadean.interfaces.IPingable; import xyz.valnet.hadean.interfaces.ITileThing; import xyz.valnet.hadean.interfaces.IWorkable; import xyz.valnet.hadean.util.Assets; @@ -91,12 +92,36 @@ public class Tile extends WorldObject implements IWorkable { return null; } + public void pingThings() { + for(ITileThing thing : stuff) { + if(thing instanceof IPingable) { + ((IPingable)thing).ping(); + } + } + } + + private void pingNeighbors() { + Vector2i pos = getCoords(); + Tile north = terrain.getTile(pos.x, pos.y - 1); + Tile east = terrain.getTile(pos.x - 1, pos.y); + Tile south = terrain.getTile(pos.x, pos.y + 1); + Tile west = terrain.getTile(pos.x + 1, pos.y); + if(north != null) north.pingThings(); + if(east != null) east.pingThings(); + if(south != null) south.pingThings(); + if(west != null) west.pingThings(); + } + public void placeThing(ITileThing thing) { stuff.add(thing); if(thing instanceof GameObject) { add((GameObject)thing); } thing.onPlaced(this); + + pingThings(); + pingNeighbors(); + if(thing instanceof FarmPlot) { get(JobBoard.class).postSimpleWorkJob("Till Soil", this); } @@ -107,6 +132,10 @@ public class Tile extends WorldObject implements IWorkable { if(toRemove.contains(thing)) return null; toRemove.add(thing); + + pingThings(); + pingNeighbors(); + return thing; } @@ -197,4 +226,13 @@ public class Tile extends WorldObject implements IWorkable { } return str.stripTrailing(); } + + public boolean has(Class clazz) { + for(ITileThing thing : stuff) { + if(clazz.isInstance(thing)) { + return true; + } + } + return false; + } } diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java b/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java index 55f51d8..d4b4e34 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/ui/tabs/BuildTab.java @@ -17,9 +17,10 @@ import xyz.valnet.hadean.gameobjects.BottomBar; import xyz.valnet.hadean.gameobjects.Camera; import xyz.valnet.hadean.gameobjects.inputlayer.BuildLayer; import xyz.valnet.hadean.gameobjects.inputlayer.SelectionLayer; -import xyz.valnet.hadean.gameobjects.worldobjects.Bed; import xyz.valnet.hadean.gameobjects.worldobjects.FarmPlot; import xyz.valnet.hadean.gameobjects.worldobjects.Stockpile; +import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Bed; +import xyz.valnet.hadean.gameobjects.worldobjects.constructions.Wall; import xyz.valnet.hadean.input.Button; import xyz.valnet.hadean.input.IButtonListener; import xyz.valnet.hadean.input.SimpleButton; @@ -59,6 +60,8 @@ public class BuildTab extends Tab implements ISelectionChangeListener, IMouseCap BuildTab.registerBuildable(CutTreesDesignation.class); BuildTab.registerBuildable(Bed.class); + + BuildTab.registerBuildable(Wall.class); BuildTab.registerBuildable(FarmPlot.class); BuildTab.registerBuildable(Stockpile.class); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java index 394e4f4..e3d2ddb 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/WorldObject.java @@ -43,7 +43,6 @@ public abstract class WorldObject extends GameObject { private void updateTileLinks(Set tiles) { if(tiles == null || tiles.size() == 0) return; if(!(this instanceof ITileThing)) return; - boolean inScene = inScene(); Set removeTiles = new HashSet(); Set addTiles = new HashSet(); diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Bed.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Bed.java similarity index 96% rename from src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Bed.java rename to src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Bed.java index 5d3f430..15498d8 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/Bed.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Bed.java @@ -1,10 +1,11 @@ -package xyz.valnet.hadean.gameobjects.worldobjects; +package xyz.valnet.hadean.gameobjects.worldobjects.constructions; import xyz.valnet.engine.math.Vector2i; import xyz.valnet.engine.math.Vector4f; import xyz.valnet.hadean.gameobjects.Job; import xyz.valnet.hadean.gameobjects.JobBoard; import xyz.valnet.hadean.gameobjects.Tile; +import xyz.valnet.hadean.gameobjects.worldobjects.Buildable; import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; import xyz.valnet.hadean.gameobjects.worldobjects.items.Log; import xyz.valnet.hadean.interfaces.BuildableMetadata; diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Wall.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Wall.java new file mode 100644 index 0000000..a606a14 --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/constructions/Wall.java @@ -0,0 +1,187 @@ +package xyz.valnet.hadean.gameobjects.worldobjects.constructions; + +import java.util.EnumSet; + +import xyz.valnet.engine.graphics.Tile16.Direction; +import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.engine.math.Vector4f; +import xyz.valnet.hadean.gameobjects.Job; +import xyz.valnet.hadean.gameobjects.JobBoard; +import xyz.valnet.hadean.gameobjects.Tile; +import xyz.valnet.hadean.gameobjects.worldobjects.Buildable; +import xyz.valnet.hadean.gameobjects.worldobjects.items.Boulder; +import xyz.valnet.hadean.gameobjects.worldobjects.items.Item; +import xyz.valnet.hadean.interfaces.BuildableMetadata; +import xyz.valnet.hadean.interfaces.IItemReceiver; +import xyz.valnet.hadean.interfaces.IPingable; +import xyz.valnet.hadean.interfaces.ISelectable; +import xyz.valnet.hadean.interfaces.IWorkable; +import xyz.valnet.hadean.util.Action; +import xyz.valnet.hadean.util.Assets; +import xyz.valnet.hadean.util.Layers; +import xyz.valnet.hadean.util.detail.BooleanDetail; +import xyz.valnet.hadean.util.detail.Detail; +import xyz.valnet.hadean.util.detail.ObjectDetail; +import xyz.valnet.hadean.util.detail.PercentDetail; + +@BuildableMetadata(category = "Structure", name = "Wall", type = BuildableMetadata.Type.SINGLE) +public class Wall extends Buildable implements IItemReceiver, IWorkable, ISelectable, IPingable { + + private int boulders = 0; + private float work = 0; + private final float maxWork = 500; + + private Job job = null; + + @Override + protected void create() { + super.create(); + job = add(new Job("Build Wall")); + job.addStep(job.new PickupItemByPredicate(Boulder.BOULDER_PREDICATE)); + job.addStep(job.new DropoffPredicateAtItemReceiver(this, Boulder.BOULDER_PREDICATE)); + job.addStep(job.new Work(this)); + get(JobBoard.class).postJob(job); + } + + @Override + protected void start() { + super.start(); + ping(); + } + + @Override + public void render() { + super.render(); + Vector2i pos = getWorldPosition().xy(); + + if(isBuilt()) { + float b = 0.7f; + Assets.flat.pushColor(new Vector4f(b, b, b, 1f)); + camera.draw(Layers.GROUND, Assets.wall.getTextureFor(wallSides), pos.x, pos.y); + Assets.flat.popColor(); + } else { + float p = work / maxWork; + float b = 4; + + Assets.flat.pushColor(new Vector4f(b, b, b, 0.5f)); + camera.draw(Layers.GROUND, Assets.wall.getTextureFor(wallSides), pos.x, pos.y); + Assets.flat.popColor(); + + if(boulders > 0) { + camera.drawProgressBar(p, getWorldBox()); + } + } + } + + @Override + public String getName() { + return "Wall"; + } + + @Override + public boolean receive(Item item) { + if(item == null) return false; + if(!item.matches(Boulder.BOULDER_PREDICATE)) return false; + remove(item); + boulders ++; + return true; + } + + private boolean isBuilt() { + return work >= maxWork; + } + + @Override + public boolean doWork(float dTime) { + work += dTime; + return isBuilt(); + } + + private Vector2i[] getBorders() { + Vector2i pos = getWorldPosition().xy(); + return new Vector2i[] { + new Vector2i(pos.x, pos.y - 1), + + new Vector2i(pos.x - 1, pos.y), + new Vector2i(pos.x + 1, pos.y), + + new Vector2i(pos.x - 1, pos.y + 1), + new Vector2i(pos.x + 1, pos.y + 1), + + new Vector2i(pos.x, pos.y + 2), + }; + } + + @Override + public Vector2i[] getWorkablePositions() { + return getBorders(); + } + + @Override + public String getJobName() { + return "Build Wall"; + } + + @Override + public Vector2i[] getItemDropoffLocations() { + return getBorders(); + } + + @Override + public Action[] getActions() { + return new Action[0]; + } + + @Override + public void runAction(Action action) { + + } + + @Override + public Detail[] getDetails() { + return new Detail[] { + new BooleanDetail("Built", isBuilt()), + new PercentDetail("Work", work / maxWork, 1), + new ObjectDetail("Logs", boulders), + new BooleanDetail("North", wallSides.contains(Direction.NORTH)), + new BooleanDetail("East", wallSides.contains(Direction.EAST)), + new BooleanDetail("South", wallSides.contains(Direction.SOUTH)), + new BooleanDetail("West", wallSides.contains(Direction.WEST)), + }; + } + + @Override + public boolean isWalkable() { + return false; + } + + @Override + public boolean shouldRemove() { + return false; + } + + @Override + public void onRemove() { + + } + + private EnumSet wallSides = EnumSet.noneOf(Direction.class); + + @Override + public void ping() { + Vector2i pos = getWorldBox().asInt().xy(); + wallSides = EnumSet.noneOf(Direction.class); + + Tile north = terrain.getTile(pos.x, pos.y - 1); + if(north != null && north.has(Wall.class)) wallSides.add(Direction.NORTH); + + Tile east = terrain.getTile(pos.x - 1, pos.y); + if(east != null && east.has(Wall.class)) wallSides.add(Direction.EAST); + + Tile south = terrain.getTile(pos.x, pos.y + 1); + if(south != null && south.has(Wall.class)) wallSides.add(Direction.SOUTH); + + Tile west = terrain.getTile(pos.x + 1, pos.y); + if(west != null && west.has(Wall.class)) wallSides.add(Direction.WEST); + } +} diff --git a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java index fa31d73..b1b4d67 100644 --- a/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java +++ b/src/main/java/xyz/valnet/hadean/gameobjects/worldobjects/items/Boulder.java @@ -1,12 +1,15 @@ package xyz.valnet.hadean.gameobjects.worldobjects.items; import xyz.valnet.engine.math.Vector2i; +import xyz.valnet.hadean.interfaces.IItemPredicate; import xyz.valnet.hadean.util.Assets; import xyz.valnet.hadean.util.Layers; import xyz.valnet.hadean.util.detail.Detail; public class Boulder extends Item { + public static IItemPredicate BOULDER_PREDICATE = (item) -> (item instanceof Boulder); + public Boulder(int x, int y) { setPosition(x, y); } diff --git a/src/main/java/xyz/valnet/hadean/interfaces/BuildableMetadata.java b/src/main/java/xyz/valnet/hadean/interfaces/BuildableMetadata.java index 89b6978..b36788a 100644 --- a/src/main/java/xyz/valnet/hadean/interfaces/BuildableMetadata.java +++ b/src/main/java/xyz/valnet/hadean/interfaces/BuildableMetadata.java @@ -8,6 +8,7 @@ public @interface BuildableMetadata { public enum Type { AREA, + LINE, SINGLE } diff --git a/src/main/java/xyz/valnet/hadean/interfaces/IPingable.java b/src/main/java/xyz/valnet/hadean/interfaces/IPingable.java new file mode 100644 index 0000000..f16850f --- /dev/null +++ b/src/main/java/xyz/valnet/hadean/interfaces/IPingable.java @@ -0,0 +1,7 @@ +package xyz.valnet.hadean.interfaces; + +import java.io.Serializable; + +public interface IPingable extends Serializable { + public void ping(); +} diff --git a/src/main/java/xyz/valnet/hadean/util/Assets.java b/src/main/java/xyz/valnet/hadean/util/Assets.java index 36153ee..9693eba 100644 --- a/src/main/java/xyz/valnet/hadean/util/Assets.java +++ b/src/main/java/xyz/valnet/hadean/util/Assets.java @@ -6,6 +6,7 @@ import java.util.Map; import xyz.valnet.engine.graphics.Font; import xyz.valnet.engine.graphics.Sprite; import xyz.valnet.engine.graphics.Texture; +import xyz.valnet.engine.graphics.Tile16; import xyz.valnet.engine.graphics.Tile9; import xyz.valnet.engine.math.Vector4i; import xyz.valnet.engine.shaders.SimpleShader; @@ -24,7 +25,8 @@ public class Assets { public static final Tile9 uiFrameDark; public static final Tile9 fillColor; - + public static final Tile16 wall; + public static final Sprite[] defaultTerrain; public static final Sprite[] growingRice; public static final Sprite[] farmPlot; @@ -304,6 +306,8 @@ public class Assets { new Sprite(atlas, 7, 103, 1, 1) ); + wall = new Tile16(atlas, new Vector4i(0, 17 * 8, 32, 32)); + System.out.println("END ASSETS"); } }