From 26fd32615cb9007ac8ec4bef8a9f30a9dff7e9f5 Mon Sep 17 00:00:00 2001 From: eaglercraft Date: Thu, 4 Jul 2024 00:39:59 -0700 Subject: [PATCH] u36 --- javascript/SignedBundleTemplate.txt | 3 +- .../eagler/capes/21.15th_anniversary.png | Bin 0 -> 841 bytes .../assets/eagler/capes/22.vanilla.png | Bin 0 -> 860 bytes .../assets/eagler/capes/23.tiktok.png | Bin 0 -> 855 bytes .../assets/eagler/capes/24.purple_heart.png | Bin 0 -> 1084 bytes .../assets/eagler/capes/25.cherry_blossom.png | Bin 0 -> 689 bytes .../eagler/glsl/deferred/deferred_core.vsh | 58 +- .../eagler/glsl/deferred/deferred_shadow.vsh | 49 +- .../eagler/glsl/deferred/post_lens_ghosts.vsh | 50 +- .../v1_8/internal/PlatformApplication.java | 4 + .../v1_8/internal/PlatformAssets.java | 2 +- .../v1_8/internal/PlatformRuntime.java | 6 +- .../lwjgl/DesktopClientConfigAdapter.java | 346 ++--- .../lax1dude/eaglercraft/v1_8/EagRuntime.java | 7 + .../eaglercraft/v1_8/EaglercraftVersion.java | 8 +- .../internal/IClientConfigAdapterHooks.java | 4 + .../minecraft/AcceleratedEffectRenderer.java | 4 +- .../v1_8/minecraft/EaglerFontRenderer.java | 6 +- .../v1_8/netty/ByteBufEaglercraftImpl.java | 4 +- .../eaglercraft/v1_8/opengl/ImageData.java | 16 +- .../v1_8/opengl/InstancedFontRenderer.java | 4 +- .../v1_8/opengl/WorldRenderer.java | 10 +- .../eaglercraft/v1_8/profile/CapePackets.java | 4 +- .../v1_8/profile/DefaultCapes.java | 153 +- .../v1_8/profile/GuiScreenEditProfile.java | 8 +- .../v1_8/profile/ProfileExporter.java | 12 +- .../v1_8/profile/SkinConverter.java | 20 +- .../eaglercraft/v1_8/profile/SkinPackets.java | 4 +- .../v1_8/socket/ConnectionHandshake.java | 14 +- .../eaglercraft/v1_8/sp/SkullCommand.java | 6 +- .../v1_8/sp/gui/GuiScreenLANConnecting.java | 3 + .../v1_8/sp/lan/LANServerController.java | 2 +- .../v1_8/sp/relay/pkt/IPacket.java | 2 +- .../v1_8/sp/server/EaglerChunkLoader.java | 4 +- .../v1_8/sp/server/export/EPKCompiler.java | 30 +- .../server/skins/IntegratedCapePackets.java | 6 +- .../server/skins/IntegratedSkinPackets.java | 34 +- .../IntegratedServerPlayerNetworkManager.java | 6 +- .../v1_8/update/GuiUpdateVersionSlot.java | 12 +- .../v1_8/update/UpdateCertificate.java | 13 +- .../eaglercraft/v1_8/voice/GuiVoiceMenu.java | 6 +- .../java/net/minecraft/client/Minecraft.java | 18 + .../net/minecraft/client/gui/GuiMainMenu.java | 6 +- .../minecraft/client/gui/MapItemRenderer.java | 2 +- .../renderer/entity/RendererLivingEntity.java | 6 +- .../v1_8/internal/PlatformApplication.java | 3 + .../v1_8/internal/PlatformInput.java | 4 + .../v1_8/internal/PlatformRuntime.java | 1293 +++++++++-------- .../buffer/EaglerArrayByteBuffer.java | 20 +- .../v1_8/internal/teavm/ClientMain.java | 1157 ++++++++------- .../internal/teavm/DebugConsoleWindow.java | 12 +- .../teavm/TeaVMClientConfigAdapter.java | 7 +- .../teavm/TeaVMClientConfigAdapterHooks.java | 254 ++-- .../teavm/opts/JSEaglercraftXOptsHooks.java | 3 + .../teavm/opts/JSEaglercraftXOptsRoot.java | 3 + 55 files changed, 1941 insertions(+), 1767 deletions(-) create mode 100755 resources/resources/assets/eagler/capes/21.15th_anniversary.png create mode 100755 resources/resources/assets/eagler/capes/22.vanilla.png create mode 100755 resources/resources/assets/eagler/capes/23.tiktok.png create mode 100755 resources/resources/assets/eagler/capes/24.purple_heart.png create mode 100755 resources/resources/assets/eagler/capes/25.cherry_blossom.png diff --git a/javascript/SignedBundleTemplate.txt b/javascript/SignedBundleTemplate.txt index badf239..ef983d2 100644 --- a/javascript/SignedBundleTemplate.txt +++ b/javascript/SignedBundleTemplate.txt @@ -1,4 +1,5 @@ "use strict"; +${classes_js} // %%%%%%%%% launch options %%%%%%%%%%%% @@ -26,8 +27,6 @@ if(typeof window !== "undefined") { // %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -${classes_js} - if(typeof window !== "undefined") { window.eaglercraftXOpts.enableSignatureBadge = true; window.eaglercraftXOpts.assetsURI = ${assets_epk}; } if(typeof window !== "undefined") setTimeout(() => { diff --git a/resources/resources/assets/eagler/capes/21.15th_anniversary.png b/resources/resources/assets/eagler/capes/21.15th_anniversary.png new file mode 100755 index 0000000000000000000000000000000000000000..41331f89fd15be54b63df157a327c10f464f9b59 GIT binary patch literal 841 zcmV-P1GfB$P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+HFu#4#OY_{pS=rf&x-Jj$ONCH`wuqLYunoB|d>i zo(Sxp_X{2!m>IY%Dpe#IxN^m2fhI>AoD&Zoz>qAT>Tn8ZC9<15Rf+zio=*e6nnmSe zq|Xr6S*RTT`ePI?Q=h2ETNu?aB6J~#LGy1Vsk&Uhu4(VnIWo&DQ9Z{a^3vOj3duK|E}N?O5(-MUQ`dWyrA;) zwlOd_E90fx9+`1*S;0yT|} zBX1g=v4O``=h6za>s@KE)pQ7e&zlv=+x4z&&Hsc?I2|2c7j_9~eyQ9%D|J*4gKjS~ z^No?p1wX8wOjZGad(R>?jgC|<_%z`wXKPZiss&|m(SnVwB$m;dng_0lLBG0S~OELzpxOC9ca2P3-xNtz_@z z-S^5w9_YV>0B$8!TX}r=M{!aF#0mPVd%)7{9t)*A#g72QV-bj*^L`Hq<;TV;B+e6Z z`&NwffE#{My=aZVof~WJJ&?S8AAs!-Zw8bXOZJIKKYDC?;@c+~D4@6_WOAwAL>{;*Of7-s1r-k-Jb3Wn!43WZa@iS= TFAT~D00000NkvXXu0mjfQ-pO{ literal 0 HcmV?d00001 diff --git a/resources/resources/assets/eagler/capes/22.vanilla.png b/resources/resources/assets/eagler/capes/22.vanilla.png new file mode 100755 index 0000000000000000000000000000000000000000..d7f97ab45b226b95d540b28152cbfeeed132d570 GIT binary patch literal 860 zcmV-i1Ec(jP) zaB^>EX>4U6ba`-PAZ2)IW&i+q+HFul62l+}y!(niL0KgD9Mh&V{Xw5!3?viV?u;w2 z&I+XM{d%U`02NML7nLTG4cxd<#SZASe`0JNZ{EX4jh#z6p!U*I-34`uqWof!xM_9K!L;a*dtaIBx`C{99RQm@+ z8w#>9Al?AR;e>917?VBnaz}+41IMVgkbiqRkUrWhSrc=@^3VVP010qNS#tmY3ljhU z3ljkVnw%H_00KZsL_t(o!|jz%YZE~j#(x{~2g+vCAw);FL1;tq(1Wyv-ZZD;#Y3-t zk6iiz{2mhU+JgnPRIC@lLS&9bY$V#$m_H1=!9B#7^`N^XR>63$A<*v}I9KjU%Q8R1`8d_3#%<<%IiHIal6Xsr=KAf-e~iBgJ2qhVnv zYj1xiENx`CBMb3@V?PTJFTUhtP^XuaHZlN4?7@@wMj=wxai4qd99kVOHcUGs0Q?IJ zXC(?@Gnm_33AjS+en`Zbvc>^Q#UcQuVv%<07F|7zCofN55G=1ztJR3Or0m>A^l*1K1SklB_qWTr zlW%B0AXr`lpf?!In3}LJkB-b5Q9%d_LQt(%DF}gEE~9i7)emvYWeP%2sZ@wKQ+9QA z)o3qLwrvA&a&m%g+bE^tey@}wnvb4IS>rx1Z775QKuSrc)1g|e&J-nK=LXo`-i{5Y zZ@6jG!^1-&&XhGigj-u%ArQaKzt`=wc_b57YfZD+w2ZePGM+Yz45gG;3X`zcBICc{ mx`QqPq*!R7g%(=qn)Mrq*`K0000 zaB^>EX>4U6ba`-PAZ2)IW&i+q+HFwV4Z|=9{AY@eU>+uT9H&jCZqV_I1Bv3cC;1E< zI%8mazn*X#AQX_gm^RhokS2|~2UY@oXDqVw4ob=MsSc+=UShvFQq$}|>UbK&)jg^g zBfF=t&O(#)w=bi7na4yUexy-LBc>2A4SIa5XtU+|g>@@4EDj73o5%ji7vJ8a`a4Xt zF>-Nc));`t5#a8DI+Hg=xpQT6M#ePrh5Xyo0r&vfI9Uxe%l&cy000SaNLh0L01FcU z01FcV0GgZ_0006yNklzlsz=5XOJi-J^+^TwtWQ+^LITBr8S-3Yv(Ckv@P6 z!aatMV5I0Hn23R^TwtVfV0!26-J+qQ!667v|1mgg?42EDX7wWXgJq^?n69tB`l@;b zVDRjD`f}$s03w2OjCEX!Hu<`;KWA;wsht+N8g7(xiu zPf5fW8x>H3N=}u~1UeJY4KyPW!CFfQ0c-7y{6$eTdZmeMD*{LF-Dm6FnC5GitRq;ojPi{!b;|?7RZt!=dY3 z?QKF2R{aurxzzRAj&*XK6$l~h2fuQudU@je6GoGMqpTuAQ4~|gtCQ)Zz@JcewyyII z&`z4$ggNu!@=4qjIOiyeqM8|bhjgBV`Mrqzb_m57F~(FT%t!ZMwPD^$8lY*isni-=hftn%TOy_& zynYZh$*E&l-)jl@=KLGxnJd7UBn>zpi002ovPDHLkV1m>wiBbRn literal 0 HcmV?d00001 diff --git a/resources/resources/assets/eagler/capes/24.purple_heart.png b/resources/resources/assets/eagler/capes/24.purple_heart.png new file mode 100755 index 0000000000000000000000000000000000000000..3d6d57736eb7a07c67d228cf8449692ca3b45aa6 GIT binary patch literal 1084 zcmV-C1jGA@P) zaB^>EX>4U6ba`-PAZ2)IW&i+q+HFu#4#OY_{pS=rf&wBQ$F5zn8|?VQLYunoB|d>i zo(OE8_X{2am>IZKl_ru5+_+)4K$D~IoD=W714FWWs>3OumB?=LR3-Y4dOi*O>K2uY zkv>CMW}$KT>yJ^qOk<)EuVK`}h|q-`2Hn4vq-ni=VcF6Q^#g-g=do{jwe79N-XX+| zG9_ao@d0QY2I>}wFUQf%ONL$E=aZvopn^rf1fG#Q5aPmNe>*>8^UK z>aA)6u)Ve?Z{J=dFaRKc0dj%RLRP@*!+j|C1vok$^5j*YG=;}KN4FDW3={%i>@Jm> z{$I>sbx)4|7}Dv)EZtee7#J7OvN{?Azx}??;qj1eCuV73k#PaGG~vgrP;jPPKl;%$ z0$~mgM8Xg@?>hkEZp=cwNXx?h>wON6hXe+myy}zZY9P-c2z0bo=KvQM`rlgUb{hgX zIT6V+5Ydh8o&pJshWe}BK3N7~2t}cv2+YjXcRZL$AaUFfz|oP2znEpvZmWVY)O8Tl zUZ$ze!|O1htJ=4)uC_KuU<-19m7!P9!OE>z6aSvT0t;zQQ(8MepPDLKyS5A znd&OX8oH~a=YZGMI0AXDp1gDS9>&1ST~`^j27dmmEK zVNOp)Jn6ptFyYNNB7myaN9PF-Uqt`Pu_tFyXbMGOcD7E@{Cq3&xO1QgpkHJnvyA5A|q-V0M zE=dtBLr-F#hN_>e?MWjNUR-Dd9_~b3UTOtw{SaYot@Lb^kYy1wGj*@XvO46GG7!(j1f}BfSiMVA7`%wsT-LI@ zJr`rBL43CAn4PU3r!>|3Qa)(c>V(F?TjhKHsC zaB^>EX>4U6ba`-PAZ2)IW&i+q+HFu#4#OY_{pS=rf&x-Jj$K`{8|?VQLYunoB|d>i zo(S~M`vs2y%nV!>l`4`9T)ASiK$D~GoD=W714FWWs>3OumB?=LR3-Y4dOi*OY8I7? zkv>CMXQ6WV>yJ^qOk<)EZ(&r!h|q-`2F<^fr0R10!rIde^#g-g=do}3V%yt_y+eqd zG9_ao@d0QY25J_FFNogqbbm-<}S@7ukwg54f0w{{R3032;bRa{vGf6951U z69E94oEQKA0hUQbK~z}7?UpfX!cY*$|F4F03IzqHfDjk$*1<{en>e}pt@--Wv`M9D#;2qmxFDc05%68PV1@B5LgWK0RXR`#dR0k zIsyK29(Xhag@I0Rb0{-$>Sm=qP$?G=9H+X(fDX*d%NcG5V?`C9FepFZ2y7bAW^K7_ zY_x!v(hg#KUFW^zUR?sFyB7mzQ&AW|MZP|StauXsef*N~_R3elOD|zn6v)m(wg z&aQgL?nznNAB9c0KWezHq|0f=S0|faYuf{rlI8)H)8b|Jj^k9%d(MVIJ=@d+^h1>I z%rw~Mpnbf|d3*eFHZQe`{K{JLvuv7>H&~lNa;yIZHMh@Q_00000NkvXXu0mjfg2*+3 literal 0 HcmV?d00001 diff --git a/resources/resources/assets/eagler/glsl/deferred/deferred_core.vsh b/resources/resources/assets/eagler/glsl/deferred/deferred_core.vsh index 30ebf7c..5fd1f74 100644 --- a/resources/resources/assets/eagler/glsl/deferred/deferred_core.vsh +++ b/resources/resources/assets/eagler/glsl/deferred/deferred_core.vsh @@ -1,7 +1,7 @@ #line 2 /* - * Copyright (c) 2023 lax1dude. All Rights Reserved. +* Copyright (c) 2023 lax1dude. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -45,8 +45,8 @@ uniform float u_blockConstant1f; #endif #define DO_COMPILE_STATE_WAVING_BLOCKS #define FAKE_SIN(valueIn, valueOut)\ - valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ - valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; +valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ +valueOut = valueOut * valueOut * (6.0 - 4.0 * valueOut) - 1.0; #define LIB_INCLUDE_WAVING_BLOCKS_FUNCTION #endif @@ -68,49 +68,47 @@ uniform mat4 u_projectionMat4f; #define TEX_MAT3(mat4In) mat3(mat4In[0].xyw,mat4In[1].xyw,mat4In[3].xyw) void main() { - #ifdef COMPILE_TEXTURE_ATTRIB - vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); - v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; #endif - + #ifdef COMPILE_COLOR_ATTRIB - v_color4f = a_color4f; + v_color4f = a_color4f; #endif - + #ifdef COMPILE_NORMAL_ATTRIB - v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); - float blockId = v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); + v_normal3f = normalize(mat3(u_modelviewMat4f) * a_normal4f.xyz); + float blockId = v_block1f = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); #endif - + #ifdef COMPILE_LIGHTMAP_ATTRIB - vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); - v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; + vec3 v_lightmapTmp3f = TEX_MAT3(u_textureMat4f02) * vec3(a_lightmap2f, 1.0); + v_lightmap2f = v_lightmapTmp3f.xy / v_lightmapTmp3f.z; #endif - - vec4 pos = vec4(a_position3f, 1.0); - + + vec4 pos = vec4(a_position3f, 1.0); + #ifdef DO_COMPILE_STATE_WAVING_BLOCKS #ifndef COMPILE_NORMAL_ATTRIB - float blockId = u_blockConstant1f; + float blockId = u_blockConstant1f; #endif #ifdef COMPILE_LIGHTMAP_ATTRIB - if(v_lightmap2f.y > 0.33) { - COMPUTE_WAVING_BLOCKS(pos, min(v_lightmap2f.y * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) - }else { - pos = u_modelviewMat4f * pos; - } + if(v_lightmap2f.y > 0.33) { + COMPUTE_WAVING_BLOCKS(pos, min(v_lightmap2f.y * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + }else { + pos = u_modelviewMat4f * pos; + } #else - COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) #endif #else - pos = u_modelviewMat4f * pos; + pos = u_modelviewMat4f * pos; #endif - + #ifdef COMPILE_NORMAL_MATERIAL_TEXTURE - v_viewdir3f = pos.xyz / pos.w; + v_viewdir3f = pos.xyz / pos.w; #endif - - gl_Position = u_projectionMat4f * pos; - + + gl_Position = u_projectionMat4f * pos; } diff --git a/resources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh b/resources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh index 4811a3e..1553efa 100644 --- a/resources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh +++ b/resources/resources/assets/eagler/glsl/deferred/deferred_shadow.vsh @@ -1,7 +1,7 @@ #line 2 /* - * Copyright (c) 2023 lax1dude. All Rights Reserved. +* Copyright (c) 2023 lax1dude. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -52,8 +52,8 @@ uniform vec3 u_wavingBlockOffset3f; uniform vec4 u_wavingBlockParam4f; #define DO_COMPILE_STATE_WAVING_BLOCKS #define FAKE_SIN(valueIn, valueOut)\ - valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ - valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; +valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ +valueOut = valueOut * valueOut * (6.0 - 4.0 * valueOut) - 1.0; #define LIB_INCLUDE_WAVING_BLOCKS_FUNCTION #endif @@ -64,40 +64,39 @@ uniform vec4 u_wavingBlockParam4f; void main() { #ifdef DO_SHADOW_ALPHA_TEST #ifdef COMPILE_TEXTURE_ATTRIB - vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); - v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; + vec3 v_textureTmp3f = TEX_MAT3(u_textureMat4f01) * vec3(a_texture2f, 1.0); + v_texture2f = v_textureTmp3f.xy / v_textureTmp3f.z; #endif #endif #ifdef DO_COMPILE_STATE_WAVING_BLOCKS - vec4 pos = vec4(a_position3f, 1.0); + vec4 pos = vec4(a_position3f, 1.0); #ifdef COMPILE_NORMAL_ATTRIB - float blockId = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); + float blockId = floor((a_normal4f.w + 1.0) * 127.0 + 0.5); #else - float blockId = u_blockConstant1f; + float blockId = u_blockConstant1f; #endif #ifdef COMPILE_ENABLE_LIGHTMAP #ifdef COMPILE_LIGHTMAP_ATTRIB - mat4x2 texMat4x2 = mat4x2( - u_textureMat4f02[0].yw, - u_textureMat4f02[1].yw, - u_textureMat4f02[2].yw, - u_textureMat4f02[3].yw - ); - vec2 v_lightmapTmp2f = texMat4x2 * vec4(a_lightmap2f, 0.0, 1.0); - v_lightmapTmp2f.x = v_lightmapTmp2f.x / v_lightmapTmp2f.y; + mat4x2 texMat4x2 = mat4x2( + u_textureMat4f02[0].yw, + u_textureMat4f02[1].yw, + u_textureMat4f02[2].yw, + u_textureMat4f02[3].yw); + vec2 v_lightmapTmp2f = texMat4x2 * vec4(a_lightmap2f, 0.0, 1.0); + v_lightmapTmp2f.x = v_lightmapTmp2f.x / v_lightmapTmp2f.y; #else - vec2 v_lightmapTmp2f = vec2(u_textureCoords02.y, 0.0); + vec2 v_lightmapTmp2f = vec2(u_textureCoords02.y, 0.0); #endif - if(v_lightmapTmp2f.x > 0.33) { - COMPUTE_WAVING_BLOCKS(pos, min(v_lightmapTmp2f.x * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) - }else { - pos = u_modelviewProjMat4f * pos; - } + if(v_lightmapTmp2f.x > 0.33) { + COMPUTE_WAVING_BLOCKS(pos, min(v_lightmapTmp2f.x * 3.0 - 1.0, 1.0), 24.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + }else { + pos = u_modelviewProjMat4f * pos; + } #else - COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) + COMPUTE_WAVING_BLOCKS(pos, 1.0, 32.0, blockId, u_modelMatrix4f, u_viewMatrix4f, u_modelviewProjMat4f, u_wavingBlockOffset3f, u_wavingBlockParam4f) #endif - gl_Position = pos; + gl_Position = pos; #else - gl_Position = u_modelviewProjMat4f * vec4(a_position3f, 1.0); + gl_Position = u_modelviewProjMat4f * vec4(a_position3f, 1.0); #endif } diff --git a/resources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh b/resources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh index 5a73c7b..4d9e743 100644 --- a/resources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh +++ b/resources/resources/assets/eagler/glsl/deferred/post_lens_ghosts.vsh @@ -1,7 +1,7 @@ #line 2 /* - * Copyright (c) 2023 lax1dude. All Rights Reserved. +* Copyright (c) 2023 lax1dude. All Rights Reserved. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -38,30 +38,30 @@ uniform float u_aspectRatio1f; uniform float u_baseScale1f; #define FAKE_SIN(valueIn, valueOut)\ - valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ - valueOut = valueOut * valueOut * (3.0 - 2.0 * valueOut) * 2.0 - 1.0; +valueOut = abs(1.0 - fract(valueIn * 0.159155) * 2.0);\ +valueOut = valueOut * valueOut * (6.0 - 4.0 * valueOut) - 1.0; void main() { - v_occlusion1f = max(textureLod(u_sunOcclusionValue, vec2(0.5, 0.5), 0.0).r * 1.5 - 0.5, 0.0); - if(v_occlusion1f == 0.0) { - gl_Position = vec4(-10.0, -10.0, -10.0, 1.0); - return; - } - - v_texcoord2f = e_elementTexture4f.xy + (a_position2f * 0.5 + 0.5) * e_elementTexture4f.zw; - - float r = textureLod(u_exposureValue, vec2(0.5, 0.5), 0.0).r * 7.5; - - mat2 rotationMatrix; - FAKE_SIN(vec2(r + 1.570795, r), rotationMatrix[0]) - rotationMatrix[1].x = -rotationMatrix[0].y; - rotationMatrix[1].y = rotationMatrix[0].x; - - vec2 transformedVertex = rotationMatrix * (a_position2f * u_baseScale1f * e_elementOffsetScale.y / (4.0 + r * 0.75)); - transformedVertex.x *= u_aspectRatio1f; - transformedVertex += u_sunPosition2f * (1.0 - e_elementOffsetScale.x); - - v_color3f = e_elementColor3f * (0.05 + dot(u_sunPosition2f, u_sunPosition2f)); - - gl_Position = vec4(transformedVertex, 0.0, 1.0); + v_occlusion1f = max(textureLod(u_sunOcclusionValue, vec2(0.5, 0.5), 0.0).r * 1.5 - 0.5, 0.0); + if(v_occlusion1f == 0.0) { + gl_Position = vec4(-10.0, -10.0, -10.0, 1.0); + return; + } + + v_texcoord2f = e_elementTexture4f.xy + (a_position2f * 0.5 + 0.5) * e_elementTexture4f.zw; + + float r = textureLod(u_exposureValue, vec2(0.5, 0.5), 0.0).r * 7.5; + + mat2 rotationMatrix; + FAKE_SIN(vec2(r + 1.570795, r), rotationMatrix[0]) + rotationMatrix[1].x = -rotationMatrix[0].y; + rotationMatrix[1].y = rotationMatrix[0].x; + + vec2 transformedVertex = rotationMatrix * (a_position2f * u_baseScale1f * e_elementOffsetScale.y / (4.0 + r * 0.75)); + transformedVertex.x *= u_aspectRatio1f; + transformedVertex += u_sunPosition2f * (1.0 - e_elementOffsetScale.x); + + v_color3f = e_elementColor3f * (0.05 + dot(u_sunPosition2f, u_sunPosition2f)); + + gl_Position = vec4(transformedVertex, 0.0, 1.0); } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index 0e68432..8d11c54 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -279,7 +279,11 @@ public class PlatformApplication { } public static void showDebugConsole() { + + } + public static void setMCServerWindowGlobal(String str) { + } } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java index 0000e3b..e1dced3 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAssets.java @@ -81,7 +81,7 @@ public class PlatformAssets { if (!a) { j = j | 0xFF000000; } - pixels[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >> 16) | + pixels[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >>> 16) | ((j & 0x000000FF) << 16); } return new ImageData(w, h, pixels, a); diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java index 59b00bb..ad6ace9 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java @@ -148,9 +148,9 @@ public class PlatformRuntime { int[] px = new int[w * h]; windowIcons[i].getRGB(0, 0, w, h, px, 0, w); - - for (int j = 0; j < px.length; ++j) { - px[j] = (px[j] & 0xFF00FF00) | ((px[j] >> 16) & 0xFF) | ((px[j] & 0xFF) << 16); // swap R/B + + for(int j = 0; j < px.length; ++j) { + px[j] = (px[j] & 0xFF00FF00) | ((px[j] >>> 16) & 0xFF) | ((px[j] & 0xFF) << 16); // swap R/B } java.nio.ByteBuffer iconBuffer = st.malloc(w * h * 4); diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java index 2edc7f5..c912934 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DesktopClientConfigAdapter.java @@ -1,170 +1,176 @@ -package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; - -import java.util.ArrayList; -import java.util.List; - -import org.json.JSONObject; - -import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; -import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; -import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter; -import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; -import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry; - -/** - * Copyright (c) 2022 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public class DesktopClientConfigAdapter implements IClientConfigAdapter { - - public static final IClientConfigAdapter instance = new DesktopClientConfigAdapter(); - - public final List defaultServers = new ArrayList(); - - private final DesktopClientConfigAdapterHooks hooks = new DesktopClientConfigAdapterHooks(); - - @Override - public String getDefaultLocale() { - return "en_US"; - } - - @Override - public List getDefaultServerList() { - return defaultServers; - } - - @Override - public String getServerToJoin() { - return null; - } - - @Override - public String getWorldsDB() { - return "desktop"; - } - - @Override - public String getResourcePacksDB() { - return "desktop"; - } - - @Override - public JSONObject getIntegratedServerOpts() { - return new JSONObject("{\"container\":null,\"worldsDB\":\"desktop\"}"); - } - - private final List relays = new ArrayList<>(); - - @Override - public List getRelays() { - if (relays.isEmpty()) { - int relayId = (new EaglercraftRandom()).nextInt(3); - relays.add(new RelayEntry("wss://relay.deev.is/", "lax1dude relay #1", relayId == 0)); - relays.add(new RelayEntry("wss://relay.lax1dude.net/", "lax1dude relay #2", relayId == 1)); - relays.add(new RelayEntry("wss://relay.shhnowisnottheti.me/", "ayunami relay #1", relayId == 2)); - } - return relays; - } - - @Override - public boolean isCheckShaderGLErrors() { - return true; - } - - @Override - public boolean isDemo() { - return EaglercraftVersion.forceDemoMode; - } - - @Override - public boolean allowUpdateSvc() { - return false; - } - - @Override - public boolean allowUpdateDL() { - return false; - } - - @Override - public boolean isEnableDownloadOfflineButton() { - return false; - } - - @Override - public String getDownloadOfflineButtonLink() { - return null; - } - - @Override - public boolean useSpecialCursors() { - return false; - } - - @Override - public boolean isLogInvalidCerts() { - return false; - } - - @Override - public boolean isCheckRelaysForUpdates() { - return false; - } - - @Override - public boolean isEnableSignatureBadge() { - return false; - } - - @Override - public boolean isAllowVoiceClient() { - return false; - } - - @Override - public boolean isAllowFNAWSkins() { - return true; - } - - @Override - public String getLocalStorageNamespace() { - return EaglercraftVersion.localStorageNamespace; - } - - @Override - public IClientConfigAdapterHooks getHooks() { - return hooks; - } - - private static class DesktopClientConfigAdapterHooks implements IClientConfigAdapterHooks { - - @Override - public void callLocalStorageSavedHook(String key, String base64) { - - } - - @Override - public String callLocalStorageLoadHook(String key) { - return null; - } - - } -} +package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +import org.json.JSONObject; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftRandom; +import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapter; +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; +import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayEntry; + +/** + * Copyright (c) 2022 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class DesktopClientConfigAdapter implements IClientConfigAdapter { + + public static final IClientConfigAdapter instance = new DesktopClientConfigAdapter(); + + public final List defaultServers = new ArrayList(); + + private final DesktopClientConfigAdapterHooks hooks = new DesktopClientConfigAdapterHooks(); + + @Override + public String getDefaultLocale() { + return "en_US"; + } + + @Override + public List getDefaultServerList() { + return defaultServers; + } + + @Override + public String getServerToJoin() { + return null; + } + + @Override + public String getWorldsDB() { + return "desktop"; + } + + @Override + public String getResourcePacksDB() { + return "desktop"; + } + + @Override + public JSONObject getIntegratedServerOpts() { + return new JSONObject("{\"container\":null,\"worldsDB\":\"desktop\"}"); + } + + private final List relays = new ArrayList<>(); + + @Override + public List getRelays() { + if (relays.isEmpty()) { + int relayId = (new EaglercraftRandom()).nextInt(3); + relays.add(new RelayEntry("wss://relay.deev.is/", "lax1dude relay #1", relayId == 0)); + relays.add(new RelayEntry("wss://relay.lax1dude.net/", "lax1dude relay #2", relayId == 1)); + relays.add(new RelayEntry("wss://relay.shhnowisnottheti.me/", "ayunami relay #1", relayId == 2)); + } + return relays; + } + + @Override + public boolean isCheckShaderGLErrors() { + return true; + } + + @Override + public boolean isDemo() { + return EaglercraftVersion.forceDemoMode; + } + + @Override + public boolean allowUpdateSvc() { + return false; + } + + @Override + public boolean allowUpdateDL() { + return false; + } + + @Override + public boolean isEnableDownloadOfflineButton() { + return false; + } + + @Override + public String getDownloadOfflineButtonLink() { + return null; + } + + @Override + public boolean useSpecialCursors() { + return false; + } + + @Override + public boolean isLogInvalidCerts() { + return false; + } + + @Override + public boolean isCheckRelaysForUpdates() { + return false; + } + + @Override + public boolean isEnableSignatureBadge() { + return false; + } + + @Override + public boolean isAllowVoiceClient() { + return false; + } + + @Override + public boolean isAllowFNAWSkins() { + return true; + } + + @Override + public String getLocalStorageNamespace() { + return EaglercraftVersion.localStorageNamespace; + } + + @Override + public IClientConfigAdapterHooks getHooks() { + return hooks; + } + + private static class DesktopClientConfigAdapterHooks implements IClientConfigAdapterHooks { + + @Override + public void callLocalStorageSavedHook(String key, String base64) { + + } + + @Override + public String callLocalStorageLoadHook(String key) { + return null; + } + + @Override + public void callCrashReportHook(String crashReport, Consumer customMessageCB) { + + } + + } +} diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java index a80b6dd..84e1e22 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EagRuntime.java @@ -237,6 +237,9 @@ public class EagRuntime { return PlatformRuntime.maxMemory(); } + /** + * Note to skids: This doesn't do anything in TeaVM runtime! + */ public static long totalMemory() { return PlatformRuntime.totalMemory(); } @@ -333,4 +336,8 @@ public class EagRuntime { input.setCalendar(getLocaleCalendar()); return input; } + + public static void setMCServerWindowGlobal(String url) { + PlatformApplication.setMCServerWindowGlobal(url); + } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java index 166d58b..5a5880a 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java @@ -19,9 +19,9 @@ public class EaglercraftVersion { public static final String projectOriginName = "EaglercraftX"; public static final String projectOriginAuthor = "lax1dude"; - public static final String projectOriginRevision = "1.9.4"; - public static final String projectOriginVersion = "u35"; - + public static final String projectOriginRevision = "1.8"; + public static final String projectOriginVersion = "u36"; + public static final String projectOriginURL = "https://gitlab.com/lax1dude/eaglercraftx-1.8"; // rest in peace // Updating configuration @@ -34,7 +34,7 @@ public class EaglercraftVersion { "https://update.hoosiertransfer.xyz/cert"); public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client"; - public static final int updateBundlePackageVersionInt = 2; + public static final int updateBundlePackageVersionInt = 3; public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java index 9cedf14..8de6e09 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapterHooks.java @@ -1,5 +1,7 @@ package net.lax1dude.eaglercraft.v1_8.internal; +import java.util.function.Consumer; + /** * Copyright (c) 2024 lax1dude. All Rights Reserved. * @@ -28,4 +30,6 @@ public interface IClientConfigAdapterHooks { String callLocalStorageLoadHook(String key); + void callCrashReportHook(String crashReport, Consumer customMessageCB); + } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java index d1926f4..1fb4985 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/AcceleratedEffectRenderer.java @@ -77,7 +77,7 @@ public class AcceleratedEffectRenderer implements IAcceleratedParticleEngine { int lightMapData, int texSize, float particleSize, float r, float g, float b, float a) { if (!Config.renderParticles()) return; InstancedParticleRenderer.appendParticle(posX, posY, posZ, particleIndexX, particleIndexY, lightMapData & 0xFF, - (lightMapData >> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, r, g, b, a); + (lightMapData >>> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, r, g, b, a); } @Override @@ -85,7 +85,7 @@ public class AcceleratedEffectRenderer implements IAcceleratedParticleEngine { int lightMapData, int texSize, float particleSize, int rgba) { if (!Config.renderParticles()) return; InstancedParticleRenderer.appendParticle(posX, posY, posZ, particleIndexX, particleIndexY, lightMapData & 0xFF, - (lightMapData >> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, rgba); + (lightMapData >>> 16) & 0xFF, (int)(particleSize * 16.0f), texSize, rgba); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerFontRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerFontRenderer.java index d71e2a8..61a5249 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerFontRenderer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/minecraft/EaglerFontRenderer.java @@ -47,10 +47,10 @@ public class EaglerFontRenderer extends FontRenderer { if ((color & 0xFC000000) == 0) { color |= 0xFF000000; } - this.red = (float) (color >> 16 & 255) / 255.0F; - this.blue = (float) (color >> 8 & 255) / 255.0F; + this.red = (float) (color >>> 16 & 255) / 255.0F; + this.blue = (float) (color >>> 8 & 255) / 255.0F; this.green = (float) (color & 255) / 255.0F; - this.alpha = (float) (color >> 24 & 255) / 255.0F; + this.alpha = (float) (color >>> 24 & 255) / 255.0F; this.posX = x; this.posY = y; this.textColor = color; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/netty/ByteBufEaglercraftImpl.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/netty/ByteBufEaglercraftImpl.java index d0963a1..118576e 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/netty/ByteBufEaglercraftImpl.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/netty/ByteBufEaglercraftImpl.java @@ -72,8 +72,8 @@ public class ByteBufEaglercraftImpl extends AbstractByteBuf { @Override protected void _setMedium(int index, int value) { - internal.put(index, (byte)((value >> 16) & 0xFF)); - internal.put(index + 1, (byte)((value >> 8) & 0xFF)); + internal.put(index, (byte)((value >>> 16) & 0xFF)); + internal.put(index + 1, (byte)((value >>> 8) & 0xFF)); internal.put(index + 2, (byte)(value & 0xFF)); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ImageData.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ImageData.java index 71eb24d..ca5a5b1 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ImageData.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ImageData.java @@ -118,14 +118,14 @@ public class ImageData { if((spx & 0xFF000000) == 0xFF000000 || (dpx & 0xFF000000) == 0) { pixels[di] = spx; }else { - int sa = (spx >> 24) & 0xFF; - int da = (dpx >> 24) & 0xFF; - int r = ((spx >> 16) & 0xFF) * sa / 255; - int g = ((spx >> 8) & 0xFF) * sa / 255; + int sa = (spx >>> 24) & 0xFF; + int da = (dpx >>> 24) & 0xFF; + int r = ((spx >>> 16) & 0xFF) * sa / 255; + int g = ((spx >>> 8) & 0xFF) * sa / 255; int b = (spx & 0xFF) * sa / 255; int aa = (255 - sa) * da; - r += ((dpx >> 16) & 0xFF) * aa / 65025; - g += ((dpx >> 8) & 0xFF) * aa / 65025; + r += ((dpx >>> 16) & 0xFF) * aa / 65025; + g += ((dpx >>> 8) & 0xFF) * aa / 65025; b += (dpx & 0xFF) * aa / 65025; sa += da; if(sa > 0xFF) sa = 0xFF; @@ -138,14 +138,14 @@ public class ImageData { public ImageData swapRB() { for(int i = 0; i < pixels.length; ++i) { int j = pixels[i]; - pixels[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >> 16) | + pixels[i] = (j & 0xFF00FF00) | ((j & 0x00FF0000) >>> 16) | ((j & 0x000000FF) << 16); } return this; } public static int swapRB(int c) { - return (c & 0xFF00FF00) | ((c & 0x00FF0000) >> 16) | ((c & 0x000000FF) << 16); + return (c & 0xFF00FF00) | ((c & 0x00FF0000) >>> 16) | ((c & 0x000000FF) << 16); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java index eff5bd1..0a36fd0 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/InstancedFontRenderer.java @@ -413,7 +413,7 @@ public class InstancedFontRenderer { buf.putShort((short)y); buf.put((byte)cx); buf.put((byte)cy); - color = ((color >> 1) & 0x7F000000) | (color & 0xFFFFFF); + color = ((color >>> 1) & 0x7F000000) | (color & 0xFFFFFF); if(italic) { color |= 0x80000000; } @@ -438,7 +438,7 @@ public class InstancedFontRenderer { buf.putShort((short)y); buf.put((byte)cx); buf.put((byte)cy); - color = ((color >> 1) & 0x7F000000) | (color & 0xFFFFFF); + color = ((color >>> 1) & 0x7F000000) | (color & 0xFFFFFF); if(italic) { color |= 0x80000000; } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java index 6f7a498..8905ee0 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/WorldRenderer.java @@ -275,8 +275,8 @@ public class WorldRenderer { if (!this.needsUpdate) { j = this.intBuffer.get(i); int k = (int) ((float) (j & 255) * red); - int l = (int) ((float) (j >> 8 & 255) * green); - int i1 = (int) ((float) (j >> 16 & 255) * blue); + int l = (int) ((float) (j >>> 8 & 255) * green); + int i1 = (int) ((float) (j >>> 16 & 255) * blue); j = j & -16777216; j = j | i1 << 16 | l << 8 | k; } @@ -288,10 +288,10 @@ public class WorldRenderer { */ private void putColor(int argb, int parInt2) { int i = this.getColorIndex(parInt2); - int j = argb >> 16 & 255; - int k = argb >> 8 & 255; + int j = argb >>> 16 & 255; + int k = argb >>> 8 & 255; int l = argb & 255; - int i1 = argb >> 24 & 255; + int i1 = argb >>> 24 & 255; this.putColorRGBA(i, j, k, l, i1); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java index 371dcd7..8c84bd7 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java @@ -63,8 +63,8 @@ public class CapePackets { } public static byte[] writeMyCapePreset(int capeId) { - return new byte[] { (byte) PACKET_MY_CAPE_PRESET, (byte) (capeId >> 24), (byte) (capeId >> 16), - (byte) (capeId >> 8), (byte) (capeId & 0xFF) }; + return new byte[] { (byte) PACKET_MY_CAPE_PRESET, (byte) (capeId >>> 24), (byte) (capeId >>> 16), + (byte) (capeId >>> 8), (byte) (capeId & 0xFF) }; } public static byte[] writeMyCapeCustom(CustomCape customCape) { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java index 33e7dc8..6445f4c 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java @@ -1,75 +1,80 @@ -package net.lax1dude.eaglercraft.v1_8.profile; - -import net.minecraft.util.ResourceLocation; - -/** - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public enum DefaultCapes { - - NO_CAPE(0, "No Cape", null), - MINECON_2011(1, "Minecon 2011", new ResourceLocation("eagler:capes/01.minecon_2011.png")), - MINECON_2012(2, "Minecon 2012", new ResourceLocation("eagler:capes/02.minecon_2012.png")), - MINECON_2013(3, "Minecon 2013", new ResourceLocation("eagler:capes/03.minecon_2013.png")), - MINECON_2015(4, "Minecon 2015", new ResourceLocation("eagler:capes/04.minecon_2015.png")), - MINECON_2016(5, "Minecon 2016", new ResourceLocation("eagler:capes/05.minecon_2016.png")), - MICROSOFT_ACCOUNT(6, "Microsoft Account", new ResourceLocation("eagler:capes/06.microsoft_account.png")), - MAPMAKER(7, "Realms Mapmaker", new ResourceLocation("eagler:capes/07.mapmaker.png")), - MOJANG_OLD(8, "Mojang Old", new ResourceLocation("eagler:capes/08.mojang_old.png")), - MOJANG_NEW(9, "Mojang New", new ResourceLocation("eagler:capes/09.mojang_new.png")), - JIRA_MOD(10, "Jira Moderator", new ResourceLocation("eagler:capes/10.jira_mod.png")), - MOJANG_VERY_OLD(11, "Mojang Very Old", new ResourceLocation("eagler:capes/11.mojang_very_old.png")), - SCROLLS(12, "Scrolls", new ResourceLocation("eagler:capes/12.scrolls.png")), - COBALT(13, "Cobalt", new ResourceLocation("eagler:capes/13.cobalt.png")), - TRANSLATOR(14, "Lang Translator", new ResourceLocation("eagler:capes/14.translator.png")), - MILLIONTH_ACCOUNT(15, "Millionth Player", new ResourceLocation("eagler:capes/15.millionth_account.png")), - PRISMARINE(16, "Prismarine", new ResourceLocation("eagler:capes/16.prismarine.png")), - SNOWMAN(17, "Snowman", new ResourceLocation("eagler:capes/17.snowman.png")), - SPADE(18, "Spade", new ResourceLocation("eagler:capes/18.spade.png")), - BIRTHDAY(19, "Birthday", new ResourceLocation("eagler:capes/19.birthday.png")), - DB(20, "dB", new ResourceLocation("eagler:capes/20.db.png")); - - public static final DefaultCapes[] defaultCapesMap = new DefaultCapes[21]; - - public final int id; - public final String name; - public final ResourceLocation location; - - private DefaultCapes(int id, String name, ResourceLocation location) { - this.id = id; - this.name = name; - this.location = location; - } - - public static DefaultCapes getCapeFromId(int id) { - DefaultCapes e = null; - if(id >= 0 && id < defaultCapesMap.length) { - e = defaultCapesMap[id]; - } - if(e != null) { - return e; - }else { - return NO_CAPE; - } - } - - static { - DefaultCapes[] capes = values(); - for(int i = 0; i < capes.length; ++i) { - defaultCapesMap[capes[i].id] = capes[i]; - } - } - +package net.lax1dude.eaglercraft.v1_8.profile; + +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2024 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public enum DefaultCapes { + + NO_CAPE(0, "No Cape", null), + MINECON_2011(1, "Minecon 2011", new ResourceLocation("eagler:capes/01.minecon_2011.png")), + MINECON_2012(2, "Minecon 2012", new ResourceLocation("eagler:capes/02.minecon_2012.png")), + MINECON_2013(3, "Minecon 2013", new ResourceLocation("eagler:capes/03.minecon_2013.png")), + MINECON_2015(4, "Minecon 2015", new ResourceLocation("eagler:capes/04.minecon_2015.png")), + MINECON_2016(5, "Minecon 2016", new ResourceLocation("eagler:capes/05.minecon_2016.png")), + MICROSOFT_ACCOUNT(6, "Microsoft Account", new ResourceLocation("eagler:capes/06.microsoft_account.png")), + MAPMAKER(7, "Realms Mapmaker", new ResourceLocation("eagler:capes/07.mapmaker.png")), + MOJANG_OLD(8, "Mojang Old", new ResourceLocation("eagler:capes/08.mojang_old.png")), + MOJANG_NEW(9, "Mojang New", new ResourceLocation("eagler:capes/09.mojang_new.png")), + JIRA_MOD(10, "Jira Moderator", new ResourceLocation("eagler:capes/10.jira_mod.png")), + MOJANG_VERY_OLD(11, "Mojang Very Old", new ResourceLocation("eagler:capes/11.mojang_very_old.png")), + SCROLLS(12, "Scrolls", new ResourceLocation("eagler:capes/12.scrolls.png")), + COBALT(13, "Cobalt", new ResourceLocation("eagler:capes/13.cobalt.png")), + TRANSLATOR(14, "Lang Translator", new ResourceLocation("eagler:capes/14.translator.png")), + MILLIONTH_ACCOUNT(15, "Millionth Player", new ResourceLocation("eagler:capes/15.millionth_account.png")), + PRISMARINE(16, "Prismarine", new ResourceLocation("eagler:capes/16.prismarine.png")), + SNOWMAN(17, "Snowman", new ResourceLocation("eagler:capes/17.snowman.png")), + SPADE(18, "Spade", new ResourceLocation("eagler:capes/18.spade.png")), + BIRTHDAY(19, "Birthday", new ResourceLocation("eagler:capes/19.birthday.png")), + DB(20, "dB", new ResourceLocation("eagler:capes/20.db.png")), + _15TH_ANNIVERSARY(21, "15th Anniversary", new ResourceLocation("eagler:capes/21.15th_anniversary.png")), + VANILLA(22, "Vanilla", new ResourceLocation("eagler:capes/22.vanilla.png")), + TIKTOK(23, "TikTok", new ResourceLocation("eagler:capes/23.tiktok.png")), + PURPLE_HEART(24, "Purple Heart", new ResourceLocation("eagler:capes/24.purple_heart.png")), + CHERRY_BLOSSOM(25, "Cherry Blossom", new ResourceLocation("eagler:capes/25.cherry_blossom.png")); + + public static final DefaultCapes[] defaultCapesMap = new DefaultCapes[26]; + + public final int id; + public final String name; + public final ResourceLocation location; + + private DefaultCapes(int id, String name, ResourceLocation location) { + this.id = id; + this.name = name; + this.location = location; + } + + public static DefaultCapes getCapeFromId(int id) { + DefaultCapes e = null; + if(id >= 0 && id < defaultCapesMap.length) { + e = defaultCapesMap[id]; + } + if(e != null) { + return e; + }else { + return NO_CAPE; + } + } + + static { + DefaultCapes[] capes = values(); + for(int i = 0; i < capes.length; ++i) { + defaultCapesMap[capes[i].id] = capes[i]; + } + } + } \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java index 2598187..6814efc 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditProfile.java @@ -363,10 +363,10 @@ public class GuiScreenEditProfile extends GuiScreen { for (int i = 0, j, k; i < 4096; ++i) { j = i << 2; k = loadedSkin.pixels[i]; - rawSkin[j] = (byte) (k >> 24); - rawSkin[j + 1] = (byte) (k >> 16); - rawSkin[j + 2] = (byte) (k >> 8); - rawSkin[j + 3] = (byte) (k & 0xFF); + rawSkin[j] = (byte)(k >>> 24); + rawSkin[j + 1] = (byte)(k >>> 16); + rawSkin[j + 2] = (byte)(k >>> 8); + rawSkin[j + 3] = (byte)(k & 0xFF); } for (int y = 20; y < 32; ++y) { for (int x = 16; x < 40; ++x) { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java index a56b0db..7217cc6 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ProfileExporter.java @@ -68,7 +68,7 @@ public class ProfileExporter { + (doExportServers ? "servers " : "") + (doExportResourcePacks ? "resourcePacks" : "") + "\n\n") .getBytes(StandardCharsets.UTF_8); - osb.write((comment.length >> 8) & 255); + osb.write((comment.length >>> 8) & 255); osb.write(comment.length & 255); osb.write(comment); @@ -181,11 +181,11 @@ public class ProfileExporter { byte[] ret = osb.toByteArray(); - ret[lengthIntegerOffset] = (byte) ((fileCount >> 24) & 0xFF); - ret[lengthIntegerOffset + 1] = (byte) ((fileCount >> 16) & 0xFF); - ret[lengthIntegerOffset + 2] = (byte) ((fileCount >> 8) & 0xFF); - ret[lengthIntegerOffset + 3] = (byte) (fileCount & 0xFF); - + ret[lengthIntegerOffset] = (byte)((fileCount >>> 24) & 0xFF); + ret[lengthIntegerOffset + 1] = (byte)((fileCount >>> 16) & 0xFF); + ret[lengthIntegerOffset + 2] = (byte)((fileCount >>> 8) & 0xFF); + ret[lengthIntegerOffset + 3] = (byte)(fileCount & 0xFF); + logger.info("Export complete!"); EagRuntime.downloadFileWithName(EaglerProfile.getName() + "-backup.epk", ret); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinConverter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinConverter.java index 5919c34..316b483 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinConverter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinConverter.java @@ -49,11 +49,11 @@ public class SkinConverter { for (int x = 0; x < 22; ++x) { i = (y * 23 + x) * 3; j = skinIn.pixels[y * skinIn.width + x]; - if ((j & 0xFF000000) != 0) { - skinOut[i] = (byte) (j >> 16); - skinOut[i + 1] = (byte) (j >> 8); - skinOut[i + 2] = (byte) (j & 0xFF); - } else { + if((j & 0xFF000000) != 0) { + skinOut[i] = (byte)(j >>> 16); + skinOut[i + 1] = (byte)(j >>> 8); + skinOut[i + 2] = (byte)(j & 0xFF); + }else { skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0; } } @@ -61,11 +61,11 @@ public class SkinConverter { for (int y = 0; y < 11; ++y) { i = ((y + 6) * 23 + 22) * 3; j = skinIn.pixels[(y + 11) * skinIn.width + 22]; - if ((j & 0xFF000000) != 0) { - skinOut[i] = (byte) (j >> 16); - skinOut[i + 1] = (byte) (j >> 8); - skinOut[i + 2] = (byte) (j & 0xFF); - } else { + if((j & 0xFF000000) != 0) { + skinOut[i] = (byte)(j >>> 16); + skinOut[i + 1] = (byte)(j >>> 8); + skinOut[i + 2] = (byte)(j & 0xFF); + }else { skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0; } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPackets.java index 0f28184..3abb60b 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPackets.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPackets.java @@ -91,8 +91,8 @@ public class SkinPackets { } public static byte[] writeMySkinPreset(int skinId) { - return new byte[] { (byte) PACKET_MY_SKIN_PRESET, (byte) (skinId >> 24), (byte) (skinId >> 16), - (byte) (skinId >> 8), (byte) (skinId & 0xFF) }; + return new byte[] { (byte) PACKET_MY_SKIN_PRESET, (byte) (skinId >>> 24), (byte) (skinId >>> 16), + (byte) (skinId >>> 8), (byte) (skinId & 0xFF) }; } public static byte[] writeMySkinCustom(CustomSkin customSkin) { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java index 28a6d8f..18d7fe2 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/socket/ConnectionHandshake.java @@ -205,14 +205,14 @@ public class ConnectionHandshake { SHA256Digest digest = new SHA256Digest(); int passLen = password.length(); - - digest.update((byte) ((passLen >> 8) & 0xFF)); - digest.update((byte) (passLen & 0xFF)); - - for (int i = 0; i < passLen; ++i) { + + digest.update((byte)((passLen >>> 8) & 0xFF)); + digest.update((byte)(passLen & 0xFF)); + + for(int i = 0; i < passLen; ++i) { char codePoint = password.charAt(i); - digest.update((byte) ((codePoint >> 8) & 0xFF)); - digest.update((byte) (codePoint & 0xFF)); + digest.update((byte)((codePoint >>> 8) & 0xFF)); + digest.update((byte)(codePoint & 0xFF)); } digest.update(HandshakePacketTypes.EAGLER_SHA256_SALT_SAVE, 0, 32); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SkullCommand.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SkullCommand.java index ce73c22..5d2bf32 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SkullCommand.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/SkullCommand.java @@ -57,9 +57,9 @@ public class SkullCommand { for(int i = 0, j, k; i < 4096; ++i) { j = i << 2; k = loaded.pixels[i]; - rawSkin[j] = (byte)(k >> 24); - rawSkin[j + 1] = (byte)(k >> 16); - rawSkin[j + 2] = (byte)(k >> 8); + rawSkin[j] = (byte)(k >>> 24); + rawSkin[j + 1] = (byte)(k >>> 16); + rawSkin[j + 2] = (byte)(k >>> 8); rawSkin[j + 3] = (byte)(k & 0xFF); } mc.thePlayer.sendQueue.addToSendQueue(new C17PacketCustomPayload("EAG|Skins-1.8", SkinPackets.writeCreateCustomSkull(rawSkin))); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenLANConnecting.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenLANConnecting.java index 86f8948..1c6f530 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenLANConnecting.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenLANConnecting.java @@ -8,8 +8,10 @@ import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServer; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayServerSocket; import net.lax1dude.eaglercraft.v1_8.sp.socket.NetHandlerSingleplayerLogin; import net.minecraft.client.LoadingScreenRenderer; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiDisconnected; import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.multiplayer.ServerData; import net.minecraft.client.resources.I18n; import net.minecraft.network.EnumConnectionState; import net.minecraft.network.login.client.C00PacketLoginStart; @@ -62,6 +64,7 @@ public class GuiScreenLANConnecting extends GuiScreen { this.parent = parent; this.code = code; this.relay = relay; + Minecraft.getMinecraft().setServerData(new ServerData("Shared World", "shared:" + relay.address, false)); } public boolean doesGuiPauseGame() { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANServerController.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANServerController.java index 1f2fae7..fd81cbb 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANServerController.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/lan/LANServerController.java @@ -40,7 +40,7 @@ import net.lax1dude.eaglercraft.v1_8.sp.relay.pkt.*; */ public class LANServerController { - public static final Logger logger = LogManager.getLogger("IntegratedServerLAN"); + public static final Logger logger = LogManager.getLogger("LANServerController"); public static final List currentICEServers = new ArrayList(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/pkt/IPacket.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/pkt/IPacket.java index 9f79a77..33dc3a0 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/pkt/IPacket.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/relay/pkt/IPacket.java @@ -154,7 +154,7 @@ public class IPacket { is.write(0); }else { int l = txt.length(); - is.write((l >> 8) & 0xFF); + is.write((l >>> 8) & 0xFF); is.write(l & 0xFF); for(int i = 0; i < l; ++i) { is.write((int)txt.charAt(i)); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerChunkLoader.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerChunkLoader.java index ed72e8e..933b88e 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerChunkLoader.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerChunkLoader.java @@ -42,8 +42,8 @@ public class EaglerChunkLoader extends AnvilChunkLoader { char[] path = new char[12]; for(int i = 5; i >= 0; --i) { - path[i] = hex.charAt((unsignedX >> (i * 4)) & 0xF); - path[i + 6] = hex.charAt((unsignedZ >> (i * 4)) & 0xF); + path[i] = hex.charAt((unsignedX >>> (i << 2)) & 0xF); + path[i + 6] = hex.charAt((unsignedZ >>> (i << 2)) & 0xF); } return new String(path); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKCompiler.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKCompiler.java index 27989d1..86e198c 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKCompiler.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/export/EPKCompiler.java @@ -49,7 +49,7 @@ public class EPKCompiler { EagRuntime.fixDateFormat(new SimpleDateFormat("hh:mm:ss aa")).format(d) + "\n\n # world name: " + name + "\n\n") .getBytes(StandardCharsets.UTF_8); - os.write((comment.length >> 8) & 255); + os.write((comment.length >>> 8) & 255); os.write(comment.length & 255); os.write(comment); @@ -134,9 +134,9 @@ public class EPKCompiler { byte[] ret = os.toByteArray(); - ret[lengthIntegerOffset] = (byte)((totalFileCount >> 24) & 0xFF); - ret[lengthIntegerOffset + 1] = (byte)((totalFileCount >> 16) & 0xFF); - ret[lengthIntegerOffset + 2] = (byte)((totalFileCount >> 8) & 0xFF); + ret[lengthIntegerOffset] = (byte)(totalFileCount >>> 24); + ret[lengthIntegerOffset + 1] = (byte)(totalFileCount >>> 16); + ret[lengthIntegerOffset + 2] = (byte)(totalFileCount >>> 8); ret[lengthIntegerOffset + 3] = (byte)(totalFileCount & 0xFF); return ret; @@ -147,21 +147,21 @@ public class EPKCompiler { } public static void writeInt(int i, OutputStream os) throws IOException { - os.write((i >> 24) & 0xFF); - os.write((i >> 16) & 0xFF); - os.write((i >> 8) & 0xFF); + os.write((i >>> 24) & 0xFF); + os.write((i >>> 16) & 0xFF); + os.write((i >>> 8) & 0xFF); os.write(i & 0xFF); } public static void writeLong(long i, OutputStream os) throws IOException { - os.write((int)((i >> 56) & 0xFF)); - os.write((int)((i >> 48) & 0xFF)); - os.write((int)((i >> 40) & 0xFF)); - os.write((int)((i >> 32) & 0xFF)); - os.write((int)((i >> 24) & 0xFF)); - os.write((int)((i >> 16) & 0xFF)); - os.write((int)((i >> 8) & 0xFF)); - os.write((int)(i & 0xFF)); + os.write((int)((i >>> 56l) & 0xFFl)); + os.write((int)((i >>> 48l) & 0xFFl)); + os.write((int)((i >>> 40l) & 0xFFl)); + os.write((int)((i >>> 32l) & 0xFFl)); + os.write((int)((i >>> 24l) & 0xFFl)); + os.write((int)((i >>> 16l) & 0xFFl)); + os.write((int)((i >>> 8l) & 0xFFl)); + os.write((int)(i & 0xFFl)); } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java index 003c447..f1f63f6 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java @@ -89,9 +89,9 @@ public class IntegratedCapePackets { byte[] ret = new byte[1 + 16 + 4]; ret[0] = (byte)PACKET_OTHER_CAPE_PRESET; IntegratedSkinPackets.UUIDToBytes(uuid, ret, 1); - ret[17] = (byte)(presetId >> 24); - ret[18] = (byte)(presetId >> 16); - ret[19] = (byte)(presetId >> 8); + ret[17] = (byte)(presetId >>> 24); + ret[18] = (byte)(presetId >>> 16); + ret[19] = (byte)(presetId >>> 8); ret[20] = (byte)(presetId & 0xFF); return ret; } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedSkinPackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedSkinPackets.java index 9080558..4c93d56 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedSkinPackets.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedSkinPackets.java @@ -143,9 +143,9 @@ public class IntegratedSkinPackets { byte[] ret = new byte[1 + 16 + 4]; ret[0] = (byte)PACKET_OTHER_SKIN_PRESET; UUIDToBytes(uuid, ret, 1); - ret[17] = (byte)(presetId >> 24); - ret[18] = (byte)(presetId >> 16); - ret[19] = (byte)(presetId >> 8); + ret[17] = (byte)(presetId >>> 24); + ret[18] = (byte)(presetId >>> 16); + ret[19] = (byte)(presetId >>> 8); ret[20] = (byte)(presetId & 0xFF); return ret; } @@ -197,21 +197,21 @@ public class IntegratedSkinPackets { public static void UUIDToBytes(EaglercraftUUID uuid, byte[] bytes, int off) { long msb = uuid.getMostSignificantBits(); long lsb = uuid.getLeastSignificantBits(); - bytes[off] = (byte)(msb >> 56l); - bytes[off + 1] = (byte)(msb >> 48l); - bytes[off + 2] = (byte)(msb >> 40l); - bytes[off + 3] = (byte)(msb >> 32l); - bytes[off + 4] = (byte)(msb >> 24l); - bytes[off + 5] = (byte)(msb >> 16l); - bytes[off + 6] = (byte)(msb >> 8l); + bytes[off] = (byte)(msb >>> 56l); + bytes[off + 1] = (byte)(msb >>> 48l); + bytes[off + 2] = (byte)(msb >>> 40l); + bytes[off + 3] = (byte)(msb >>> 32l); + bytes[off + 4] = (byte)(msb >>> 24l); + bytes[off + 5] = (byte)(msb >>> 16l); + bytes[off + 6] = (byte)(msb >>> 8l); bytes[off + 7] = (byte)(msb & 0xFFl); - bytes[off + 8] = (byte)(lsb >> 56l); - bytes[off + 9] = (byte)(lsb >> 48l); - bytes[off + 10] = (byte)(lsb >> 40l); - bytes[off + 11] = (byte)(lsb >> 32l); - bytes[off + 12] = (byte)(lsb >> 24l); - bytes[off + 13] = (byte)(lsb >> 16l); - bytes[off + 14] = (byte)(lsb >> 8l); + bytes[off + 8] = (byte)(lsb >>> 56l); + bytes[off + 9] = (byte)(lsb >>> 48l); + bytes[off + 10] = (byte)(lsb >>> 40l); + bytes[off + 11] = (byte)(lsb >>> 32l); + bytes[off + 12] = (byte)(lsb >>> 24l); + bytes[off + 13] = (byte)(lsb >>> 16l); + bytes[off + 14] = (byte)(lsb >>> 8l); bytes[off + 15] = (byte)(lsb & 0xFFl); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java index ef11493..68ce33a 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/socket/IntegratedServerPlayerNetworkManager.java @@ -253,9 +253,9 @@ public class IntegratedServerPlayerNetworkManager { byte[] compressedData; try { temporaryOutputStream.write(2); - temporaryOutputStream.write((len >> 24) & 0xFF); - temporaryOutputStream.write((len >> 16) & 0xFF); - temporaryOutputStream.write((len >> 8) & 0xFF); + temporaryOutputStream.write((len >>> 24) & 0xFF); + temporaryOutputStream.write((len >>> 16) & 0xFF); + temporaryOutputStream.write((len >>> 8) & 0xFF); temporaryOutputStream.write(len & 0xFF); try (OutputStream os = EaglerZLIB.newDeflaterOutputStream(temporaryOutputStream)) { temporaryBuffer.readBytes(os, len); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateVersionSlot.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateVersionSlot.java index 0b9c76c..0ed9008 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateVersionSlot.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateVersionSlot.java @@ -127,13 +127,13 @@ public class GuiUpdateVersionSlot extends GuiSlot { if(strs.size() > 2 && screen.mx > xx + iconSize && screen.my > yy + 8 && screen.mx < xx + getListWidth() - 5 && screen.my < yy + 25) { screen.tooltip = cert.bundleVersionComment; } - char[] hexStr1 = new char[] { hexChars[(cert.bundleDataHash[0] >> 4) & 0xF], - hexChars[cert.bundleDataHash[1] & 0xF], hexChars[(cert.bundleDataHash[1] >> 4) & 0xF], - hexChars[cert.bundleDataHash[1] & 0xF], hexChars[(cert.bundleDataHash[2] >> 4) & 0xF], + char[] hexStr1 = new char[] { hexChars[(cert.bundleDataHash[0] >>> 4) & 0xF], + hexChars[cert.bundleDataHash[1] & 0xF], hexChars[(cert.bundleDataHash[1] >>> 4) & 0xF], + hexChars[cert.bundleDataHash[1] & 0xF], hexChars[(cert.bundleDataHash[2] >>> 4) & 0xF], hexChars[cert.bundleDataHash[2] & 0xF] }; - char[] hexStr2 = new char[] { hexChars[(cert.bundleDataHash[29] >> 4) & 0xF], - hexChars[cert.bundleDataHash[29] & 0xF], hexChars[(cert.bundleDataHash[30] >> 4) & 0xF], - hexChars[cert.bundleDataHash[30] & 0xF], hexChars[(cert.bundleDataHash[31] >> 4) & 0xF], + char[] hexStr2 = new char[] { hexChars[(cert.bundleDataHash[29] >>> 4) & 0xF], + hexChars[cert.bundleDataHash[29] & 0xF], hexChars[(cert.bundleDataHash[30] >>> 4) & 0xF], + hexChars[cert.bundleDataHash[30] & 0xF], hexChars[(cert.bundleDataHash[31] >>> 4) & 0xF], hexChars[cert.bundleDataHash[31] & 0xF] }; screen.drawString(mc.fontRendererObj, "Author: " + EnumChatFormatting.GRAY + cert.bundleAuthorName + EnumChatFormatting.WHITE + " Hash: " diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java index e2a68c4..ea82e4e 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/UpdateCertificate.java @@ -152,13 +152,12 @@ public class UpdateCertificate { (byte) 88, (byte) 215, (byte) 216, (byte) 253, (byte) 235, (byte) 7, (byte) 60 }, 0, 32); sha256.update(signaturePayload, 0, signaturePayload.length); sha256.doFinal(hash2048, 96); - - hash2048[0] = (byte) ((signaturePayload.length >> 8) & 0xFF); - hash2048[1] = (byte) (signaturePayload.length & 0xFF); - - if (!Arrays.equals(hash2048, rsa2048sumDec)) { - UpdateService.logger.error("SHA256 checksum of signature payload is invalid!"); - return null; + + hash2048[0] = (byte)((signaturePayload.length >>> 8) & 0xFF); + hash2048[1] = (byte)(signaturePayload.length & 0xFF); + + if(!Arrays.equals(hash2048, rsa2048sumDec)) { + throw new CertificateInvalidException("SHA256 checksum of signature payload is invalid!"); } UpdateCertificate cert; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java index c1485cb..19e0503 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java @@ -615,9 +615,9 @@ public class GuiVoiceMenu extends Gui { } public static int attenuate(int cin, float r, float g, float b, float a) { - float var10 = (float) (cin >> 24 & 255) / 255.0F; - float var6 = (float) (cin >> 16 & 255) / 255.0F; - float var7 = (float) (cin >> 8 & 255) / 255.0F; + float var10 = (float) (cin >>> 24 & 255) / 255.0F; + float var6 = (float) (cin >>> 16 & 255) / 255.0F; + float var7 = (float) (cin >>> 8 & 255) / 255.0F; float var8 = (float) (cin & 255) / 255.0F; var10 *= a; var6 *= r; diff --git a/src/main/java/net/minecraft/client/Minecraft.java b/src/main/java/net/minecraft/client/Minecraft.java index afd326c..ff9b9e4 100644 --- a/src/main/java/net/minecraft/client/Minecraft.java +++ b/src/main/java/net/minecraft/client/Minecraft.java @@ -1827,6 +1827,7 @@ public class Minecraft implements IThreadListener { session.reset(); SingleplayerServerController.launchEaglercraftServer(folderName, gameSettings.difficulty.getDifficultyId(), Math.max(gameSettings.renderDistanceChunks, 2), worldSettingsIn); + EagRuntime.setMCServerWindowGlobal("singleplayer"); this.displayGuiScreen(new GuiScreenIntegratedServerBusy( new GuiScreenSingleplayerConnecting(new GuiMainMenu(), "Connecting to " + folderName), "singleplayer.busy.startingIntegratedServer", "singleplayer.failed.startingIntegratedServer", @@ -2115,6 +2116,22 @@ public class Minecraft implements IThreadListener { + EaglercraftGPU.glGetString(7936); } }); + theCrash.getCategory().addCrashSectionCallable("Is Eagler Shaders", new Callable() { + public String call() throws Exception { + return Minecraft.this.gameSettings.shaders ? "Yes" : "No"; + } + }); + theCrash.getCategory().addCrashSectionCallable("Is Dynamic Lights", new Callable() { + public String call() throws Exception { + return !Minecraft.this.gameSettings.shaders && Minecraft.this.gameSettings.enableDynamicLights ? "Yes" + : "No"; + } + }); + theCrash.getCategory().addCrashSectionCallable("In Ext. Pipeline", new Callable() { + public String call() throws Exception { + return GlStateManager.isExtensionPipeline() ? "Yes" : "No"; + } + }); theCrash.getCategory().addCrashSectionCallable("Is Modded", new Callable() { public String call() throws Exception { return "Definitely Not; You're an eagler"; @@ -2197,6 +2214,7 @@ public class Minecraft implements IThreadListener { */ public void setServerData(ServerData serverDataIn) { this.currentServerData = serverDataIn; + EagRuntime.setMCServerWindowGlobal(serverDataIn != null ? serverDataIn.serverIP : null); } public ServerData getCurrentServerData() { diff --git a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java index 16cda39..69b9f33 100644 --- a/src/main/java/net/minecraft/client/gui/GuiMainMenu.java +++ b/src/main/java/net/minecraft/client/gui/GuiMainMenu.java @@ -598,8 +598,10 @@ public class GuiMainMenu extends GuiScreen implements GuiYesNoCallback { short short1 = 274; int k = this.width / 2 - short1 / 2; byte b0 = 30; - this.drawGradientRect(0, 0, this.width, this.height, -2130706433, 16777215); - this.drawGradientRect(0, 0, this.width, this.height, 0, Integer.MIN_VALUE); + if (enableBlur) { + this.drawGradientRect(0, 0, this.width, this.height, -2130706433, 16777215); + this.drawGradientRect(0, 0, this.width, this.height, 0, Integer.MIN_VALUE); + } this.mc.getTextureManager().bindTexture(minecraftTitleTextures); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); boolean minc = (double) this.updateCounter < 1.0E-4D; diff --git a/src/main/java/net/minecraft/client/gui/MapItemRenderer.java b/src/main/java/net/minecraft/client/gui/MapItemRenderer.java index aaf4031..c563f52 100644 --- a/src/main/java/net/minecraft/client/gui/MapItemRenderer.java +++ b/src/main/java/net/minecraft/client/gui/MapItemRenderer.java @@ -129,7 +129,7 @@ public class MapItemRenderer { } else { c = MapColor.mapColorArray[j / 4].func_151643_b(j & 3); } - this.mapTextureData[i] = (c & 0xFF00FF00) | ((c & 0x00FF0000) >> 16) | ((c & 0x000000FF) << 16); + this.mapTextureData[i] = (c & 0xFF00FF00) | ((c & 0x00FF0000) >>> 16) | ((c & 0x000000FF) << 16); } this.mapTexture.updateDynamicTexture(); diff --git a/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java b/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java index 5850ae3..fd8d05a 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java +++ b/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java @@ -366,9 +366,9 @@ public abstract class RendererLivingEntity extends R return false; } else { GlStateManager.enableShaderBlendAdd(); - float f1 = 1.0F - (float) (i >> 24 & 255) / 255.0F; - float f2 = (float) (i >> 16 & 255) / 255.0F; - float f3 = (float) (i >> 8 & 255) / 255.0F; + float f1 = 1.0F - (float) (i >>> 24 & 255) / 255.0F; + float f2 = (float) (i >>> 16 & 255) / 255.0F; + float f3 = (float) (i >>> 8 & 255) / 255.0F; float f4 = (float) (i & 255) / 255.0F; GlStateManager.setShaderBlendSrc(f1, f1, f1, 1.0F); GlStateManager.setShaderBlendAdd(f2 * f1 + 0.4F, f3 * f1, f4 * f1, 0.0f); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java index adfc28c..c93657e 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformApplication.java @@ -320,4 +320,7 @@ public class PlatformApplication { public static boolean isShowingDebugConsole() { return DebugConsoleWindow.isShowingDebugConsole(); } + + @JSBody(params = { "str" }, script = "window.minecraftServer = str;") + public static native void setMCServerWindowGlobal(String str); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java index 67e2379..c4da90b 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -630,6 +630,10 @@ public class PlatformInput { Window.clearTimeout(mouseUngrabTimeout); mouseUngrabTimeout = -1; } + try { + win.getDocument().exitPointerLock(); + }catch(Throwable t) { + } } public static void pressAnyKeyScreen() { diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java index aa2eceb..2dfd5ab 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformRuntime.java @@ -1,646 +1,647 @@ -package net.lax1dude.eaglercraft.v1_8.internal; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.function.Consumer; - -import net.lax1dude.eaglercraft.v1_8.EagRuntime; -import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; -import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; -import org.teavm.interop.Async; -import org.teavm.interop.AsyncCallback; -import org.teavm.jso.JSBody; -import org.teavm.jso.JSExceptions; -import org.teavm.jso.JSFunctor; -import org.teavm.jso.JSObject; -import org.teavm.jso.ajax.XMLHttpRequest; -import org.teavm.jso.browser.Window; -import org.teavm.jso.canvas.CanvasRenderingContext2D; -import org.teavm.jso.core.JSError; -import org.teavm.jso.dom.css.CSSStyleDeclaration; -import org.teavm.jso.dom.events.Event; -import org.teavm.jso.dom.events.EventListener; -import org.teavm.jso.dom.html.HTMLAnchorElement; -import org.teavm.jso.dom.html.HTMLCanvasElement; -import org.teavm.jso.dom.html.HTMLDocument; -import org.teavm.jso.dom.html.HTMLElement; -import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.webaudio.MediaStream; -import org.teavm.jso.webgl.WebGLFramebuffer; - -import com.jcraft.jzlib.DeflaterOutputStream; -import com.jcraft.jzlib.GZIPInputStream; -import com.jcraft.jzlib.GZIPOutputStream; -import com.jcraft.jzlib.InflaterInputStream; - -import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.FilesystemDatabaseLockedException; -import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; -import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerArrayBufferAllocator; -import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; -import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.EPKLoader; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.EarlyLoadScreen; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.FixWebMDurationJS; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain.EPKFileEntry; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.DebugConsoleWindow; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMClientConfigAdapter; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext; -import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; -import net.lax1dude.eaglercraft.v1_8.log4j.Logger; -import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack; -import net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums; - -/** - * Copyright (c) 2022-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights - * Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public class PlatformRuntime { - - static final Logger logger = LogManager.getLogger("BrowserRuntime"); - - public static Window win = null; - public static HTMLDocument doc = null; - public static HTMLElement parent = null; - public static HTMLCanvasElement canvas = null; - public static WebGL2RenderingContext webgl = null; - - static WebGLFramebuffer mainFramebuffer = null; - - public static void create() { - win = Window.current(); - doc = win.getDocument(); - DebugConsoleWindow.initialize(win); - - logger.info("Creating main game canvas"); - - parent = doc.getElementById(ClientMain.configRootElementId); - if (parent == null) { - throw new RuntimeInitializationFailureException( - "Root element \"" + ClientMain.configRootElementId + "\" was not found in this document!"); - } - - CSSStyleDeclaration style = parent.getStyle(); - style.setProperty("overflowX", "hidden"); - style.setProperty("overflowY", "hidden"); - - canvas = (HTMLCanvasElement) doc.createElement("canvas"); - - style = canvas.getStyle(); - style.setProperty("width", "100%"); - style.setProperty("height", "100%"); - style.setProperty("image-rendering", "pixelated"); - - double r = win.getDevicePixelRatio(); - int iw = (int) (parent.getClientWidth()); - int ih = (int) (parent.getClientHeight()); - int sw = (int) (r * iw); - int sh = (int) (r * ih); - - canvas.setWidth(sw); - canvas.setHeight(sh); - - parent.appendChild(canvas); - - try { - PlatformInput.initHooks(win, canvas); - } catch (Throwable t) { - throw new RuntimeInitializationFailureException("Exception while registering window event handlers", t); - } - - try { - doc.exitPointerLock(); - } catch (Throwable t) { - throw new PlatformIncompatibleException("Mouse cursor lock is not available on this device!"); - } - - logger.info("Creating WebGL context"); - - JSObject webgl_ = canvas.getContext("webgl2", youEagler()); - if (webgl_ == null) { - throw new PlatformIncompatibleException("WebGL 2.0 is not supported on this device!"); - } - - webgl = (WebGL2RenderingContext) webgl_; - PlatformOpenGL.setCurrentContext(webgl); - - mainFramebuffer = webgl.createFramebuffer(); - PlatformInput.initFramebuffer(webgl, mainFramebuffer, sw, sh); - - EarlyLoadScreen.paintScreen(); - - EPKFileEntry[] epkFiles = ClientMain.configEPKFiles; - - for (int i = 0; i < epkFiles.length; ++i) { - String url = epkFiles[i].url; - String logURL = url.startsWith("data:") ? "" : url; - - logger.info("Downloading: {}", logURL); - - ArrayBuffer epkFileData = downloadRemoteURI(url); - - if (epkFileData == null) { - throw new RuntimeInitializationFailureException("Could not download EPK file \"" + url + "\""); - } - - logger.info("Decompressing: {}", logURL); - - try { - EPKLoader.loadEPK(epkFileData, epkFiles[i].path, PlatformAssets.assets); - } catch (Throwable t) { - throw new RuntimeInitializationFailureException("Could not extract EPK file \"" + url + "\"", t); - } - } - - logger.info("Loaded {} resources from EPKs", PlatformAssets.assets.size()); - - byte[] finalLoadScreen = PlatformAssets.getResourceBytes("/assets/eagler/eagtek.png"); - - logger.info("Initializing filesystem..."); - - try { - PlatformFilesystem.initialize(getClientConfigAdapter().getResourcePacksDB()); - EaglerFolderResourcePack.setSupported(true); - } catch (FilesystemDatabaseLockedException t) { - logger.error("Could not initialize filesystem, database is locked!"); - } catch (Throwable t) { - logger.error("Could not initialize filesystem, encountered an exception!"); - logger.error(t); - } - - if (!EaglerFolderResourcePack.isSupported()) { - logger.error("Resource packs will be disabled for this session"); - } - - logger.info("Initializing sound engine..."); - - PlatformInput.pressAnyKeyScreen(); - - PlatformAudio.initialize(); - - if (finalLoadScreen != null) { - EarlyLoadScreen.paintFinal(finalLoadScreen); - } - - EarlyLoadScreen.destroy(); - - logger.info("Platform initialization complete"); - - FixWebMDurationJS.checkOldScriptStillLoaded(); - } - - @JSBody(params = {}, script = "return {antialias: false, depth: false, powerPreference: \"high-performance\", desynchronized: true, preserveDrawingBuffer: false, premultipliedAlpha: false, alpha: false, stencil: false, failIfMajorPerformanceCaveat: false, xrCompatible: false, xrWebGLLayer: false};") - public static native JSObject youEagler(); - - public static class RuntimeInitializationFailureException extends IllegalStateException { - - public RuntimeInitializationFailureException(String message, Throwable cause) { - super(message, cause); - } - - public RuntimeInitializationFailureException(String s) { - super(s); - } - - } - - public static class PlatformIncompatibleException extends IllegalStateException { - - public PlatformIncompatibleException(String s) { - super(s); - } - - } - - public static void destroy() { - logger.fatal("Game tried to destroy the context! Browser runtime can't do that"); - } - - public static EnumPlatformType getPlatformType() { - return EnumPlatformType.JAVASCRIPT; - } - - public static EnumPlatformAgent getPlatformAgent() { - return EnumPlatformAgent.getFromUA(getUserAgentString()); - } - - @JSBody(params = {}, script = "return window.navigator.userAgent;") - public static native String getUserAgentString(); - - public static EnumPlatformOS getPlatformOS() { - return EnumPlatformOS.getFromUA(getUserAgentString()); - } - - public static void requestANGLE(EnumPlatformANGLE plaf) { - } - - public static EnumPlatformANGLE getPlatformANGLE() { - return EnumPlatformANGLE.fromGLRendererString(getGLRenderer()); - } - - public static String getGLVersion() { - return PlatformOpenGL._wglGetString(RealOpenGLEnums.GL_VERSION); - } - - public static String getGLRenderer() { - return PlatformOpenGL._wglGetString(RealOpenGLEnums.GL_RENDERER); - } - - public static ByteBuffer allocateByteBuffer(int length) { - return EaglerArrayBufferAllocator.allocateByteBuffer(length); - } - - public static IntBuffer allocateIntBuffer(int length) { - return EaglerArrayBufferAllocator.allocateIntBuffer(length); - } - - public static FloatBuffer allocateFloatBuffer(int length) { - return EaglerArrayBufferAllocator.allocateFloatBuffer(length); - } - - public static ByteBuffer castPrimitiveByteArray(byte[] array) { - return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(TeaVMUtils.unwrapByteArray(array)); - } - - public static IntBuffer castPrimitiveIntArray(int[] array) { - return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(TeaVMUtils.unwrapIntArray(array)); - } - - public static FloatBuffer castPrimitiveFloatArray(float[] array) { - return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(TeaVMUtils.unwrapFloatArray(array)); - } - - public static byte[] castNativeByteBuffer(ByteBuffer buffer) { - return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataView8Unsigned(buffer)); - } - - public static int[] castNativeIntBuffer(IntBuffer buffer) { - return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataView32(buffer)); - } - - public static float[] castNativeFloatBuffer(FloatBuffer buffer) { - return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getDataView32F(buffer)); - } - - public static void freeByteBuffer(ByteBuffer byteBuffer) { - - } - - public static void freeIntBuffer(IntBuffer intBuffer) { - - } - - public static void freeFloatBuffer(FloatBuffer floatBuffer) { - - } - - public static void downloadRemoteURIByteArray(String assetPackageURI, final Consumer cb) { - downloadRemoteURI(assetPackageURI, arr -> cb.accept(TeaVMUtils.wrapByteArrayBuffer(arr))); - } - - public static void downloadRemoteURI(String assetPackageURI, final Consumer cb) { - downloadRemoteURI(assetPackageURI, false, cb); - } - - public static void downloadRemoteURI(String assetPackageURI, boolean useCache, final Consumer cb) { - downloadRemoteURI(assetPackageURI, useCache, new AsyncCallback() { - @Override - public void complete(ArrayBuffer result) { - cb.accept(result); - } - - @Override - public void error(Throwable e) { - EagRuntime.debugPrintStackTrace(e); - cb.accept(null); - } - }); - } - - @Async - public static native ArrayBuffer downloadRemoteURIOld(String assetPackageURI); - - private static void downloadRemoteURIOld(String assetPackageURI, final AsyncCallback cb) { - final XMLHttpRequest request = XMLHttpRequest.create(); - request.setResponseType("arraybuffer"); - request.open("GET", assetPackageURI, true); - - TeaVMUtils.addEventListener(request, "load", new EventListener() { - @Override - public void handleEvent(Event evt) { - int stat = request.getStatus(); - if (stat == 0 || (stat >= 200 && stat < 400)) { - cb.complete((ArrayBuffer) request.getResponse()); - } else { - cb.complete(null); - } - } - }); - - TeaVMUtils.addEventListener(request, "error", new EventListener() { - @Override - public void handleEvent(Event evt) { - cb.complete(null); - } - }); - - request.send(); - } - - @JSFunctor - private static interface FetchHandler extends JSObject { - void onFetch(ArrayBuffer data); - } - - @JSBody(params = { "uri", "forceCache", "callback" }, script = "fetch(uri, { cache: forceCache, mode: \"cors\" })" - + ".then(function(res) { return res.arrayBuffer(); }).then(function(arr) { callback(arr); })" - + ".catch(function(err) { console.error(err); callback(null); });") - private static native void doFetchDownload(String uri, String forceCache, FetchHandler callback); - - public static ArrayBuffer downloadRemoteURI(String assetPackageURI) { - return downloadRemoteURI(assetPackageURI, true); - } - - @Async - public static native ArrayBuffer downloadRemoteURI(String assetPackageURI, boolean forceCache); - - private static void downloadRemoteURI(String assetPackageURI, boolean useCache, - final AsyncCallback cb) { - doFetchDownload(assetPackageURI, useCache ? "force-cache" : "no-store", cb::complete); - } - - public static boolean isDebugRuntime() { - return false; - } - - public static void writeCrashReport(String crashDump) { - ClientMain.showCrashScreen(crashDump); - } - - public static void removeEventHandlers() { - try { - PlatformInput.removeEventHandlers(); - } catch (Throwable t) { - } - } - - public static void getStackTrace(Throwable t, Consumer ret) { - JSObject o = JSExceptions.getJSException(t); - if (o != null) { - try { - JSError err = o.cast(); - String stack = err.getStack(); - if (stack != null) { - String[] stackElements = stack.split("[\\r\\n]+"); - if (stackElements.length > 0) { - for (int i = 0; i < stackElements.length; ++i) { - String str = stackElements[i].trim(); - if (str.startsWith("at ")) { - str = str.substring(3).trim(); - } - ret.accept(str); - } - return; - } - } - } catch (Throwable tt) { - ret.accept("[ error: " + t.toString() + " ]"); - } - } - getFallbackStackTrace(t, ret); - } - - private static void getFallbackStackTrace(Throwable t, Consumer ret) { - StackTraceElement[] el = t.getStackTrace(); - if (el.length > 0) { - for (int i = 0; i < el.length; ++i) { - ret.accept(el[i].toString()); - } - } else { - ret.accept("[no stack trace]"); - } - } - - @JSBody(params = { "o" }, script = "console.error(o);") - public static native void printNativeExceptionToConsoleTeaVM(JSObject o); - - public static boolean printJSExceptionIfBrowser(Throwable t) { - if (t != null) { - JSObject o = JSExceptions.getJSException(t); - if (o != null) { - printNativeExceptionToConsoleTeaVM(o); - return true; - } - } - return false; - } - - public static void exit() { - logger.fatal("Game is attempting to exit!"); - } - - public static void setThreadName(String string) { - currentThreadName = string; - } - - public static long maxMemory() { - return 1073741824l; - } - - public static long totalMemory() { - return 1073741824l; - } - - public static long freeMemory() { - return 1073741824l; - } - - public static String getCallingClass(int backTrace) { - return null; - } - - public static OutputStream newDeflaterOutputStream(OutputStream os) throws IOException { - return new DeflaterOutputStream(os); - } - - public static OutputStream newGZIPOutputStream(OutputStream os) throws IOException { - return new GZIPOutputStream(os); - } - - public static InputStream newInflaterInputStream(InputStream is) throws IOException { - return new InflaterInputStream(is); - } - - public static InputStream newGZIPInputStream(InputStream is) throws IOException { - return new GZIPInputStream(is); - } - - @JSBody(params = {}, script = "return window.location.protocol && window.location.protocol.toLowerCase().startsWith(\"https\");") - public static native boolean requireSSL(); - - @JSBody(params = {}, script = "return window.location.protocol && window.location.protocol.toLowerCase().startsWith(\"file\");") - public static native boolean isOfflineDownloadURL(); - - public static IClientConfigAdapter getClientConfigAdapter() { - return TeaVMClientConfigAdapter.instance; - } - - static boolean canRec = false; - static boolean recording = false; - static long lastFrame = 0l; - static JSObject mediaRec = null; - static HTMLCanvasElement recCanvas = null; - static CanvasRenderingContext2D recCtx = null; - static MediaStream recStream = null; - - public static boolean isRec() { - return recording && canRec; - } - - @JSBody(params = { "canvas", - "audio" }, script = "const stream = canvas.captureStream(); stream.addTrack(audio.getTracks()[0]); return stream;") - private static native MediaStream captureStreamAndAddAudio(HTMLCanvasElement canvas, MediaStream audio); - - @JSBody(params = { - "stream" }, script = "const rec = new MediaRecorder(stream, { mimeType: MediaRecorder.isTypeSupported(\"video/webm;codecs=vp9,opus\") ? \"video/webm;codecs=vp9,opus\" : \"video/webm\" }); rec.start(); return rec;") - private static native JSObject createMediaRecorder(MediaStream stream); - - @JSBody(params = { "rec" }, script = "rec.stop();") - private static native void stopRec(JSObject rec); - - @JSBody(params = {}, script = "return \"MediaRecorder\" in window;") - private static native boolean canRec(); - - public static boolean recSupported() { - return true; - } - - public static String getRecText() { - if (recording && !canRec) { - return "recording.unsupported"; - } - return recording ? "recording.stop" : "recording.start"; - } - - static void recFrame() { - if (mediaRec != null) { - int w = PlatformRuntime.canvas.getWidth(); - int h = PlatformRuntime.canvas.getHeight(); - if (recCanvas.getWidth() != w || recCanvas.getHeight() != h) { - recCanvas.setWidth(w); - recCanvas.setHeight(h); - } - recCtx.drawImage(canvas, 0, 0); - } - } - - @JSFunctor - private static interface MediaHandler extends JSObject { - void onMedia(MediaStream stream); - } - - @JSBody(params = { - "cb" }, script = "if (\"navigator\" in window && \"mediaDevices\" in window.navigator && \"getUserMedia\" in window.navigator.mediaDevices) { try { window.navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(function(stream) { cb(stream); }).catch(function(err) { console.error(err); cb(null); }); } catch(e) { console.error(\"getUserMedia Error!\"); cb(null); } } else { console.error(\"No getUserMedia!\"); cb(null); }") - private static native void getMic0(MediaHandler cb); - - @Async - private static native MediaStream getMic1(); - - private static void getMic1(AsyncCallback cb) { - getMic0(cb::complete); - } - - private static boolean canMic = true; - private static MediaStream mic = null; - - protected static MediaStream getMic() { - if (canMic) { - if (mic == null) { - mic = getMic1(); - if (mic == null) { - canMic = false; - return null; - } - return mic; - } - return mic; - } - return null; - } - - private static final SimpleDateFormat fmt = EagRuntime.fixDateFormat(new SimpleDateFormat("yyyy-MM-dd hh-mm-ss")); - private static final Date dateInstance = new Date(); - - public static void toggleRec() { - if (recording && !canRec) { - return; - } - recording = !recording; - if (recording) { - if (!canRec) { - canRec = canRec(); - if (!canRec) { - return; - } - } - if (recCanvas == null) { - recCanvas = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); - recCtx = (CanvasRenderingContext2D) recCanvas.getContext("2d"); - PlatformAudio.initRecDest(); - recStream = captureStreamAndAddAudio(recCanvas, PlatformAudio.getRecStream()); - } - mediaRec = createMediaRecorder(recStream); - long startTime = System.currentTimeMillis(); - TeaVMUtils.addEventListener(mediaRec, "dataavailable", new EventListener() { - @Override - public void handleEvent(Event evt) { - FixWebMDurationJS.getRecUrl(evt, (int) (System.currentTimeMillis() - startTime), url -> { - HTMLAnchorElement a = (HTMLAnchorElement) doc.createElement("a"); - dateInstance.setTime(startTime); - a.setDownload(EaglercraftVersion.mainMenuStringB + " - " + EaglerProfile.getName() + " - " - + fmt.format(dateInstance) + ".webm"); - a.setHref(url); - a.click(); - TeaVMUtils.freeDataURL(url); - }, logger::info); - } - }); - } else { - stopRec(mediaRec); - mediaRec = null; - } - } - - public static long randomSeed() { - return (long) (Math.random() * 9007199254740991.0); - } - - private static String currentThreadName = "main"; - - public static String currentThreadName() { - return currentThreadName; - } -} +package net.lax1dude.eaglercraft.v1_8.internal; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.function.Consumer; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; +import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; +import org.teavm.interop.Async; +import org.teavm.interop.AsyncCallback; +import org.teavm.jso.JSBody; +import org.teavm.jso.JSExceptions; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.ajax.XMLHttpRequest; +import org.teavm.jso.browser.Window; +import org.teavm.jso.canvas.CanvasRenderingContext2D; +import org.teavm.jso.core.JSError; +import org.teavm.jso.dom.css.CSSStyleDeclaration; +import org.teavm.jso.dom.events.Event; +import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.html.HTMLAnchorElement; +import org.teavm.jso.dom.html.HTMLCanvasElement; +import org.teavm.jso.dom.html.HTMLDocument; +import org.teavm.jso.dom.html.HTMLElement; +import org.teavm.jso.typedarrays.ArrayBuffer; +import org.teavm.jso.webaudio.MediaStream; +import org.teavm.jso.webgl.WebGLFramebuffer; + +import com.jcraft.jzlib.DeflaterOutputStream; +import com.jcraft.jzlib.GZIPInputStream; +import com.jcraft.jzlib.GZIPOutputStream; +import com.jcraft.jzlib.InflaterInputStream; + +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.FilesystemDatabaseLockedException; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerArrayBufferAllocator; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.FloatBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.EPKLoader; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.EarlyLoadScreen; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.FixWebMDurationJS; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.ClientMain.EPKFileEntry; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.DebugConsoleWindow; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMClientConfigAdapter; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.WebGL2RenderingContext; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack; +import net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums; + +/** + * Copyright (c) 2022-2024 lax1dude, hoosiertransfer, ayunami2000. All Rights + * Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class PlatformRuntime { + + static final Logger logger = LogManager.getLogger("BrowserRuntime"); + + public static Window win = null; + public static HTMLDocument doc = null; + public static HTMLElement parent = null; + public static HTMLCanvasElement canvas = null; + public static WebGL2RenderingContext webgl = null; + + static WebGLFramebuffer mainFramebuffer = null; + + public static void create() { + win = Window.current(); + doc = win.getDocument(); + DebugConsoleWindow.initialize(win); + PlatformApplication.setMCServerWindowGlobal(null); + + logger.info("Creating main game canvas"); + + parent = doc.getElementById(ClientMain.configRootElementId); + if (parent == null) { + throw new RuntimeInitializationFailureException( + "Root element \"" + ClientMain.configRootElementId + "\" was not found in this document!"); + } + + CSSStyleDeclaration style = parent.getStyle(); + style.setProperty("overflowX", "hidden"); + style.setProperty("overflowY", "hidden"); + + canvas = (HTMLCanvasElement) doc.createElement("canvas"); + + style = canvas.getStyle(); + style.setProperty("width", "100%"); + style.setProperty("height", "100%"); + style.setProperty("image-rendering", "pixelated"); + + double r = win.getDevicePixelRatio(); + int iw = (int) (parent.getClientWidth()); + int ih = (int) (parent.getClientHeight()); + int sw = (int) (r * iw); + int sh = (int) (r * ih); + + canvas.setWidth(sw); + canvas.setHeight(sh); + + parent.appendChild(canvas); + + try { + PlatformInput.initHooks(win, canvas); + } catch (Throwable t) { + throw new RuntimeInitializationFailureException("Exception while registering window event handlers", t); + } + + try { + doc.exitPointerLock(); + } catch (Throwable t) { + throw new PlatformIncompatibleException("Mouse cursor lock is not available on this device!"); + } + + logger.info("Creating WebGL context"); + + JSObject webgl_ = canvas.getContext("webgl2", youEagler()); + if (webgl_ == null) { + throw new PlatformIncompatibleException("WebGL 2.0 is not supported on this device!"); + } + + webgl = (WebGL2RenderingContext) webgl_; + PlatformOpenGL.setCurrentContext(webgl); + + mainFramebuffer = webgl.createFramebuffer(); + PlatformInput.initFramebuffer(webgl, mainFramebuffer, sw, sh); + + EarlyLoadScreen.paintScreen(); + + EPKFileEntry[] epkFiles = ClientMain.configEPKFiles; + + for (int i = 0; i < epkFiles.length; ++i) { + String url = epkFiles[i].url; + String logURL = url.startsWith("data:") ? "" : url; + + logger.info("Downloading: {}", logURL); + + ArrayBuffer epkFileData = downloadRemoteURI(url); + + if (epkFileData == null) { + throw new RuntimeInitializationFailureException("Could not download EPK file \"" + url + "\""); + } + + logger.info("Decompressing: {}", logURL); + + try { + EPKLoader.loadEPK(epkFileData, epkFiles[i].path, PlatformAssets.assets); + } catch (Throwable t) { + throw new RuntimeInitializationFailureException("Could not extract EPK file \"" + url + "\"", t); + } + } + + logger.info("Loaded {} resources from EPKs", PlatformAssets.assets.size()); + + byte[] finalLoadScreen = PlatformAssets.getResourceBytes("/assets/eagler/eagtek.png"); + + logger.info("Initializing filesystem..."); + + try { + PlatformFilesystem.initialize(getClientConfigAdapter().getResourcePacksDB()); + EaglerFolderResourcePack.setSupported(true); + } catch (FilesystemDatabaseLockedException t) { + logger.error("Could not initialize filesystem, database is locked!"); + } catch (Throwable t) { + logger.error("Could not initialize filesystem, encountered an exception!"); + logger.error(t); + } + + if (!EaglerFolderResourcePack.isSupported()) { + logger.error("Resource packs will be disabled for this session"); + } + + logger.info("Initializing sound engine..."); + + PlatformInput.pressAnyKeyScreen(); + + PlatformAudio.initialize(); + + if (finalLoadScreen != null) { + EarlyLoadScreen.paintFinal(finalLoadScreen); + } + + EarlyLoadScreen.destroy(); + + logger.info("Platform initialization complete"); + + FixWebMDurationJS.checkOldScriptStillLoaded(); + } + + @JSBody(params = {}, script = "return {antialias: false, depth: false, powerPreference: \"high-performance\", desynchronized: true, preserveDrawingBuffer: false, premultipliedAlpha: false, alpha: false, stencil: false, failIfMajorPerformanceCaveat: false, xrCompatible: false, xrWebGLLayer: false};") + public static native JSObject youEagler(); + + public static class RuntimeInitializationFailureException extends IllegalStateException { + + public RuntimeInitializationFailureException(String message, Throwable cause) { + super(message, cause); + } + + public RuntimeInitializationFailureException(String s) { + super(s); + } + + } + + public static class PlatformIncompatibleException extends IllegalStateException { + + public PlatformIncompatibleException(String s) { + super(s); + } + + } + + public static void destroy() { + logger.fatal("Game tried to destroy the context! Browser runtime can't do that"); + } + + public static EnumPlatformType getPlatformType() { + return EnumPlatformType.JAVASCRIPT; + } + + public static EnumPlatformAgent getPlatformAgent() { + return EnumPlatformAgent.getFromUA(getUserAgentString()); + } + + @JSBody(params = {}, script = "return window.navigator.userAgent;") + public static native String getUserAgentString(); + + public static EnumPlatformOS getPlatformOS() { + return EnumPlatformOS.getFromUA(getUserAgentString()); + } + + public static void requestANGLE(EnumPlatformANGLE plaf) { + } + + public static EnumPlatformANGLE getPlatformANGLE() { + return EnumPlatformANGLE.fromGLRendererString(getGLRenderer()); + } + + public static String getGLVersion() { + return PlatformOpenGL._wglGetString(RealOpenGLEnums.GL_VERSION); + } + + public static String getGLRenderer() { + return PlatformOpenGL._wglGetString(RealOpenGLEnums.GL_RENDERER); + } + + public static ByteBuffer allocateByteBuffer(int length) { + return EaglerArrayBufferAllocator.allocateByteBuffer(length); + } + + public static IntBuffer allocateIntBuffer(int length) { + return EaglerArrayBufferAllocator.allocateIntBuffer(length); + } + + public static FloatBuffer allocateFloatBuffer(int length) { + return EaglerArrayBufferAllocator.allocateFloatBuffer(length); + } + + public static ByteBuffer castPrimitiveByteArray(byte[] array) { + return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(TeaVMUtils.unwrapByteArray(array)); + } + + public static IntBuffer castPrimitiveIntArray(int[] array) { + return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(TeaVMUtils.unwrapIntArray(array)); + } + + public static FloatBuffer castPrimitiveFloatArray(float[] array) { + return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(TeaVMUtils.unwrapFloatArray(array)); + } + + public static byte[] castNativeByteBuffer(ByteBuffer buffer) { + return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataView8Unsigned(buffer)); + } + + public static int[] castNativeIntBuffer(IntBuffer buffer) { + return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataView32(buffer)); + } + + public static float[] castNativeFloatBuffer(FloatBuffer buffer) { + return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getDataView32F(buffer)); + } + + public static void freeByteBuffer(ByteBuffer byteBuffer) { + + } + + public static void freeIntBuffer(IntBuffer intBuffer) { + + } + + public static void freeFloatBuffer(FloatBuffer floatBuffer) { + + } + + public static void downloadRemoteURIByteArray(String assetPackageURI, final Consumer cb) { + downloadRemoteURI(assetPackageURI, arr -> cb.accept(TeaVMUtils.wrapByteArrayBuffer(arr))); + } + + public static void downloadRemoteURI(String assetPackageURI, final Consumer cb) { + downloadRemoteURI(assetPackageURI, false, cb); + } + + public static void downloadRemoteURI(String assetPackageURI, boolean useCache, final Consumer cb) { + downloadRemoteURI(assetPackageURI, useCache, new AsyncCallback() { + @Override + public void complete(ArrayBuffer result) { + cb.accept(result); + } + + @Override + public void error(Throwable e) { + EagRuntime.debugPrintStackTrace(e); + cb.accept(null); + } + }); + } + + @Async + public static native ArrayBuffer downloadRemoteURIOld(String assetPackageURI); + + private static void downloadRemoteURIOld(String assetPackageURI, final AsyncCallback cb) { + final XMLHttpRequest request = XMLHttpRequest.create(); + request.setResponseType("arraybuffer"); + request.open("GET", assetPackageURI, true); + + TeaVMUtils.addEventListener(request, "load", new EventListener() { + @Override + public void handleEvent(Event evt) { + int stat = request.getStatus(); + if (stat == 0 || (stat >= 200 && stat < 400)) { + cb.complete((ArrayBuffer) request.getResponse()); + } else { + cb.complete(null); + } + } + }); + + TeaVMUtils.addEventListener(request, "error", new EventListener() { + @Override + public void handleEvent(Event evt) { + cb.complete(null); + } + }); + + request.send(); + } + + @JSFunctor + private static interface FetchHandler extends JSObject { + void onFetch(ArrayBuffer data); + } + + @JSBody(params = { "uri", "forceCache", "callback" }, script = "fetch(uri, { cache: forceCache, mode: \"cors\" })" + + ".then(function(res) { return res.arrayBuffer(); }).then(function(arr) { callback(arr); })" + + ".catch(function(err) { console.error(err); callback(null); });") + private static native void doFetchDownload(String uri, String forceCache, FetchHandler callback); + + public static ArrayBuffer downloadRemoteURI(String assetPackageURI) { + return downloadRemoteURI(assetPackageURI, true); + } + + @Async + public static native ArrayBuffer downloadRemoteURI(String assetPackageURI, boolean forceCache); + + private static void downloadRemoteURI(String assetPackageURI, boolean useCache, + final AsyncCallback cb) { + doFetchDownload(assetPackageURI, useCache ? "force-cache" : "no-store", cb::complete); + } + + public static boolean isDebugRuntime() { + return false; + } + + public static void writeCrashReport(String crashDump) { + ClientMain.showCrashScreen(crashDump); + } + + public static void removeEventHandlers() { + try { + PlatformInput.removeEventHandlers(); + } catch (Throwable t) { + } + } + + public static void getStackTrace(Throwable t, Consumer ret) { + JSObject o = JSExceptions.getJSException(t); + if (o != null) { + try { + JSError err = o.cast(); + String stack = err.getStack(); + if (stack != null) { + String[] stackElements = stack.split("[\\r\\n]+"); + if (stackElements.length > 0) { + for (int i = 0; i < stackElements.length; ++i) { + String str = stackElements[i].trim(); + if (str.startsWith("at ")) { + str = str.substring(3).trim(); + } + ret.accept(str); + } + return; + } + } + } catch (Throwable tt) { + ret.accept("[ error: " + t.toString() + " ]"); + } + } + getFallbackStackTrace(t, ret); + } + + private static void getFallbackStackTrace(Throwable t, Consumer ret) { + StackTraceElement[] el = t.getStackTrace(); + if (el.length > 0) { + for (int i = 0; i < el.length; ++i) { + ret.accept(el[i].toString()); + } + } else { + ret.accept("[no stack trace]"); + } + } + + @JSBody(params = { "o" }, script = "console.error(o);") + public static native void printNativeExceptionToConsoleTeaVM(JSObject o); + + public static boolean printJSExceptionIfBrowser(Throwable t) { + if (t != null) { + JSObject o = JSExceptions.getJSException(t); + if (o != null) { + printNativeExceptionToConsoleTeaVM(o); + return true; + } + } + return false; + } + + public static void exit() { + logger.fatal("Game is attempting to exit!"); + } + + public static void setThreadName(String string) { + currentThreadName = string; + } + + public static long maxMemory() { + return 1073741824l; + } + + public static long totalMemory() { + return 1073741824l; + } + + public static long freeMemory() { + return 1073741824l; + } + + public static String getCallingClass(int backTrace) { + return null; + } + + public static OutputStream newDeflaterOutputStream(OutputStream os) throws IOException { + return new DeflaterOutputStream(os); + } + + public static OutputStream newGZIPOutputStream(OutputStream os) throws IOException { + return new GZIPOutputStream(os); + } + + public static InputStream newInflaterInputStream(InputStream is) throws IOException { + return new InflaterInputStream(is); + } + + public static InputStream newGZIPInputStream(InputStream is) throws IOException { + return new GZIPInputStream(is); + } + + @JSBody(params = {}, script = "return window.location.protocol && window.location.protocol.toLowerCase().startsWith(\"https\");") + public static native boolean requireSSL(); + + @JSBody(params = {}, script = "return window.location.protocol && window.location.protocol.toLowerCase().startsWith(\"file\");") + public static native boolean isOfflineDownloadURL(); + + public static IClientConfigAdapter getClientConfigAdapter() { + return TeaVMClientConfigAdapter.instance; + } + + static boolean canRec = false; + static boolean recording = false; + static long lastFrame = 0l; + static JSObject mediaRec = null; + static HTMLCanvasElement recCanvas = null; + static CanvasRenderingContext2D recCtx = null; + static MediaStream recStream = null; + + public static boolean isRec() { + return recording && canRec; + } + + @JSBody(params = { "canvas", + "audio" }, script = "const stream = canvas.captureStream(); stream.addTrack(audio.getTracks()[0]); return stream;") + private static native MediaStream captureStreamAndAddAudio(HTMLCanvasElement canvas, MediaStream audio); + + @JSBody(params = { + "stream" }, script = "const rec = new MediaRecorder(stream, { mimeType: MediaRecorder.isTypeSupported(\"video/webm;codecs=vp9,opus\") ? \"video/webm;codecs=vp9,opus\" : \"video/webm\" }); rec.start(); return rec;") + private static native JSObject createMediaRecorder(MediaStream stream); + + @JSBody(params = { "rec" }, script = "rec.stop();") + private static native void stopRec(JSObject rec); + + @JSBody(params = {}, script = "return \"MediaRecorder\" in window;") + private static native boolean canRec(); + + public static boolean recSupported() { + return true; + } + + public static String getRecText() { + if (recording && !canRec) { + return "recording.unsupported"; + } + return recording ? "recording.stop" : "recording.start"; + } + + static void recFrame() { + if (mediaRec != null) { + int w = PlatformRuntime.canvas.getWidth(); + int h = PlatformRuntime.canvas.getHeight(); + if (recCanvas.getWidth() != w || recCanvas.getHeight() != h) { + recCanvas.setWidth(w); + recCanvas.setHeight(h); + } + recCtx.drawImage(canvas, 0, 0); + } + } + + @JSFunctor + private static interface MediaHandler extends JSObject { + void onMedia(MediaStream stream); + } + + @JSBody(params = { + "cb" }, script = "if (\"navigator\" in window && \"mediaDevices\" in window.navigator && \"getUserMedia\" in window.navigator.mediaDevices) { try { window.navigator.mediaDevices.getUserMedia({ audio: true, video: false }).then(function(stream) { cb(stream); }).catch(function(err) { console.error(err); cb(null); }); } catch(e) { console.error(\"getUserMedia Error!\"); cb(null); } } else { console.error(\"No getUserMedia!\"); cb(null); }") + private static native void getMic0(MediaHandler cb); + + @Async + private static native MediaStream getMic1(); + + private static void getMic1(AsyncCallback cb) { + getMic0(cb::complete); + } + + private static boolean canMic = true; + private static MediaStream mic = null; + + protected static MediaStream getMic() { + if (canMic) { + if (mic == null) { + mic = getMic1(); + if (mic == null) { + canMic = false; + return null; + } + return mic; + } + return mic; + } + return null; + } + + private static final SimpleDateFormat fmt = EagRuntime.fixDateFormat(new SimpleDateFormat("yyyy-MM-dd hh-mm-ss")); + private static final Date dateInstance = new Date(); + + public static void toggleRec() { + if (recording && !canRec) { + return; + } + recording = !recording; + if (recording) { + if (!canRec) { + canRec = canRec(); + if (!canRec) { + return; + } + } + if (recCanvas == null) { + recCanvas = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); + recCtx = (CanvasRenderingContext2D) recCanvas.getContext("2d"); + PlatformAudio.initRecDest(); + recStream = captureStreamAndAddAudio(recCanvas, PlatformAudio.getRecStream()); + } + mediaRec = createMediaRecorder(recStream); + long startTime = System.currentTimeMillis(); + TeaVMUtils.addEventListener(mediaRec, "dataavailable", new EventListener() { + @Override + public void handleEvent(Event evt) { + FixWebMDurationJS.getRecUrl(evt, (int) (System.currentTimeMillis() - startTime), url -> { + HTMLAnchorElement a = (HTMLAnchorElement) doc.createElement("a"); + dateInstance.setTime(startTime); + a.setDownload(EaglercraftVersion.mainMenuStringB + " - " + EaglerProfile.getName() + " - " + + fmt.format(dateInstance) + ".webm"); + a.setHref(url); + a.click(); + TeaVMUtils.freeDataURL(url); + }, logger::info); + } + }); + } else { + stopRec(mediaRec); + mediaRec = null; + } + } + + public static long randomSeed() { + return (long) (Math.random() * 9007199254740991.0); + } + + private static String currentThreadName = "main"; + + public static String currentThreadName() { + return currentThreadName; + } +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java index adda4b2..a0ce5d7 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayByteBuffer.java @@ -348,11 +348,11 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer putLong(long value) { if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position); - dataView.setUint32(position, (int) (value & 0xFFFFFFFF), true); - dataView.setUint8(position + 4, (short) ((value >> 32) & 0xFF)); - dataView.setUint8(position + 5, (short) ((value >> 40) & 0xFF)); - dataView.setUint8(position + 6, (short) ((value >> 48) & 0xFF)); - dataView.setUint8(position + 7, (short) ((value >> 56) & 0xFF)); + dataView.setUint32(position, (int) (value & 0xFFFFFFFFl), true); + dataView.setUint8(position + 4, (short) ((value >>> 32l) & 0xFFl)); + dataView.setUint8(position + 5, (short) ((value >>> 40l) & 0xFFl)); + dataView.setUint8(position + 6, (short) ((value >>> 48l) & 0xFFl)); + dataView.setUint8(position + 7, (short) ((value >>> 56l) & 0xFFl)); position += 8; return this; } @@ -368,11 +368,11 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer putLong(int index, long value) { if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setUint32(index, (int) (value & 0xFFFFFFFF), true); - dataView.setUint8(index + 4, (short) ((value >> 32) & 0xFF)); - dataView.setUint8(index + 5, (short) ((value >> 40) & 0xFF)); - dataView.setUint8(index + 6, (short) ((value >> 48) & 0xFF)); - dataView.setUint8(index + 7, (short) ((value >> 56) & 0xFF)); + dataView.setUint32(index, (int) (value & 0xFFFFFFFFl), true); + dataView.setUint8(index + 4, (short) ((value >>> 32l) & 0xFFl)); + dataView.setUint8(index + 5, (short) ((value >>> 40l) & 0xFFl)); + dataView.setUint8(index + 6, (short) ((value >>> 48l) & 0xFFl)); + dataView.setUint8(index + 7, (short) ((value >>> 56l) & 0xFFl)); return this; } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java index 0fc50e0..6a41a37 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/ClientMain.java @@ -1,543 +1,614 @@ -package net.lax1dude.eaglercraft.v1_8.internal.teavm; - -import java.io.PrintStream; -import java.text.SimpleDateFormat; -import java.util.Date; - -import org.json.JSONException; -import org.teavm.jso.JSBody; -import org.teavm.jso.JSFunctor; -import org.teavm.jso.JSObject; -import org.teavm.jso.browser.Window; -import org.teavm.jso.core.JSArrayReader; -import org.teavm.jso.core.JSError; -import org.teavm.jso.dom.css.CSSStyleDeclaration; -import org.teavm.jso.dom.html.HTMLCanvasElement; -import org.teavm.jso.dom.html.HTMLDocument; -import org.teavm.jso.dom.html.HTMLElement; -import org.teavm.jso.webgl.WebGLRenderingContext; - -import net.lax1dude.eaglercraft.v1_8.EagRuntime; -import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; -import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication; -import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsAssetsURI; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRoot; -import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector; -import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; -import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; -import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer; -import net.minecraft.client.main.Main; - -/** - * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public class ClientMain { - - private static final String crashImage = "data:image/png;base64,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"; - - // avoid inlining of constant - private static String crashImageWrapper() { - return crashImage.substring(0); - } - - @JSBody(params = {}, script = "if((typeof window.__isEaglerX188Running === \"string\") && window.__isEaglerX188Running === \"yes\") return true; window.__isEaglerX188Running = \"yes\"; return false;") - private static native boolean getRunningFlag(); - - public static void _main() { - PrintStream systemOut = System.out; - PrintStream systemErr = System.err; - if (getRunningFlag()) { - systemErr.println("ClientMain: [ERROR] eaglercraftx is already running!"); - return; - } - try { - systemOut.println("ClientMain: [INFO] eaglercraftx is starting..."); - JSObject opts = getEaglerXOpts(); - - if (opts == null) { - systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is undefined"); - systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); - Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is undefined"); - return; - } - - try { - JSEaglercraftXOptsRoot eaglercraftOpts = (JSEaglercraftXOptsRoot) opts; - - configRootElementId = eaglercraftOpts.getContainer(); - if (configRootElementId == null) { - throw new JSONException("window.eaglercraftXOpts.container is undefined!"); - } - configRootElement = Window.current().getDocument().getElementById(configRootElementId); - - String epkSingleURL = eaglercraftOpts.getAssetsURI(); - if (epkSingleURL != null) { - configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") }; - } else { - JSArrayReader epkURLs = eaglercraftOpts.getAssetsURIArray(); - int len = epkURLs.getLength(); - if (len == 0) { - throw new JSONException("assetsURI array cannot be empty!"); - } - configEPKFiles = new EPKFileEntry[len]; - for (int i = 0; i < len; ++i) { - JSEaglercraftXOptsAssetsURI etr = epkURLs.get(i); - String url = etr.getURL(); - if (url == null) { - throw new JSONException("assetsURI is missing a url!"); - } - configEPKFiles[i] = new EPKFileEntry(url, etr.getPath("")); - } - } - - configLocalesFolder = eaglercraftOpts.getLocalesURI("lang"); - if (configLocalesFolder.endsWith("/")) { - configLocalesFolder = configLocalesFolder.substring(0, configLocalesFolder.length() - 1); - } - - ((TeaVMClientConfigAdapter) TeaVMClientConfigAdapter.instance).loadNative(eaglercraftOpts); - - systemOut.println("ClientMain: [INFO] configuration was successful"); - } catch (Throwable t) { - systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is invalid"); - EagRuntime.debugPrintStackTraceToSTDERR(t); - systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); - Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is invalid: " - + t.toString()); - return; - } - - systemOut.println("ClientMain: [INFO] registering crash handlers"); - - setWindowErrorHandler(new WindowErrorHandler() { - - @Override - public void call(String message, String file, int line, int col, JSError error) { - StringBuilder str = new StringBuilder(); - - str.append("Native Browser Exception\n"); - str.append("----------------------------------\n"); - str.append(" Line: ").append((file == null ? "unknown" : file) + ":" + line + ":" + col) - .append('\n'); - str.append(" Type: ").append(error == null ? "generic" : error.getName()).append('\n'); - - if (error != null) { - str.append(" Desc: ").append(error.getMessage() == null ? "null" : error.getMessage()) - .append('\n'); - } - - if (message != null) { - if (error == null || error.getMessage() == null || !message.endsWith(error.getMessage())) { - str.append(" Desc: ").append(message).append('\n'); - } - } - - str.append("----------------------------------\n\n"); - str.append(error.getStack() == null ? "No stack trace is available" : error.getStack()) - .append('\n'); - - showCrashScreen(str.toString()); - } - - }); - - systemOut.println("ClientMain: [INFO] initializing eaglercraftx runtime"); - - LogManager.logRedirector = new ILogRedirector() { - @Override - public void log(String txt, boolean err) { - PlatformApplication.addLogMessage(txt, err); - } - }; - - try { - EagRuntime.create(); - } catch (PlatformRuntime.PlatformIncompatibleException ex) { - systemErr.println("ClientMain: [ERROR] this browser is incompatible with eaglercraftx!"); - systemErr.println("ClientMain: [ERROR] Reason: " + ex.getMessage()); - try { - showIncompatibleScreen(ex.getMessage()); - } catch (Throwable t) { - } - return; - } catch (Throwable t) { - systemErr.println("ClientMain: [ERROR] eaglercraftx's runtime could not be initialized!"); - EagRuntime.debugPrintStackTraceToSTDERR(t); - showCrashScreen("EaglercraftX's runtime could not be initialized!", t); - systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); - return; - } - - systemOut.println("ClientMain: [INFO] launching eaglercraftx main thread"); - - try { - Main.appMain(new String[0]); - } catch (Throwable t) { - systemErr.println("ClientMain: [ERROR] unhandled exception caused main thread to exit"); - EagRuntime.debugPrintStackTraceToSTDERR(t); - showCrashScreen("Unhandled exception caused main thread to exit!", t); - } - - } finally { - systemErr.println("ClientMain: [ERROR] eaglercraftx main thread has exited"); - } - } - - @JSBody(params = {}, script = "if(typeof window.eaglercraftXOpts === \"undefined\") {return null;}" - + "else if(typeof window.eaglercraftXOpts === \"string\") {return JSON.parse(window.eaglercraftXOpts);}" - + "else {return window.eaglercraftXOpts;}") - private static native JSObject getEaglerXOpts(); - - public static class EPKFileEntry { - - public final String url; - public final String path; - - protected EPKFileEntry(String url, String path) { - this.url = url; - this.path = path; - } - } - - public static String configRootElementId = null; - public static HTMLElement configRootElement = null; - public static EPKFileEntry[] configEPKFiles = null; - public static String configLocalesFolder = null; - - @JSFunctor - private static interface WindowErrorHandler extends JSObject { - void call(String message, String file, int line, int col, JSError error); - } - - @JSBody(params = { "handler" }, script = "window.addEventListener(\"error\", function(e) { handler(" - + "(typeof e.message === \"string\") ? e.message : null," - + "(typeof e.filename === \"string\") ? e.filename : null," - + "(typeof e.lineno === \"number\") ? e.lineno : 0," - + "(typeof e.colno === \"number\") ? e.colno : 0," - + "(typeof e.error === \"undefined\") ? null : e.error); });") - public static native void setWindowErrorHandler(WindowErrorHandler handler); - - public static void showCrashScreen(String message, Throwable t) { - try { - showCrashScreen(message + "\n\n" + EagRuntime.getStackTrace(t)); - } catch (Throwable tt) { - } - } - - private static boolean isCrashed = false; - - public static void showCrashScreen(String t) { - if (!isCrashed) { - isCrashed = true; - - HTMLDocument doc = Window.current().getDocument(); - if (configRootElement == null) { - configRootElement = doc.getElementById(configRootElementId); - } - - HTMLElement el = configRootElement; - - StringBuilder str = new StringBuilder(); - str.append("Game Crashed! I have fallen and I can't get up!\n\n"); - str.append(t); - str.append('\n').append('\n'); - str.append("eaglercraft.version = \"").append(EaglercraftVersion.projectForkVersion).append("\"\n"); - str.append("eaglercraft.minecraft = \"1.8.8\"\n"); - str.append("eaglercraft.brand = \"" + EaglercraftVersion.projectForkVendor + "\"\n"); - str.append("eaglercraft.username = \"").append(EaglerProfile.getName()).append("\"\n"); - str.append('\n'); - str.append(addWebGLToCrash()); - str.append('\n'); - str.append("window.eaglercraftXOpts = "); - str.append(TeaVMClientConfigAdapter.instance.toString()).append('\n'); - str.append('\n'); - str.append("currentTime = "); - str.append(EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date())) - .append('\n'); - str.append('\n'); - addDebugNav(str, "userAgent"); - addDebugNav(str, "vendor"); - addDebugNav(str, "language"); - addDebugNav(str, "hardwareConcurrency"); - addDebugNav(str, "deviceMemory"); - addDebugNav(str, "platform"); - addDebugNav(str, "product"); - str.append('\n'); - str.append("rootElement.clientWidth = ").append(el == null ? "undefined" : el.getClientWidth()) - .append('\n'); - str.append("rootElement.clientHeight = ").append(el == null ? "undefined" : el.getClientHeight()) - .append('\n'); - addDebug(str, "innerWidth"); - addDebug(str, "innerHeight"); - addDebug(str, "outerWidth"); - addDebug(str, "outerHeight"); - addDebug(str, "devicePixelRatio"); - addDebugScreen(str, "availWidth"); - addDebugScreen(str, "availHeight"); - addDebugScreen(str, "colorDepth"); - addDebugScreen(str, "pixelDepth"); - str.append('\n'); - addDebug(str, "currentContext"); - str.append('\n'); - addDebugLocation(str, "href"); - str.append('\n'); - - if (el == null) { - Window.alert("Root element not found, crash report was printed to console"); - System.err.println(str.toString()); - return; - } - - String s = el.getAttribute("style"); - el.setAttribute("style", (s == null ? "" : s) + "position:relative;"); - HTMLElement img = doc.createElement("img"); - HTMLElement div = doc.createElement("div"); - img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); - img.setAttribute("src", crashImageWrapper()); - div.setAttribute("style", - "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font: 14px monospace;padding:10px;"); - el.appendChild(img); - el.appendChild(div); - div.appendChild(doc.createTextNode(str.toString())); - - PlatformRuntime.removeEventHandlers(); - - } else { - System.err.println(); - System.err.println("An additional crash report was supressed:"); - String[] s = t.split("[\\r\\n]+"); - for (int i = 0; i < s.length; ++i) { - System.err.println(" " + s[i]); - } - } - } - - private static String addWebGLToCrash() { - StringBuilder ret = new StringBuilder(); - - WebGLRenderingContext ctx = PlatformRuntime.webgl; - - if (ctx == null) { - HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); - - cvs.setWidth(64); - cvs.setHeight(64); - - ctx = (WebGLRenderingContext) cvs.getContext("webgl"); - } - - if (ctx != null) { - if (PlatformRuntime.webgl != null) { - ret.append("webgl.version = ").append(ctx.getParameterString(WebGLRenderingContext.VERSION)) - .append('\n'); - } - if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { - ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)) - .append('\n'); - ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)) - .append('\n'); - } else { - ret.append("webgl.renderer = ") - .append(ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); - ret.append("webgl.vendor = ").append(ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]") - .append('\n'); - } - // ret.append('\n').append("\nwebgl.anisotropicGlitch = - // ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO - ret.append('\n').append("webgl.ext.HDR16f = ") - .append(ctx.getExtension("EXT_color_buffer_half_float") != null).append('\n'); - ret.append("webgl.ext.HDR32f = ").append(ctx.getExtension("EXT_color_buffer_float") != null).append('\n'); - - } else { - ret.append("Failed to query GPU info!\n"); - } - - return ret.toString(); - } - - public static void showIncompatibleScreen(String t) { - if (!isCrashed) { - isCrashed = true; - - HTMLDocument doc = Window.current().getDocument(); - if (configRootElement == null) { - configRootElement = doc.getElementById(configRootElementId); - } - - HTMLElement el = configRootElement; - - if (el == null) { - System.err.println("Compatibility error: " + t); - return; - } - - String s = el.getAttribute("style"); - el.setAttribute("style", (s == null ? "" : s) + "position:relative;"); - HTMLElement img = doc.createElement("img"); - HTMLElement div = doc.createElement("div"); - img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); - img.setAttribute("src", crashImageWrapper()); - div.setAttribute("style", - "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;font:18px sans-serif;padding:40px;"); - el.appendChild(img); - el.appendChild(div); - div.setInnerHTML( - "

