From 495e444d1ff06f6a45b099fdab1985e219a8e511 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 19 Nov 2024 13:30:52 +0300 Subject: [PATCH 01/14] fix MainBatch::cube --- src/graphics/render/MainBatch.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/graphics/render/MainBatch.cpp b/src/graphics/render/MainBatch.cpp index e3a87db7..a440a43b 100644 --- a/src/graphics/render/MainBatch.cpp +++ b/src/graphics/render/MainBatch.cpp @@ -97,38 +97,38 @@ void MainBatch::cube( const glm::vec3 Z(0.0f, 0.0f, 1.0f); quad( - coord + glm::vec3(0.0f, 0.0f, 0.0f), + coord + Z * size.z * 0.5f, X, Y, glm::vec2(size.x, size.y), (shading ? do_tint(0.8) * tint : tint), glm::vec3(1.0f), texfaces[5] ); quad( - coord + glm::vec3(size.x, 0.0f, -size.z), + coord - Z * size.z * 0.5f, -X, Y, glm::vec2(size.x, size.y), - (shading ? do_tint(0.8) * tint : tint), + (shading ? do_tint(0.9f) * tint : tint), glm::vec3(1.0f), texfaces[4] ); quad( - coord + glm::vec3(0.0f, size.y, 0.0f), - X, -Z, glm::vec2(size.x, size.z), + coord + Y * size.y * 0.5f, + -X, Z, glm::vec2(size.x, size.z), (shading ? do_tint(1.0f) * tint : tint), glm::vec3(1.0f), texfaces[3] ); quad( - coord + glm::vec3(0.0f, 0.0f, -size.z), + coord - Y * size.y * 0.5f, X, Z, glm::vec2(size.x, size.z), (shading ? do_tint(0.7f) * tint : tint), glm::vec3(1.0f), texfaces[2] ); quad( - coord + glm::vec3(0.0f, 0.0f, -size.z), - Z, Y, glm::vec2(size.z, size.y), - (shading ? do_tint(0.9f) * tint : tint), - glm::vec3(1.0f), texfaces[0] + coord + X * size.x * 0.5f, + -Z, Y, glm::vec2(size.z, size.y), + (shading ? do_tint(0.8f) * tint : tint), + glm::vec3(1.0f), texfaces[1] ); quad( - coord + glm::vec3(size.x, 0.0f, 0.0f), - -Z, Y, glm::vec2(size.z, size.y), + coord - X * size.x * 0.5f, + Z, Y, glm::vec2(size.z, size.y), (shading ? do_tint(0.9f) * tint : tint), glm::vec3(1.0f), texfaces[1] ); From 0144709e037db1454f7e2358559221cbc1c47872 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 19 Nov 2024 14:33:14 +0300 Subject: [PATCH 02/14] add 'u_alphaClip' to entity shader --- res/shaders/entity.glslf | 3 ++- src/graphics/render/WorldRenderer.cpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/res/shaders/entity.glslf b/res/shaders/entity.glslf index 5da4142c..143b3eaa 100644 --- a/res/shaders/entity.glslf +++ b/res/shaders/entity.glslf @@ -9,6 +9,7 @@ uniform samplerCube u_cubemap; uniform vec3 u_fogColor; uniform float u_fogFactor; uniform float u_fogCurve; +uniform bool u_alphaClip; void main() { vec3 fogColor = texture(u_cubemap, a_dir).rgb; @@ -16,7 +17,7 @@ void main() { float depth = (a_distance/256.0); float alpha = a_color.a * tex_color.a; // anyway it's any alpha-test alternative required - if (alpha < 0.5f) + if (alpha < (u_alphaClip ? 0.5f : 0.2f)) discard; f_color = mix(a_color * tex_color, vec4(fogColor,1.0), min(1.0, pow(depth*u_fogFactor, u_fogCurve))); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 0593305d..30284187 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -153,6 +153,7 @@ void WorldRenderer::renderLevel( frustumCulling->update(camera.getProjView()); } + entityShader.uniform1i("u_alphaClip", true); level.entities->render( assets, *modelBatch, From 784f93666cffa9bf7fcad69a4ebee302bf506341 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 04:30:19 +0300 Subject: [PATCH 03/14] add 'separate' atlas type & get rid of assets loading entries duplicates --- src/assets/AssetsLoader.cpp | 14 ++++++++++++++ src/assets/AssetsLoader.hpp | 13 +++++++++++++ src/assets/assetload_funcs.cpp | 17 +++++++++++++++-- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 142934d1..d3806157 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -43,7 +43,11 @@ void AssetsLoader::add( const std::string& alias, std::shared_ptr settings ) { + if (enqueued.find({tag, alias}) != enqueued.end()){ + return; + } entries.push(aloader_entry {tag, filename, alias, std::move(settings)}); + enqueued.insert({tag, alias}); } bool AssetsLoader::hasNext() const { @@ -148,6 +152,16 @@ void AssetsLoader::processPreload( std::make_shared(map.at("keep-pcm").get(keepPCM))); break; } + case AssetType::ATLAS: { + std::string typeName = "atlas"; + map.at("type").get(typeName); + auto type = AtlasType::ATLAS; + if (typeName == "separate") { + type = AtlasType::SEPARATE; + } + add(tag, path, name, std::make_shared(type)); + break; + } default: add(tag, path, name); break; diff --git a/src/assets/AssetsLoader.hpp b/src/assets/AssetsLoader.hpp index 2321f9a3..cd6db950 100644 --- a/src/assets/AssetsLoader.hpp +++ b/src/assets/AssetsLoader.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,17 @@ struct SoundCfg : AssetCfg { } }; +enum class AtlasType { + ATLAS, SEPARATE +}; + +struct AtlasCfg : AssetCfg { + AtlasType type; + + AtlasCfg(AtlasType type) : type(type) { + } +}; + using aloader_func = std::function< assetload:: postfunc(AssetsLoader*, const ResPaths*, const std::string&, const std::string&, std::shared_ptr)>; @@ -52,6 +64,7 @@ class AssetsLoader { Assets* assets; std::map loaders; std::queue entries; + std::set> enqueued; const ResPaths* paths; void tryAddSound(const std::string& name); diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index ce8b65c9..813d1c87 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -103,12 +103,25 @@ static bool append_atlas(AtlasBuilder& atlas, const fs::path& file) { } assetload::postfunc assetload::atlas( - AssetsLoader*, + AssetsLoader* loader, const ResPaths* paths, const std::string& directory, const std::string& name, - const std::shared_ptr& + const std::shared_ptr& config ) { + auto atlasConfig = std::dynamic_pointer_cast(config); + if (atlasConfig && atlasConfig->type == AtlasType::SEPARATE) { + for (const auto& file : paths->listdir(directory)) { + if (!imageio::is_read_supported(file.extension().u8string())) + continue; + loader->add( + AssetType::TEXTURE, + directory + "/" + file.stem().u8string(), + name + "/" + file.stem().u8string() + ); + } + return [](auto){}; + } AtlasBuilder builder; for (const auto& file : paths->listdir(directory)) { if (!imageio::is_read_supported(file.extension().u8string())) continue; From 4edab4a89a02e0603a45f7cf7e52a85233dade38 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 04:58:56 +0300 Subject: [PATCH 04/14] add 'cracks' separate atlas to base --- res/content/base/preload.json | 3 +++ res/content/base/textures/cracks/cracks_0.png | Bin 0 -> 4757 bytes res/content/base/textures/cracks/cracks_1.png | Bin 0 -> 4768 bytes res/content/base/textures/cracks/cracks_10.png | Bin 0 -> 4904 bytes res/content/base/textures/cracks/cracks_2.png | Bin 0 -> 5018 bytes res/content/base/textures/cracks/cracks_3.png | Bin 0 -> 4798 bytes res/content/base/textures/cracks/cracks_4.png | Bin 0 -> 5050 bytes res/content/base/textures/cracks/cracks_5.png | Bin 0 -> 5062 bytes res/content/base/textures/cracks/cracks_6.png | Bin 0 -> 4846 bytes res/content/base/textures/cracks/cracks_7.png | Bin 0 -> 4847 bytes res/content/base/textures/cracks/cracks_8.png | Bin 0 -> 4872 bytes res/content/base/textures/cracks/cracks_9.png | Bin 0 -> 4877 bytes 12 files changed, 3 insertions(+) create mode 100644 res/content/base/textures/cracks/cracks_0.png create mode 100644 res/content/base/textures/cracks/cracks_1.png create mode 100644 res/content/base/textures/cracks/cracks_10.png create mode 100644 res/content/base/textures/cracks/cracks_2.png create mode 100644 res/content/base/textures/cracks/cracks_3.png create mode 100644 res/content/base/textures/cracks/cracks_4.png create mode 100644 res/content/base/textures/cracks/cracks_5.png create mode 100644 res/content/base/textures/cracks/cracks_6.png create mode 100644 res/content/base/textures/cracks/cracks_7.png create mode 100644 res/content/base/textures/cracks/cracks_8.png create mode 100644 res/content/base/textures/cracks/cracks_9.png diff --git a/res/content/base/preload.json b/res/content/base/preload.json index 33f38f36..56b9896e 100644 --- a/res/content/base/preload.json +++ b/res/content/base/preload.json @@ -1,4 +1,7 @@ { + "atlases": [ + {"name": "cracks", "type": "separate"} + ], "sounds": [ "blocks/door_open", "blocks/door_close", diff --git a/res/content/base/textures/cracks/cracks_0.png b/res/content/base/textures/cracks/cracks_0.png new file mode 100644 index 0000000000000000000000000000000000000000..84d56c433a4d837eb460db23a805ea5121f65e58 GIT binary patch literal 4757 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 IH+KF109r`~e*gdg literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_1.png b/res/content/base/textures/cracks/cracks_1.png new file mode 100644 index 0000000000000000000000000000000000000000..40bd0ce87bf410b3f8d9fc8d744cac70b3d5cb18 GIT binary patch literal 4768 zcmeHKc~leE8jom!vZ%;Xa2MZ(f+nG5t*xK>!iAB8yvkpH+r-=tIw{GNkqe_`9+e9Jj;QRo8d z(+*ut{;^dZ^r{oP&)M2&ysvR=G*)K0E-YPGuKBLS6;WBgtP~anOc^m1e z*$%I_IG%2-a<|~m=_<6;d9P^-`mtg{=bdI$Z9Q3+FKIT6^{B_Xg|8i`i}!q%lk@69 zN@cA%#8(|MHcT&YkW49ApSAvG)+T?WJvptHH>72d%G7?FcD80_tbUxK^gxe>Eq*oS z&Y^j8_Xw(NZ&;OOGLk$M!aY9B=-S_+ok5eUk$lhu){@Ja_wRi zXX?rOiuTk$o)=q|;QK=_rQP~N%I@_pGq;oVoN1` zGrxwH|Ms#o&(yNr_3Yc0M-jT$1798GKa6SEu5;+AMfO$RnN-+$_!st{NThLVWIUcQfX913UBD#SnZB9p-ypPF8ys3vWNpOE zaub&Z+4%COA2Z>XPL5d{J|l41Ya@YKK+d{-T}xDb(jyPLy2}r)J_s4V%W!jdn_KOl z{o>2DHuPoMleztm*(Z}`K|064tMwBHZ$XZ)6ABm)4LP8%LL7LPX;?x<`r2KTIMdneY*WB4tmzbQ&XJ! z0xzE{zMsVxmECBHnO2ooVi`Q8*|~jB+U(w{rsQ>1%gQS6abKD4OGcBkdyi&rI&EMx zo3|=w-nr6KK06avTTPR3f+xH*;?@OH^Os_kKXf)f!b6L2n>4Emw>@yS&J z!3TPUW>^KF2ThBpXmlz}lgnu%Ei^bk5s(ZA^tTq8Fz_!x3&AwX1T~8B6EOvDKaxU> zey~?1sN?kMh*26Ahsgm{1H95lx%3MV2tQa55=doomEH=7Jqn4-Bp<~Z6&ul`PiJHx z!2AR6DD?Z>^BH*CZfB!VyH7kA`&wI73xMoFcFg?Vk2Ud4ZFf3hMS&B zjB*wz)p7(3r%aAWF`7yt)prnrb9{sWTrz_Se{2!PA-Dt>aLIu(MS}KYN0>~Gh2jXI zCf$|EfLSaS9cH_@FVtc$cY9?#Kd|> zz;37ujYbqw49xH0f_mRB`@6w%!Ccs`V00L+bTC+$gh635BrFOdLERW^I>S|jBBR+g zN(r8Xs4*WY$P{D)3P_&~W|Dq8hl!yi z86FK0+qsBuCw>7y_5r>=VQ%Nq6}F%8NCSg|bvA__mKIZII2=i*U8sRg49Am5QD-N{ U-iVqN2jHXtevog){1vPI2OWA6j{pDw literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_10.png b/res/content/base/textures/cracks/cracks_10.png new file mode 100644 index 0000000000000000000000000000000000000000..8253dd6d988a667399ed4839beb2f3fe2a7dd218 GIT binary patch literal 4904 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 Js+YuX{u4*6PXzz~ literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_2.png b/res/content/base/textures/cracks/cracks_2.png new file mode 100644 index 0000000000000000000000000000000000000000..d13052d2cdba2f20531ad7a134d38f07417efd81 GIT binary patch literal 5018 zcmeHKdsq`!77uEL0=6O#!RHXbqBzN9l8|I1ASNLo1S6oLtE`jB1OntiGK7Fykzzqn zK>d7HeBuK|TtyeF_$;d{s0g)Kb@5fcO2w*3yJ$t(I{_8G?LU6I{%7W!Waiv+e&?Lu zJ@@3^Wy)yz5XTXY3BTC#`&|? zKd3T@g+f5#nae6Vs(RhM<`*jv!cM9HK9+w&g$*g5c4@zX+oamB4d|KU~Z z5B&aj@gDfu1NO4Crl@ts=uwwVXK#weNrGQGQ#@8(aqzG#r;4`7wJxq(rwmK;xG}x9 z%df21^~$l&lq({ARl<7sN{xJ*)FJ;!s+@oOV%LUm5(`fWPgNdp_~NI{wPW{+om!3t zKXzZ_eTOv0c2pbw8PK%h$&2--#=5KN5`9QlLuJ*ij)H%+SPq$gv+MM1zHpOgnI0R) zdUpHT(X~f&ZgVP+ZK?J2Fi-vg^Dw(P7x4qH#T5-HvCN;BfA&k|j_9?6OH%aLhN|wb z8NxL?O^j^KjytC4@*nIxA~mM8VCU4E`?mWoyfCFsH~aC3%tzjqoC&TgT*kb(?z3=K z+KL;I(uOBy09n%7u)OufXz zf5Ol5>uY}3F~;Yl$dJ}bDQAs8DOFzz%avk`8M%e}mVtx9*G|f5@m+0a-)wisdOoS_ z@H5GZs(q!<1g~EoLUDEhezI5brfbR>4W;{LE9Mn6P0X|;Tv_*^?b}W9=+RWonDY4a z_Lhe?E;kokKPP+oM^jEPoG`V_Jvw0Gte|<@m2GG9M*VWtXRPJ<^mEfk*6!K08y2M8 zp1Qx}1jVz~Hy`h8Y>W6}>Mv1yw!ApYrRUKcBSp z$rXd7?{)g5w-=FH*gfF8zsl=tTE+L*?`AOUaK!gyU5n;Wq4(t# z`-4xXv9cyUjcTYZeUL9xmHl`=d1U44U9QuHUEnouTjri7CU! zoqtuDG@x~1T5}N&9d_a+SG-*G==e%ksLOe-7u+2-dc$kqlTD2(`Q$r+#hSdex0`^(wR$o0 z$%)fUNUIhzXYmz?!YCn=wBcDMGBztZj>t+OL~3S8uw#%F0{}Xb!Xc|JRd2?uVx|oj z1JAUW&4g?!REn4xuTVk~gNcNAEFKGiWmc^PWd=J!K_;~Zi;;%)LV!0hGl`;%7@M7u zk-^H~vJ9p~Hb*29u@RJwqA<{a&6#=%x59d}4-L_SAtlX(No%CE20cV$;wnQrC1x_g zIP@kyol&893$Hi#vHM5VT5NhJBy)oUCYD-5=u*pDfPLDEnFoTUXgA^`{IqZ$>g(FjnOr@;wWg=&N_ zm&+F*s7Ry|kwhPeX(lbGN<6i1R5X+tKoKgHkPwmrSfoa{Fb_vHu!@VTVYN`L<_oz5 zkEh|;pwt8wW-#e+Fr8W*o=CEd`b66RO*j^+j1V(X7V=J_OvNb;Fc34NwEA@GyMZ{Z zj*O*nnoW*?iz0!6fhb2P;P3+l@04beCNro+8k2*txIMV^v|u0^KrBwzDFCopfLt(% ziNq;`Db8R>6*K9OAllMa-cV4_q=akDKqHf`_}-e2CDVG|dX_+{);0t|wz9==qQ{9D zw~%U^BVgAvL?q$*L=vp;-hz4~*Z#?5aZr*Jaso9lUnJtgyg&qpMO;(`s{_@zhKH&U zKy`m~vq3{;;3hIO5o8Lo0R?2s2J*L2IljMkMiNQ$grGc_!+}vG4&h=P9>zxlzypFX z*&jYdR7esCSHpw(LXH6Dk!T={3wSCRCpaX@=khfiO<@0^|JM|G7*~KHoc<{WvFXP3 zW>SOL|26GB3Vk{qpr%I#Iw)w!?6)1cmovIjKH#Uf+&-WO0R7R)d-3~`u8(xR7X$C5 z{IR+|()C^pyqEIF>iWOY<@oMQN9w^wF9V#|+`~&-z-e!=DpD?Gbko^igPd>FojGI7j#>Zc oAA2?yJ0*L0d6mf5xU95eG;n>3#>IP%0Vs?JS+ulb%KV)F0G7j3od5s; literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_3.png b/res/content/base/textures/cracks/cracks_3.png new file mode 100644 index 0000000000000000000000000000000000000000..40275992bb1f1b460471b9e1aa6ecb463378cfe3 GIT binary patch literal 4798 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 literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_4.png b/res/content/base/textures/cracks/cracks_4.png new file mode 100644 index 0000000000000000000000000000000000000000..ced0d18925c30bbb02dbba10f8ed50276a827690 GIT binary patch literal 5050 zcmeHKc~}$I7LTAtSyVtlpIF8K3dKn#lZ7M_5JP|n0R*bZr<7ze38Q2o8A-scQbmCR zf-BX!6nTImR?%7&iz_b3qg7lgqSpEeRb0`E8@!tU3Saw=-+TUN=9}csx##@OJ->7A z$=s}{h!A_5f7wtd6njZ%P&D`*VZMh92H$S&T`~&A+C4osj*ONWA)Q{UB$9E6Ow-{I zZX%Qvis{;e^PXhtIJq9Sg%NtuhW>XuF!28)DkPTeJC;r|rHe)0qK> zHdkn^Lmg)OWCU*U%q|M@cBf%nn#Y9!Wi*m>cY~(vxbEOFvA~YkI;^9X6&$v9t((01 z3(rB*&nC^JZnKH=_P%$zusCx^_Jl9$=iZCor#xHLuK&^R%Z5uQ3(Ij7PAk}dc)2FEf&(D{Bw|HIEur=3K6=df5O|o;t8#i97eRZ*e+L#pchj{Mi z*QEB*RdoaFuVh6iq1r6U^(pozqpq%=MNZ3_c<`*Aldn zcx-x~>(vAMv!mU~H!h<)t(G>NY}>`F$)QjNEF(msD2YhayIsI0*|exY7%-JnLF@B@=;Db2bH5*?2le4_7+5{__~YFBtX*)U^W z%#e!R3+`<{l+#{u>*s)-GwYh{hDc7b&hK-*J^yyO^z@zT$Vqz(zjxT;lpjw9-VUkU z>0gsVPoMNS{MU2aTULtY4 zc6*Xl>%x@gd>ORYmOZ!f^`f>zxlYgpvFlVWKt(<3<8soX2BJJ zv02QZK^7Hqo{$zNje;MK2+BZF7-+zTGz}>;!5V|R8KN5_2sdDQLPru>4P?fY$+h!IA&my+ zq2BeWbyDd&c#WZl1;7WxB-1gNbcCT+Gx}N>NO39v=~>V}S{P!%zW^f|H)!YUF7lf*%FQdW8lfS8mJn8S7tw#ArfiSI}0-fDnhNZSOK#8X_AEUJz4$M zW}dNx({~}j{2gvT?cUfe%0Nph6$EK9(5N+}BuGdz`xhv*7@-hYhHMTC^Ee!o$7kbxpd=atDbrxM847^Y34nw8;&PO!vm$0 zrQ!;UBVgA(g(b-}Dje+Zo`UL?6aSDbB@+kf<|<%5SI&po2!g_V9v7rd&PJ4cM6N_p zd4F_+R!JIVdOT1CA_dWa0v%nVHAl)SOO+0VEg)j0fNvN zA3sE%48eW*Y!=MnBTAT!@!2pRln=~9IBcBDL0BACcS*k^@P7@FEnxWyP*(pC{TSxP z)tgj5#^2K3t2M8r(KCV*o9o7{1Hfr-uskdzh|*=gwjL>64J1Q# zp|cDW3ffeR##Wo{*F6EWyI)+aWyQu)k!CT>m4tSpi+o-iM+br Rs~&ivNW>9Al~WTl{tGdGUETly literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_5.png b/res/content/base/textures/cracks/cracks_5.png new file mode 100644 index 0000000000000000000000000000000000000000..3db95bf439c3f5699f39408d3de3994d8af2e8c3 GIT binary patch literal 5062 zcmeHKc~}$I7LS5OBWf#~qLd+s(&{9Wjbs90k%SN-5CIi=eyuZ;NeGgKWPk*%`+}l^ zv@UI}6$AxAP{F$5!n6A7T9x|TaG|#3iB(+s(2CkS0TtitKYs7|pP6rxnRCzioqK-g z+>?73s}mFhn7&K~gE2rED@y{u@6&hR_rSORgXb87;S!jal1e3Exscgn(&{rwh_ahW zh_vao42JE}Z>!^qZw9+B>{yF0pFLv!;VfiL{_ZIMSu<-yXL%gcj(cCOy? z`*+e!@cmZK;;i%WtIP?*Pg)LLLPti2KXIo7?Bhk@gY){=w8gFbz~kGogR{IZjz88J zR9WP4YS%#Z(zp?L+uDgOfohhkEbY4uzIQb7u%XC?eHsA*lF`)U3i zOZFGtDUvn)Bl;{;^p5S%Z--37tlXuPhWb6F!=7R_$biF zZn|~pSX$KGHIt_#lI{iQ`V7AUl)3Pz@34%`M;9i9Ze<^y8WB8x)3|x3grbbT+m!lb#i_a3jA(#JKs{NlDlzJ={bRve+^gwcO!|36GqevO6#~fi=|pqhI?n-O^Pb zkB&HOs~X2FEk08-aIDwXq@GT(Z>t zx~2Zo?l{G~jw@THa~jrBrC*$)Zhe^;`gDxWFL*~l-~c~+>X7hb6`~!>e&2L&P{o;z zM+%x!>c93a)2{CKRjtQ2CnA@6^x8GYH@{@-s5-|NgA*;E58bbDFiF=+kAzK1ch_^u z>UqYTuct(MKld>nnvwPM^KtBW>e`47{?1Rww>=nr#(SG$*r~FZsEz@{R{G6))HzeS z=s@zLJDnj9dtR4^6?0=8k2pwYpLM4X-l|O~&?Agyb2Y^aAg!a5ZhA@I|6r_p zabu=+;;Q7n)wR=amF+2bP0do~(#ts7Qr>XV-~esysUEbiR8_o$Fd5jG#)Ok>o52j)8-o!RVKZaIG?IdF zQl~dcS$FpyU_p9~lr>4HLR98xGF=~=XCagG5>kk~X#}caMT9fMY!U!qASn#888VGl ziA~CK;!40XE#|NwrwTPq%1TwKp=gtZgam8>8-e9EeGZQm&V<4&8m%Nr7Sjy@-lVK_ ziZV+$oZQ@8b}pZ7vgkNm6h%1*kHh1^Km)egjTB~sjn+UKq6>vn`phgouPRbw7@{hiq{*n zZLbDW^ae7S!e}9j~dFo0N$u2TTu zv;eV4qAeswnJg(LQ>K(fPYI$eo#hRMbtNTMZv`55y5hTQKAFtwdh1#OnR@3C1UbuA zf)QO#tXK}&#R0JE8Y0p$qmBgYySt!X$n}4bEG{m@Lc|yjbFmOU$Tv?5i!qW1i^L=@ z)@XzpKB{$w@eeadR;p=ouqj}cmkNqg?UH{!jo`? z5m6Nh#K0RVzpJiybiEM+Z>0RLy8dr;F<+hONF&(j<$@C%e_HEPaN2thk5kAP&*^J@ z!=}%Hq@Ou8AE2aF%A!)l$4?eVF%LrSu65;uJpN!O?vHbv-Z-ixzj8||B6116 z_`UFNd9%e{XL}nDq}FhHohjHb>UeRIJ#JhrV}QDdYI@T9N@!)H%JanShiiA)=eXZ2 osf8PFgg=zDPYx^pvh8G_w)3ezKkRCl4?HrI@&sAU*r{{>1Z`<&umAu6 literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_6.png b/res/content/base/textures/cracks/cracks_6.png new file mode 100644 index 0000000000000000000000000000000000000000..1eda5a644e4e08b5b7f89830a8c39c0c9e4b9ab9 GIT binary patch literal 4846 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 literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_8.png b/res/content/base/textures/cracks/cracks_8.png new file mode 100644 index 0000000000000000000000000000000000000000..79669ab131e86074456f240d204a4c5479e004e8 GIT binary patch literal 4872 zcmeHKX;f3!77o%S$Rslg`nU$g0WuFHfq)PYA_O8(1yt%yauY6+f#gC$z>2e|Oe$)X zsvs&9q)(hGDq6KrQ5+~mTZ>ciiK0009H3c{?6Xt-sj|; zJaKfmt(ChKfk3boMuf(KUwizv90|TXd*8wYg1MJ5J^_n`^^iuZmZND1gk@SX>qs@`)JEz#Jd|4_f$epZ8G)i@%I`SX0xprYg(VSiGloLE@(6f#(XW z?iB`wzcRN77fqMg0EOd-+L6-WW9;?e&5wZbvrndw!U| zm-Or&B`>`_YLg~PWb+kSC$(s&5AcYs%-TC%2U^S;fh<6{;?)I*Bn3-v?{8eW^}+tKpX_R^Y1c;2Y^!SBscXr14~fdDgXO9v z$f)r}R(`i8JDZQRWlwFL_PN3z4FE!bUA=^0tz{>`+l@vQ2qg;%ytx^(gUFVAxLbDSdgY-+i%%%z&VeIEbV z(d?&5-&rQ#OuD@HhsddiPNOUCuG#D3oXUSyR5a#SD?3k8CA(*;bD(nZDmh%;j66)|zU%UvuO zt2wgDXxGrNafhtJD(zEO%pM<={D+0eM!06}u3Jf(CyMA6- z69ikxCnku*kU*_PASRhfrjo)8XeON)XaxmmWpZ9@=!`)M@Wv;mV3>wSq3HE`vYtU! zYZVk4m&>J4=@dGh1P~-$mI{LnB$dt!rx@S}MRZavs=-jT3c@*Ii8=%06N#W7dgq@~ zBN7eKt8{}Z06i!MSVN(asT8G>GTcIkg=GSgL5Kd0aOP@rF}4DxKJb>vcM%!ph}I&3W)sy5<}(h#rnWEyvG#I za7Tdo5bp=*cd?tm03{OfLeA@W2c@TMlp}mW;tBF(nLy#HGV55)-ES zaanARADadbqlnR>peo_C;a=fXGC;*;OIU0=8zCVaIS2QKMdETeRKSODxpEm>BIn3V zR5B@VhFYtHK{`<-tUxFlmBQ443(gA`3;9Gknfks(oCafZV8ACvp{fkS`;K^2iNs+r zt|rZoL8r3Wz+r|Ti^k!;2hB#bI#7u?Cyh#G4DjM<;elX)urOYyfWTw{V&Mt22#l$< z@oIG%pNP8z;g+WIh5`nX5`pRfA`7qh!J3al(g)rKra&5M>VhCs+45lNz#uv}6B*C| z*bQ_^Q(%<>0rPvXpx(8kf0HaaTPk76V1&e!%R!3dbc7_4_%TQf7ER8O(GZ%HIgqR& zcAZ*|>0vDrtN@XMXg~p(qJgHEq?~FBdI+sgL2#X@bS4Ru5}g`PW%3vt9@Wo>%HUC{ zM9N^m6ns{{i#UMtKbi!X0K=96U^mbPmKU&EQHGYQLCt^%|Kw*d7yslC5cFw~kJ9&( zT%Y9nCR0)xA?X5 z#NG{{Wt1i&QAZ$PG#cBHnZ_qRr3roNRY9+pJCYZK! zhz!!BSPF!1=jJT2a|58Y!qDJ&&iUQ3!FH!0%UwZ?r}MYxxa9>&-R2h&>esCmm&Gri zLUTZgt-h|_*^1?hyq`KBZzwT7Qv}8})>0dKRJ<-(!RnpCghk1&ME98yX5xKG1ir_V zZ1tfB_7}>=7<@mk?%s1M`f46`9QK0c^P=Ix{BP2fE{TzAGbD$bJ%nw235L3D&-<05 Yd$MeM6lbi-z%7C>EIPC{WWmzE0IJk7$N&HU literal 0 HcmV?d00001 diff --git a/res/content/base/textures/cracks/cracks_9.png b/res/content/base/textures/cracks/cracks_9.png new file mode 100644 index 0000000000000000000000000000000000000000..18eb1a5364c961a4be3d103f711e13b7e64f8317 GIT binary patch literal 4877 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 literal 0 HcmV?d00001 From eb9a89ed9619f899d4eadcd6eaace6b65c4689d6 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 06:56:48 +0300 Subject: [PATCH 05/14] fix first console open --- res/layouts/console.xml.lua | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/res/layouts/console.xml.lua b/res/layouts/console.xml.lua index 679645b7..7d4c2771 100644 --- a/res/layouts/console.xml.lua +++ b/res/layouts/console.xml.lua @@ -202,9 +202,8 @@ function on_open(mode) debug=document.s_debug }, function (mode) set_mode(mode) - end, "console") - end - if mode then + end, mode or "console") + elseif mode then modes:set(mode) end end From 02578a62763f563057e58ef84fd5b9109adfc348 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 07:49:21 +0300 Subject: [PATCH 06/14] simplify local modules loading --- res/scripts/stdmin.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/res/scripts/stdmin.lua b/res/scripts/stdmin.lua index 924c235f..14479c7d 100644 --- a/res/scripts/stdmin.lua +++ b/res/scripts/stdmin.lua @@ -292,6 +292,10 @@ function __load_script(path, nocache) end function require(path) + if not string.find(path, ':') then + local prefix, _ = parse_path(debug.getinfo(2).source) + return require(prefix..':'..path) + end local prefix, file = parse_path(path) return __load_script(prefix..":modules/"..file..".lua") end From e842b217da5eae5eaf8e756b09668f50234c2b2e Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 11:10:05 +0300 Subject: [PATCH 07/14] add 'args' parameter to hud.show_overlay --- doc/en/scripting/builtins/libhud.md | 4 +++- doc/ru/scripting/builtins/libhud.md | 4 +++- src/frontend/hud.cpp | 15 ++++++++++----- src/logic/scripting/lua/libs/libhud.cpp | 6 ++++-- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/doc/en/scripting/builtins/libhud.md b/doc/en/scripting/builtins/libhud.md index 4beb5d93..963e428c 100644 --- a/doc/en/scripting/builtins/libhud.md +++ b/doc/en/scripting/builtins/libhud.md @@ -24,7 +24,9 @@ hud.open_block(x: int, y: int, z: int) -> int, str ```lua -- Show overlay with layout specified. -- Shows player inventory also if playerinv is true. -hud.show_overlay(layoutid: str, playerinv: bool) +-- Using `args` you can specify an array of parameter values ​​that will be passed +-- to on_open of the overlay being shown. +hud.show_overlay(layoutid: str, playerinv: bool, [optional] args: table) -- Add element to the screen. -- The element will be removed on world close only. diff --git a/doc/ru/scripting/builtins/libhud.md b/doc/ru/scripting/builtins/libhud.md index ae5a69c3..4bf14d99 100644 --- a/doc/ru/scripting/builtins/libhud.md +++ b/doc/ru/scripting/builtins/libhud.md @@ -25,7 +25,9 @@ hud.open_block(x: int, y: int, z: int) -> int, str ```lua -- Показывает элемент в режиме оверлея. -- Также показывает инвентарь игрока, если playerinv - **true**. -hud.show_overlay(layoutid: str, playerinv: bool) +-- Через args можно указать массив значений параметров, что будут переданы +-- в on_open показываемого оверлея. +hud.show_overlay(layoutid: str, playerinv: bool, [опционально] args: table) -- Добавляет постоянный элемент на экран. Элемент не удаляется при -- закрытии инвентаря. Чтобы не перекрывать затенение в режиме diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index 889b102f..f81a4c26 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -233,7 +233,7 @@ void Hud::processInput(bool visible) { showOverlay( assets->get("core:console"), false, - std::string("console") + dv::list({std::string("console")}) ); } if (!Window::isFocused() && !pause && !isInventoryOpen()) { @@ -470,7 +470,7 @@ void Hud::showExchangeSlot() { } void Hud::showOverlay( - UiDocument* doc, bool playerInventory, const dv::value& arg + UiDocument* doc, bool playerInventory, const dv::value& args ) { if (isInventoryOpen()) { closeInventory(); @@ -483,7 +483,7 @@ void Hud::showOverlay( inventoryOpen = true; } add(HudElement(hud_element_mode::inventory_bound, doc, secondUI, false), - arg); + args); } void Hud::openPermanent(UiDocument* doc) { @@ -515,13 +515,18 @@ void Hud::closeInventory() { cleanup(); } -void Hud::add(const HudElement& element, const dv::value& arg) { +void Hud::add(const HudElement& element, const dv::value& argsArray) { gui->add(element.getNode()); auto document = element.getDocument(); if (document) { auto invview = std::dynamic_pointer_cast(element.getNode()); auto inventory = invview ? invview->getInventory() : nullptr; - std::vector args {arg}; + std::vector args; + if (argsArray != nullptr) { + for (const auto& arg : argsArray) { + args.push_back(arg); + } + } args.emplace_back(inventory ? inventory.get()->getId() : 0); for (int i = 0; i < 3; i++) { args.emplace_back(static_cast(blockPos[i])); diff --git a/src/logic/scripting/lua/libs/libhud.cpp b/src/logic/scripting/lua/libs/libhud.cpp index 17e1211a..460cf66b 100644 --- a/src/logic/scripting/lua/libs/libhud.cpp +++ b/src/logic/scripting/lua/libs/libhud.cpp @@ -98,7 +98,8 @@ static int l_show_overlay(lua::State* L) { if (layout == nullptr) { throw std::runtime_error("there is no ui layout " + util::quote(name)); } - hud->showOverlay(layout, playerInventory); + auto args = lua::tovalue(L, 3); + hud->showOverlay(layout, playerInventory, std::move(args)); return 0; } @@ -188,4 +189,5 @@ const luaL_Reg hudlib[] = { {"_is_content_access", lua::wrap}, {"_set_content_access", lua::wrap}, {"_set_debug_cheats", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; From f4f479d3897f0472119cea4c940b699cd374fd0b Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 12:15:09 +0300 Subject: [PATCH 08/14] move 'devtools:console' binding handler to __vc_on_hud_open --- res/scripts/stdlib.lua | 10 +++++++++- src/core_defs.hpp | 1 - src/frontend/hud.cpp | 8 -------- src/logic/scripting/scripting_hud.cpp | 2 +- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/res/scripts/stdlib.lua b/res/scripts/stdlib.lua index 7fc726f8..2c48bdfc 100644 --- a/res/scripts/stdlib.lua +++ b/res/scripts/stdlib.lua @@ -269,7 +269,7 @@ function _rules.clear() _rules.create("allow-cheats", true) end -function __vc_create_hud_rules() +function __vc_on_hud_open() _rules.create("allow-content-access", hud._is_content_access(), function(value) hud._set_content_access(value) input.set_enabled("player.pick", value) @@ -295,6 +295,14 @@ function __vc_create_hud_rules() _rules.create("allow-debug-cheats", true, function(value) hud._set_debug_cheats(value) end) + input.add_callback("devtools.console", function() + if hud.is_paused() then + return + end + time.post_runnable(function() + hud.show_overlay("core:console", false, {"console"}) + end) + end) end local RULES_FILE = "world:rules.toml" diff --git a/src/core_defs.hpp b/src/core_defs.hpp index 4a02cac9..9f26b1c8 100644 --- a/src/core_defs.hpp +++ b/src/core_defs.hpp @@ -10,7 +10,6 @@ inline const std::string CORE_STRUCT_AIR = "core:struct_air"; inline const std::string TEXTURE_NOTFOUND = "notfound"; // built-in bindings -inline const std::string BIND_DEVTOOLS_CONSOLE = "devtools.console"; inline const std::string BIND_CHUNKS_RELOAD = "chunks.reload"; inline const std::string BIND_MOVE_FORWARD = "movement.forward"; inline const std::string BIND_MOVE_BACK = "movement.back"; diff --git a/src/frontend/hud.cpp b/src/frontend/hud.cpp index f81a4c26..cc9c54d0 100644 --- a/src/frontend/hud.cpp +++ b/src/frontend/hud.cpp @@ -229,17 +229,9 @@ void Hud::processInput(bool visible) { setPause(true); } } - if (!pause && Events::jactive(BIND_DEVTOOLS_CONSOLE)) { - showOverlay( - assets->get("core:console"), - false, - dv::list({std::string("console")}) - ); - } if (!Window::isFocused() && !pause && !isInventoryOpen()) { setPause(true); } - if (!pause && visible && Events::jactive(BIND_HUD_INVENTORY)) { if (inventoryOpen) { closeInventory(); diff --git a/src/logic/scripting/scripting_hud.cpp b/src/logic/scripting/scripting_hud.cpp index a7be1892..146fe817 100644 --- a/src/logic/scripting/scripting_hud.cpp +++ b/src/logic/scripting/scripting_hud.cpp @@ -37,7 +37,7 @@ void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) { load_script("hud_classes.lua"); - if (lua::getglobal(L, "__vc_create_hud_rules")) { + if (lua::getglobal(L, "__vc_on_hud_open")) { lua::call_nothrow(L, 0, 0); } From 14b596140d50a35f54b921876063e69281c41ec2 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 13:19:49 +0300 Subject: [PATCH 09/14] add player.is_infinite_items, .set_infinite_items --- doc/en/scripting/builtins/libplayer.md | 9 ++++++++- doc/ru/scripting/builtins/libplayer.md | 7 +++++++ src/logic/PlayerController.cpp | 8 ++++++-- src/logic/scripting/lua/libs/libplayer.cpp | 19 ++++++++++++++++++- src/objects/Player.cpp | 11 +++++++++++ src/objects/Player.hpp | 4 ++++ 6 files changed, 54 insertions(+), 4 deletions(-) diff --git a/doc/en/scripting/builtins/libplayer.md b/doc/en/scripting/builtins/libplayer.md index 4ef892dd..932b17d6 100644 --- a/doc/en/scripting/builtins/libplayer.md +++ b/doc/en/scripting/builtins/libplayer.md @@ -56,12 +56,19 @@ player.set_noclip(bool) Getter and setter for player noclip mode (collisions disabled) +```lua +player.is_infinite_items() -> bool +player.set_infinite_items(bool) +``` + +Getter and setter for infinite items (not removed from inventory after use) + ``` lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number ``` -Point setter and getter added by player +Spawn point setter and getter ```lua player.get_selected_block(playerid: int) -> x,y,z diff --git a/doc/ru/scripting/builtins/libplayer.md b/doc/ru/scripting/builtins/libplayer.md index bd2e8f65..6da5028b 100644 --- a/doc/ru/scripting/builtins/libplayer.md +++ b/doc/ru/scripting/builtins/libplayer.md @@ -56,6 +56,13 @@ player.set_noclip(bool) Геттер и сеттер noclip режима (выключенная коллизия игрока) +```lua +player.is_infinite_items() -> bool +player.set_infinite_items(bool) +``` + +Геттер и сеттер бесконечных предметов (не удаляются из инвентаря при использовании) + ```lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 57af3c13..0471d080 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -461,6 +461,10 @@ void PlayerController::processRightClick(const Block& def, const Block& target) } } if (chosenBlock != vox->id && chosenBlock) { + if (!player->isInfiniteItems()) { + auto& slot = player->getInventory()->getSlot(player->getChosenSlot()); + slot.setCount(slot.getCount()-1); + } blocksController->placeBlock( player.get(), def, state, coord.x, coord.y, coord.z ); @@ -522,8 +526,8 @@ void PlayerController::updateInteraction(float delta) { auto iend = selection.position; if (lclick && !input.shift && item.rt.funcsset.on_block_break_by) { if (scripting::on_item_break_block( - player.get(), item, iend.x, iend.y, iend.z - )) { + player.get(), item, iend.x, iend.y, iend.z + )) { return; } } diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index 0d0a7223..cbd166a6 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -128,6 +128,20 @@ static int l_set_noclip(lua::State* L) { return 0; } +static int l_is_infinite_items(lua::State* L) { + if (auto player = get_player(L, 1)) { + return lua::pushboolean(L, player->isInfiniteItems()); + } + return 0; +} + +static int l_set_infinite_items(lua::State* L) { + if (auto player = get_player(L, 1)) { + player->setInfiniteItems(lua::toboolean(L, 2)); + } + return 0; +} + static int l_get_selected_block(lua::State* L) { if (auto player = get_player(L, 1)) { if (player->selection.vox.id == BLOCK_VOID) { @@ -220,6 +234,8 @@ const luaL_Reg playerlib[] = { {"set_flight", lua::wrap}, {"is_noclip", lua::wrap}, {"set_noclip", lua::wrap}, + {"is_infinite_items", lua::wrap}, + {"set_infinite_items", lua::wrap}, {"get_selected_block", lua::wrap}, {"get_selected_entity", lua::wrap}, {"set_spawnpoint", lua::wrap}, @@ -228,4 +244,5 @@ const luaL_Reg playerlib[] = { {"set_entity", lua::wrap}, {"get_camera", lua::wrap}, {"set_camera", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 5b925f58..2ab41eea 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -240,6 +240,14 @@ void Player::setNoclip(bool flag) { this->noclip = flag; } +bool Player::isInfiniteItems() const { + return infiniteItems; +} + +void Player::setInfiniteItems(bool flag) { + infiniteItems = flag; +} + entityid_t Player::getEntity() const { return eid; } @@ -273,6 +281,7 @@ dv::value Player::serialize() const { root["flight"] = flight; root["noclip"] = noclip; + root["infinite-items"] = infiniteItems; root["chosen-slot"] = chosenSlot; root["entity"] = eid; root["inventory"] = inventory->serialize(); @@ -300,6 +309,8 @@ void Player::deserialize(const dv::value& src) { flight = src["flight"].asBoolean(); noclip = src["noclip"].asBoolean(); + src.at("infinite-items").get(infiniteItems); + setChosenSlot(src["chosen-slot"].asInteger()); eid = src["entity"].asNumber(); diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 985aba55..62c818a6 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -49,6 +49,7 @@ class Player : public Object, public Serializable { std::shared_ptr inventory; bool flight = false; bool noclip = false; + bool infiniteItems = true; entityid_t eid; entityid_t selectedEid; public: @@ -86,6 +87,9 @@ public: bool isNoclip() const; void setNoclip(bool flag); + bool isInfiniteItems() const; + void setInfiniteItems(bool flag); + entityid_t getEntity() const; void setEntity(entityid_t eid); From 9e02f1122f58e1b9afd3dd02b27ccd62ea78e29f Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 14:42:53 +0300 Subject: [PATCH 10/14] add BlockWrapsRenderer (WIP) --- src/graphics/render/BlockWrapsRenderer.cpp | 103 +++++++++++++++++++++ src/graphics/render/BlockWrapsRenderer.hpp | 38 ++++++++ src/graphics/render/ChunksRenderer.cpp | 1 + src/graphics/render/WorldRenderer.cpp | 5 +- src/graphics/render/WorldRenderer.hpp | 2 + src/maths/UVRegion.hpp | 11 +++ src/world/Level.hpp | 2 +- 7 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 src/graphics/render/BlockWrapsRenderer.cpp create mode 100644 src/graphics/render/BlockWrapsRenderer.hpp diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp new file mode 100644 index 00000000..82ddf951 --- /dev/null +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -0,0 +1,103 @@ +#include "BlockWrapsRenderer.hpp" + +#include "assets/Assets.hpp" +#include "assets/assets_util.hpp" +#include "constants.hpp" +#include "content/Content.hpp" +#include "graphics/core/Atlas.hpp" +#include "graphics/core/Shader.hpp" +#include "graphics/core/DrawContext.hpp" +#include "graphics/render/MainBatch.hpp" +#include "objects/Player.hpp" +#include "voxels/Block.hpp" +#include "voxels/Chunks.hpp" +#include "window/Window.hpp" +#include "world/Level.hpp" + +BlockWrapsRenderer::BlockWrapsRenderer(const Assets& assets, const Level& level) + : assets(assets), level(level), batch(std::make_unique(1024)) { +} + +BlockWrapsRenderer::~BlockWrapsRenderer() = default; + +void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { + const auto& chunks = *level.chunks; + + auto textureRegion = util::get_texture_region(assets, wrapper.texture, ""); + + auto& shader = assets.require("entity"); + shader.use(); + shader.uniform1i("u_alphaClip", false); + + const UVRegion& cracksRegion = textureRegion.region; + UVRegion regions[6] { + cracksRegion, cracksRegion, cracksRegion, + cracksRegion, cracksRegion, cracksRegion + }; + batch->setTexture(textureRegion.texture); + + const voxel* vox = chunks.get(wrapper.position); + if (vox == nullptr) { + return; + } + if (vox->id != BLOCK_VOID) { + const auto& def = + level.content->getIndices()->blocks.require(vox->id); + switch (def.model) { + case BlockModel::block: + batch->cube( + glm::vec3(wrapper.position) + glm::vec3(0.5f), + glm::vec3(1.01f), + regions, + glm::vec4(0), + false + ); + break; + case BlockModel::aabb: { + const auto& aabb = def.rt.hitboxes[vox->state.rotation].at(0); + const auto& size = aabb.size(); + regions[0].scale(size.z, size.y); + regions[1].scale(size.z, size.y); + regions[2].scale(size.x, size.z); + regions[3].scale(size.x, size.z); + regions[4].scale(size.x, size.y); + regions[5].scale(size.x, size.y); + batch->cube( + glm::vec3(wrapper.position) + aabb.center(), + size * glm::vec3(1.01f), + regions, + glm::vec4(0), + false + ); + break; + } + default: + break; + } + } +} + +void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { + auto ctx = pctx.sub(); + + + batch->flush(); +} + +u64id_t BlockWrapsRenderer::add( + const glm::ivec3& position, const std::string& texture +) { + u64id_t id = nextWrapper++; + wrappers[id] = std::make_unique( + BlockWrapper {position, texture} + ); + return id; +} + +BlockWrapper* BlockWrapsRenderer::get(u64id_t id) const { + const auto& found = wrappers.find(id); + if (found == wrappers.end()) { + return nullptr; + } + return found->second.get(); +} diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp new file mode 100644 index 00000000..3cb21cba --- /dev/null +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include +#include +#include + +#include "MainBatch.hpp" +#include "typedefs.hpp" + +class Assets; +class Player; +class Level; +class DrawContext; + +struct BlockWrapper { + glm::ivec3 position; + std::string texture; +}; + +class BlockWrapsRenderer { + const Assets& assets; + const Level& level; + std::unique_ptr batch; + + std::unordered_map> wrappers; + u64id_t nextWrapper = 1; + + void draw(const BlockWrapper& wrapper); +public: + BlockWrapsRenderer(const Assets& assets, const Level& level); + ~BlockWrapsRenderer(); + + void draw(const DrawContext& ctx, const Player& player); + + u64id_t add(const glm::ivec3& position, const std::string& texture); + + BlockWrapper* get(u64id_t id) const; +}; diff --git a/src/graphics/render/ChunksRenderer.cpp b/src/graphics/render/ChunksRenderer.cpp index d3686a86..78ed45bf 100644 --- a/src/graphics/render/ChunksRenderer.cpp +++ b/src/graphics/render/ChunksRenderer.cpp @@ -236,6 +236,7 @@ void ChunksRenderer::drawSortedMeshes(const Camera& camera, Shader& shader) { const auto& cameraPos = camera.position; const auto& atlas = assets.require("blocks"); + shader.use(); atlas.getTexture()->bind(); shader.uniformMatrix("u_model", glm::mat4(1.0f)); shader.uniform1i("u_alphaClip", false); diff --git a/src/graphics/render/WorldRenderer.cpp b/src/graphics/render/WorldRenderer.cpp index 30284187..7084d2de 100644 --- a/src/graphics/render/WorldRenderer.cpp +++ b/src/graphics/render/WorldRenderer.cpp @@ -41,6 +41,7 @@ #include "graphics/core/Shader.hpp" #include "graphics/core/Texture.hpp" #include "graphics/core/Font.hpp" +#include "BlockWrapsRenderer.hpp" #include "ParticlesRenderer.hpp" #include "TextsRenderer.hpp" #include "ChunksRenderer.hpp" @@ -80,7 +81,8 @@ WorldRenderer::WorldRenderer( *frustumCulling, frontend.getContentGfxCache(), engine->getSettings() - )) { + )), + blockWraps(std::make_unique(assets, level)) { auto& settings = engine->getSettings(); level.events->listen( EVT_CHUNK_HIDDEN, @@ -170,6 +172,7 @@ void WorldRenderer::renderLevel( setupWorldShader(shader, camera, settings, fogFactor); chunks->drawChunks(camera, shader); + blockWraps->draw(ctx, *player); if (hudVisible) { renderLines(camera, linesShader, ctx); diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index b94694bd..94105726 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -17,6 +17,7 @@ class Batch3D; class LineBatch; class ChunksRenderer; class ParticlesRenderer; +class BlockWrapsRenderer; class GuidesRenderer; class TextsRenderer; class Shader; @@ -39,6 +40,7 @@ class WorldRenderer { std::unique_ptr lineBatch; std::unique_ptr batch3d; std::unique_ptr chunks; + std::unique_ptr blockWraps; std::unique_ptr guides; std::unique_ptr skybox; std::unique_ptr modelBatch; diff --git a/src/maths/UVRegion.hpp b/src/maths/UVRegion.hpp index 75b0ab6b..019c8760 100644 --- a/src/maths/UVRegion.hpp +++ b/src/maths/UVRegion.hpp @@ -40,4 +40,15 @@ struct UVRegion { float h = getHeight(); return glm::vec2(u1 + uv.x * w, v1 + uv.y * h); } + + void scale(float x, float y) { + float w = getWidth(); + float h = getHeight(); + float cx = (u1 + u2) * 0.5f; + float cy = (v1 + v2) * 0.5f; + u1 = cx - w * 0.5f * x; + v1 = cy - h * 0.5f * y; + u2 = cx + w * 0.5f * x; + v2 = cy + h * 0.5f * y; + } }; diff --git a/src/world/Level.hpp b/src/world/Level.hpp index c88a1617..767844cf 100644 --- a/src/world/Level.hpp +++ b/src/world/Level.hpp @@ -72,7 +72,7 @@ public: } template - std::shared_ptr getObject(uint64_t id) { + std::shared_ptr getObject(uint64_t id) const { static_assert( std::is_base_of::value, "T must be a derived of Object class" From 005bcfb43610c14a1f80fe3d484d68b6db888d1a Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 20 Nov 2024 18:03:39 +0300 Subject: [PATCH 11/14] minor controllers refactor --- src/logic/BlocksController.cpp | 54 ++++++++++++++++------------------ src/logic/BlocksController.hpp | 8 ++--- src/logic/ChunksController.cpp | 36 +++++++++++------------ src/logic/ChunksController.hpp | 8 ++--- src/logic/LevelController.cpp | 8 ++--- 5 files changed, 56 insertions(+), 58 deletions(-) diff --git a/src/logic/BlocksController.cpp b/src/logic/BlocksController.cpp index b0362fd9..01679546 100644 --- a/src/logic/BlocksController.cpp +++ b/src/logic/BlocksController.cpp @@ -14,10 +14,10 @@ #include "world/Level.hpp" #include "world/World.hpp" -BlocksController::BlocksController(Level* level, uint padding) +BlocksController::BlocksController(const Level& level, uint padding) : level(level), - chunks(level->chunks.get()), - lighting(level->lighting.get()), + chunks(*level.chunks), + lighting(*level.lighting), randTickClock(20, 3), blocksTickClock(20, 1), worldTickClock(20, 1), @@ -34,8 +34,8 @@ void BlocksController::updateSides(int x, int y, int z) { } void BlocksController::updateSides(int x, int y, int z, int w, int h, int d) { - voxel* vox = chunks->get(x, y, z); - const auto& def = level->content->getIndices()->blocks.require(vox->id); + voxel* vox = chunks.get(x, y, z); + const auto& def = level.content->getIndices()->blocks.require(vox->id); const auto& rot = def.rotations.variants[vox->state.rotation]; const auto& xaxis = rot.axisX; const auto& yaxis = rot.axisY; @@ -62,8 +62,8 @@ void BlocksController::breakBlock( onBlockInteraction( player, glm::ivec3(x, y, z), def, BlockInteraction::destruction ); - chunks->set(x, y, z, 0, {}); - lighting->onBlockSet(x, y, z, 0); + chunks.set(x, y, z, 0, {}); + lighting.onBlockSet(x, y, z, 0); scripting::on_block_broken(player, def, glm::ivec3(x, y, z)); if (def.rt.extended) { updateSides(x, y, z , def.size.x, def.size.y, def.size.z); @@ -78,8 +78,8 @@ void BlocksController::placeBlock( onBlockInteraction( player, glm::ivec3(x, y, z), def, BlockInteraction::placing ); - chunks->set(x, y, z, def.rt.id, state); - lighting->onBlockSet(x, y, z, def.rt.id); + chunks.set(x, y, z, def.rt.id, state); + lighting.onBlockSet(x, y, z, def.rt.id); scripting::on_block_placed(player, def, glm::ivec3(x, y, z)); if (def.rt.extended) { updateSides(x, y, z , def.size.x, def.size.y, def.size.z); @@ -89,12 +89,12 @@ void BlocksController::placeBlock( } void BlocksController::updateBlock(int x, int y, int z) { - voxel* vox = chunks->get(x, y, z); + voxel* vox = chunks.get(x, y, z); if (vox == nullptr) return; - const auto& def = level->content->getIndices()->blocks.require(vox->id); + const auto& def = level.content->getIndices()->blocks.require(vox->id); if (def.grounded) { const auto& vec = get_ground_direction(def, vox->state.rotation); - if (!chunks->isSolidBlock(x + vec.x, y + vec.y, z + vec.z)) { + if (!chunks.isSolidBlock(x + vec.x, y + vec.y, z + vec.z)) { breakBlock(nullptr, def, x, y, z); return; } @@ -117,12 +117,11 @@ void BlocksController::update(float delta) { } void BlocksController::onBlocksTick(int tickid, int parts) { - auto content = level->content; - auto indices = content->getIndices(); + const auto& indices = level.content->getIndices()->blocks; int tickRate = blocksTickClock.getTickRate(); - for (size_t id = 0; id < indices->blocks.count(); id++) { + for (size_t id = 0; id < indices.count(); id++) { if ((id + tickid) % parts != 0) continue; - auto& def = indices->blocks.require(id); + auto& def = indices.require(id); auto interval = def.tickInterval; if (def.rt.funcsset.onblockstick && tickid / parts % interval == 0) { scripting::on_blocks_tick(def, tickRate / interval); @@ -155,9 +154,9 @@ void BlocksController::randomTick( } void BlocksController::randomTick(int tickid, int parts) { - auto indices = level->content->getIndices(); - int width = chunks->getWidth(); - int height = chunks->getHeight(); + auto indices = level.content->getIndices(); + int width = chunks.getWidth(); + int height = chunks.getHeight(); int segments = 4; for (uint z = padding; z < height - padding; z++) { @@ -166,7 +165,7 @@ void BlocksController::randomTick(int tickid, int parts) { if ((index + tickid) % parts != 0) { continue; } - auto& chunk = chunks->getChunks()[index]; + auto& chunk = chunks.getChunks()[index]; if (chunk == nullptr || !chunk->flags.lighted) { continue; } @@ -176,7 +175,7 @@ void BlocksController::randomTick(int tickid, int parts) { } int64_t BlocksController::createBlockInventory(int x, int y, int z) { - auto chunk = chunks->getChunkByVoxel(x, y, z); + auto chunk = chunks.getChunkByVoxel(x, y, z); if (chunk == nullptr) { return 0; } @@ -184,21 +183,20 @@ int64_t BlocksController::createBlockInventory(int x, int y, int z) { int lz = z - chunk->z * CHUNK_D; auto inv = chunk->getBlockInventory(lx, y, lz); if (inv == nullptr) { - auto indices = level->content->getIndices(); - auto& def = - indices->blocks.require(chunk->voxels[vox_index(lx, y, lz)].id); + const auto& indices = level.content->getIndices()->blocks; + auto& def = indices.require(chunk->voxels[vox_index(lx, y, lz)].id); int invsize = def.inventorySize; if (invsize == 0) { return 0; } - inv = level->inventories->create(invsize); + inv = level.inventories->create(invsize); chunk->addBlockInventory(inv, lx, y, lz); } return inv->getId(); } void BlocksController::bindInventory(int64_t invid, int x, int y, int z) { - auto chunk = chunks->getChunkByVoxel(x, y, z); + auto chunk = chunks.getChunkByVoxel(x, y, z); if (chunk == nullptr) { throw std::runtime_error("block does not exists"); } @@ -207,11 +205,11 @@ void BlocksController::bindInventory(int64_t invid, int x, int y, int z) { } int lx = x - chunk->x * CHUNK_W; int lz = z - chunk->z * CHUNK_D; - chunk->addBlockInventory(level->inventories->get(invid), lx, y, lz); + chunk->addBlockInventory(level.inventories->get(invid), lx, y, lz); } void BlocksController::unbindInventory(int x, int y, int z) { - auto chunk = chunks->getChunkByVoxel(x, y, z); + auto chunk = chunks.getChunkByVoxel(x, y, z); if (chunk == nullptr) { throw std::runtime_error("block does not exists"); } diff --git a/src/logic/BlocksController.hpp b/src/logic/BlocksController.hpp index 86bbe395..0937b3f7 100644 --- a/src/logic/BlocksController.hpp +++ b/src/logic/BlocksController.hpp @@ -24,9 +24,9 @@ using on_block_interaction = std::function< /// BlocksController manages block updates and data (inventories, metadata) class BlocksController { - Level* level; - Chunks* chunks; - Lighting* lighting; + const Level& level; + Chunks& chunks; + Lighting& lighting; util::Clock randTickClock; util::Clock blocksTickClock; util::Clock worldTickClock; @@ -34,7 +34,7 @@ class BlocksController { FastRandom random {}; std::vector blockInteractionCallbacks; public: - BlocksController(Level* level, uint padding); + BlocksController(const Level& level, uint padding); void updateSides(int x, int y, int z); void updateSides(int x, int y, int z, int w, int h, int d); diff --git a/src/logic/ChunksController.cpp b/src/logic/ChunksController.cpp index 07492f29..f61a2755 100644 --- a/src/logic/ChunksController.cpp +++ b/src/logic/ChunksController.cpp @@ -22,15 +22,15 @@ const uint MAX_WORK_PER_FRAME = 128; const uint MIN_SURROUNDING = 9; -ChunksController::ChunksController(Level* level, uint padding) +ChunksController::ChunksController(Level& level, uint padding) : level(level), - chunks(level->chunks.get()), - lighting(level->lighting.get()), + chunks(*level.chunks), + lighting(*level.lighting), padding(padding), generator(std::make_unique( - level->content->generators.require(level->getWorld()->getGenerator()), - level->content, - level->getWorld()->getSeed() + level.content->generators.require(level.getWorld()->getGenerator()), + level.content, + level.getWorld()->getSeed() )) {} ChunksController::~ChunksController() = default; @@ -56,8 +56,8 @@ void ChunksController::update( } bool ChunksController::loadVisible() { - int sizeX = chunks->getWidth(); - int sizeY = chunks->getHeight(); + int sizeX = chunks.getWidth(); + int sizeY = chunks.getHeight(); int nearX = 0; int nearZ = 0; @@ -66,7 +66,7 @@ bool ChunksController::loadVisible() { for (uint z = padding; z < sizeY - padding; z++) { for (uint x = padding; x < sizeX - padding; x++) { int index = z * sizeX + x; - auto& chunk = chunks->getChunks()[index]; + auto& chunk = chunks.getChunks()[index]; if (chunk != nullptr) { if (chunk->flags.loaded && !chunk->flags.lighted) { if (buildLights(chunk)) { @@ -87,12 +87,12 @@ bool ChunksController::loadVisible() { } } - const auto& chunk = chunks->getChunks()[nearZ * sizeX + nearX]; + const auto& chunk = chunks.getChunks()[nearZ * sizeX + nearX]; if (chunk != nullptr || !assigned) { return false; } - int offsetX = chunks->getOffsetX(); - int offsetY = chunks->getOffsetY(); + int offsetX = chunks.getOffsetX(); + int offsetY = chunks.getOffsetY(); createChunk(nearX + offsetX, nearZ + offsetY); return true; } @@ -101,15 +101,15 @@ bool ChunksController::buildLights(const std::shared_ptr& chunk) { int surrounding = 0; for (int oz = -1; oz <= 1; oz++) { for (int ox = -1; ox <= 1; ox++) { - if (chunks->getChunk(chunk->x + ox, chunk->z + oz)) surrounding++; + if (chunks.getChunk(chunk->x + ox, chunk->z + oz)) surrounding++; } } if (surrounding == MIN_SURROUNDING) { bool lightsCache = chunk->flags.loadedLights; if (!lightsCache) { - lighting->buildSkyLight(chunk->x, chunk->z); + lighting.buildSkyLight(chunk->x, chunk->z); } - lighting->onChunkLoaded(chunk->x, chunk->z, !lightsCache); + lighting.onChunkLoaded(chunk->x, chunk->z, !lightsCache); chunk->flags.lighted = true; return true; } @@ -117,8 +117,8 @@ bool ChunksController::buildLights(const std::shared_ptr& chunk) { } void ChunksController::createChunk(int x, int z) { - auto chunk = level->chunksStorage->create(x, z); - chunks->putChunk(chunk); + auto chunk = level.chunksStorage->create(x, z); + chunks.putChunk(chunk); auto& chunkFlags = chunk->flags; if (!chunkFlags.loaded) { @@ -128,7 +128,7 @@ void ChunksController::createChunk(int x, int z) { chunk->updateHeights(); if (!chunkFlags.loadedLights) { - Lighting::prebuildSkyLight(chunk.get(), level->content->getIndices()); + Lighting::prebuildSkyLight(chunk.get(), level.content->getIndices()); } chunkFlags.loaded = true; chunkFlags.ready = true; diff --git a/src/logic/ChunksController.hpp b/src/logic/ChunksController.hpp index 8566ee1b..e9f1ab62 100644 --- a/src/logic/ChunksController.hpp +++ b/src/logic/ChunksController.hpp @@ -13,9 +13,9 @@ class WorldGenerator; /// @brief ChunksController manages chunks dynamic loading/unloading class ChunksController { private: - Level* level; - Chunks* chunks; - Lighting* lighting; + Level& level; + Chunks& chunks; + Lighting& lighting; uint padding; std::unique_ptr generator; @@ -24,7 +24,7 @@ private: bool buildLights(const std::shared_ptr& chunk); void createChunk(int x, int y); public: - ChunksController(Level* level, uint padding); + ChunksController(Level& level, uint padding); ~ChunksController(); /// @param maxDuration milliseconds reserved for chunks loading diff --git a/src/logic/LevelController.cpp b/src/logic/LevelController.cpp index 2cd491d4..bd8af15c 100644 --- a/src/logic/LevelController.cpp +++ b/src/logic/LevelController.cpp @@ -16,14 +16,14 @@ static debug::Logger logger("level-control"); -LevelController::LevelController(Engine* engine, std::unique_ptr level) +LevelController::LevelController(Engine* engine, std::unique_ptr levelPtr) : settings(engine->getSettings()), - level(std::move(level)), + level(std::move(levelPtr)), blocks(std::make_unique( - this->level.get(), settings.chunks.padding.get() + *level, settings.chunks.padding.get() )), chunks(std::make_unique( - this->level.get(), settings.chunks.padding.get() + *level, settings.chunks.padding.get() )), player(std::make_unique( settings, this->level.get(), blocks.get() From 2ba90625ce2f12633c278a1904ad752b1400994d Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 21 Nov 2024 05:02:45 +0300 Subject: [PATCH 12/14] add player.is_instant_destruction, .set_instant_destruction --- doc/en/scripting/builtins/libplayer.md | 7 +++++++ doc/ru/scripting/builtins/libplayer.md | 7 +++++++ src/logic/scripting/lua/libs/libplayer.cpp | 16 ++++++++++++++++ src/objects/Player.cpp | 10 ++++++++++ src/objects/Player.hpp | 4 ++++ 5 files changed, 44 insertions(+) diff --git a/doc/en/scripting/builtins/libplayer.md b/doc/en/scripting/builtins/libplayer.md index 932b17d6..99482c68 100644 --- a/doc/en/scripting/builtins/libplayer.md +++ b/doc/en/scripting/builtins/libplayer.md @@ -63,6 +63,13 @@ player.set_infinite_items(bool) Getter and setter for infinite items (not removed from inventory after use) +```lua +player.is_instant_destruction() -> bool +player.set_instant_destruction(bool) +``` + +Getter and setter for instant destruction of blocks when the `player.destroy` binding is activated. + ``` lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number diff --git a/doc/ru/scripting/builtins/libplayer.md b/doc/ru/scripting/builtins/libplayer.md index 6da5028b..179e6b18 100644 --- a/doc/ru/scripting/builtins/libplayer.md +++ b/doc/ru/scripting/builtins/libplayer.md @@ -63,6 +63,13 @@ player.set_infinite_items(bool) Геттер и сеттер бесконечных предметов (не удаляются из инвентаря при использовании) +```lua +player.is_instant_destruction() -> bool +player.set_instant_destruction(bool) +``` + +Геттер и сеттер мнгновенного разрушения блоков при активации привязки `player.destroy`. + ```lua player.set_spawnpoint(playerid: int, x: number, y: number, z: number) player.get_spawnpoint(playerid: int) -> number, number, number diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index cbd166a6..18b29405 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -142,6 +142,20 @@ static int l_set_infinite_items(lua::State* L) { return 0; } +static int l_is_instant_destruction(lua::State* L) { + if (auto player = get_player(L, 1)) { + return lua::pushboolean(L, player->isInstantDestruction()); + } + return 0; +} + +static int l_set_instant_destruction(lua::State* L) { + if (auto player = get_player(L, 1)) { + player->setInstantDestruction(lua::toboolean(L, 2)); + } + return 0; +} + static int l_get_selected_block(lua::State* L) { if (auto player = get_player(L, 1)) { if (player->selection.vox.id == BLOCK_VOID) { @@ -236,6 +250,8 @@ const luaL_Reg playerlib[] = { {"set_noclip", lua::wrap}, {"is_infinite_items", lua::wrap}, {"set_infinite_items", lua::wrap}, + {"is_instant_destruction", lua::wrap}, + {"set_instant_destruction", lua::wrap}, {"get_selected_block", lua::wrap}, {"get_selected_entity", lua::wrap}, {"set_spawnpoint", lua::wrap}, diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 2ab41eea..5c2a2b85 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -248,6 +248,14 @@ void Player::setInfiniteItems(bool flag) { infiniteItems = flag; } +bool Player::isInstantDestruction() const { + return instantDestruction; +} + +void Player::setInstantDestruction(bool flag) { + instantDestruction = flag; +} + entityid_t Player::getEntity() const { return eid; } @@ -282,6 +290,7 @@ dv::value Player::serialize() const { root["flight"] = flight; root["noclip"] = noclip; root["infinite-items"] = infiniteItems; + root["instant-destruction"] = instantDestruction; root["chosen-slot"] = chosenSlot; root["entity"] = eid; root["inventory"] = inventory->serialize(); @@ -310,6 +319,7 @@ void Player::deserialize(const dv::value& src) { flight = src["flight"].asBoolean(); noclip = src["noclip"].asBoolean(); src.at("infinite-items").get(infiniteItems); + src.at("instant-destruction").get(instantDestruction); setChosenSlot(src["chosen-slot"].asInteger()); eid = src["entity"].asNumber(); diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index 62c818a6..2badd9dc 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -50,6 +50,7 @@ class Player : public Object, public Serializable { bool flight = false; bool noclip = false; bool infiniteItems = true; + bool instantDestruction = true; entityid_t eid; entityid_t selectedEid; public: @@ -90,6 +91,9 @@ public: bool isInfiniteItems() const; void setInfiniteItems(bool flag); + bool isInstantDestruction() const; + void setInstantDestruction(bool flag); + entityid_t getEntity() const; void setEntity(entityid_t eid); From 61b1aa8e3d6c355bb3db4c0e4902b09278a56d60 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 21 Nov 2024 06:48:23 +0300 Subject: [PATCH 13/14] add gfx.blockwraps library & add on_player_tick world event --- src/content/ContentPack.hpp | 1 + src/graphics/render/BlockWrapsRenderer.cpp | 9 +++- src/graphics/render/BlockWrapsRenderer.hpp | 2 + src/graphics/render/WorldRenderer.hpp | 2 +- src/logic/PlayerController.cpp | 22 +++++++--- src/logic/PlayerController.hpp | 2 + src/logic/scripting/lua/libs/api_lua.hpp | 5 ++- .../scripting/lua/libs/libblockwraps.cpp | 43 +++++++++++++++++++ src/logic/scripting/scripting.cpp | 17 ++++++++ src/logic/scripting/scripting.hpp | 1 + src/logic/scripting/scripting_hud.cpp | 1 + src/voxels/Chunks.cpp | 4 +- src/voxels/Chunks.hpp | 4 +- 13 files changed, 98 insertions(+), 15 deletions(-) create mode 100644 src/logic/scripting/lua/libs/libblockwraps.cpp diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index 9d25d752..b790d0e7 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -99,6 +99,7 @@ struct world_funcs_set { bool onblockplaced : 1; bool onblockbroken : 1; bool onblockinteract : 1; + bool onplayertick : 1; }; class ContentPackRuntime { diff --git a/src/graphics/render/BlockWrapsRenderer.cpp b/src/graphics/render/BlockWrapsRenderer.cpp index 82ddf951..ddb93d3a 100644 --- a/src/graphics/render/BlockWrapsRenderer.cpp +++ b/src/graphics/render/BlockWrapsRenderer.cpp @@ -79,8 +79,9 @@ void BlockWrapsRenderer::draw(const BlockWrapper& wrapper) { void BlockWrapsRenderer::draw(const DrawContext& pctx, const Player& player) { auto ctx = pctx.sub(); - - + for (const auto& [_, wrapper] : wrappers) { + draw(*wrapper); + } batch->flush(); } @@ -101,3 +102,7 @@ BlockWrapper* BlockWrapsRenderer::get(u64id_t id) const { } return found->second.get(); } + +void BlockWrapsRenderer::remove(u64id_t id) { + wrappers.erase(id); +} diff --git a/src/graphics/render/BlockWrapsRenderer.hpp b/src/graphics/render/BlockWrapsRenderer.hpp index 3cb21cba..728e664a 100644 --- a/src/graphics/render/BlockWrapsRenderer.hpp +++ b/src/graphics/render/BlockWrapsRenderer.hpp @@ -35,4 +35,6 @@ public: u64id_t add(const glm::ivec3& position, const std::string& texture); BlockWrapper* get(u64id_t id) const; + + void remove(u64id_t id); }; diff --git a/src/graphics/render/WorldRenderer.hpp b/src/graphics/render/WorldRenderer.hpp index 94105726..c3ea72f1 100644 --- a/src/graphics/render/WorldRenderer.hpp +++ b/src/graphics/render/WorldRenderer.hpp @@ -40,7 +40,6 @@ class WorldRenderer { std::unique_ptr lineBatch; std::unique_ptr batch3d; std::unique_ptr chunks; - std::unique_ptr blockWraps; std::unique_ptr guides; std::unique_ptr skybox; std::unique_ptr modelBatch; @@ -70,6 +69,7 @@ class WorldRenderer { public: std::unique_ptr texts; std::unique_ptr particles; + std::unique_ptr blockWraps; static bool showChunkBorders; static bool showEntitiesDebug; diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index 0471d080..0ad5ef6b 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -195,7 +195,8 @@ PlayerController::PlayerController( : settings(settings), level(level), player(level->getObject(0)), camControl(player, settings.camera), - blocksController(blocksController) { + blocksController(blocksController), + playerTickClock(20, 3) { } void PlayerController::onFootstep(const Hitbox& hitbox) { @@ -249,6 +250,13 @@ void PlayerController::update(float delta, bool input, bool pause) { resetKeyboard(); } updatePlayer(delta); + + if (playerTickClock.update(delta)) { + if (player->getId() % playerTickClock.getParts() == + playerTickClock.getPart()) { + scripting::on_player_tick(player.get(), playerTickClock.getTickRate()); + } + } } } @@ -302,7 +310,7 @@ void PlayerController::updatePlayer(float delta) { } static int determine_rotation( - const Block* def, const glm::ivec3& norm, glm::vec3& camDir + const Block* def, const glm::ivec3& norm, const glm::vec3& camDir ) { if (def && def->rotatable) { const std::string& name = def->rotations.name; @@ -532,10 +540,12 @@ void PlayerController::updateInteraction(float delta) { } } auto& target = indices->blocks.require(vox->id); - if (lclick && target.breakable) { - blocksController->breakBlock( - player.get(), target, iend.x, iend.y, iend.z - ); + if (lclick) { + if (player->isInstantDestruction() && target.breakable) { + blocksController->breakBlock( + player.get(), target, iend.x, iend.y, iend.z + ); + } } if (rclick && !input.shift) { bool preventDefault = false; diff --git a/src/logic/PlayerController.hpp b/src/logic/PlayerController.hpp index 6affa43d..3fe3decf 100644 --- a/src/logic/PlayerController.hpp +++ b/src/logic/PlayerController.hpp @@ -5,6 +5,7 @@ #include #include "objects/Player.hpp" +#include "util/Clock.hpp" class Engine; class Camera; @@ -53,6 +54,7 @@ class PlayerController { PlayerInput input {}; CameraControl camControl; BlocksController* blocksController; + util::Clock playerTickClock; float interactionTimer = 0.0f; void updateKeyboard(); diff --git a/src/logic/scripting/lua/libs/api_lua.hpp b/src/logic/scripting/lua/libs/api_lua.hpp index b0edba79..12df1d66 100644 --- a/src/logic/scripting/lua/libs/api_lua.hpp +++ b/src/logic/scripting/lua/libs/api_lua.hpp @@ -18,6 +18,7 @@ extern const luaL_Reg audiolib[]; extern const luaL_Reg base64lib[]; extern const luaL_Reg bjsonlib[]; extern const luaL_Reg blocklib[]; +extern const luaL_Reg blockwrapslib[]; // gfx.blockwraps extern const luaL_Reg cameralib[]; extern const luaL_Reg consolelib[]; extern const luaL_Reg corelib[]; @@ -32,10 +33,10 @@ extern const luaL_Reg itemlib[]; extern const luaL_Reg jsonlib[]; extern const luaL_Reg mat4lib[]; extern const luaL_Reg packlib[]; -extern const luaL_Reg particleslib[]; +extern const luaL_Reg particleslib[]; // gfx.particles extern const luaL_Reg playerlib[]; extern const luaL_Reg quatlib[]; -extern const luaL_Reg text3dlib[]; +extern const luaL_Reg text3dlib[]; // gfx.text3d extern const luaL_Reg timelib[]; extern const luaL_Reg tomllib[]; extern const luaL_Reg utf8lib[]; diff --git a/src/logic/scripting/lua/libs/libblockwraps.cpp b/src/logic/scripting/lua/libs/libblockwraps.cpp new file mode 100644 index 00000000..fec1c5d7 --- /dev/null +++ b/src/logic/scripting/lua/libs/libblockwraps.cpp @@ -0,0 +1,43 @@ +#include "api_lua.hpp" + +#include "logic/scripting/scripting_hud.hpp" +#include "graphics/render/WorldRenderer.hpp" +#include "graphics/render/BlockWrapsRenderer.hpp" + +using namespace scripting; + +static int l_wrap(lua::State* L) { + auto position = lua::tovec3(L, 1); + std::string texture = lua::require_string(L, 2); + + return lua::pushinteger( + L, renderer->blockWraps->add(position, std::move(texture)) + ); +} + +static int l_unwrap(lua::State* L) { + renderer->blockWraps->remove(lua::tointeger(L, 1)); + return 0; +} + +static int l_set_pos(lua::State* L) { + if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + wrapper->position = lua::tovec3(L, 2); + } + return 0; +} + +static int l_set_texture(lua::State* L) { + if (auto wrapper = renderer->blockWraps->get(lua::tointeger(L, 1))) { + wrapper->texture = lua::require_string(L, 2); + } + return 0; +} + +const luaL_Reg blockwrapslib[] = { + {"wrap", lua::wrap}, + {"unwrap", lua::wrap}, + {"set_pos", lua::wrap}, + {"set_texture", lua::wrap}, + {NULL, NULL} +}; diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 3f3161ae..f0082a3c 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -323,6 +323,21 @@ bool scripting::on_block_interact( } } +void scripting::on_player_tick(Player* player, int tps) { + auto args = [=](lua::State* L) { + lua::pushinteger(L, player ? player->getId() : -1); + lua::pushinteger(L, tps); + return 2; + }; + for (auto& [packid, pack] : content->getPacks()) { + if (pack->worldfuncsset.onplayertick) { + lua::emit_event( + lua::get_main_state(), packid + ":.playertick", args + ); + } + } +} + bool scripting::on_item_use(Player* player, const ItemDef& item) { std::string name = item.name + ".use"; return lua::emit_event( @@ -724,6 +739,8 @@ void scripting::load_world_script( register_event(env, "on_block_broken", prefix + ":.blockbroken"); funcsset.onblockinteract = register_event(env, "on_block_interact", prefix + ":.blockinteract"); + funcsset.onplayertick = + register_event(env, "on_player_tick", prefix + ":.playertick"); } void scripting::load_layout_script( diff --git a/src/logic/scripting/scripting.hpp b/src/logic/scripting/scripting.hpp index c103a97a..ca0ea433 100644 --- a/src/logic/scripting/scripting.hpp +++ b/src/logic/scripting/scripting.hpp @@ -73,6 +73,7 @@ namespace scripting { Player* player, const Block& block, const glm::ivec3& pos ); bool on_block_interact(Player* player, const Block& block, const glm::ivec3& pos); + void on_player_tick(Player* player, int tps); /// @brief Called on RMB click with the item selected /// @return true if prevents default action diff --git a/src/logic/scripting/scripting_hud.cpp b/src/logic/scripting/scripting_hud.cpp index 146fe817..7adb5076 100644 --- a/src/logic/scripting/scripting_hud.cpp +++ b/src/logic/scripting/scripting_hud.cpp @@ -32,6 +32,7 @@ void scripting::on_frontend_init(Hud* hud, WorldRenderer* renderer) { auto L = lua::get_main_state(); lua::openlib(L, "hud", hudlib); + lua::openlib(L, "gfx", "blockwraps", blockwrapslib); lua::openlib(L, "gfx", "particles", particleslib); lua::openlib(L, "gfx", "text3d", text3dlib); diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index c27ed9e7..0942550e 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -438,7 +438,7 @@ voxel* Chunks::rayCast( glm::ivec3& norm, glm::ivec3& iend, std::set filter -) { +) const { float px = start.x; float py = start.y; float pz = start.z; @@ -571,7 +571,7 @@ voxel* Chunks::rayCast( glm::vec3 Chunks::rayCastToObstacle( const glm::vec3& start, const glm::vec3& dir, float maxDist -) { +) const { const float px = start.x; const float py = start.y; const float pz = start.z; diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index 38a5be8c..01648301 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -102,11 +102,11 @@ public: glm::ivec3& norm, glm::ivec3& iend, std::set filter = {} - ); + ) const; glm::vec3 rayCastToObstacle( const glm::vec3& start, const glm::vec3& dir, float maxDist - ); + ) const; const AABB* isObstacleAt(float x, float y, float z) const; From 3cd3fe94dec1fa422b1d02bb7f219ed29180b517 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 21 Nov 2024 07:25:31 +0300 Subject: [PATCH 14/14] update doc/*/scripting/events.md --- doc/en/scripting/events.md | 8 +++++++- doc/ru/scripting/events.md | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/en/scripting/events.md b/doc/en/scripting/events.md index ccc61673..8dcd1a06 100644 --- a/doc/en/scripting/events.md +++ b/doc/en/scripting/events.md @@ -38,7 +38,13 @@ Called on random block update (grass growth) function on_blocks_tick(tps: int) ``` -Called tps (20) times per second. +Called tps (20) times per second. Use 1/tps instead of `time.delta()`. + +```lua +function on_player_tick(playerid: int, tps: int) +``` + +Called tps (20) times per second. Use 1/tps instead of `time.delta()`. ## Item events diff --git a/doc/ru/scripting/events.md b/doc/ru/scripting/events.md index 31c958fc..6d908459 100644 --- a/doc/ru/scripting/events.md +++ b/doc/ru/scripting/events.md @@ -38,7 +38,13 @@ function on_random_update(x, y, z) function on_blocks_tick(tps: int) ``` -Вызывается tps (20) раз в секунду +Вызывается tps (20) раз в секунду. Используйте 1/tps вместо `time.delta()`. + +```lua +function on_player_tick(playerid: int, tps: int) +``` + +Вызывается tps (20) раз в секунду. Используйте 1/tps вместо `time.delta()`. ## События предметов