From ad1c75d0507df9303bd31dac1f18ec2af05888eb Mon Sep 17 00:00:00 2001 From: Anuken Date: Thu, 14 Oct 2021 19:15:03 -0400 Subject: [PATCH] WIP branch merging --- .../sprites/blocks/payload/block-forge.png | Bin 1374 -> 0 bytes .../sprites/blocks/payload/block-loader.png | Bin 1602 -> 0 bytes .../sprites/blocks/payload/block-unloader.png | Bin 895 -> 0 bytes .../blocks/payload/constructor-top.png | Bin 0 -> 1510 bytes .../sprites/blocks/payload/constructor.png | Bin 0 -> 1578 bytes .../blocks/payload/deconstructor-top.png | Bin 0 -> 2030 bytes .../sprites/blocks/payload/deconstructor.png | Bin 0 -> 4242 bytes .../sprites/blocks/payload/factory-in-3.png | Bin 0 -> 655 bytes .../{units => payload}/factory-in-5.png | Bin .../{units => payload}/factory-in-7.png | Bin .../{units => payload}/factory-in-9.png | Bin .../sprites/blocks/payload/factory-out-3.png | Bin 0 -> 609 bytes .../{units => payload}/factory-out-5.png | Bin .../{units => payload}/factory-out-7.png | Bin .../{units => payload}/factory-out-9.png | Bin .../{units => payload}/factory-top-3.png | Bin .../{units => payload}/factory-top-5.png | Bin .../blocks/payload/large-constructor-top.png | Bin 0 -> 2555 bytes .../blocks/payload/large-constructor.png | Bin 0 -> 4197 bytes .../blocks/payload/payload-loader-top.png | Bin 0 -> 1032 bytes .../sprites/blocks/payload/payload-loader.png | Bin 0 -> 1412 bytes .../sprites/blocks/payload/payload-source.png | Bin 1263 -> 8026 bytes .../blocks/payload/payload-unloader-top.png | Bin 0 -> 1033 bytes .../blocks/payload/payload-unloader.png | Bin 0 -> 1417 bytes .../sprites/blocks/units/factory-in-3.png | Bin 1407 -> 0 bytes .../sprites/blocks/units/factory-out-3.png | Bin 651 -> 0 bytes core/assets/bundles/bundle.properties | 14 +- core/src/mindustry/content/Blocks.java | 153 ++++++++----- .../world/blocks/payloads/BlockProducer.java | 21 +- .../world/blocks/payloads/BlockUnloader.java | 67 ------ .../world/blocks/payloads/BuildPayload.java | 18 +- .../{BlockForge.java => Constructor.java} | 11 +- .../world/blocks/payloads/Payload.java | 9 + .../world/blocks/payloads/PayloadBlock.java | 12 +- .../blocks/payloads/PayloadDeconstructor.java | 205 ++++++++++++++++++ .../{BlockLoader.java => PayloadLoader.java} | 44 ++-- .../blocks/payloads/PayloadUnloader.java | 97 +++++++++ .../world/blocks/payloads/UnitPayload.java | 20 ++ 38 files changed, 502 insertions(+), 169 deletions(-) delete mode 100644 core/assets-raw/sprites/blocks/payload/block-forge.png delete mode 100644 core/assets-raw/sprites/blocks/payload/block-loader.png delete mode 100644 core/assets-raw/sprites/blocks/payload/block-unloader.png create mode 100644 core/assets-raw/sprites/blocks/payload/constructor-top.png create mode 100644 core/assets-raw/sprites/blocks/payload/constructor.png create mode 100644 core/assets-raw/sprites/blocks/payload/deconstructor-top.png create mode 100644 core/assets-raw/sprites/blocks/payload/deconstructor.png create mode 100644 core/assets-raw/sprites/blocks/payload/factory-in-3.png rename core/assets-raw/sprites/blocks/{units => payload}/factory-in-5.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-in-7.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-in-9.png (100%) create mode 100644 core/assets-raw/sprites/blocks/payload/factory-out-3.png rename core/assets-raw/sprites/blocks/{units => payload}/factory-out-5.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-out-7.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-out-9.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-top-3.png (100%) rename core/assets-raw/sprites/blocks/{units => payload}/factory-top-5.png (100%) create mode 100644 core/assets-raw/sprites/blocks/payload/large-constructor-top.png create mode 100644 core/assets-raw/sprites/blocks/payload/large-constructor.png create mode 100644 core/assets-raw/sprites/blocks/payload/payload-loader-top.png create mode 100644 core/assets-raw/sprites/blocks/payload/payload-loader.png create mode 100644 core/assets-raw/sprites/blocks/payload/payload-unloader-top.png create mode 100644 core/assets-raw/sprites/blocks/payload/payload-unloader.png delete mode 100644 core/assets-raw/sprites/blocks/units/factory-in-3.png delete mode 100644 core/assets-raw/sprites/blocks/units/factory-out-3.png delete mode 100644 core/src/mindustry/world/blocks/payloads/BlockUnloader.java rename core/src/mindustry/world/blocks/payloads/{BlockForge.java => Constructor.java} (88%) create mode 100644 core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java rename core/src/mindustry/world/blocks/payloads/{BlockLoader.java => PayloadLoader.java} (74%) create mode 100644 core/src/mindustry/world/blocks/payloads/PayloadUnloader.java diff --git a/core/assets-raw/sprites/blocks/payload/block-forge.png b/core/assets-raw/sprites/blocks/payload/block-forge.png deleted file mode 100644 index 6d37c59675a4a4818c15c21234d9b698fee49cc2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1374 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW7>k44ofy`glX=O&z$)SC z;uumf=j~i;KN&}XHtr*=96F6I4jWXm3)yF1;M}h8SkUqr*EHk%hr|u`F<(;4acE$f zq+7@$v*4Jqul?(bp|;lhTef^V^DXTE{cpRg(_cS&_3P=A)9M=*UH&V5@k_m3otW?b zu-gm_{@?j;73Qqj#>f!1`YVs4=k0f`q8yV#TeiMpPhen3xFw)7i~j*5!wfZ+)z6q& z7#MuGn^HeBDlss;ahS2IEJ!?jwJ8I`8(BG)_4aq|_uLI$wfV07$=CMt?0f$0z414C z>b~{y=l6TgpMSY%XUDJLMH!q0T~k?leg=zdU3P+rqxMA3zX%bIlUgVKPq^?pa{Z~$ z>xQCJ8GNr^I~nu-C`YhR7vqj&Y41NUOgrsbS|F0xlasqIShq!qq0ZaCae@(BweMr& zpjC|%SOs3E6*_C2-1Eftj_NWIr)`3Mrdsc!Rt3i0zq@a5oQ&-Ly?v<_74;tRlfxMq z=1mHZ<)YLW6BElx}0>Io%s5mkG#VhGa%K@eZ&t~73 zV%q+5Ms=_f^MMd+G3iVnADN#4vwJqPI2wyxy&1qQuq9a|j=w`Q?D({_oZ514zs0V< zg6=-nX}A%0_D){&(TjzmES_5>W*@mWtJpjIh1QA`;k8c|teUFvYL+xeki;!6C-Kb-MFM-S7|Pt92hS|_2uj> z-|rT|ag|}q^`>C9?CU=zI4*u=n117=@;`IezkwRhYxaiRV%V~ymgC(18+#%*uoTRZ z>eroBkXc)9{p<0hkUJY^J(gwA{9HXj%D;n9ca&V9oMr8_gImO#bP&Hc4zg@7s$t%O~CNJ>T{% zXWwL#mN%A(Z=OgWSIp3BnACo9Zq_+=9#=a}{Ys8m$%l2re{KA|f;sT2swem2jJFb3 z7&6jpG|onxU^u6De)aw2lQrsV|1Q^2UBK3KML(i&$-<4yv)6KIHD0(?;}f;^yuyZU zj5A(osC0g8E}1T-{mpF#mt)ZfH{aiHKF#^N{I_eBV~py-Nip+w%%87tjd!jPi@p9F z0hi;9!3_eZnZ;YycCUUt{R;1u=P5^@tY0?uoaNK7hZ|ldJl_-KKSk>!-(MNSE+@5V zI{9Arnq%X7r?y`V)aG zS4k!IveyKa#eLb3y|~KOVY5oawEGg%e>J~qJJ-KU_O$u@ua-%MX9eO!U$;&BHCdKD zqkGq9pVt%H{C3Js{24rHuXebQ5A%Z`FHQPPR(LrYa5r4GI4$7AG{NAE7E3XMO7A9) pgE9@i7X+9p)9>iaxpU*8ychRvn{^!u5)2Fs44$rjF6*2UngFBMX+i)1 diff --git a/core/assets-raw/sprites/blocks/payload/block-loader.png b/core/assets-raw/sprites/blocks/payload/block-loader.png deleted file mode 100644 index 08c851a0cd73d2f233a3063cc24787b57eb0773f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1602 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^TsI6Yk)Ln`9l-nH#ha}{EH zU@1RihjL$o1ylL~CkqQ1hH9A|VqzMOrXlu|>jP(oPK^&fmR#x*lCmcw?8}-m`FqrPZE3o?pMR z>)Ljg=aKh=cKi3IF)Zzuv8;R4EV?$o^W5fr?(gjO?qd3&?A|~BM}q6?=tZB`ye~Cr zdB?D=zemRY<3Wg4`9hVJr_3*2Y8LvP*Ll5okzxsZ!F74Zy|tV6m-l^jcX4{brC|P{ zM_|q5ud3fp{<^oXOv;EVP{g;H_^9W}4i1~Gb`OWO3@2A`-PdRq%cSaV2o_6~68`h_OntnU= zODca!CgYBj&d=FzY)|bp{Wk4J_@lWdstnV!KT4Z^bF*B3?4H=~;yqK_m0lFeYtzrpTQoKGxc|)d?bE*p88iH!bbJ4sZFT3}_h{Xp`dI(FnOsae^9`pBadywH{+K7zUl+;H z`PI_yRp^gC8Gb$fb>2)KHFsX!*?*+@bo1*?3_|idwZ5<;|8x?}yKulKZX z{%`)H))2#CcDgmnJ94+w_uRL6y?dtDPpT1YP_%H+yApL~*VP^Q+4-+Stm_OLYB}U$ z^g^P~&F_y$-L`d=?0%^O$J#s?(mzhLZMW*S-tumF0YlpZr}WPUH~q`m`gr;~bD0Bn zEaFy^kLzuG@3Zysb&!Bq6ZhPs%G+<$PrLOo`nxorLg7N=iaT-VEStYi`hMvXW5pGX z=VzboeX@5;34`2cjpyf{?0vHL3yZ;t>XX$kITI#;R0$tYc(3|?=~8A7o3tsP(>}+2 zii@&qII{R#(K*RI)AvkoW2*S)`sP@@V0E47$MtV#-&x0Er805ce)wuVu zPiMa#z>wMS^;6*bW8a@teDP+w!4|Rqd2-y;_oqI7xXiS{@mhY3OYdIyv?~_hPt;Ub zSL*Y!KUfr4=YP%J5{&P8Z)bb3z35G6QCy#`;JHcPFXb}+m@D*q(VXz4c>U)msxvJb zjx3G(3U4ZR-!|{QuetI4iJso?7r!tFP4CmmKc7>le|(;A)$IS=2X*hcEoYgq znBbTMhyMt-S>AkE9!_hxX(WO{%)fDA>jkQ i+XUt@57 diff --git a/core/assets-raw/sprites/blocks/payload/block-unloader.png b/core/assets-raw/sprites/blocks/payload/block-unloader.png deleted file mode 100644 index 2ee0b89d9bae55ce804c89c1df79800af95cf419..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 895 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^S>-8@|!Ln>~)y=z!>$AE`5 z;GULdP1BMyqK^uve-te0@yU`uP^xwRjGXA~i)+eVIe#$Nt&HFBX`RNywXR)DI=;RB z`Th6n{pPbieg3Gq#US=|&@HA9&);`5Xfe(Z@Z&CEW7+ngo@s_;qu~#8#x$1%-hZ(T zGX-We@8>+wRFKsmcj(jhd*9ceK73t&_R|;7FCMq9vb`stxj8I}^Is1`Tua)@BT|1N z8ErV;W~k14aGoc@bpiVag$1wrT^8(TjTF4_)m?Fk`JrgX505JQn>qdkwtUHZu~)(6 zKl{R0?#d;MRqQVmYkvQGTz|9p((Ci?Qx-pe;L5>%!|6ku4ReFIBI^S&rdN+78EiN* z8M0Zv95rT$5Da3R_Gs@94;GidR~S|>xF{&RUdFP5!zFcY2m=q}$`##A3qIAI2{^xj zA#(4c7glX-H;Ne-%iGH^6efoD7KB7IvA*yv3%3hN6+N$zC~<&w;jfd^EPp&?@J^J7 zOW?KRJ_NLR6yl)d=@*2b;%^D5)6 z{n*Jk?a-fsDTR6Weq3a(5I@efz~F}@2a`Yp1B(KK>7iF`^EOJaV&8a(-H_K+gwHj@ zU|oTM-{Fg%hcC{WpgCv4#VIKdrz}x>%B}u%tIpDd$S$!oQT;QQE*){4u9j7}Zrbwf z%3X06Bv>5QYrIt5`!nv+0XIKii2RL#0otGN)c-8K3Yf%5_s1(7} za7I~jX7#5@&$M;=C72#&FkCok)6V`u=?vF|B5o&zGaM5xaV!={WA=F27A96=bpFjH zX8{L8r`eW2lohtzY(C$2;haECT1(lq2b+~R7DzZU9OaOgzAN2U%WqW1z`(%Z>FVdQ I&MBb@0H!XKJOBUy diff --git a/core/assets-raw/sprites/blocks/payload/constructor-top.png b/core/assets-raw/sprites/blocks/payload/constructor-top.png new file mode 100644 index 0000000000000000000000000000000000000000..39a3ca79f354cd47c5902cee3907a1b6e6bf2960 GIT binary patch literal 1510 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW7>k44ofy`glX=O&z`DTG z#WAE}&fB@R*&&W1ZRhpEx>60CCUkU7@YBiBJ#s6^<5hy{NBJl6E^AauFWu%$O4R0f zDR!hoiBVb8^=-^*VfD!~E#-@!o!eXfe63Jt`T0HPYu=yPIeGf->d#NFih8`fc=-3^ zC-Nq&UtgWwZTZ#w^368_ef#B7?N_{9vtynwBZCx6wCA2#kNA0;dY8!g-i?=PvB}&s z^Vk0i3NMy?eImoqz~;D0M!$)HL5gKvk!=SPLxzAxJ1^#g zZ*|YjRBe1PyI)G1<$lc+mZtlm?7fd1b`-x<`RSP4EMP2uv{67xy?OHj@$=g!Kl}Uh zgH&D3?-_p#v>qsS22YE~Z|L$3n&j3Vb?EE;`F{2L3jZ3#>@2hXdC)nZ^HP^c7UxPy zrOZC=gQoIRn;H)Cly-Fm`>rbcU8ES0nlAadB)eM9NM5w*!S$Afjvt=?l;W6UwAuIO z%@}_(S8=Bthc4DBQCB>;-)Wm#cs-tYw z=}aor-zom&_04y6pAP2N>vVtX+i|+`Y*PF0`XwI&&QJBT3i(^KLbYaR#p^HWS?^!` zcrCbdyNJ+s)r-`zBTtSknwyt?)~C$u`g6t4 zfp#qc-%~ghuh;ncg!}Vtx@L7V*!kT(K~u9YzA+p-FK18QX~}*_;OfzGg|zO)5-kg7 z^>;aLh>DoC&aalk*6O>l##zFPwONjKkY@N(5K z;#e*seP)B|6eIZtw&-M=S27M>s>>?(c`;pEVa~AY&$%7`0#(cjfmazqrb#wj**JBh z=JzFS+Ly&Pa0uv}W!JdC+AG<#^(RB?u?9mYjYK<#gN_wG0$wxu11iK!*f> zA_r!ib&qs5VBWy-Y_X2wmduP)Q--Nmr5R$E*-f7JNPFcy28I`GP0wD`c$V@lNE12` zo`3IbaC%_2jPIHvvnjhoVt1+jNDpLu6}#LhoAJ`+w5{vc?$UM4`ls-&gYksE{S|@b zN>lbM2z(>4V@cT6CWXw_)2p>z&#f1eY+35N%dK4H@0lROZ?9%$h3h&dKT}w@a$EPU zqOBpUEo>84El_=ZLAzSu*_+i@_HnNX3}5-XTP^34XcniG#YW}+S?^U=%vkXy`>K#x zpyuhMBJP~beQIKPK874ugQf*~{?=H#_O4FSJ~c5B(aHP=wKC^d@N_)on>weZZqrV~ ziSJ}R=jq!{{rl+Wx0YQ>ulqPR3SXYp@^o2eG~Qj-{@n)cI!Zd=fc<)Yb~5sIeyG9u?s*8UVYmSuOU{lRy( zAdWZTlFM2Ij^){LDIVFC#L05)w2h_ItB_#r)#3~MX8o*+bU5+PDJ}3U`vX ctsnTU*^O6C5M1WPz`(%Z>FVdQ&MBb@07O!;r2qf` literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/constructor.png b/core/assets-raw/sprites/blocks/payload/constructor.png new file mode 100644 index 0000000000000000000000000000000000000000..8f68ec170879938cc45ddfed92a486ead4294580 GIT binary patch literal 1578 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW7>k44ofy`glX=O&!1~0~ z#WAE}&fB@RelorSZQT=KEyUuX zAZV$0v@vw`!tJ|vt=jb~y)N$M<@WMr)w}McFRNZwpZ2Zp?!P*FE89jXtGd0xORMen z=uC>|EM0w-ElzHJm%K%LWR&vO)Qth`3;|M3=Zs4;1g!on7HJW>dSrq^$=~`XZ2_D5 zY(Kpzwx)VMBYs=XXm=IpP=?$^@cznC3_xQqOvvwUv>f;X?7D(~mEg z&7UBapIx|6?%Q;R5AIX%|KBn#^{029y}dp6ufu^KxExy7vGo0vS}Nu7*7@n$&@5j; z)(6%etDhBr%jIQ?WZlXB@o%o`>s84gxA8suxnY0EQ%}vX*!Cm4n2NNIM@BxLF-yCV zmqB{=;>*Go_V&s03St_^IeH_-erEM)w;o`6ua?OX ztoTwyh<^;nMYkDQAqCP`HS({0FW9z+fnoN6qOIclYJR6)&)9m)Mf&Lzw;8*H%wGTI z|1UquYwF!6dMDTq>i(FZFhytg&D;!mrxgcgIheiv{kGon@|VkAb^cRd79Y6y(sRp# zAmyc*!RO*mZz@jZdhqSI|Ft?PWlNCAx}Dbq&M*|5b zU&@jcxj(yqeo=Rq5~I$&YXyI*HhiwGZ*b23C-KDTL+J!ffiYYNp+uAI!&0>|H<(OgF@+qBrbuV)Blkma2d7`n)*rvE}*jHI=Ea{qNEp(eAd^x0c`f`*G`WWsTNf zSDKWQuH1Ihn5(Pb)#Gz@!q%S*6Q4IsTi-P= zpUpohy?Kj3P}r^=nWmX4nL8^zQ_b{Wym}V3rT&zc`28|psk~cP{%X$jJM+lNBl6`U z!%Ib}y*C&ox&O7{jR_;?)3)N8YT(I=J zZ==G`U2?m5FF19u2EAHy?akswg}+-Ct`N+78@%1wdYS*D-3z1y*4V$8bGYWup5$ro zJ9cKtI_Z86Ty|fOdu1rc*0b(~e{cT&_4fDf%9T}@&Pi>kYjs*%bVTauo7XK{86(!+ zTT>}?WL=9A_ttEujE7uH6hxvm@cZ<~RTV literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/deconstructor-top.png b/core/assets-raw/sprites/blocks/payload/deconstructor-top.png new file mode 100644 index 0000000000000000000000000000000000000000..e75a3e44cfe94f51317a2b76f63a387672ac1da2 GIT binary patch literal 2030 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 literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/factory-in-3.png b/core/assets-raw/sprites/blocks/payload/factory-in-3.png new file mode 100644 index 0000000000000000000000000000000000000000..9ea0ed0f19111354b1c316180b7d0a775af5ca67 GIT binary patch literal 655 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW6p}rHd>I(3)EF2VS{N99 zF)%PRykKA`)n{OM70T{@)i+jFYr?Xo;B2pybkFBJI$^5h%voA)t6Di$PGSVl|t9V$JT^>Rn8!&6cNNKpx89^)7PI1|0OELtn26yP&{8L?$RRD{GB1UW%~2S z2cO)0bK&8;e~F*2SJxKb{=;o@@!tJ7&Tr}8G**N} zNwe13EoHx8=iV0noJ-kpQ{oT1PkT9+IcAgfL(v7{E)sRi4t*$Ixt`UqMtT(k&wamg zhPM3G+6;%cUzcfk_&bB^z=yvf%my{_s~IKs?LW%EV}C4%p-nzrsNvypDVBsEAI~vL j)Cq|NGcX*``^)gg@vYzce#Sct3=9mOu6{1-oD!M<0G|_e literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/units/factory-in-5.png b/core/assets-raw/sprites/blocks/payload/factory-in-5.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-5.png rename to core/assets-raw/sprites/blocks/payload/factory-in-5.png diff --git a/core/assets-raw/sprites/blocks/units/factory-in-7.png b/core/assets-raw/sprites/blocks/payload/factory-in-7.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-7.png rename to core/assets-raw/sprites/blocks/payload/factory-in-7.png diff --git a/core/assets-raw/sprites/blocks/units/factory-in-9.png b/core/assets-raw/sprites/blocks/payload/factory-in-9.png similarity index 100% rename from core/assets-raw/sprites/blocks/units/factory-in-9.png rename to core/assets-raw/sprites/blocks/payload/factory-in-9.png diff --git a/core/assets-raw/sprites/blocks/payload/factory-out-3.png b/core/assets-raw/sprites/blocks/payload/factory-out-3.png new file mode 100644 index 0000000000000000000000000000000000000000..84caaa1c31d85b3cd47eb6483a66d13d070c7c37 GIT binary patch literal 609 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 literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/large-constructor.png b/core/assets-raw/sprites/blocks/payload/large-constructor.png new file mode 100644 index 0000000000000000000000000000000000000000..f82c56b17d2d1439df097ece8e9eedb1d7446a62 GIT binary patch literal 4197 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 A2><{9 literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/payload-loader-top.png b/core/assets-raw/sprites/blocks/payload/payload-loader-top.png new file mode 100644 index 0000000000000000000000000000000000000000..2207273e024adb89929c78a5dd111eb6f47be8fd GIT binary patch literal 1032 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW7>k44ofy`glX=O&zB+( zH7kUeO;E^aa=7xqOQ1W$Uvk;!!e@{3(rvu{Sk1vuFTZIYU8AK+xU zQnL4Le1Mak<;@rYh5#qNoii<18Kz8d@)T2MxKXk7<==*>Q&m6M9rXA7@j83;;?Ey6 z6z5+0(72gPK*Q0$_XDFhg9E2jRx7^+3&RwFMQJ}8+!-7=^|IReSy&jRBpA8;aCl(H zz_2YYzly)-uKJ$)ziLz83487H&QV&GmYJn`=hvqvf4*++ogEwAB>8VWyZq$7t818E z6>JeY^Px3Pbw}F1u%z}IpamI@7T23jQOnBg_irL-iRlK zGW?0>+^V;Fb(_K5H|MH&;xBlusPqrs!!q;7H08-*huKS#SJygQdPwY>d8O!w+Gm;n z35_@67ft`rdha;@gD>70*RF=Wto_p>;KZSbn<(*n-~Z!G@}C-y^N05wJAXVxw&d@O ztTido(+%E#46hBcyJG2@@pH}s$>_J|;&ZMQx?MkO6=S?#opa?wZc`NzeaC&N&lCRp zzjQZmUY{7;`*ekeL(W-#&y3V>%nvv6+~qBru&mbXThW!EA8Ox%Qv4L+%};n|-V)D> ze(9{TMQWddP|VeA?;TUNP2KlyrxfR`Hb313FWFwco@br$_*%g0Bn6#?(?7IEn4gGR z`+K#?d$U5%7rHeERTCe66KtsZtuC^CeR-nS3)7l|Qxrh%arv)cTJ!Kp#m3(sT3@D= zr?u-(@#470{-llni~VO`r~6Awjvrj(Ta(ms>(2Kx0@bfn@{>g$uWHl3GHt?^iP1f) z<@N;xH&tmLmbk83vv3;A)wFqr>!N=+@p4{#o0A-K{X=UIr*d1oUuVmk|Lg{T>ZiQ1 zn4#M6FkU6xX%j=+dv$lGt-W_nXs#5x!X&Y8o(QKFBagl8+LjdzZS(ux4#g`kN=sgm TUVn*!fq}u()z4*}Q$iB}`zPI5 literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/payload-loader.png b/core/assets-raw/sprites/blocks/payload/payload-loader.png new file mode 100644 index 0000000000000000000000000000000000000000..19762a9ef46e49d5e71e36ca20ef2fa6b60cd640 GIT binary patch literal 1412 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 Fng9aOJyZYy delta 1254 zcmca*_nvctWIZzj1H&G{>GBK=42;D=?oJHr&dI!FU|`@0@Ck99F>A?&T?g_C8oa!N z_rCmW$H2fc(bL5-q+-t7JFlx2J8-Zi7~T7C`+l2e2_H|50efa}-Pca0_v@_Ysa74~ z^E%i%rHT7Lb29h-hJ~&751crp9v~{Weu43hs2fMhb%g^2<=E>LRGQS{w)!{(R>(9= z@DM1n^QmBBeOSogq~v(wx57i#H(dS90@wDPJF;sU=MBMYrjd!SlhwCv^>GNhaV=$K zP=~6IgP%rNdrJ|k^ar7N-5z@U98;M>t$BZl#c59riWklL8EP&1Lu6lYmMN@dpZ0cwYfh|3a^O~GGojyECKs=B%}zYF zd6EB@t;Zc#^`r#rmjA>v1ZZn z=R#)tuQ^2f-ZWnx#W^Q%qAWjKlGz3sFLjYW%zek&nQD_2rM(-D$~SLhiui9T!g`_R z#36xo^N)091aN+l6Upd3fAfv?0j><8d9PcqS~5R+^RxW*x*bf5+D)$2rQM$x@2ZubvHoRx+@XHG z3p-?!?Xvki9YSAxyt&DPEz4>8`AKe40%B1$6;dw`JpFDSdOzsFgP(Vb7S!H+&sufO zkGcLr>DBFDdpTAL20i}FT&pa=p7Q;u3D=qMX@LsGCeB6y`E!IcraW8V=F!{F`l>gW zsr8Y}6^@l33mx|6zjb~#rSXnuF#n5>KU?e;oPRE~t08W_`wPZjwR{iPv$Vw@`Di}r z$6=qAMyo&T^!^=m`g3^g5B4=5`F}p1Z&G_8GyRY7_xg(t4PKnjr*$oR>9FNu?DYFQ zbMtmKSZ<%L@6L4Y{j-xV;%%ZXpZ}--D$d5}_qKZ{7~Ky{$&p?A*}idZw>#hcZL>Qc z*e!Xx{biZXuF1DK{w(chIa0qu>0h#Dx!sNC)cfBvL}t}qKb%_e&9?t}dcS=Rs+#`o?}7@vkFQd%4Row6I?1?f8gQ|iw9G* z*Hlhv|6{DR?!(_X*RNHTpS5vn=dbvR!??KRoZ^xC3BqJ*(~9mt$Fev ze!Y`)ncWh)m|fWZqv$6!-5cINe4qTBUJhZ&LC+)sEr**upHUIQPr)d|stc4Zh^;{Y_KU_WZ&gI1P`i)|Y zY6rr(T01Aa7fL$7@}sE5Lh#dECxHt0fRYEVSMM*^Ub5iDf%or)?&nTuUc@Z?mw92) XoqPBGCLd&AU|{fc^>bP0l+XkK5rjzN diff --git a/core/assets-raw/sprites/blocks/payload/payload-unloader-top.png b/core/assets-raw/sprites/blocks/payload/payload-unloader-top.png new file mode 100644 index 0000000000000000000000000000000000000000..34ec963e54056d923cfcd0219b668bdd4ad21f82 GIT binary patch literal 1033 zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RW7>k44ofy`glX=O&zK-mVmCVhsK75Q@J;|2@5@zJ#eql(9khU&mme` z*JlR)z^Qi2%-*N0s#la%S8x2utU6`# ztcy4Pv8q0qJo#)7LxWJ!iL*yE85XpNcx{qkJa9VP`W}Bo+&=z$>OV9&>yvA9OXTEK zmjp}M6__!xcwGoqt~nsY5YW^X^^lp5kwLX(g{0jBL56^)?pqI;85tQ=XYdHx3GCo! zXfR)2zK8wTJK<&V+t;6|bvn88h}EK1)0g$NEcc$Tx9`ElC9fwYwEchh!}HR{S&kb^H!lP!39AEhMeca_x;?z!kBYmrn;J9>R;}4jAjc>6TkjoP`CeI z)&Dlrw`1#7(^IWiy8G9}W%jq6ZJqr2`gXbdM;_gkHa@<`x`KhBV&l&>FDGu;z1^Nw zK;~?dtx(arKbsBamF=rMHXIg@nw-$CpP@2k zP5x2E7L}UFC{DTCT`ciG4owgj_w3%#-F`cNE^kNcec^q9F^^BJi{dwNZ&LdcR<&P1 zn)Sec<%QQ$ORoy>sYhRyJ1o9MDC^#35r0RueJ@Wex%z=I_IB3&06w9%_3B$?_MNo3 zZ6BfV&GU=Uz6;gA8RyJvNsG&!dhfPBhhmF>6Hdb8`Imnk=WTACZ~tO*X7%41pR117 z`&S-o%XuyI?C!r+{-@ftmUHN?=bW|e>bgHilVsCNV%HqL`nh`21gU)i&Q2dip3E)_ z>*x2f-z8bYIy=k9-IXb+xX!~#d#^ml_S6?y6PiWdZr-?j@w7wc8<#6>X8yU#G0yAa zzJQxv@=6P@eqf#WKx*%{7H`eym#gQkp145s#TBMmSrhiX+Sx3Y$2(Pz?T}CvXM9I! z^P13I`@KHq2~TgicSt-&=-WRXrWM=koeFf3dGL3`oez!ws`q)mi18|yIdkiXy4#8~wdZ*@F8BLn7G}6E>xWY=r>FGJ zqdQ(b{uypyv9_6q#sYGc%1lG&v1DE zf|TP2br^Z-r^RrdWRlo7UxxFlS&{PcC0+sC2|ucWR93JU{3+QYw1`Qf&Q6N+KSKah X%5#=qvtt<;7#KWV{an^LB{Ts56eZMX literal 0 HcmV?d00001 diff --git a/core/assets-raw/sprites/blocks/payload/payload-unloader.png b/core/assets-raw/sprites/blocks/payload/payload-unloader.png new file mode 100644 index 0000000000000000000000000000000000000000..2511a0db65fb117fb5188631e06109a6e755ef18 GIT binary patch literal 1417 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 diff --git a/core/assets/bundles/bundle.properties b/core/assets/bundles/bundle.properties index 6b6df7cfd7..1a85f5e625 100644 --- a/core/assets/bundles/bundle.properties +++ b/core/assets/bundles/bundle.properties @@ -1341,10 +1341,16 @@ block.disassembler.name = Disassembler block.silicon-crucible.name = Silicon Crucible block.overdrive-dome.name = Overdrive Dome block.interplanetary-accelerator.name = Interplanetary Accelerator -#experimental, may be removed -block.block-forge.name = Block Forge -block.block-loader.name = Block Loader -block.block-unloader.name = Block Unloader +block.constructor.name = Constructor +block.constructor.description = Fabricates structures up to 2x2 tiles in size. +block.large-constructor.name = Large Constructor +block.large-constructor.description = Fabricates structures up to 4x4 tiles in size. +block.deconstructor.name = Deconstructor +block.deconstructor.description = Deconstructs structures and units. Returns 100% of build cost. +block.payload-loader.name = Payload Loader +block.payload-loader.description = Load liquids and items into blocks. +block.payload-unloader.name = Payload Unloader +block.payload-unloader.description = Unloads liquids and items from blocks. block.switch.name = Switch block.micro-processor.name = Micro Processor diff --git a/core/src/mindustry/content/Blocks.java b/core/src/mindustry/content/Blocks.java index c2697d7487..e4ec21e238 100644 --- a/core/src/mindustry/content/Blocks.java +++ b/core/src/mindustry/content/Blocks.java @@ -64,7 +64,7 @@ public class Blocks implements ContentList{ duct, ductRouter, ductBridge, //liquid - mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidTank, liquidJunction, bridgeConduit, phaseConduit, + mechanicalPump, rotaryPump, thermalPump, conduit, pulseConduit, platedConduit, liquidRouter, liquidContainer, liquidTank, liquidJunction, bridgeConduit, phaseConduit, //power combustionGenerator, thermalGenerator, steamGenerator, differentialGenerator, rtgGenerator, solarPanel, largeSolarPanel, thoriumReactor, @@ -86,18 +86,19 @@ public class Blocks implements ContentList{ repairPoint, repairTurret, //payloads - payloadConveyor, payloadRouter, payloadPropulsionTower, + payloadConveyor, payloadRouter, payloadPropulsionTower, deconstructor, constructor, largeConstructor, payloadLoader, payloadUnloader, //logic message, switchBlock, microProcessor, logicProcessor, hyperProcessor, largeLogicDisplay, logicDisplay, memoryCell, memoryBank, //campaign - launchPad, interplanetaryAccelerator, - - //misc experimental - blockForge, blockLoader, blockUnloader + launchPad, interplanetaryAccelerator ; + /** @deprecated use the blocks with proper names, */ + @Deprecated + public static Block blockForge, blockLoader, blockUnloader; + @Override public void load(){ //region environment @@ -125,7 +126,7 @@ public class Blocks implements ContentList{ isLiquid = true; status = StatusEffects.wet; statusDuration = 120f; - drownTime = 140f; + drownTime = 200f; cacheLayer = CacheLayer.water; albedo = 0.9f; }}; @@ -158,7 +159,7 @@ public class Blocks implements ContentList{ variants = 0; status = StatusEffects.wet; statusDuration = 140f; - drownTime = 120f; + drownTime = 200f; liquidDrop = Liquids.water; isLiquid = true; cacheLayer = CacheLayer.water; @@ -186,7 +187,7 @@ public class Blocks implements ContentList{ }}; tar = new Floor("tar"){{ - drownTime = 150f; + drownTime = 230f; status = StatusEffects.tarred; statusDuration = 240f; speedMultiplier = 0.19f; @@ -213,7 +214,7 @@ public class Blocks implements ContentList{ }}; slag = new Floor("molten-slag"){{ - drownTime = 150f; + drownTime = 230f; status = StatusEffects.melting; statusDuration = 240f; speedMultiplier = 0.19f; @@ -233,6 +234,12 @@ public class Blocks implements ContentList{ placeableOn = false; solid = true; variants = 0; + canShadow = false; + }}; + + empty = new EmptyFloor("empty"){{ + placeableOn = false; + solid = true; }}; stone = new Floor("stone"); @@ -337,34 +344,36 @@ public class Blocks implements ContentList{ attributes.set(Attribute.oil, 1.6f); }}; + moss = new Floor("moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.15f); + }}; + + sporeMoss = new Floor("spore-moss"){{ + variants = 3; + attributes.set(Attribute.spores, 0.3f); + }}; + stoneWall = new StaticWall("stone-wall"){{ variants = 2; }}; sporeWall = new StaticWall("spore-wall"){{ - variants = 2; - taintedWater.asFloor().wall = deepTaintedWater.asFloor().wall = this; + taintedWater.asFloor().wall = deepTaintedWater.asFloor().wall = sporeMoss.asFloor().wall = this; }}; - dirtWall = new StaticWall("dirt-wall"){{ - variants = 2; - }}; + dirtWall = new StaticWall("dirt-wall"); - daciteWall = new StaticWall("dacite-wall"){{ - variants = 2; - }}; + daciteWall = new StaticWall("dacite-wall"); iceWall = new StaticWall("ice-wall"){{ - variants = 2; iceSnow.asFloor().wall = this; + albedo = 0.6f; }}; - snowWall = new StaticWall("snow-wall"){{ - variants = 2; - }}; + snowWall = new StaticWall("snow-wall"); duneWall = new StaticWall("dune-wall"){{ - variants = 2; basalt.asFloor().wall = darksandWater.asFloor().wall = darksandTaintedWater.asFloor().wall = this; }}; @@ -377,21 +386,15 @@ public class Blocks implements ContentList{ shrubs = new StaticWall("shrubs"); - shaleWall = new StaticWall("shale-wall"){{ - variants = 2; - }}; + shaleWall = new StaticWall("shale-wall"); sporePine = new StaticTree("spore-pine"){{ - variants = 0; + moss.asFloor().wall = this; }}; - snowPine = new StaticTree("snow-pine"){{ - variants = 0; - }}; + snowPine = new StaticTree("snow-pine"); - pine = new StaticTree("pine"){{ - variants = 0; - }}; + pine = new StaticTree("pine"); whiteTreeDead = new TreeBlock("white-tree-dead"); @@ -404,7 +407,7 @@ public class Blocks implements ContentList{ boulder = new Prop("boulder"){{ variants = 2; - stone.asFloor().decoration = this; + stone.asFloor().decoration = craters.asFloor().decoration = charr.asFloor().decoration = this; }}; snowBoulder = new Prop("snow-boulder"){{ @@ -414,18 +417,22 @@ public class Blocks implements ContentList{ shaleBoulder = new Prop("shale-boulder"){{ variants = 2; + shale.asFloor().decoration = this; }}; sandBoulder = new Prop("sand-boulder"){{ variants = 2; + sand.asFloor().decoration = this; }}; daciteBoulder = new Prop("dacite-boulder"){{ variants = 2; + dacite.asFloor().decoration = this; }}; basaltBoulder = new Prop("basalt-boulder"){{ variants = 2; + basalt.asFloor().decoration = hotrock.asFloor().decoration = darksand.asFloor().decoration = magmarock.asFloor().decoration = this; }}; moss = new Floor("moss"){{ @@ -1130,10 +1137,16 @@ public class Blocks implements ContentList{ liquidCapacity = 20f; }}; + liquidContainer = new LiquidRouter("liquid-container"){{ + requirements(Category.liquid, with(Items.titanium, 10, Items.metaglass, 15)); + liquidCapacity = 700f; + size = 2; + }}; + liquidTank = new LiquidRouter("liquid-tank"){{ - requirements(Category.liquid, with(Items.titanium, 25, Items.metaglass, 25)); + requirements(Category.liquid, with(Items.titanium, 30, Items.metaglass, 40)); size = 3; - liquidCapacity = 1500f; + liquidCapacity = 1800f; health = 500; }}; @@ -1899,6 +1912,7 @@ public class Blocks implements ContentList{ length = 200f; hitEffect = Fx.hitMeltdown; hitColor = Pal.meltdownHit; + status = StatusEffects.melting; drawSize = 420f; incendChance = 0.4f; @@ -2082,6 +2096,49 @@ public class Blocks implements ContentList{ consumes.power(6f); }}; + deconstructor = new PayloadDeconstructor("deconstructor"){{ + requirements(Category.units, with(Items.thorium, 250, Items.silicon, 200, Items.graphite, 250)); + itemCapacity = 250; + consumes.power(3f); + size = 5; + deconstructSpeed = 2f; + }}; + + constructor = new Constructor("constructor"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + largeConstructor = new Constructor("large-constructor"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + maxBlockSize = 4; + minBlockSize = 3; + size = 5; + }}; + + payloadLoader = new PayloadLoader("payload-loader"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + payloadUnloader = new PayloadUnloader("payload-unloader"){{ + requirements(Category.units, with(Items.thorium, 100)); + hasPower = true; + consumes.power(2f); + size = 3; + }}; + + //TODO deprecated + blockForge = constructor; + blockLoader = payloadLoader; + blockUnloader = payloadUnloader; + //endregion //region sandbox @@ -2244,30 +2301,6 @@ public class Blocks implements ContentList{ size = 6; }}; - //endregion - //region experimental - - blockForge = new BlockForge("block-forge"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - - blockLoader = new BlockLoader("block-loader"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - - blockUnloader = new BlockUnloader("block-unloader"){{ - requirements(Category.units, BuildVisibility.debugOnly, with(Items.thorium, 100)); - hasPower = true; - consumes.power(2f); - size = 3; - }}; - //endregion } } diff --git a/core/src/mindustry/world/blocks/payloads/BlockProducer.java b/core/src/mindustry/world/blocks/payloads/BlockProducer.java index ec8642cc90..a3186a0dc3 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockProducer.java +++ b/core/src/mindustry/world/blocks/payloads/BlockProducer.java @@ -5,6 +5,7 @@ import arc.math.*; import arc.util.*; import arc.util.io.*; import mindustry.*; +import mindustry.content.*; import mindustry.entities.units.*; import mindustry.gen.*; import mindustry.graphics.*; @@ -34,7 +35,14 @@ public abstract class BlockProducer extends PayloadBlock{ @Override public TextureRegion[] icons(){ - return new TextureRegion[]{region, outRegion}; + return new TextureRegion[]{region, outRegion, topRegion}; + } + + @Override + public void drawRequestRegion(BuildPlan req, Eachable list){ + Draw.rect(region, req.drawx(), req.drawy()); + Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); + Draw.rect(topRegion, req.drawx(), req.drawy()); } @Override @@ -43,12 +51,6 @@ public abstract class BlockProducer extends PayloadBlock{ bars.add("progress", (BlockProducerBuild entity) -> new Bar("bar.progress", Pal.ammo, () -> entity.recipe() == null ? 0f : (entity.progress / entity.recipe().buildCost))); } - - @Override - public void drawRequestRegion(BuildPlan req, Eachable list){ - Draw.rect(region, req.drawx(), req.drawy()); - Draw.rect(outRegion, req.drawx(), req.drawy(), req.rotation * 90); - } public abstract class BlockProducerBuild extends PayloadBlockBuild{ public float progress, time, heat; @@ -85,6 +87,7 @@ public abstract class BlockProducer extends PayloadBlock{ if(progress >= recipe.buildCost){ consume(); payload = new BuildPayload(recipe, team); + Fx.placeBlock.at(x, y, payload.size() / tilesize); payVector.setZero(); progress %= 1f; } @@ -109,6 +112,7 @@ public abstract class BlockProducer extends PayloadBlock{ for(TextureRegion region : recipe.getGeneratedIcons()){ Shaders.blockbuild.region = region; + Shaders.blockbuild.time = time; Shaders.blockbuild.progress = progress / recipe.buildCost; Draw.rect(region, x, y, recipe.rotate ? rotdeg() : 0); @@ -126,6 +130,9 @@ public abstract class BlockProducer extends PayloadBlock{ } drawPayload(); + + Draw.z(Layer.blockBuilding + 1.1f); + Draw.rect(topRegion, x, y); } @Override diff --git a/core/src/mindustry/world/blocks/payloads/BlockUnloader.java b/core/src/mindustry/world/blocks/payloads/BlockUnloader.java deleted file mode 100644 index 8f4a644fce..0000000000 --- a/core/src/mindustry/world/blocks/payloads/BlockUnloader.java +++ /dev/null @@ -1,67 +0,0 @@ -package mindustry.world.blocks.payloads; - -import mindustry.gen.*; -import mindustry.type.*; - -import static mindustry.Vars.*; - -public class BlockUnloader extends BlockLoader{ - - public BlockUnloader(String name){ - super(name); - } - - @Override - public boolean outputsItems(){ - return true; - } - - @Override - public boolean rotatedOutput(int x, int y){ - return false; - } - - public class BlockUnloaderBuild extends BlockLoaderBuild{ - - @Override - public boolean acceptItem(Building source, Item item){ - return false; - } - - @Override - public void updateTile(){ - if(shouldExport()){ - moveOutPayload(); - }else if(moveInPayload()){ - - //load up items - if(payload.block().hasItems && !full()){ - if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ - //load up items a set amount of times - for(int j = 0; j < itemsLoaded && !full(); j++){ - for(int i = 0; i < items.length(); i++){ - if(payload.build.items.get(i) > 0){ - Item item = content.item(i); - payload.build.items.remove(item, 1); - items.add(item, 1); - break; - } - } - } - } - } - } - - dump(); - } - - public boolean full(){ - return items.total() >= itemCapacity; - } - - @Override - public boolean shouldExport(){ - return payload != null && (payload.block().hasItems && payload.build.items.empty()); - } - } -} diff --git a/core/src/mindustry/world/blocks/payloads/BuildPayload.java b/core/src/mindustry/world/blocks/payloads/BuildPayload.java index d9e6c08fa0..ad6a6a0fc9 100644 --- a/core/src/mindustry/world/blocks/payloads/BuildPayload.java +++ b/core/src/mindustry/world/blocks/payloads/BuildPayload.java @@ -5,6 +5,7 @@ import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.graphics.*; +import mindustry.type.*; import mindustry.world.*; import static mindustry.Vars.*; @@ -33,6 +34,16 @@ public class BuildPayload implements Payload{ build.dropped(); } + @Override + public ItemStack[] requirements(){ + return build.block.requirements; + } + + @Override + public float buildTime(){ + return build.block.buildCost; + } + @Override public float x(){ return build.x; @@ -61,9 +72,14 @@ public class BuildPayload implements Payload{ build.set(x, y); } + @Override + public void drawShadow(float alpha){ + Drawf.shadow(build.x, build.y, build.block.size * tilesize * 2f, alpha); + } + @Override public void draw(){ - Drawf.shadow(build.x, build.y, build.block.size * tilesize * 2f); + drawShadow(1f); Draw.rect(build.block.fullIcon, build.x, build.y); } diff --git a/core/src/mindustry/world/blocks/payloads/BlockForge.java b/core/src/mindustry/world/blocks/payloads/Constructor.java similarity index 88% rename from core/src/mindustry/world/blocks/payloads/BlockForge.java rename to core/src/mindustry/world/blocks/payloads/Constructor.java index 52827780af..4359fd581d 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockForge.java +++ b/core/src/mindustry/world/blocks/payloads/Constructor.java @@ -6,7 +6,6 @@ import arc.scene.ui.layout.*; import arc.util.*; import arc.util.io.*; import mindustry.*; -import mindustry.ui.*; import mindustry.world.*; import mindustry.world.blocks.*; import mindustry.world.meta.*; @@ -14,17 +13,17 @@ import mindustry.world.meta.*; import static mindustry.Vars.*; /** Configurable BlockProducer variant. */ -public class BlockForge extends BlockProducer{ +public class Constructor extends BlockProducer{ public float buildSpeed = 0.4f; public int minBlockSize = 1, maxBlockSize = 2; - public BlockForge(String name){ + public Constructor(String name){ super(name); size = 3; configurable = true; - config(Block.class, (BlockForgeBuild tile, Block block) -> { + config(Block.class, (ConstructorBuild tile, Block block) -> { if(tile.recipe != block) tile.progress = 0f; if(canProduce(block)){ tile.recipe = block; @@ -43,7 +42,7 @@ public class BlockForge extends BlockProducer{ return b.isVisible() && b.size >= minBlockSize && b.size <= maxBlockSize; } - public class BlockForgeBuild extends BlockProducerBuild{ + public class ConstructorBuild extends BlockProducerBuild{ public @Nullable Block recipe; @Override @@ -53,7 +52,7 @@ public class BlockForge extends BlockProducer{ @Override public void buildConfiguration(Table table){ - ItemSelection.buildTable(table, content.blocks().select(BlockForge.this::canProduce), () -> recipe, this::configure); + ItemSelection.buildTable(table, content.blocks().select(Constructor.this::canProduce), () -> recipe, this::configure); } @Override diff --git a/core/src/mindustry/world/blocks/payloads/Payload.java b/core/src/mindustry/world/blocks/payloads/Payload.java index 9563db51d3..4be19f66bf 100644 --- a/core/src/mindustry/world/blocks/payloads/Payload.java +++ b/core/src/mindustry/world/blocks/payloads/Payload.java @@ -7,6 +7,7 @@ import arc.util.io.*; import mindustry.game.*; import mindustry.gen.*; import mindustry.ui.*; +import mindustry.type.*; import mindustry.world.*; import static mindustry.Vars.*; @@ -20,6 +21,8 @@ public interface Payload extends Position{ /** draws this payload at a position. */ void draw(); + void drawShadow(float alpha); + /** @return hitbox size of the payload. */ float size(); @@ -27,6 +30,12 @@ public interface Payload extends Position{ float y(); + /** @return the items needed to make this payload; may be empty. */ + ItemStack[] requirements(); + + /** @return the time taken to build this payload. */ + float buildTime(); + /** @return whether this payload was dumped. */ default boolean dump(){ return false; diff --git a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java index 45bb21eee0..a7885e76c7 100644 --- a/core/src/mindustry/world/blocks/payloads/PayloadBlock.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadBlock.java @@ -9,6 +9,7 @@ import mindustry.annotations.Annotations.*; import mindustry.gen.*; import mindustry.graphics.*; import mindustry.world.*; +import mindustry.world.meta.*; import static mindustry.Vars.*; @@ -24,6 +25,7 @@ public class PayloadBlock extends Block{ update = true; sync = true; + envEnabled |= Env.space; } public static boolean blends(Building build, int direction){ @@ -78,16 +80,16 @@ public class PayloadBlock extends Block{ } @Override - public boolean canControlSelect(Unit player){ - return !player.spawnedByCore && this.payload == null && acceptUnitPayload(player) && player.tileOn() != null && player.tileOn().build == this; + public boolean canControlSelect(Player player){ + return !player.unit().spawnedByCore && this.payload == null && acceptUnitPayload(player.unit()) && player.tileOn() != null && player.tileOn().build == this; } @Override - public void onControlSelect(Unit player){ + public void onControlSelect(Player player){ float x = player.x, y = player.y; - handleUnitPayload(player, p -> payload = (T)p); + acceptPlayerPayload(player, p -> payload = (T)p); this.payVector.set(x, y).sub(this).clamp(-size * tilesize / 2f, -size * tilesize / 2f, size * tilesize / 2f, size * tilesize / 2f); - this.payRotation = player.rotation; + this.payRotation = player.unit().rotation; } @Override diff --git a/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java new file mode 100644 index 0000000000..328549f0a4 --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadDeconstructor.java @@ -0,0 +1,205 @@ +package mindustry.world.blocks.payloads; + +import arc.graphics.g2d.*; +import arc.math.*; +import arc.util.*; +import arc.util.io.*; +import mindustry.content.*; +import mindustry.gen.*; +import mindustry.graphics.*; +import mindustry.ui.*; + +import static mindustry.Vars.*; + +public class PayloadDeconstructor extends PayloadBlock{ + public float maxPayloadSize = 4; + public float deconstructSpeed = 2.5f; + public int dumpRate = 4; + + public PayloadDeconstructor(String name){ + super(name); + + outputsPayload = false; + acceptsPayload = true; + update = true; + rotate = false; + solid = true; + size = 5; + payloadSpeed = 1f; + //make sure to display large units. + clipSize = 120; + hasItems = true; + hasPower = true; + itemCapacity = 100; + } + + @Override + public TextureRegion[] icons(){ + return new TextureRegion[]{region, topRegion}; + } + + @Override + public void setBars(){ + super.setBars(); + + bars.add("progress", (PayloadDeconstructorBuild e) -> new Bar("bar.progress", Pal.ammo, () -> e.progress)); + } + + public class PayloadDeconstructorBuild extends PayloadBlockBuild{ + public @Nullable Payload deconstructing; + public @Nullable float[] accum; + public float progress; + public float time, speedScl; + + @Override + public void draw(){ + Draw.rect(region, x, y); + + //draw input + for(int i = 0; i < 4; i++){ + if(blends(i)){ + Draw.rect(inRegion, x, y, (i * 90) - 180); + } + } + + Draw.z(Layer.blockOver); + drawPayload(); + if(deconstructing != null){ + deconstructing.set(x + payVector.x, y + payVector.y, payRotation); + + Draw.z(Layer.blockOver); + deconstructing.drawShadow(1f - progress); + + //TODO looks really bad + Draw.draw(Layer.blockOver, () -> { + Drawf.construct(x, y, deconstructing.icon(), Pal.remove, deconstructing instanceof BuildPayload ? 0f : payRotation - 90f, 1f - progress, 1f - progress, time); + Draw.color(Pal.remove); + Draw.alpha(1f); + + Lines.lineAngleCenter(x + Mathf.sin(time, 20f, tilesize / 2f * block.size - 3f), y, 90f, block.size * tilesize - 6f); + + Draw.reset(); + }); + } + + Draw.rect(topRegion, x, y); + } + + @Override + public void handlePayload(Building source, Payload payload){ + super.handlePayload(source, payload); + accum = null; + } + + @Override + public boolean acceptPayload(Building source, Payload payload){ + return deconstructing == null && super.acceptPayload(source, payload) && payload.requirements().length > 0 && payload.fits(maxPayloadSize); + } + + @Override + public void updateTile(){ + if(items.total() > 0){ + for(int i = 0; i < dumpRate; i++){ + dumpAccumulate(); + } + } + + if(deconstructing == null){ + progress = 0f; + } + + payRotation = Angles.moveToward(payRotation, 90f, payloadRotateSpeed * edelta()); + + if(deconstructing != null){ + var reqs = deconstructing.requirements(); + if(accum == null || reqs.length != accum.length){ + accum = new float[reqs.length]; + } + + //check if there is enough space to get the items for deconstruction + boolean canProgress = items.total() <= itemCapacity; + if(canProgress){ + for(var ac : accum){ + if(ac >= 1f){ + canProgress = false; + break; + } + } + } + + //move progress forward if possible + if(canProgress){ + float shift = edelta() * deconstructSpeed / deconstructing.buildTime(); + float realShift = Math.min(shift, 1f - progress); + + progress += shift; + time += edelta(); + + for(int i = 0; i < reqs.length; i++){ + accum[i] += reqs[i].amount * realShift; + } + } + + speedScl = Mathf.lerpDelta(speedScl, canProgress ? 1f : 0f, 0.1f); + + //transfer items from accumulation buffer into block inventory when they reach integers + for(int i = 0; i < reqs.length; i++){ + int taken = Math.min((int)accum[i], itemCapacity - items.total()); + if(taken > 0){ + items.add(reqs[i].item, taken); + accum[i] -= taken; + } + } + + //finish deconstruction, prepare for next payload. + if(progress >= 1f){ + Fx.breakBlock.at(x, y, deconstructing.size() / tilesize); + + deconstructing = null; + accum = null; + } + }else if(moveInPayload(false) && payload != null){ + accum = new float[payload.requirements().length]; + deconstructing = payload; + payload = null; + progress = 0f; + } + } + + @Override + public boolean shouldConsume(){ + return deconstructing != null && enabled; + } + + @Override + public void write(Writes write){ + super.write(write); + + write.f(progress); + if(accum != null){ + write.s(accum.length); + for(float v : accum){ + write.f(v); + } + }else{ + write.s(0); + } + Payload.write(deconstructing, write); + } + + @Override + public void read(Reads read, byte revision){ + super.read(read, revision); + + progress = read.f(); + short accums = read.s(); + if(accums > 0){ + accum = new float[accums]; + for(int i = 0; i < accums; i++){ + accum[i] = read.f(); + } + } + deconstructing = Payload.read(read); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/BlockLoader.java b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java similarity index 74% rename from core/src/mindustry/world/blocks/payloads/BlockLoader.java rename to core/src/mindustry/world/blocks/payloads/PayloadLoader.java index 001f93712a..04c2d7c60b 100644 --- a/core/src/mindustry/world/blocks/payloads/BlockLoader.java +++ b/core/src/mindustry/world/blocks/payloads/PayloadLoader.java @@ -11,20 +11,21 @@ import mindustry.ui.*; import static mindustry.Vars.*; -public class BlockLoader extends PayloadBlock{ +public class PayloadLoader extends PayloadBlock{ public final int timerLoad = timers++; public float loadTime = 2f; - public int itemsLoaded = 5; - public float liquidsLoaded = 5f; + public int itemsLoaded = 8; + public float liquidsLoaded = 40f; public int maxBlockSize = 2; - public BlockLoader(String name){ + public PayloadLoader(String name){ super(name); hasItems = true; - itemCapacity = 25; - //liquidCapacity = 25; + hasLiquids = true; + itemCapacity = 100; + liquidCapacity = 100f; update = true; outputsPayload = true; size = 3; @@ -45,7 +46,7 @@ public class BlockLoader extends PayloadBlock{ public void setBars(){ super.setBars(); - bars.add("progress", (BlockLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); + bars.add("progress", (PayloadLoaderBuild entity) -> new Bar(() -> Core.bundle.format("bar.items", entity.payload == null ? 0 : entity.payload.build.items.total()), () -> Pal.items, entity::fraction)); } @Override @@ -56,14 +57,14 @@ public class BlockLoader extends PayloadBlock{ Draw.rect(topRegion, req.drawx(), req.drawy()); } - public class BlockLoaderBuild extends PayloadBlockBuild{ + public class PayloadLoaderBuild extends PayloadBlockBuild{ @Override public boolean acceptPayload(Building source, Payload payload){ return super.acceptPayload(source, payload) && - (payload instanceof BuildPayload build) && - ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize)/* || - ((BlockPayload)payload).entity.block().hasLiquids && ((BlockPayload)payload).block().liquidCapacity >= 10f)*/); + payload instanceof BuildPayload build && + ((build.build.block.hasItems && build.block().unloadable && build.block().itemCapacity >= 10 && build.block().size <= maxBlockSize) || + build.build.block().hasLiquids && build.block().liquidCapacity >= 10f); } @Override @@ -71,6 +72,11 @@ public class BlockLoader extends PayloadBlock{ return items.total() < itemCapacity; } + @Override + public boolean acceptLiquid(Building source, Liquid liquid){ + return liquids.current() == liquid || liquids.currentAmount() < 0.2f; + } + @Override public void draw(){ Draw.rect(region, x, y); @@ -120,17 +126,17 @@ public class BlockLoader extends PayloadBlock{ } } - //load up liquids (disabled) - /* + //load up liquids if(payload.block().hasLiquids && liquids.total() >= 0.001f){ Liquid liq = liquids.current(); float total = liquids.currentAmount(); - float flow = Math.min(Math.min(liquidsLoaded * delta(), payload.block().liquidCapacity - payload.entity.liquids.get(liq) - 0.0001f), total); - if(payload.entity.acceptLiquid(payload.entity, liq, flow)){ - payload.entity.liquids.add(liq, flow); + float flow = Math.min(Math.min(liquidsLoaded * edelta(), payload.block().liquidCapacity - payload.build.liquids.get(liq)), total); + //TODO potential crash here + if(payload.build.acceptLiquid(payload.build, liq)){ + payload.build.liquids.add(liq, flow); liquids.remove(liq, flow); } - }*/ + } } } @@ -139,8 +145,8 @@ public class BlockLoader extends PayloadBlock{ } public boolean shouldExport(){ - return payload != null && - ((payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || + return payload != null && ( + (payload.block().hasLiquids && payload.build.liquids.total() >= payload.block().liquidCapacity - 0.001f) || (payload.block().hasItems && payload.build.items.total() >= payload.block().itemCapacity)); } } diff --git a/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java new file mode 100644 index 0000000000..7d63380528 --- /dev/null +++ b/core/src/mindustry/world/blocks/payloads/PayloadUnloader.java @@ -0,0 +1,97 @@ +package mindustry.world.blocks.payloads; + +import mindustry.gen.*; +import mindustry.type.*; + +import static mindustry.Vars.*; + +public class PayloadUnloader extends PayloadLoader{ + public int offloadSpeed = 4; + + public PayloadUnloader(String name){ + super(name); + } + + @Override + public boolean outputsItems(){ + return true; + } + + @Override + public boolean rotatedOutput(int x, int y){ + return false; + } + + public class PayloadUnloaderBuild extends PayloadLoaderBuild{ + + @Override + public boolean acceptItem(Building source, Item item){ + return false; + } + + @Override + public boolean acceptLiquid(Building source, Liquid liquid){ + return false; + } + + @Override + public void updateTile(){ + if(shouldExport()){ + //one-use, disposable block + if(payload.block().instantDeconstruct){ + payload.block().breakEffect.at(this, payload.block().size); + payload = null; + }else{ + moveOutPayload(); + } + }else if(moveInPayload()){ + + //unload items + if(payload.block().hasItems && !full()){ + if(efficiency() > 0.01f && timer(timerLoad, loadTime / efficiency())){ + //load up items a set amount of times + for(int j = 0; j < itemsLoaded && !full(); j++){ + for(int i = 0; i < items.length(); i++){ + if(payload.build.items.get(i) > 0){ + Item item = content.item(i); + payload.build.items.remove(item, 1); + items.add(item, 1); + break; + } + } + } + } + } + + //unload liquids + //TODO tile is null may crash + if(payload.block().hasLiquids && payload.build.liquids.currentAmount() >= 0.01f && + (liquids.current() == payload.build.liquids.current() || liquids.currentAmount() <= 0.2f)){ + var liq = payload.build.liquids.current(); + float remaining = liquidCapacity - liquids.currentAmount(); + float flow = Math.min(Math.min(liquidsLoaded * delta(), remaining), payload.build.liquids.currentAmount()); + + liquids.add(liq, flow); + payload.build.liquids.remove(liq, flow); + } + } + + dumpLiquid(liquids.current()); + for(int i = 0; i < offloadSpeed; i++){ + dumpAccumulate(); + } + } + + public boolean full(){ + return items.total() >= itemCapacity; + } + + @Override + public boolean shouldExport(){ + return payload != null && ( + (!payload.block().hasItems || payload.build.items.empty()) && + (!payload.block().hasLiquids || payload.build.liquids.currentAmount() <= 0.001f) + ); + } + } +} diff --git a/core/src/mindustry/world/blocks/payloads/UnitPayload.java b/core/src/mindustry/world/blocks/payloads/UnitPayload.java index 99558971da..838f987477 100644 --- a/core/src/mindustry/world/blocks/payloads/UnitPayload.java +++ b/core/src/mindustry/world/blocks/payloads/UnitPayload.java @@ -13,6 +13,7 @@ import mindustry.entities.EntityCollisions.*; import mindustry.entities.*; import mindustry.game.EventType.*; import mindustry.gen.*; +import mindustry.type.*; import static mindustry.Vars.*; @@ -39,6 +40,16 @@ public class UnitPayload implements Payload{ showOverlay(icon.getRegion()); } + @Override + public ItemStack[] requirements(){ + return unit.type.getTotalRequirements(); + } + + @Override + public float buildTime(){ + return unit.type.getBuildTime(); + } + @Override public void write(Writes write){ write.b(payloadUnit); @@ -105,11 +116,20 @@ public class UnitPayload implements Payload{ //prevents stacking unit.vel.add(Mathf.range(0.5f), Mathf.range(0.5f)); unit.add(); + unit.unloaded(); Events.fire(new UnitUnloadEvent(unit)); return true; } + @Override + public void drawShadow(float alpha){ + //TODO should not happen + if(unit.type == null) return; + + unit.type.drawSoftShadow(unit, alpha); + } + @Override public void draw(){ //TODO should not happen