+ This device is incompatible with Eaglercraft :(

" - + "
" - + "

Issue:

" - + "

" - + "

" - + "

Current Date: " - + EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) - .format(new Date()) - + "

" - + "


Things you can try:

" - + "
    " - + "
  1. Just try using Eaglercraft on a different device, it isn't a bug it's common sense
  2. " - + "
  3. If you are on a mobile device, please try a proper desktop or a laptop computer
  4. " - + "
  5. If you are using a device with no mouse cursor, please use a device with a mouse cursor
  6. " - + "
  7. If you are not using Chrome/Edge, try installing the latest Google Chrome
  8. " - + "
  9. If your browser is out of date, please update it to the latest version
  10. " - + "
  11. If you are using an old OS such as Windows 7, please try Windows 10 or 11
  12. " - + "
  13. If you have a GPU launched before 2009, WebGL 2.0 support may be impossible
  14. " - + "
" - + "
"); - - div.querySelector("#crashReason").appendChild(doc.createTextNode(t)); - div.querySelector("#crashUserAgent").appendChild(doc.createTextNode(getStringNav("userAgent"))); - - PlatformRuntime.removeEventHandlers(); - - String webGLRenderer = "No GL_RENDERER string could be queried"; - - try { - HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); - - cvs.setWidth(64); - cvs.setHeight(64); - - WebGLRenderingContext ctx = (WebGLRenderingContext) cvs.getContext("webgl"); - - if (ctx != null) { - String r; - if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { - r = ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246); - } else { - r = ctx.getParameterString(WebGLRenderingContext.RENDERER); - if (r != null) { - r += " [masked]"; - } - } - if (r != null) { - webGLRenderer = r; - } - } - } catch (Throwable tt) { - } - - div.querySelector("#crashWebGL").appendChild(doc.createTextNode(webGLRenderer)); - - } - } - - private static HTMLElement integratedServerCrashPanel = null; - - public static void showIntegratedServerCrashReportOverlay(String report, int x, int y, int w, int h) { - if (integratedServerCrashPanel == null) { - HTMLDocument doc = Window.current().getDocument(); - if (configRootElement == null) { - configRootElement = doc.getElementById(configRootElementId); - } - - integratedServerCrashPanel = doc.createElement("div"); - integratedServerCrashPanel.setAttribute("style", - "z-index:99;position:absolute;background-color:black;color:white;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font:18px sans-serif;padding:20px;display:none;"); - configRootElement.appendChild(integratedServerCrashPanel); - } - String sourceURL = ClientPlatformSingleplayer.getLoadedWorkerSourceURLTeaVM(); - String workerURL = ClientPlatformSingleplayer.getLoadedWorkerURLTeaVM(); - String currentDate = EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) - .format(new Date()); - if (workerURL != null) { - report = "WORKER SRC: " + sourceURL + "\nWORKER URL: " + workerURL + "\n\nCURRENT DATE: " + currentDate - + "\n\n" + report.replaceAll(workerURL, ""); - } else { - report = "CURRENT DATE: " + currentDate + "\n\n" + report; - } - setInnerText(integratedServerCrashPanel, ""); - setInnerText(integratedServerCrashPanel, report); - CSSStyleDeclaration style = integratedServerCrashPanel.getStyle(); - float s = (float) Window.current().getDevicePixelRatio(); - style.setProperty("top", "" + (y / s) + "px"); - style.setProperty("left", "" + (x / s) + "px"); - style.setProperty("width", "" + ((w / s) - 20) + "px"); - style.setProperty("height", "" + ((h / s) - 20) + "px"); - style.setProperty("display", "block"); - } - - public static void hideIntegratedServerCrashReportOverlay() { - if (integratedServerCrashPanel != null) { - integratedServerCrashPanel.getStyle().setProperty("display", "none"); - } - } - - @JSBody(params = { "el", "str" }, script = "el.innerText = str;") - private static native void setInnerText(HTMLElement el, String str); - - @JSBody(params = { "v" }, script = "try { return \"\"+window[v]; } catch(e) { return \"\"; }") - private static native String getString(String var); - - @JSBody(params = { "v" }, script = "try { return \"\"+window.navigator[v]; } catch(e) { return \"\"; }") - private static native String getStringNav(String var); - - @JSBody(params = { "v" }, script = "try { return \"\"+window.screen[v]; } catch(e) { return \"\"; }") - private static native String getStringScreen(String var); - - @JSBody(params = { "v" }, script = "try { return \"\"+window.location[v]; } catch(e) { return \"\"; }") - private static native String getStringLocation(String var); - - private static void addDebug(StringBuilder str, String var) { - str.append("window.").append(var).append(" = ").append(getString(var)).append('\n'); - } - - private static void addDebugNav(StringBuilder str, String var) { - str.append("window.navigator.").append(var).append(" = ").append(getStringNav(var)).append('\n'); - } - - private static void addDebugScreen(StringBuilder str, String var) { - str.append("window.screen.").append(var).append(" = ").append(getStringScreen(var)).append('\n'); - } - - private static void addDebugLocation(StringBuilder str, String var) { - str.append("window.location.").append(var).append(" = ").append(getStringLocation(var)).append('\n'); - } - - private static void addArray(StringBuilder str, String var) { - str.append("window.").append(var).append(" = ").append(getArray(var)).append('\n'); - } - - @JSBody(params = { - "v" }, script = "try { return (typeof window[v] !== \"undefined\") ? JSON.stringify(window[v]) : \"[\\\"\\\"]\"; } catch(e) { return \"[\\\"\\\"]\"; }") - private static native String getArray(String var); - -} +package net.lax1dude.eaglercraft.v1_8.internal.teavm; + +import java.io.PrintStream; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.json.JSONException; +import org.teavm.jso.JSBody; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.browser.Window; +import org.teavm.jso.core.JSArrayReader; +import org.teavm.jso.core.JSError; +import org.teavm.jso.dom.css.CSSStyleDeclaration; +import org.teavm.jso.dom.html.HTMLCanvasElement; +import org.teavm.jso.dom.html.HTMLDocument; +import org.teavm.jso.dom.html.HTMLElement; +import org.teavm.jso.webgl.WebGLRenderingContext; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EaglercraftVersion; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformApplication; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsAssetsURI; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsRoot; +import net.lax1dude.eaglercraft.v1_8.log4j.ILogRedirector; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; +import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer; +import net.minecraft.client.main.Main; + +/** + * Copyright (c) 2022-2024 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class ClientMain { + + private static final String crashImage = "data:image/png;base64,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"; + + // avoid inlining of constant + private static String crashImageWrapper() { + return crashImage.substring(0); + } + + @JSBody(params = {}, script = "if((typeof window.__isEaglerX188Running === \"string\") && window.__isEaglerX188Running === \"yes\") return true; window.__isEaglerX188Running = \"yes\"; return false;") + private static native boolean getRunningFlag(); + + public static void _main() { + PrintStream systemOut = System.out; + PrintStream systemErr = System.err; + if (getRunningFlag()) { + systemErr.println("ClientMain: [ERROR] eaglercraftx is already running!"); + return; + } + try { + systemOut.println("ClientMain: [INFO] eaglercraftx is starting..."); + JSObject opts = getEaglerXOpts(); + + if (opts == null) { + systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is undefined"); + systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); + Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is undefined"); + return; + } + + try { + JSEaglercraftXOptsRoot eaglercraftOpts = (JSEaglercraftXOptsRoot)opts; + crashOnUncaughtExceptions = eaglercraftOpts.getCrashOnUncaughtExceptions(false); + + configRootElementId = eaglercraftOpts.getContainer(); + if (configRootElementId == null) { + throw new JSONException("window.eaglercraftXOpts.container is undefined!"); + } + configRootElement = Window.current().getDocument().getElementById(configRootElementId); + + String epkSingleURL = eaglercraftOpts.getAssetsURI(); + if (epkSingleURL != null) { + configEPKFiles = new EPKFileEntry[] { new EPKFileEntry(epkSingleURL, "") }; + } else { + JSArrayReader epkURLs = eaglercraftOpts.getAssetsURIArray(); + int len = epkURLs.getLength(); + if (len == 0) { + throw new JSONException("assetsURI array cannot be empty!"); + } + configEPKFiles = new EPKFileEntry[len]; + for (int i = 0; i < len; ++i) { + JSEaglercraftXOptsAssetsURI etr = epkURLs.get(i); + String url = etr.getURL(); + if (url == null) { + throw new JSONException("assetsURI is missing a url!"); + } + configEPKFiles[i] = new EPKFileEntry(url, etr.getPath("")); + } + } + + configLocalesFolder = eaglercraftOpts.getLocalesURI("lang"); + if (configLocalesFolder.endsWith("/")) { + configLocalesFolder = configLocalesFolder.substring(0, configLocalesFolder.length() - 1); + } + + ((TeaVMClientConfigAdapter) TeaVMClientConfigAdapter.instance).loadNative(eaglercraftOpts); + + systemOut.println("ClientMain: [INFO] configuration was successful"); + } catch (Throwable t) { + systemErr.println("ClientMain: [ERROR] the \"window.eaglercraftXOpts\" variable is invalid"); + EagRuntime.debugPrintStackTraceToSTDERR(t); + systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); + Window.alert("ERROR: game cannot start, the \"window.eaglercraftXOpts\" variable is invalid: " + + t.toString()); + return; + } + + if(crashOnUncaughtExceptions) { + systemOut.println("ClientMain: [INFO] registering crash handlers"); + + setWindowErrorHandler(new WindowErrorHandler() { + + @Override + public void call(String message, String file, int line, int col, JSError error) { + StringBuilder str = new StringBuilder(); + + str.append("Native Browser Exception\n"); + str.append("----------------------------------\n"); + str.append(" Line: ").append((file == null ? "unknown" : file) + ":" + line + ":" + col).append('\n'); + str.append(" Type: ").append(error == null ? "generic" : error.getName()).append('\n'); + + if(error != null) { + str.append(" Desc: ").append(error.getMessage() == null ? "null" : error.getMessage()).append('\n'); + } + + if(message != null) { + if(error == null || error.getMessage() == null || !message.endsWith(error.getMessage())) { + str.append(" Desc: ").append(message).append('\n'); + } + } + + str.append("----------------------------------\n\n"); + str.append(error.getStack() == null ? "No stack trace is available" : error.getStack()).append('\n'); + + showCrashScreen(str.toString()); + } + + }); + } + + systemOut.println("ClientMain: [INFO] initializing eaglercraftx runtime"); + + LogManager.logRedirector = new ILogRedirector() { + @Override + public void log(String txt, boolean err) { + PlatformApplication.addLogMessage(txt, err); + } + }; + + try { + EagRuntime.create(); + } catch (PlatformRuntime.PlatformIncompatibleException ex) { + systemErr.println("ClientMain: [ERROR] this browser is incompatible with eaglercraftx!"); + systemErr.println("ClientMain: [ERROR] Reason: " + ex.getMessage()); + try { + showIncompatibleScreen(ex.getMessage()); + } catch (Throwable t) { + } + return; + } catch (Throwable t) { + systemErr.println("ClientMain: [ERROR] eaglercraftx's runtime could not be initialized!"); + EagRuntime.debugPrintStackTraceToSTDERR(t); + showCrashScreen("EaglercraftX's runtime could not be initialized!", t); + systemErr.println("ClientMain: [ERROR] eaglercraftx cannot start"); + return; + } + + systemOut.println("ClientMain: [INFO] launching eaglercraftx main thread"); + + try { + Main.appMain(new String[0]); + } catch (Throwable t) { + systemErr.println("ClientMain: [ERROR] unhandled exception caused main thread to exit"); + EagRuntime.debugPrintStackTraceToSTDERR(t); + showCrashScreen("Unhandled exception caused main thread to exit!", t); + } + + } finally { + systemErr.println("ClientMain: [ERROR] eaglercraftx main thread has exited"); + } + } + + @JSBody(params = {}, script = "if(typeof window.eaglercraftXOpts === \"undefined\") {return null;}" + + "else if(typeof window.eaglercraftXOpts === \"string\") {return JSON.parse(window.eaglercraftXOpts);}" + + "else {return window.eaglercraftXOpts;}") + private static native JSObject getEaglerXOpts(); + + public static class EPKFileEntry { + + public final String url; + public final String path; + + protected EPKFileEntry(String url, String path) { + this.url = url; + this.path = path; + } + } + + public static String configRootElementId = null; + public static HTMLElement configRootElement = null; + public static EPKFileEntry[] configEPKFiles = null; + public static String configLocalesFolder = null; + public static boolean crashOnUncaughtExceptions = false; + + @JSFunctor + private static interface WindowErrorHandler extends JSObject { + void call(String message, String file, int line, int col, JSError error); + } + + @JSBody(params = { "handler" }, script = "window.addEventListener(\"error\", function(e) { handler(" + + "(typeof e.message === \"string\") ? e.message : null," + + "(typeof e.filename === \"string\") ? e.filename : null," + + "(typeof e.lineno === \"number\") ? e.lineno : 0," + + "(typeof e.colno === \"number\") ? e.colno : 0," + + "(typeof e.error === \"undefined\") ? null : e.error); });") + public static native void setWindowErrorHandler(WindowErrorHandler handler); + + public static void showCrashScreen(String message, Throwable t) { + try { + showCrashScreen(message + "\n\n" + EagRuntime.getStackTrace(t)); + } catch (Throwable tt) { + } + } + + private static boolean isCrashed = false; + + public static void showCrashScreen(String t) { + StringBuilder strBeforeBuilder = new StringBuilder(); + strBeforeBuilder.append("Game Crashed! I have fallen and I can't get up!\n\n"); + strBeforeBuilder.append(t); + strBeforeBuilder.append('\n').append('\n'); + String strBefore = strBeforeBuilder.toString(); + + HTMLDocument doc = Window.current().getDocument(); + if(configRootElement == null) { + configRootElement = doc.getElementById(configRootElementId); + } + + HTMLElement el = configRootElement; + + StringBuilder str = new StringBuilder(); + str.append("eaglercraft.version = \"").append(EaglercraftVersion.projectForkVersion).append("\"\n"); + str.append("eaglercraft.minecraft = \"1.8.8\"\n"); + str.append("eaglercraft.brand = \"" + EaglercraftVersion.projectForkVendor + "\"\n"); + str.append("eaglercraft.username = \"").append(EaglerProfile.getName()).append("\"\n"); + str.append('\n'); + str.append(addWebGLToCrash()); + str.append('\n'); + str.append("window.eaglercraftXOpts = "); + str.append(TeaVMClientConfigAdapter.instance.toString()).append('\n'); + str.append('\n'); + str.append("currentTime = "); + str.append(EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")).format(new Date())).append('\n'); + str.append('\n'); + addDebugNav(str, "userAgent"); + addDebugNav(str, "vendor"); + addDebugNav(str, "language"); + addDebugNav(str, "hardwareConcurrency"); + addDebugNav(str, "deviceMemory"); + addDebugNav(str, "platform"); + addDebugNav(str, "product"); + addDebugNavPlugins(str); + str.append('\n'); + addDebug(str, "localStorage"); + addDebug(str, "sessionStorage"); + addDebug(str, "indexedDB"); + str.append('\n'); + str.append("rootElement.clientWidth = ").append(el == null ? "undefined" : el.getClientWidth()).append('\n'); + str.append("rootElement.clientHeight = ").append(el == null ? "undefined" : el.getClientHeight()).append('\n'); + addDebug(str, "innerWidth"); + addDebug(str, "innerHeight"); + addDebug(str, "outerWidth"); + addDebug(str, "outerHeight"); + addDebug(str, "devicePixelRatio"); + addDebugScreen(str, "availWidth"); + addDebugScreen(str, "availHeight"); + addDebugScreen(str, "colorDepth"); + addDebugScreen(str, "pixelDepth"); + str.append('\n'); + addDebug(str, "minecraftServer"); + str.append('\n'); + addDebugLocation(str, "href"); + str.append('\n'); + String strAfter = str.toString(); + + String strFinal = strBefore + strAfter; + List additionalInfo = new LinkedList(); + try { + TeaVMClientConfigAdapter.instance.getHooks().callCrashReportHook(strFinal, additionalInfo::add); + }catch(Throwable tt) { + System.err.println("Uncaught exception invoking crash report hook!"); + EagRuntime.debugPrintStackTraceToSTDERR(tt); + } + + if(!isCrashed) { + isCrashed = true; + + if(additionalInfo.size() > 0) { + try { + StringBuilder builderFinal = new StringBuilder(); + builderFinal.append(strBefore); + builderFinal.append("Got the following messages from the crash report hook registered in eaglercraftXOpts:\n\n"); + for(String str2 : additionalInfo) { + builderFinal.append("----------[ CRASH HOOK ]----------\n"); + builderFinal.append(str2).append('\n'); + builderFinal.append("----------------------------------\n\n"); + } + builderFinal.append(strAfter); + strFinal = builderFinal.toString(); + }catch(Throwable tt) { + System.err.println("Uncaught exception concatenating crash report hook messages!"); + EagRuntime.debugPrintStackTraceToSTDERR(tt); + } + } + + if(el == null) { + Window.alert("Root element not found, crash report was printed to console"); + System.err.println(strFinal); + return; + } + + String s = el.getAttribute("style"); + el.setAttribute("style", (s == null ? "" : s) + "position:relative;"); + HTMLElement img = doc.createElement("img"); + HTMLElement div = doc.createElement("div"); + img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); + img.setAttribute("src", crashImageWrapper()); + div.setAttribute("style", + "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font: 14px monospace;padding:10px;"); + el.appendChild(img); + el.appendChild(div); + div.appendChild(doc.createTextNode(strFinal)); + + PlatformRuntime.removeEventHandlers(); + + } else { + System.err.println(); + System.err.println("An additional crash report was supressed:"); + String[] s = t.split("[\\r\\n]+"); + for (int i = 0; i < s.length; ++i) { + System.err.println(" " + s[i]); + } + if(additionalInfo.size() > 0) { + for(String str2 : additionalInfo) { + if(str2 != null) { + System.err.println(); + System.err.println(" ----------[ CRASH HOOK ]----------"); + s = str2.split("[\\r\\n]+"); + for(int i = 0; i < s.length; ++i) { + System.err.println(" " + s[i]); + } + System.err.println(" ----------------------------------"); + } + } + } + } + } + + private static String webGLCrashStringCache = null; + + private static String addWebGLToCrash() { + if(webGLCrashStringCache != null) { + return webGLCrashStringCache; + } + + StringBuilder ret = new StringBuilder(); + + WebGLRenderingContext ctx = PlatformRuntime.webgl; + + if (ctx == null) { + HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); + + cvs.setWidth(64); + cvs.setHeight(64); + + ctx = (WebGLRenderingContext)cvs.getContext("webgl2"); + + if(ctx == null) { + ctx = (WebGLRenderingContext)cvs.getContext("webgl"); + } + } + + if (ctx != null) { + if (PlatformRuntime.webgl != null) { + ret.append("webgl.version = ").append(ctx.getParameterString(WebGLRenderingContext.VERSION)) + .append('\n'); + } + if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { + ret.append("webgl.renderer = ").append(ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246)) + .append('\n'); + ret.append("webgl.vendor = ").append(ctx.getParameterString(/* UNMASKED_VENDOR_WEBGL */ 0x9245)) + .append('\n'); + } else { + ret.append("webgl.renderer = ") + .append(ctx.getParameterString(WebGLRenderingContext.RENDERER) + " [masked]").append('\n'); + ret.append("webgl.vendor = ").append(ctx.getParameterString(WebGLRenderingContext.VENDOR) + " [masked]") + .append('\n'); + } + // ret.append('\n').append("\nwebgl.anisotropicGlitch = + // ").append(DetectAnisotropicGlitch.hasGlitch()).append('\n'); //TODO + ret.append('\n').append("webgl.ext.HDR16f = ") + .append(ctx.getExtension("EXT_color_buffer_half_float") != null).append('\n'); + ret.append("webgl.ext.HDR32f = ").append(ctx.getExtension("EXT_color_buffer_float") != null).append('\n'); + ret.append("webgl.ext.HDR32f_linear = ").append(ctx.getExtension("OES_texture_float_linear") != null).append('\n'); + + }else { + ret.append("Failed to query GPU info!\n"); + } + + return webGLCrashStringCache = ret.toString(); + } + + public static void showIncompatibleScreen(String t) { + if (!isCrashed) { + isCrashed = true; + + HTMLDocument doc = Window.current().getDocument(); + if (configRootElement == null) { + configRootElement = doc.getElementById(configRootElementId); + } + + HTMLElement el = configRootElement; + + if (el == null) { + System.err.println("Compatibility error: " + t); + return; + } + + String s = el.getAttribute("style"); + el.setAttribute("style", (s == null ? "" : s) + "position:relative;"); + HTMLElement img = doc.createElement("img"); + HTMLElement div = doc.createElement("div"); + img.setAttribute("style", "z-index:100;position:absolute;top:10px;left:calc(50% - 151px);"); + img.setAttribute("src", crashImageWrapper()); + div.setAttribute("style", + "z-index:100;position:absolute;top:135px;left:10%;right:10%;bottom:50px;background-color:white;border:1px solid #cccccc;overflow-x:hidden;overflow-y:scroll;font:18px sans-serif;padding:40px;"); + el.appendChild(img); + el.appendChild(div); + div.setInnerHTML( + "

+ This device is incompatible with Eaglercraft :(

" + + "
" + + "

Issue:

" + + "

" + + "

" + + "

Current Date: " + + EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) + .format(new Date()) + + "

" + + "


Things you can try:

" + + "
    " + + "
  1. Just try using Eaglercraft on a different device, it isn't a bug it's common sense
  2. " + + "
  3. If you are on a mobile device, please try a proper desktop or a laptop computer
  4. " + + "
  5. If you are using a device with no mouse cursor, please use a device with a mouse cursor
  6. " + + "
  7. If you are not using Chrome/Edge, try installing the latest Google Chrome
  8. " + + "
  9. If your browser is out of date, please update it to the latest version
  10. " + + "
  11. If you are using an old OS such as Windows 7, please try Windows 10 or 11
  12. " + + "
  13. If you have a GPU launched before 2009, WebGL 2.0 support may be impossible
  14. " + + "
" + + "
"); + + div.querySelector("#crashReason").appendChild(doc.createTextNode(t)); + div.querySelector("#crashUserAgent").appendChild(doc.createTextNode(getStringNav("userAgent"))); + + PlatformRuntime.removeEventHandlers(); + + String webGLRenderer = "No GL_RENDERER string could be queried"; + + try { + HTMLCanvasElement cvs = (HTMLCanvasElement) Window.current().getDocument().createElement("canvas"); + + cvs.setWidth(64); + cvs.setHeight(64); + + WebGLRenderingContext ctx = (WebGLRenderingContext) cvs.getContext("webgl"); + + if (ctx != null) { + String r; + if (ctx.getExtension("WEBGL_debug_renderer_info") != null) { + r = ctx.getParameterString(/* UNMASKED_RENDERER_WEBGL */ 0x9246); + } else { + r = ctx.getParameterString(WebGLRenderingContext.RENDERER); + if (r != null) { + r += " [masked]"; + } + } + if (r != null) { + webGLRenderer = r; + } + } + } catch (Throwable tt) { + } + + div.querySelector("#crashWebGL").appendChild(doc.createTextNode(webGLRenderer)); + + } + } + + private static HTMLElement integratedServerCrashPanel = null; + + public static void showIntegratedServerCrashReportOverlay(String report, int x, int y, int w, int h) { + if (integratedServerCrashPanel == null) { + HTMLDocument doc = Window.current().getDocument(); + if (configRootElement == null) { + configRootElement = doc.getElementById(configRootElementId); + } + + integratedServerCrashPanel = doc.createElement("div"); + integratedServerCrashPanel.setAttribute("style", + "z-index:99;position:absolute;background-color:black;color:white;overflow-x:hidden;overflow-y:scroll;overflow-wrap:break-word;white-space:pre-wrap;font:18px sans-serif;padding:20px;display:none;"); + configRootElement.appendChild(integratedServerCrashPanel); + } + String sourceURL = ClientPlatformSingleplayer.getLoadedWorkerSourceURLTeaVM(); + String workerURL = ClientPlatformSingleplayer.getLoadedWorkerURLTeaVM(); + String currentDate = EagRuntime.fixDateFormat(new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z")) + .format(new Date()); + if (workerURL != null) { + report = "WORKER SRC: " + sourceURL + "\nWORKER URL: " + workerURL + "\n\nCURRENT DATE: " + currentDate + + "\n\n" + report.replaceAll(workerURL, ""); + } else { + report = "CURRENT DATE: " + currentDate + "\n\n" + report; + } + setInnerText(integratedServerCrashPanel, ""); + setInnerText(integratedServerCrashPanel, report); + CSSStyleDeclaration style = integratedServerCrashPanel.getStyle(); + float s = (float) Window.current().getDevicePixelRatio(); + style.setProperty("top", "" + (y / s) + "px"); + style.setProperty("left", "" + (x / s) + "px"); + style.setProperty("width", "" + ((w / s) - 20) + "px"); + style.setProperty("height", "" + ((h / s) - 20) + "px"); + style.setProperty("display", "block"); + } + + public static void hideIntegratedServerCrashReportOverlay() { + if (integratedServerCrashPanel != null) { + integratedServerCrashPanel.getStyle().setProperty("display", "none"); + } + } + + @JSBody(params = { "el", "str" }, script = "el.innerText = str;") + private static native void setInnerText(HTMLElement el, String str); + + @JSBody(params = { "v" }, script = "try { return \"\"+window[v]; } catch(e) { return \"\"; }") + private static native String getString(String var); + + @JSBody(params = { "v" }, script = "try { return \"\"+window.navigator[v]; } catch(e) { return \"\"; }") + private static native String getStringNav(String var); + + @JSBody(params = { "v" }, script = "try { return \"\"+window.screen[v]; } catch(e) { return \"\"; }") + private static native String getStringScreen(String var); + + @JSBody(params = { "v" }, script = "try { return \"\"+window.location[v]; } catch(e) { return \"\"; }") + private static native String getStringLocation(String var); + + @JSBody(params = { }, script = "try { var retObj = new Array; if(typeof window.navigator.plugins === \"object\")" + + "{ var len = window.navigator.plugins.length; if(len > 0) { for(var idx = 0; idx < len; ++idx) {" + + "var thePlugin = window.navigator.plugins[idx]; retObj.push({ name: thePlugin.name," + + "filename: thePlugin.filename, desc: thePlugin.description }); } } } return JSON.stringify(retObj);" + + "} catch(e) { return \"\"; }") + private static native String getStringNavPlugins(); + + private static void addDebug(StringBuilder str, String var) { + str.append("window.").append(var).append(" = ").append(getString(var)).append('\n'); + } + + private static void addDebugNav(StringBuilder str, String var) { + str.append("window.navigator.").append(var).append(" = ").append(getStringNav(var)).append('\n'); + } + + private static void addDebugNavPlugins(StringBuilder str) { + str.append("window.navigator.plugins = ").append(getStringNavPlugins()).append('\n'); + } + + private static void addDebugScreen(StringBuilder str, String var) { + str.append("window.screen.").append(var).append(" = ").append(getStringScreen(var)).append('\n'); + } + + private static void addDebugLocation(StringBuilder str, String var) { + str.append("window.location.").append(var).append(" = ").append(getStringLocation(var)).append('\n'); + } + + private static void addArray(StringBuilder str, String var) { + str.append("window.").append(var).append(" = ").append(getArray(var)).append('\n'); + } + + @JSBody(params = { + "v" }, script = "try { return (typeof window[v] !== \"undefined\") ? JSON.stringify(window[v]) : \"[\\\"\\\"]\"; } catch(e) { return \"[\\\"\\\"]\"; }") + private static native String getArray(String var); + +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java index d6ecbb3..a2ffd40 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/DebugConsoleWindow.java @@ -71,15 +71,15 @@ public class DebugConsoleWindow { destroyWindow(); } }); - if ("true".equals(parent.getLocalStorage() - .getItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole"))) { + if(parent.getLocalStorage() != null && "true".equals(parent.getLocalStorage().getItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole"))) { showDebugConsole0(); } } public static void showDebugConsole() { - parent.getLocalStorage().setItem( - PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole", "true"); + if(parent.getLocalStorage() != null) { + parent.getLocalStorage().setItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole", "true"); + } showDebugConsole0(); } @@ -120,7 +120,9 @@ public class DebugConsoleWindow { public void handleEvent(Event evt) { if (logger != null) { logger = null; - parent.getLocalStorage().setItem("_eaglercraftX.showDebugConsole", "false"); + if(parent.getLocalStorage() != null) { + parent.getLocalStorage().setItem(PlatformRuntime.getClientConfigAdapter().getLocalStorageNamespace() + ".showDebugConsole", "false"); + } } } }; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java index a2d014a..79f4505 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapter.java @@ -68,6 +68,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { private String localStorageNamespace = "_eaglercraftX"; private final TeaVMClientConfigAdapterHooks hooks = new TeaVMClientConfigAdapterHooks(); private boolean enableMinceraft = true; + private boolean crashOnUncaughtExceptions = false; public void loadNative(JSObject jsObject) { integratedServerOpts = new JSONObject(); @@ -93,6 +94,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { allowFNAWSkins = !demoMode && eaglercraftXOpts.getAllowFNAWSkins(true); localStorageNamespace = eaglercraftXOpts.getLocalStorageNamespace(EaglercraftVersion.localStorageNamespace); enableMinceraft = eaglercraftXOpts.getEnableMinceraft(true); + crashOnUncaughtExceptions = eaglercraftXOpts.getCrashOnUncaughtExceptions(false); JSEaglercraftXOptsHooks hooksObj = eaglercraftXOpts.getHooks(); if (hooksObj != null) { hooks.loadHooks(hooksObj); @@ -105,7 +107,8 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL); integratedServerOpts.put("allowVoiceClient", allowVoiceClient); integratedServerOpts.put("allowFNAWSkins", allowFNAWSkins); - + integratedServerOpts.put("crashOnUncaughtExceptions", crashOnUncaughtExceptions); + JSArrayReader serversArray = eaglercraftXOpts.getServers(); if (serversArray != null) { for (int i = 0, l = serversArray.getLength(); i < l; ++i) { @@ -194,6 +197,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { localStorageNamespace = eaglercraftOpts.optString("localStorageNamespace", EaglercraftVersion.localStorageNamespace); enableMinceraft = eaglercraftOpts.optBoolean("enableMinceraft", true); + crashOnUncaughtExceptions = eaglercraftOpts.optBoolean("crashOnUncaughtExceptions", false); JSONArray serversArray = eaglercraftOpts.optJSONArray("servers"); if (serversArray != null) { for (int i = 0, l = serversArray.length(); i < l; ++i) { @@ -384,6 +388,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { jsonObject.put("allowFNAWSkins", allowFNAWSkins); jsonObject.put("localStorageNamespace", localStorageNamespace); jsonObject.put("enableMinceraft", enableMinceraft); + jsonObject.put("crashOnUncaughtExceptions", crashOnUncaughtExceptions); JSONArray serversArr = new JSONArray(); for (int i = 0, l = defaultServers.size(); i < l; ++i) { DefaultServer srv = defaultServers.get(i); diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java index 31c1906..61be6e6 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMClientConfigAdapterHooks.java @@ -1,108 +1,146 @@ -package net.lax1dude.eaglercraft.v1_8.internal.teavm; - -import java.util.function.Supplier; - -import org.teavm.interop.Async; -import org.teavm.interop.AsyncCallback; -import org.teavm.jso.JSFunctor; -import org.teavm.jso.JSObject; -import org.teavm.jso.browser.Window; - -import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; -import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsHooks; -import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; -import net.lax1dude.eaglercraft.v1_8.log4j.Logger; - -/** - * Copyright (c) 2024 lax1dude. All Rights Reserved. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY - * DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR - * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF - * LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ -public class TeaVMClientConfigAdapterHooks implements IClientConfigAdapterHooks { - - private static final Logger logger = LogManager.getLogger("TeaVMClientConfigAdapterHooks"); - - private LocalStorageSaveHook saveHook = null; - private LocalStorageLoadHook loadHook = null; - - @JSFunctor - private static interface LocalStorageSaveHook extends JSObject { - void call(String key, String base64); - } - - @Override - public void callLocalStorageSavedHook(String key, String base64) { - if (saveHook != null) { - callHookSafe("localStorageSaved", () -> { - saveHook.call(key, base64); - }); - } - } - - @JSFunctor - private static interface LocalStorageLoadHook extends JSObject { - String call(String key); - } - - @Override - public String callLocalStorageLoadHook(String key) { - if (loadHook != null) { - return (String) callHookSafeWithReturn("localStorageLoaded", () -> { - return loadHook.call(key); - }); - } else { - return null; - } - } - - private static void callHookSafe(String identifer, Runnable hooker) { - Window.setTimeout(() -> { - try { - hooker.run(); - } catch (Throwable t) { - logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); - logger.error(t); - } - }, 0); - } - - @Async - private static native Object callHookSafeWithReturn(String identifer, Supplier hooker); - - private static void callHookSafeWithReturn(String identifer, Supplier hooker, - final AsyncCallback cb) { - Window.setTimeout(() -> { - Object res = null; - try { - res = hooker.get(); - } catch (Throwable t) { - logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); - logger.error(t); - } finally { - cb.complete(res); - } - }, 0); - } - - public void loadHooks(JSEaglercraftXOptsHooks hooks) { - saveHook = (LocalStorageSaveHook) hooks.getLocalStorageSavedHook(); - loadHook = (LocalStorageLoadHook) hooks.getLocalStorageLoadedHook(); - } -} +package net.lax1dude.eaglercraft.v1_8.internal.teavm; + +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.teavm.interop.Async; +import org.teavm.interop.AsyncCallback; +import org.teavm.jso.JSFunctor; +import org.teavm.jso.JSObject; +import org.teavm.jso.browser.Window; + +import net.lax1dude.eaglercraft.v1_8.internal.IClientConfigAdapterHooks; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.opts.JSEaglercraftXOptsHooks; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; + +/** + * Copyright (c) 2024 lax1dude. All Rights Reserved. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. + * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ +public class TeaVMClientConfigAdapterHooks implements IClientConfigAdapterHooks { + + private static final Logger logger = LogManager.getLogger("TeaVMClientConfigAdapterHooks"); + + private LocalStorageSaveHook saveHook = null; + private LocalStorageLoadHook loadHook = null; + private CrashReportHook crashHook = null; + + @JSFunctor + private static interface LocalStorageSaveHook extends JSObject { + void call(String key, String base64); + } + + @Override + public void callLocalStorageSavedHook(String key, String base64) { + if (saveHook != null) { + callHookSafe("localStorageSaved", () -> { + saveHook.call(key, base64); + }); + } + } + + @JSFunctor + private static interface LocalStorageLoadHook extends JSObject { + String call(String key); + } + + @Override + public String callLocalStorageLoadHook(String key) { + if(loadHook != null) { + return (String)callHookSafeWithReturn("localStorageLoaded", () -> { + return loadHook.call(key); + }); + }else { + return null; + } + } + + @JSFunctor + private static interface CrashReportHook extends JSObject { + void call(String crashReport, CustomMessageCB customMessageCB); + } + + @JSFunctor + private static interface CustomMessageCB extends JSObject { + void call(String msg); + } + + @Override + public void callCrashReportHook(String crashReport, Consumer customMessageCB) { + if(crashHook != null) { + callHookSafeSync("crashReportShow", () -> { + crashHook.call(crashReport, (msg) -> customMessageCB.accept(msg)); + }); + } + } + + private static void callHookSafe(String identifer, Runnable hooker) { + Window.setTimeout(() -> { + try { + hooker.run(); + }catch(Throwable t) { + logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); + logger.error(t); + } + }, 0); + } + + @Async + private static native void callHookSafeSync(String identifer, Runnable hooker); + + private static void callHookSafeSync(String identifer, Runnable hooker, final AsyncCallback cb) { + Window.setTimeout(() -> { + try { + hooker.run(); + }catch(Throwable t) { + logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); + logger.error(t); + }finally { + cb.complete(null); + } + }, 0); + } + + @Async + private static native Object callHookSafeWithReturn(String identifer, Supplier hooker); + + private static void callHookSafeWithReturn(String identifer, Supplier hooker, + final AsyncCallback cb) { + Window.setTimeout(() -> { + Object res = null; + try { + res = hooker.get(); + } catch (Throwable t) { + logger.error("Caught exception while invoking eaglercraftXOpts \"{}\" hook!", identifer); + logger.error(t); + } finally { + cb.complete(res); + } + }, 0); + } + + public void loadHooks(JSEaglercraftXOptsHooks hooks) { + saveHook = (LocalStorageSaveHook)hooks.getLocalStorageSavedHook(); + loadHook = (LocalStorageLoadHook)hooks.getLocalStorageLoadedHook(); + crashHook = (CrashReportHook)hooks.getCrashReportHook(); + } +} diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java index 25d81a0..7b2aa21 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsHooks.java @@ -33,4 +33,7 @@ public abstract class JSEaglercraftXOptsHooks implements JSObject { @JSBody(script = "return (typeof this.localStorageLoaded === \"function\") ? this.localStorageLoaded : null;") public native JSObject getLocalStorageLoadedHook(); + @JSBody(script = "return (typeof this.crashReportShow === \"function\") ? this.crashReportShow : null;") + public native JSObject getCrashReportHook(); + } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java index a050fa5..0612ef8 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/opts/JSEaglercraftXOptsRoot.java @@ -117,4 +117,7 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { "def" }, script = "return (typeof this.enableMinceraft === \"boolean\") ? this.enableMinceraft : def;") public native boolean getEnableMinceraft(boolean defaultValue); + @JSBody(params = { "def" }, script = "return (typeof this.crashOnUncaughtExceptions === \"boolean\") ? this.crashOnUncaughtExceptions : def;") + public native boolean getCrashOnUncaughtExceptions(boolean defaultValue); + }