From 38e086fb0a2d43addcd9a113a567e9ad81723e4d Mon Sep 17 00:00:00 2001 From: PeytonPlayz595 <106421860+PeytonPlayz595@users.noreply.github.com> Date: Fri, 31 May 2024 15:48:07 -0400 Subject: [PATCH] u29 --- desktopRuntime/UnsafeMemcpy.dll | Bin 0 -> 135168 bytes desktopRuntime/UnsafeMemcpy.jar | Bin 0 -> 5842 bytes .../eclipseProject/deps_fix/UnsafeMemcpy.jar | Bin 0 -> 5842 bytes desktopRuntime/libUnsafeMemcpy.so | Bin 0 -> 127880 bytes .../assets/eagler/capes/01.minecon_2011.png | Bin 0 -> 343 bytes .../assets/eagler/capes/02.minecon_2012.png | Bin 0 -> 347 bytes .../assets/eagler/capes/03.minecon_2013.png | Bin 0 -> 408 bytes .../assets/eagler/capes/04.minecon_2015.png | Bin 0 -> 384 bytes .../assets/eagler/capes/05.minecon_2016.png | Bin 0 -> 346 bytes .../eagler/capes/06.microsoft_account.png | Bin 0 -> 411 bytes .../assets/eagler/capes/07.mapmaker.png | Bin 0 -> 580 bytes .../assets/eagler/capes/08.mojang_old.png | Bin 0 -> 555 bytes .../assets/eagler/capes/09.mojang_new.png | Bin 0 -> 332 bytes .../assets/eagler/capes/10.jira_mod.png | Bin 0 -> 474 bytes .../eagler/capes/11.mojang_very_old.png | Bin 0 -> 694 bytes .../assets/eagler/capes/12.scrolls.png | Bin 0 -> 737 bytes .../assets/eagler/capes/13.cobalt.png | Bin 0 -> 917 bytes .../assets/eagler/capes/14.translator.png | Bin 0 -> 774 bytes .../eagler/capes/15.millionth_account.png | Bin 0 -> 859 bytes .../assets/eagler/capes/16.prismarine.png | Bin 0 -> 1007 bytes .../assets/eagler/capes/17.snowman.png | Bin 0 -> 578 bytes .../assets/eagler/capes/18.spade.png | Bin 0 -> 557 bytes .../assets/eagler/capes/19.birthday.png | Bin 0 -> 876 bytes .../resources/assets/eagler/capes/20.db.png | Bin 0 -> 609 bytes .../assets/eagler/mesh/charles.fallback.png | Bin 0 -> 59749 bytes .../resources/assets/eagler/mesh/charles.png | Bin 0 -> 123138 bytes .../resources/assets/eagler/mesh/charles0.mdl | Bin 0 -> 5517 bytes .../resources/assets/eagler/mesh/charles1.mdl | Bin 0 -> 15867 bytes .../resources/assets/eagler/mesh/charles2.mdl | Bin 0 -> 705 bytes .../eagler/mesh/laxativedude.fallback.png | Bin 0 -> 30405 bytes .../assets/eagler/mesh/laxativedude.png | Bin 0 -> 53774 bytes .../assets/eagler/mesh/laxativedude0.mdl | Bin 0 -> 13905 bytes .../assets/eagler/mesh/laxativedude1.mdl | Bin 0 -> 4017 bytes .../assets/eagler/mesh/laxativedude2.mdl | Bin 0 -> 4017 bytes .../assets/eagler/mesh/laxativedude3.mdl | Bin 0 -> 705 bytes .../assets/eagler/mesh/longarms.fallback.png | Bin 0 -> 20604 bytes .../resources/assets/eagler/mesh/longarms.png | Bin 0 -> 42211 bytes .../assets/eagler/mesh/longarms0.mdl | Bin 0 -> 23817 bytes .../assets/eagler/mesh/longarms1.mdl | Bin 0 -> 4425 bytes .../assets/eagler/mesh/longarms2.mdl | Bin 0 -> 705 bytes .../eagler/mesh/weirdclimber.fallback.png | Bin 0 -> 22914 bytes .../assets/eagler/mesh/weirdclimber.png | Bin 0 -> 37504 bytes .../assets/eagler/mesh/weirdclimber0.mdl | Bin 0 -> 9921 bytes .../assets/eagler/mesh/weirdclimber1.mdl | Bin 0 -> 7785 bytes .../assets/eagler/mesh/weirdclimber2.mdl | Bin 0 -> 705 bytes .../assets/eagler/mesh/winston.fallback.png | Bin 0 -> 37932 bytes .../resources/assets/eagler/mesh/winston.png | Bin 0 -> 73074 bytes .../resources/assets/eagler/mesh/winston0.mdl | Bin 0 -> 19989 bytes .../resources/assets/eagler/mesh/winston1.mdl | Bin 0 -> 705 bytes .../assets/minecraft/lang/en_US.lang | 66 +- .../v1_8/internal/PlatformAssets.java | 3 + .../internal/PlatformBufferFunctions.java | 5 +- .../v1_8/internal/PlatformFilesystem.java | 225 ++--- .../v1_8/internal/PlatformInput.java | 11 + .../v1_8/internal/PlatformOpenGL.java | 17 + .../v1_8/internal/PlatformRuntime.java | 21 +- .../v1_8/internal/PlatformVoiceClient.java | 116 +++ .../internal/buffer/EaglerLWJGLAllocator.java | 28 +- .../buffer/EaglerLWJGLByteBuffer.java | 81 +- .../buffer/EaglerLWJGLFloatBuffer.java | 45 +- .../internal/buffer/EaglerLWJGLIntBuffer.java | 45 +- .../buffer/EaglerLWJGLShortBuffer.java | 45 +- .../v1_8/internal/lwjgl/DebugFilesystem.java | 224 +++++ .../lwjgl/DesktopClientConfigAdapter.java | 5 + .../lwjgl/FilesystemConvertingDialog.java | 78 ++ .../v1_8/internal/lwjgl/JDBCFilesystem.java | 441 ++++++++++ .../lwjgl/JDBCFilesystemConverter.java | 130 +++ .../v1_8/internal/lwjgl/LWJGLEntryPoint.java | 29 +- .../v1_8/internal/lwjgl/TestProgram.java | 37 - .../v1_8/opengl/GlStateManager.java | 26 +- .../java/net/minecraft/client/Minecraft.java | 26 +- .../net/minecraft/client/gui/GuiIngame.java | 4 + .../minecraft/client/gui/GuiIngameMenu.java | 97 ++- .../net/minecraft/client/gui/GuiScreen.java | 4 + .../client/network/NetHandlerPlayClient.java | 34 + .../client/settings/GameSettings.java | 69 +- .../shadow/GuiOtherSettingsOF.java | 2 +- .../lax1dude/eaglercraft/v1_8/Display.java | 4 + .../eaglercraft/v1_8/EaglercraftVersion.java | 2 +- .../v1_8/internal/IClientConfigAdapter.java | 2 + .../v1_8/opengl/EaglerMeshLoader.java | 172 ++++ .../v1_8/opengl/EaglercraftGPU.java | 42 +- .../eaglercraft/v1_8/opengl/HighPolyMesh.java | 66 ++ .../ext/deferred/EaglerDeferredPipeline.java | 4 +- .../eaglercraft/v1_8/profile/CapePackets.java | 83 ++ .../eaglercraft/v1_8/profile/CustomCape.java | 58 ++ .../v1_8/profile/DefaultCapes.java | 75 ++ .../v1_8/profile/DefaultSkins.java | 9 +- .../v1_8/profile/EaglerProfile.java | 123 ++- .../v1_8/profile/GuiScreenEditCape.java | 359 ++++++++ .../v1_8/profile/GuiScreenEditProfile.java | 110 ++- .../v1_8/profile/HighPolySkin.java | 113 +++ .../v1_8/profile/RenderHighPoly.java | 471 +++++++++++ .../v1_8/profile/ServerCapeCache.java | 242 ++++++ .../v1_8/profile/ServerSkinCache.java | 1 + .../v1_8/profile/SkinConverter.java | 52 +- .../eaglercraft/v1_8/profile/SkinModel.java | 18 +- .../eaglercraft/v1_8/profile/SkinPackets.java | 3 + .../v1_8/profile/SkinPreviewRenderer.java | 106 ++- .../v1_8/socket/ConnectionHandshake.java | 13 + .../v1_8/sp/gui/GuiScreenAddRelay.java | 4 + .../v1_8/sp/gui/GuiScreenLANConnecting.java | 2 +- .../gui/GuiScreenSingleplayerConnecting.java | 2 +- .../v1_8/sp/gui/GuiShareToLan.java | 4 + .../server/EaglerIntegratedServerWorker.java | 3 + .../v1_8/sp/server/EaglerMinecraftServer.java | 27 + .../v1_8/sp/server/EaglerPlayerList.java | 4 +- .../server/skins/IntegratedCapePackets.java | 110 +++ .../server/skins/IntegratedCapeService.java | 77 ++ .../server/voice/IntegratedVoiceService.java | 255 ++++++ .../voice/IntegratedVoiceSignalPackets.java | 198 +++++ .../v1_8/update/GuiUpdateCheckerOverlay.java | 41 +- .../v1_8/voice/EnumVoiceChannelPeerState.java | 20 + .../voice/EnumVoiceChannelReadyState.java | 20 + .../v1_8/voice/EnumVoiceChannelStatus.java | 20 + .../v1_8/voice/EnumVoiceChannelType.java | 20 + .../eaglercraft/v1_8/voice/ExpiringSet.java | 84 ++ .../eaglercraft/v1_8/voice/GuiVoiceMenu.java | 772 ++++++++++++++++++ .../v1_8/voice/GuiVoiceOverlay.java | 258 ++++++ .../v1_8/voice/VoiceClientController.java | 367 +++++++++ .../v1_8/voice/VoiceSignalPackets.java | 142 ++++ .../v1_8/voice/VoiceTagRenderer.java | 118 +++ .../minecraft/block/BlockRedstoneWire.java | 9 +- .../client/entity/AbstractClientPlayer.java | 14 + .../net/minecraft/client/gui/GuiButton.java | 4 +- .../net/minecraft/client/gui/GuiChat.java | 4 + .../minecraft/client/gui/GuiCommandBlock.java | 4 + .../client/gui/GuiCustomizeSkin.java | 12 +- .../net/minecraft/client/gui/GuiOptions.java | 2 +- .../net/minecraft/client/gui/GuiRepair.java | 4 + .../minecraft/client/gui/GuiScreenBook.java | 4 + .../client/gui/GuiVideoSettings.java | 3 +- .../gui/inventory/GuiContainerCreative.java | 4 + .../client/gui/inventory/GuiEditSign.java | 4 + .../minecraft/client/model/ModelPlayer.java | 9 + .../multiplayer/PlayerControllerMP.java | 1 + .../client/network/NetworkPlayerInfo.java | 7 +- .../client/renderer/EntityRenderer.java | 20 +- .../client/renderer/RenderGlobal.java | 5 +- .../client/renderer/entity/Render.java | 14 + .../client/renderer/entity/RenderManager.java | 11 + .../client/renderer/entity/RenderPlayer.java | 5 + .../renderer/entity/RendererLivingEntity.java | 3 +- .../renderer/texture/TextureManager.java | 8 +- .../network/NetHandlerPlayServer.java | 10 + .../login/client/C00PacketLoginStart.java | 10 +- .../ServerConfigurationManager.java | 9 + .../server/network/NetHandlerLoginServer.java | 19 + .../net/minecraft/util/ResourceLocation.java | 5 + src/main/java/net/minecraft/world/World.java | 3 +- .../world/gen/ChunkProviderServer.java | 13 +- .../v1_8/internal/PlatformAudio.java | 4 +- .../internal/PlatformBufferFunctions.java | 5 +- .../v1_8/internal/PlatformFilesystem.java | 6 +- .../v1_8/internal/PlatformInput.java | 45 +- .../v1_8/internal/PlatformOpenGL.java | 57 +- .../v1_8/internal/PlatformRuntime.java | 44 +- .../v1_8/internal/PlatformVoiceClient.java | 439 ++++++++++ .../buffer/EaglerArrayBufferAllocator.java | 136 ++- .../buffer/EaglerArrayByteBuffer.java | 85 +- .../buffer/EaglerArrayFloatBuffer.java | 81 +- .../internal/buffer/EaglerArrayIntBuffer.java | 81 +- .../buffer/EaglerArrayShortBuffer.java | 81 +- .../teavm/TeaVMClientConfigAdapter.java | 10 + .../v1_8/internal/teavm/TeaVMUtils.java | 32 + .../teavm/opts/JSEaglercraftXOptsRoot.java | 3 + .../v1_8/opengl/GlStateManager.java | 26 +- .../java/net/minecraft/client/Minecraft.java | 26 +- .../net/minecraft/client/gui/GuiIngame.java | 4 + .../minecraft/client/gui/GuiIngameMenu.java | 93 ++- .../net/minecraft/client/gui/GuiScreen.java | 4 + .../client/network/NetHandlerPlayClient.java | 34 + .../client/settings/GameSettings.java | 69 +- 173 files changed, 7405 insertions(+), 770 deletions(-) create mode 100644 desktopRuntime/UnsafeMemcpy.dll create mode 100644 desktopRuntime/UnsafeMemcpy.jar create mode 100644 desktopRuntime/eclipseProject/deps_fix/UnsafeMemcpy.jar create mode 100644 desktopRuntime/libUnsafeMemcpy.so create mode 100644 desktopRuntime/resources/assets/eagler/capes/01.minecon_2011.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/02.minecon_2012.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/03.minecon_2013.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/04.minecon_2015.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/05.minecon_2016.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/06.microsoft_account.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/07.mapmaker.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/08.mojang_old.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/09.mojang_new.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/10.jira_mod.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/11.mojang_very_old.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/12.scrolls.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/13.cobalt.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/14.translator.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/15.millionth_account.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/16.prismarine.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/17.snowman.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/18.spade.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/19.birthday.png create mode 100644 desktopRuntime/resources/assets/eagler/capes/20.db.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/charles.fallback.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/charles.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/charles0.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/charles1.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/charles2.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude.fallback.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude0.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude1.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude2.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/laxativedude3.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/longarms.fallback.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/longarms.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/longarms0.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/longarms1.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/longarms2.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/weirdclimber.fallback.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/weirdclimber.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/weirdclimber0.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/weirdclimber1.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/weirdclimber2.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/winston.fallback.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/winston.png create mode 100644 desktopRuntime/resources/assets/eagler/mesh/winston0.mdl create mode 100644 desktopRuntime/resources/assets/eagler/mesh/winston1.mdl create mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java create mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DebugFilesystem.java create mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/FilesystemConvertingDialog.java create mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystem.java create mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystemConverter.java delete mode 100644 src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/TestProgram.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglerMeshLoader.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/HighPolyMesh.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CustomCape.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditCape.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/HighPolySkin.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerCapeCache.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapeService.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceService.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceSignalPackets.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelPeerState.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelReadyState.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelStatus.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelType.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/ExpiringSet.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceOverlay.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceClientController.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceSignalPackets.java create mode 100644 src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceTagRenderer.java create mode 100644 src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java diff --git a/desktopRuntime/UnsafeMemcpy.dll b/desktopRuntime/UnsafeMemcpy.dll new file mode 100644 index 0000000000000000000000000000000000000000..067de85c5547973cf78f05294c3760270706613a GIT binary patch literal 135168 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

;FMraH54X3E0eBLGel+S0(Z7 z$;7T^Z%OL zy?BX$lBNHTz4ri%>T26Y_aMDEV?nXSQBhGuM4Y(WSKPiR+<#SBu|>`5+-HHSag3unbPnbX-GFd zFie$(Pf0_%`GMhhX}F3EOPc11vzqikFL!&qrBK5x;dDF}^McBxNs=_d_&I2WG#M^U zQepD3GzpU?R+zjkP1=!(2u+l=rtT9Xr*)oK%W=|_c6dEjk8nr(2cGw+!Bb@yX;g)K zf&j;Nm}eY0^Dtq5=c*!(WG^L#?xBs?$s*0BOL4nwObT+;rw zb%kDK-+|j4*+NiO3!7-Y?vRW&cCMRx#W9{}Sy>FIV**8^tSphP&a=LD`9xl~sT`j(;q!=@k@?I(c15*9YY_ zJqhfn7S}=(JWQFjYj8C>6nr~kCw9u*s4gCf8}kNK7pyyZbftACp`K=YL&lcXVS7ke zqi6$LB&PdfR7tNm#)4ncI(eqNLb(Ff?YT03hiam{D14|^P)9IOKEZ6UscdpoX z6N*Noh2t=|>=3bzi#;YMFQOj1&#&W2U96Ryi9!!qa+$ic*IX`6=b%eV9TEI<7j$VU zm|;g$4q+;lMjM#=;r(ASM!raK1U*?CgGMw3XDV&i#}FG=;=YCU`kSe7OceS*-NvE1 z0&=v$NJsXs@|&pC7T)xDCZ1Igg~;pf7HFJkG8eD9NpHa9zKST}k->zrBX}&*yW|A) zbix}?sU@w!t9Z%|C%3SVD?>9`7HIrpywI%`i&<1l0YbN_9k2q&6$w29d zUpoLJoikXq%33qEdVE>i>uZw+MPJzAS#ZnR_(5v%kt?O(^2Ob>&AT+g9$%V!OuDzm_0GB zT2Jor=p{C%*T|bv#Mpsp2z+M`w#0V}7nF_n4NtCX@#UKFp7Fy9Yx3sA7GLu(j3jsK zMg@s4v(X!U;c|D@nuOit*Nxz9y7PV|_tqHl`rnB2y%C2`j$A$Y5o*s`pYdgZ*GuCE zs^iN%uNNm-qCFu!?Th!{bf+>Y)_3qBK}?IKuc8X}Y-lw_b;a&tfPO?T zwkidEnZw=@Rxx{nHC*gC=2`t1NRZV@>6mBV8C!Nzl+ATPq3!WD4^*77EgX309&ctS zN%w?3&mAS{z6xGW>wQ~UfhjC$#Gd>`iR+eOrf$Uf{Lr=D*uFT@zt9h<+UpYpt(N+T zW^YxfM#12lX5Z`TL~##qq=JrnRy2(AnfV*R&mx@|F11F7X)(lkj@XxniKz2=&yWsc zy18`lV5o>U^f04DKGQ)d#J!yv`y~0Pb?g$v_=)NRt#T2?2X#5z{uh=W2v=Qstn1{^!La)r!E^=*#KZ)Txs3K2=W3sKF zuS`7DDBhqDUski__QyFamQU^RveRnvKu-{Lm>1k1tYrL zkLsD9gZoKrj2Vkt%A|D>d6-Y;7JPhJ{CVt)O0q;@%DNx{qjkS}c=qKDA-E84i8A2E z@6vYNW5*Y`L|CVd30P|@`vwkT5EPz~`OI+^6ToF?X&rA!JC2=A&Yt`f&g4C2Dvjx_ zG)8i@LZS^4&qUw+ssKu9`Vq_l(F^eDY1?N!pg+7kpsOPuzT-s)cZxu;CqQuwl7XDO z8+MY*&Y{;T#Vl+rlA2t0X6%k@-eb{cC9TPIjw=gvj9NQ$;IMUZH%1!n#%tsEU981$ z`pr=n;s-{V>9vfp$li6MJRA>UHU-z1)wMh3Lp9Xqqe(<5@(PFN==2@HNCjH{l5 zja5Gu+;jc2;w$*fa5y~bc5f{fg;jj93f<|Q-{5@##u7i6Cm25-fTi!x#rG4lVll}x z7%c{DWW|=Co9Pt$2~`=)i96^nLs)2iV;AJKe|nz>-Vl%NR z%8h83-CKv~CDh{4VS4)m&K(XjY-HmS^)sTR(W|hNW56e_lI$riscRQ+(l1N4J6_y| zMd__r>_grpW222LcVi0tiq(#oV~5Of8n*T+2p{88T%tCdTn+QGgyZ3e-?L&C62;r< zD&FGN-!zYsnq^#$neUS5xo8XVs1V(`XBorlaNnWrVgRO zr=HWn=yftZyncnfq#i*Iz}Q1a#VvY<-|>;Z$u3!MH#gK_!+oI5F%4aU?ilZAO| zP$wyenXpqsvfffg_J0EZ4E{tsCek!LXuQNfkiL@$+~kS(!UcQZBLZu?6E=HJmo`qo z7T2-kET#d!*5Jxwy&5n%#dvai@4?3jYzvQbP^|BdJ)f~H#^1czV9{2#kW_cM1v zZig8@;uLm}{YS#4e}VHC$S6@ea6;acDCE#1!t0sAYXq83!OP&^7r}cJC!{I=+sG{A z<%j?z5~b$+$$FI5tn$KJ5R0HJSc}Iz2V{<|=oL>Vy6Gn9Zv5+oZq55njU} z#vIQGFEd?ykr?1L1{YM6sI!PH-o(e`RLRmkBQoxHTN9#SVHY4GI#b zKXwTwJd%Ibu;<7(`zfrNJ%@knIU9E2re}L{v+`Xo-Fr@+4$dU|^{0dG1fme{Ee1V1 z^T6&M`6%5mc${3GoxWqw6;qej$?g?X#9hGMN9$kjQpy(*U2y?*+J)&HVQo6dp)EDL zj~>}_5FP|QNJ)g_-N4;P_rKXxhDQ}~8Qya`^;?Lxc$EvgsXO;va^-V5+y-wD<}IdSCM;8{uq1*kxOAa_Z+$$aUZ4NG74i1Ze~RJDD01v1bvqy z%A*m{aP&pv?B=hmzOMR9wriyAf5S7!RnKO&%TX+!g1DeJE{f@b%I9mi5KSG*{QKl; zFI=7Wq>WK-A?f!5u4iP@57Rrqu*0#z@jIqs#hXrAIgWm$cP2D%eR?vzVG1|kSoWef z&0t*su6 zsB3?n{yBJZ_6@PGL5#`uscV``4t7iw5fWpeULT49*XfBE%ef{FhdX>|(iLlEjgD7O ziz`Pkb`>LPr=W-XtCxt6Okh@bJZ=5PGfrbRQfkw&djJExUKnFj7fkao7{1Z^2=19M zMy2s7x;Hb1{OGFnr%i$#I}iz85PRYS8J}r2)e@~xs48;ydOiF(y_R`TU z!DkK&jATenYf@RRNtCjn;w$K$XmKFW@hv>T?CL^kf^W}ah6>*HltXtKuqX1ZKixUr z2!0${f$_j$X+~Dcu|P1oF0kqv>OWAk+FZiQO+OV zFJ#wGn<4YShFHh~^4oxz@BoSlX>p_r8`p$UTgXoY<_B#tlVq%r;4xk-0O6ThY*I%y zipn38*!dla@ROW0mwKL&Z>=8~Eg zYZA7{mnF=m+ulU-C`{b&V%BC69(*O`TglYyScQ`8Xpc1?Yg`%*ci6g7)IMkN_J<{x;o9f{LMUV@zKAZr~Sb5Z{}(J z9G@dZyho;`Bk5heRhE;nGvQCO$ynr#t0|H5vB8dum0}?8FuEL{E|BxG3D|?L&&v*@ zp#O*SvO#FQagV&31AHFHOR@QzMHA_2lSnVJSxvu$GFgChh>nMz#KVG|*PEE573#;M zbA^5}tE#G?fh2_a)e~xqhA__07Sp^rF*}$H@;OA-lkj-h$hY^qkPjYZ^~1233#ZICQb4D8ZAhr z_!6#3!Q;tsz9oqvcE4PIqfOtBxF@dhntxst^+fbbv_Bi~+9rc_vGM_Cy!7`GvR6WzHe83>c(&w> zukoGEp=F+-u;aUnl3;vi3O>badUr+QG5DC3e$5Jn!Zb`0cQ_V1aKlf&UJ>2Mau#2?APF zv$+S%>Ge_wWQQY=4Gl1K{EE>(UTB9Qf(WW)Y@lhAr|a5xlP_H-m`V}@JumDuxroPw zon{v?l(pERSm95P9R(^jE}Aj^>jjJfV$EnrA$kRP;oIVLZ*gJ1F1g2PELlTf#>k80 z_@uk!R|!^}pzn|DIN`Oz+*P@bT9RP$6CPo+Q&dT!*-&zCjDlH1m~TZby3s8KS(soc zlR1_MbyBpgczim+)GftIP}XuyV#?`6(nD+&RyQzMGspI*rthl63diCJ-vks7cjr@0 zWuvTYZItjQv8)~HSc>BW$`!U2{ui%1b|7 zddf?GTzbgM09;}R1KABMGnCj{6j-RE=t@5=sj~=6ToFL(J>8Y;;5~v{!&~CLbhvIw z*Fn(QiXJy!Kzl|C@hOWsKbj7>>ggY6*nI$w-4V(57a)bZVB@m?j=S$fbocwOvu zgmHI>W96IFHd2>zI>1pV2=zu>gXOxoBjGA^R);qiIHuASx+1 z!vRalk?oG-Fr-1!X6s$#ZVg|N8|$V8CDUqldr-+v`>yQ z65$(N)F9pHc`JrUu2zXIlG0;GqMb`>u>+ss#{6DPTTJw&VyU1y1aEapKnr|JSxR8i zh_CYe%MyKC97q~*D6eHKy%4K9EMdfFc}MY08g~yxKdTSZ@iK!4@lYv7L*n~#7!Y@- zcWjj5=HyGqN)$tS7S31}6S~9E^nu;enlx}xj=9^7@HNmJyK95=`@lM~89sKqNehS}}?u@@9i zeD@IV>A_0?lhac?FV-csIFy)PlhotT*z{fF%G#nj#hH+FfbWHPLknX;0CxQtT4391 zQi~dVJPR9aXPnHOC+?PXO*CuoO-XCoh9*%zn~Ygi+#iG_h1Vtp3r%9}Sr4TN-NFk$gwLq^=5@cY z!>6EaR{2`-`J;Y#_ZU8Z1hc|FXNz}yUNGzIO$O^ zl-{*S-#?mxYK6T5@vVFdlf(zbaA_)x#wB)n#J375?2m0IX8MHl=lFzkR}Q4$8Qpy+ zi19hi{e^!(>~p$=sOu~X#M?%(Lt#JKOc{Dp(!^C$`fk{pi}2kPaZ7k=ZE_41{X0+g z%|lkWj2&ZaSjJ2iH+XlRZ0VArK|O`I;qgw?$S@3y&6tJRHJ6^(NU)Vn%|=^hb=$+6qHJ@s1b5SPK>K$ ztZSchk9A_%{d7}^CS4@y{hNdd)LaY6Q_Upe#a&WR++2WL3u@7zp1I8ggZE3*iOo!l zKPiTN>|2-b6NrS6)X+TcV(=}zY}?E+G?(r87JG{S>I97s$KuGd?#UJRl`?MX zTuHtBox78=6Ek|${53V2cwN~HDd+iM~nv;e`0hpUT17~ zTKeCMaR}pWj9HBLF>YjhkFlEZ3&uLe6O4_F{%2%3of-Qw#xPD}%wb%~_z>f>jGGv% z7X6(-x!*~Z{0pn`MCm3I0{D^TU<5!HoFg7rH{2{|_%NWKu zgmE;ZUX~-5E5+oZ+TS2hH@_Jxj!1h|Ur4OIA@OE=skPEPsfF~f?#sWoce6X4I~%3D z@=FpA-Y?xZ221YSPNIp?%xGbZVN7APGUhNAF_toJV60%QWUOX9z<7|cj?vC|oYBE} zhSAA*jM$Pqk~Zik?A)x#xPnLiy12z zYZx7jrVi4*g)x<}h_RIMLBqr4#2TV+vz2 zV{7rV+FNAH%u7RjiABI39z0XR!*Lyfldf_060*L^0ANp?@Jbm8 zKVV%^f&GACeG~=LG0H5Q%W(FBqh+}03wb!s2%H0O_Qa{e(MWjE3)jnV&cbP3oK=uE zCnvKv+|prPJm)4(8ttuE3zpb27iHQsUBvYq~by4oZd1fj@`SYk$Seuk2Yl?fOQv7a~&$zRh4Qp=N!nC=W z8ULizo9+FrQYpM9z5YdWP1;hIrI~r=tVMZd zyw1Ui{c?E98-`y7caTT8bGB}sL|5oHE-G9;JKltCQz87TYWu|4gReMEm&&=Js zo8f&EPhT`U?e4UB+>9#bDQHK`@tOJQdGl;d&4FSbMa@K9PFjAxo79|EV3u8lyF4~8 zFKr3yk)0&YL)Fep&tBr@SlBSfEy}e~i)@}SXFhrea}wGuw{R=CU$QfryU6}4O|dES z&=Th=`S`sX*9(E^$|5CC$;4F_Oy=M!PsnqWfiRONrCw3~$$h@E1U{xK*>ERa55kp2 zI>zq;;rBxP<|u;|y?46VUj_0ar2sBvJf(9?NGYRp@?&$5XD$zM!RDj$GBbrS^D&tP z)6#MZr5Op>e6qVajmgP;tgAT3<)L7sVo!!v=Pg>8fNdRa2Te@`xbZIFbf>N#cqLIY zz7Cvj%k_h%>fJfb`MYzPw|D0>+waaFy@}HTfxG+zkLLWtn|L5cqy?iNBk5T$1(`~J zB?I|GLz1{fc?qb;DS3<1GxM=EEcE&2_ZhaEc=kI|9=2KHOqT0dyGfcyzAiCwkHic{ zj*haM-PzdwTa2mur2X}b%XUew`)}PYx$cjSx?JZ6Z;F?ddDKnjHnXfZ)r?9v$zvFc z8EY9W-KD&kv6@lo!R{D~8LJshp;B&RtYySAnc{xL##qW&!T9&}kxXrYqBDACV@S9>w8gmb!sXhEB|82-Qig70V%7;JM zqMc4dK2ZDJ)IRGi=|A~Le&iwT3zfOe-0Ly=XZQbg`~Kf?pD)7CLb~)6$ejG|=v($! zc}RusmP&vg`+v@_BB4cDhRFxL4Cy}nef%lBraD0Ns1W{8FRAyT8A#3De-o#__mAAB z!w<@d0`!;>@NJ2RStjadmZ+=gkjS#xJg4=T%KF;8pVa&Fn|s*^v<7JiaRGkkin1s} zr#_!j^Y^->5dPl(<{HRAJgG)4g5PuSTl7ElPo_d@l*%jRR`Xigl;>0v7Q+UOYTU;Y zH)}v@3kzGEZ@OLT`&;9@d0gRUF2)sZyxF+I&Ai#Tg2KZ-1qGJl3iI-C^OTa7z5pZq zvGP8f`fLjKpT-?Dwjg^+ami`6$>JVVj7VJObi0~)TUu`BltoE#W8-19*+JtQ+Db_A zq?7u6LUJF16XO|$7V&5&1C0fIaMBoo;zvkkgjjwSG8+5nGV+()5@JPN_-kUbRzQk3 zofIC;6_DLqna47ZW1a#eHaGR{XCjZnrZlukO9iV6nbaDN7wK=3Pf;lS?uR*Ch7-yd#@LV1 z!WhXI#W<2No-u_nl`)&KfU%hILB?{%^^6-BpJl9Ie1&ln<6DfCj2|#oF;+9yFn+`M z6Ql0`apq?j&oL_fq&`fHA&g;+k&ID{F^nmU*^CBOauM@l#!|*|#tn=WjGGuM8LJs< z8SRXXjHU<~Uo&GAV+>;=V+vy`qm?n6(Z*QBSjfQ*a*ON76~GjQ}XC*v^F z#S$E3tRyB5&&?f9cVzOIEXE9Qk9K4sjHZB7ByY!WhTz#Sfv&`u19}p@Dk0q$(5PPe zE8RD7=}*4PhV+l_--$h5XUJJpzp)_4wXwOOJnZ z^H{`^jub|^PR8E==rjYrOWfi^CiK@2y(QV9KeNk(Y)adSN}@6xam>Xp-D&6tjSnM~ zsnGBLe~<>ufB6ej^uNE#{%Vql9pnGi-ztnuZvJa-e+9-g`X4@c_uu++_hF^d^yh)G z%zx)kcW?gxd?6@av9e^<{i`1+U9-0A!F3NkT>i+TkF9_Fi6=Ka_4G5(KKJ|!6)(Q@ z@++@yd~MU~Z@l@|+wW|yeD}TgKlt#YkE^z9{nxfnKHXluW9P2jd-m?D*?-`(gP(u# zW$mG_zW(Oh@4l}){KJnw{rtCmxL=PtK&HFxXYBeZ9)-eGNr{Mi9snhR}`v1@J z|1I=y;1<9fC&!0$FGNQe^A?gS7UrJJqnOkECLM{)>3)rl6y|jQNk=Mky4R$`%AD@u z=*VVH_jq*JnA1HO9YxIP-i(f7=5#MdM=A4`k}BoQ={}Z@4a`lFDizG>9*~Yr%v(#U zR5EYFyoz~S=GDxDnb$C-SnbSQv9d*n*NUGSGshE^I^;@n5)b; zG1r(^GLK|nLC(|WA0==o_Qm4eSSenkoiA> z<-W}I`3Mv9X)F(6uFpT1ncu|Cyd`rxb0c#na}#rAwA61a=K6e4 zYv%fVP#fkZw%?XHK3-f*ZEG-d3-fl&W0=#+>FG#e-hsK5c}M0p=AD=qGw;m2oOu`K z70hp8Udg;G^J?a1=C#bbF}E}C&fLko2XkeNOkXH-6Z4+T&CGi-w=nO`JcfB6<|)kk zGPg1hXKrKOk9jfk2<97@4`9BD`5@+1%p;lCFu#>~9rGc~9n6O^Z)8p%6`;d6QKo+w z^AP64nTIhS!90q&$~=*|#ypjI4D)Q}vCNB@$1yKu9?!gjc>?oF=A)TcGatjemibub zcIM-lJDHDXu8fuGO=50hej9T$^9jr?%u|@hFrUOch50n*R_3=ew=utic`@@$=H<*6 zFt1>q!@QFD3g*?!4Lks;W$wvbpXc>qZfCh4b0>3u=E^v!k3i-o<|gK5=53f;n73sf z!@M2y6y_b7TbXxZUc|f~^HSy`m{%}YnO8E8V_waC0rNWM1|Cp3n0qpBWbVV;Oe2QrUh-jR7C^AXIg%oi}XF*oo4t(dtd^K#}s%qy7tF|TCq&%By>AoE)0 z9huvik6`X(ZqNsKNiw~j%uURFn46jVF}E=HXCA{mka-I8j?AshM=&p9Zr}l9DRV#O z8<_hu-^4tSc@^`H%xjpBU~Xq_-~pwRxt~73OqS{OXKrHNk-3@q2BTX)aANOvD9?U(BAnQzeDGvB1UXI`bd50ma|bob2bbob01y8V9Aexq)m zx$kY9e&!*}4HjuXjJY54DBV8uMBRR*w4bWmXP&LwXI`Y+kCOIFbvg45x_qRRZ_?$= zt8{scl-KBT=5;!cmvV>B6D4odd6MM56FB`Tl7}$&Tqb!K^N!4;n9EsR1@oRXYpY;x zHcg6jp;lGNwdUs&^{JAXg7;Qnk^_F>SGkCi)#cQMkeGoJ0@8D!dRK?luv(=iVz zp`(!9(fltR`L1-y_~nS%Yg+G=Jd5MInA4ffbG&I-Nu(o_Q(274DwA+G? zY<5rkz35oL_7|{!`PjukM#S66BCr~u-&axjAwG%iQ#p!&l#4y|R|uYn8F6_~xgz;w z7pL76W3e704=Ps?SdGx#FGR^FuHT1IIg7wdzAmToM(NeVr*anorrW3TM_dn|$|1!^ zw@>Af^rxpkU%3lB*5!Xbv`undA5=~w5L>S12%Y?!;_{EmEyYjwkIFBlkDCd^hQgcb zmS3c=QDVKGG(hE=!qfFjd!Z=*^zf;iM<90keJ7Q7;=2B*+*5dZ`l$Rzz_xy0OZ9-# z$IEB1y;Sf!@S6lyz~ztXhkLo9dJ+Lwdb-G71WJ)!?uvw7n)p)TzKK))a<@M89H(91d1SK@lTpn6MO51;BU z<;%@_p!)1ye&&dDH^qzUxqCdRzPod(_szMiA9}i|9dMWDiu`Z#pV|j^dHzlQQF}r8 zqWhOF(m4htN*>gXxaXs6Pnvv`?FyB+>B50*U&u#U!tO$PNHe22XBLY3+mx@lBA;$^ z=~=c%W0i>&+WRxpksQ;n%O0RFSeQ1&|6zO+wAIN@+ zTR9>9O@>MH@-6FiQ#M7P0Z>gtPSGy(k)YOhkJ;k}|U%n_OGM(=6knwLyryj2q*079MlB?dxcujW2 zQ^qUFEgn?fn!=Uw8smz$9xpw=WP3ZxEuOg;OElG78GgL0{K)W=UG0D#ep7o$;Ww2x z8Gf9ry_4ZL#h3P!Qt6GwuY3EJkDiy}q35iON3tuPQvYLJNDeCmBw>EB)^NHqX~w(GoO|{{++|c}Rc9xpC6NG*@~k{bZt- z3>mNKF1d6c=W0iEJ?s4{xu=|H?p|+2XnaM|QLcQ|^{2PDGQ4rFbV~bET;)jGk9Fm% zw4dY_AM*bW*M2W)U$1R?eH-s4C;KU`c0^B)K8}$7$GWATv@_LJFQk0bP3}`}l23G% z59z<&YRYjpl{UTKmhwcmazNqT=GN~MPjRKcX}m9cdMX!m=<~*Ud#}&a_mjmyDZW$Q zcgWGUqL||(XR%Vw@;WxCVEzO1O6Kn}uV!Asyq5XH%?#M*VhSsXG?wQ^(K+!o@_sa<@&fLjQImBPhtCB z%%fPYx6i38*Vh#jS^g5+Pi6iH^K9mNdtAi)eU_Ipf0Ma|=l%6@;s%zNvE0hx`!L_c za($g9o8`VNuVVSj%xjo`&b*HKTg)BI_cL!~{wQ-_tJLpS<{`}YFb`w?0rM#4-!aE~ zt;9M+E%Q|7`Zzh8c{R(6n19XO#_988Udr-A%r`LqnfWH>-!rdbet>xm^ADNVG2g-5 z!TcNMjm%$R?wcml^EUGk=D#uzWBwTPDCTzNiOm1SJeBzu%(IyvVP3@iN9Lu>e__6X z`C;apnD1pC!}YNT^D35SGB0AezAjqB@*I|@vb-1bI+kba?m2(_nLAjX#C!w0@6WuE z<@wBu*?jzRizf0cO{^LLm>G1vR`MCKo{JeB!2-9N5x`nqd2%S&0VuZs?4 zUc_>J9kP_;8_4ofmh1Ny6`bAyEZ@NL0_F~OAHsYS%QrKxVy@qpm9zaIme;U+0`qJR zFN}E|%jYvUv%D*F2g}o#Z(#phGH+x#Ps6$PDHvJqn=bR`apob+Co0N|p~~c_Pb;nCt7%!tJ!@U=0z-D$Gk3H`agtuDa-F;Uc>I>*@RY0PU`9?X0b%Wr31#e4(v z8s-l&uVelKa|iQHx}5!Q$Gnl{sm$#xZ_nH}Q>I7GCSVNt6XqezH!`;{e@eH{>FvZkk>yV_Pi1~5^J=y~ zn0YqKmonG)sl+fZV)Dml z^BR`VW?swkTbb9fd>QjFmYbP7SU!h&2+MC_-pFz*^BR^%GWVS;^XGZyX6E-Wx3c}- z%%fO7k9i{VMa)x~w_u*l{3!Dx=H<*wnZL+<1M~NoZ({xi^D5?}nb$D4F_-hQOEH%q z4|$)Prs(4*$>(5p*Ik~$s~!4%b|$Y*>3kk$(cSIO=hYNlzJOOvbe@A*es}v#PYB5H zX|BUvz6i4q?))|hPOE1lK%Gtnlw|PKmB7bur*L|S%s0hSf z_g}8R=&Nq)NLWMGzC z9&(#J{ic=TL}d;FTpxwOC3RSxBR43#$B zKFz<-)4A?E9eLKA-z;zLo}S5dw=bWqArl#1Q+`W6*Oh;gXS>RcQ+bx0e)aHZ{x!!{9;G~2Jj+BjT8;-{K|DeeKlLIuT#6A>r1Y4 zG^I~+ef3?gzeixkT5q=(z;9{~^!hBsU4(WdB}Awce$)@O>*M7uJR|> z|L9j9a$Q*8eIWNEQ2yxpkn2SHE(MZP`0n<}|EBgpuH!YuN3JvLyBg@ZX)5n?T>6q+ z-|e8FzmqFLdW)fRy~gWYuaR<{THhrh_esdNj>z=Mb-t$f$aS2i`XhN$dL*Y`-94>; z>bouUb!B>!gf5rs2f7b5pHC%9_d#DDahKD2iMyOMs>euQPiW$_j!thm(8JT~57lbg z%OE9kedDkFp)}8j-v7?NG?jW{MRn~J=HnCXn(eFmy^{PH~YABy6j7HdlSDo0m6c{NiKMk{i)*k z_9l6)i$DDo9s6Be+TY{i!n?+Ys|DicnvZ_vj+M>rD}UU?>u=&Fmt(2_8_RWr6H_P# zAG+*+vv(`vx5mX^m{{-AW9%Fkciy>i<3X(r|uuA%LC_4#el@+&wnz5+}Xa_ zynxX9_?7~~ipA^i5ttmgf-uGRnN@_L2$#?3PSUd2VNws z_L%yTz`5OCCM<9DyTD>Y)hop9Q7d01G;JBbkuavD?Q4Y98-5a4d->%}g1<5Ub;8=$ zEpHGa9s-r8x4ucdeBFI-5t_b@eVef2F3)!eZ5ew7R=)GVX5!Uhp(4MXy;cb<|LT}P zOTV~xNgfmVl0fTeRp<`t&} zTJ9br%7eAr%K~GHuS;A%{UfsPyz>Krl|Q%qn7Gn*oJ3y&@{mz&^fBr4zgbnGF)JB?HqyS^UDO9etTb_W%N&ymwN6b z`}Vi`39S8Kia_TJ%LEoLd_`cT`Jlk^kIo82KJFrS=7&Z}teq#Y_(HirtD#Du-T8|^ z%O0=YA|3bj6Ik1Mvg8#@B>GhdR8sc}v^;o5V9dtWqCK)~j1rjg;4FdVsjCFW1iT^8 z_R5!%hn^Q$ySC$A3NNKj6IdIVDX=(ft;F!n0`0-yNcnG#0&OpL*(dZdYLvj3gINMA zqRRwYp4=?Zbogt5DJ>cWn%i}*A$R5Y1Q=oU`E-Hyoev09mb@ttvp33 zt;`)Ju=u^10+l1n1*TkjNuce@9)Xp=IRrXC2{=IE6yMihpta9Lffb+T3$&?E2y||$ z5@^2ugFuUVP2#++pOO2R<*@>7#pwc_Irj^!jDJmXpZx->KRPAQGBNNVxl8#zLgLs7 z0%KmY3AEHdB6;uk1s0F}MxZJ6yg+4gyU)qJb@)(;EmH+5Uls|pEqh8}MZ2v6YoGf; zptIE#ftLJEUyys$BY`Q`W(c(QS|-pw@>z*7+XNO5`bl7ItEgeXj(H|V2sx|f%c;50-eXQ z1=>az2`sL7K%lAN34xXo8wEP=`A}fW2fGDYkAE%YfyV?^hc^f`#TgD!_%V}A5~p_+ zXi4oaP?-=dur@kLU`6N*fwmU&1*ZH^BrxXn2LxJePYA3S@Tx$x4+5*7*eS45JtWZi z%dY}$cmE;K>U&LK#UlY9cukRY)3i^&3&@Hvt%w+W2-{62x! zHtPhMCp{yuV$JIU?OQ&Ucyy1zO3!ZurgS|juzHYFpjo>v&=wyk##@!6ItsK83lnJS zJ49f!@fhMQj)%?fb>HUyUi3FX{Rhu8z8ih}SNA!B9{(bGUhbR`@n^q|zFi&i>Zv=< zMF(s@GBP`EcXX>)_gX(+b1C|T{$0(B=3I;Z{F5K5$|jtQ4z`T?v#wN8-(C{Fv5lv% zy8G)ts@p&5rFxA0=Iy)3y&c`sGSsOpZmI6N;63L1IY*+~ZcFZZ(BQ3Z|M!K7_Oqv= zPoM30OTbb;b)QGIZOzNo(G&M!C8obgZMpFCKa?54>gEqy*!rygH9Gg@A@6Uw-K0)9 zi%cZ7)9mLtHzx@2QI)yq48P{qyR@DEoUCqD!5&y;Dw}jeh^Ya6i91PxZAs zd;j*Zt&95Gmb>nL{@1Rm)!YBI?Y(_f8IN}Aj9K$d7lwMPM!eqPad+gRR>l)Y%(qAqQ*9C4S4o}c53*xjk65CH==Xq?)^OaqdscCH+OIA=Mk>P zXa0O|ZTm~n&kt>JyEP_QwRT#%zU)w-df)5IdS|}fUVVM`3wx4FTd6B+y{)@jwO1Q` z2afFTH$WYJB>dQ(w(ZrYC*)sy?O(mrl2!H(A3k?2`tg9|ea{T&p|%NJlIY046umHY zukW^lx2PM&O}cb4xSLuvaNzWq_5;*gqcVDyec4GZ{=KZrrrBN99 zXWr0S^*iSISYkk5^?K&UH>V|cRnsR9=};cnO&!vE`t>4XWAuT}H9bownbi3Ox%W=6;<)iJ@?Z@BQer9@*`m&b&!+^3b>d>LX zul-yVs(QA5C+)tKZPXWxC&%9NU_Z6X^e2Ozr~0Tv?isjn;~O2+sor^h)AIVOQ{Gy7 zb#Uii>ZF&_z6{Umqgs0JZdDT(q7M1&j(~qAv{LoMH zyE~(Q?>Kzm_v1#Y?bqcmb7TaoAz5qd&pbR>&02i-`R5;vR;w!3IY%T8Q+uVp@kh&_ zN2ptedQAU$_b_$efz$SrXFIBI1@&Gz`HNfCty}s|E|@S(owB<0@!pX>s&o9Y0OgKA z&d1(r&6ddr$_yB1mo zt0{$L)P1TMUA}+t)=E_^Sbu-_n#IG_W2=9ew6|rnx;b^V{opGD)aU)Hzj|ra2=&m6 zoeh<*n$@Q+%;;|YE?OPxeCB@RyT0m?&&ogSQL3sJp19>~t2RT_r;RVoe4uN8_0=uI z#^ycVPd%EdE`8i9N{wvs!l_>M1603h4^2Nmd6=5Gds^e79YfS}X${8ipM|O~O^*K7 zeB@SjTEm*O<&%c1#%I5|adldh`os5OEBgmpRQs>->ucN8M{k^ds%5&Vr`qcKLB^u~ zz0@xoO&t%bzenHy`S|eb@A=B#QT zrlyTOvTx4BQ_-^g4OB}PzZjl8a;Ul@`lS6;M_+Yww|36Gm3`H$89x`4-C|MKPx;rG zMP|I=|KNnYvJafmeU7FDbS=@;&D(r-KiRP{`i+l2>zos&s*m}19~+P!rq1m5(vIMO z8_}cvI{%h1Hp?%4xcW!Tw__A7Oc8m-P6bK$jT{^+Y7w~i}WKE9XQe@WcYQ9*rF!-O`z=H5x_j4!`y*S~0- znwa&&l9?&-YPZjmPkr-xlDh5NWpkqM?W4ANW80;f@0!)07k`;@r#|Adt%hjZ#^8_cHdz2wh;@aKKe>tblgv|E&MK<)pLiB z`Pm-suO_VZEW6NYygKdm%fC+gLsdV?Jg)dHNZ|G%S+yP=y85MsiK_FZ!1~RZqt${l ziJPyr8ldhw^vdc^pC+l9i#J`LQQ1@NGOnZl&M#us7oLgnpZ$5PYD?)=Gi^wMYV96& zYu$ZA)vvb1ShlqfRU7_Xa?hU+#i%E5|7qBweaY(W=K^1Q%ri+1-1zDj-<6D0x8A-d z$o8E@_5Z}tI%j{p8r2uYvy!wXL`m*7T&M)53%#AC$HmZSkB1T(_no}1Ri81u?{o0FcG|FYY4JPPwYeWV-yHbJb?tb{ zldpCxxULoa+pvH5?bo&Zjz2AVWcYRM7I6UW2K-;w)~;?m_T9g)X$QJg{A4(AP5W`h zmc`b0u4!wR-_oPu(Q8^{zp5!8-F;1aFR!rpt(n)fF5krB|C-iu#?_bm^}ePRR4;t^ z!@z6W-tF--7dBkg0-kBHW?J1m{;^4_F=E9n!S2O3!j!(wX$`q|0p?sMZ4&|eogq#SG0T7 z(#&hSuV}SfceK6q))lSCjgatL9>1cM4gMiI=iV!t*B_rAJDPb#o6yPe!HV0iXkU2O zjY}MQMLS%a6EnnoMSG?D;eq4*u4rMKU);93;j%WXeEo9AkC(MhwmltfdoF9&PCqc9 z%jV14r|I*pe{Q&}O+R9pcw*&cEw^LsMnmppZQR;ypV-?kYaL&S#s6ikqVt{y`u4l5 zd5m9r>FahduQ1^MvUYf|>G6loT+$-47qoxj`%9X~i^p#}wDXeogK6ri(049raz5;m zcBA^CpaJ(^((F&Ra~HKP6YiMU^XNtGoY%dvvuiJE%MAS=egD&o+O9Kp-|lZ; z)XIi^wBU_rE^0Ne6s<^Fdr=G8`*bVcB^R}KUynTg)7*<%ZlPi4foT`D(e3XnIFxWv zTX#Knk2CV3w(XbE%fmu1YJSU}%`IwkQM0WGn2E2{YVEBJ?W_$Kw0%S47F;}XK})My z(QD(O3tIb}9qn>Z|AjFkDl2zx9+@lyXmp;(*5VPM=p=qyKU=v zt@;kb0TLiuJhW_Nz1lAnSNfA z^PlIn>ns0tqUV_N+G*ptM89F@ween?rrqd!UJGtKddjEEd2P?`R!6!U!BY(QKd(KL z^z)pD&z{qUc@22Y{_k^IQoo-*jjKDSE!^DmfvN-Nv?C91{8|0voHk?oq>Ar0pVP(} z7QemxrE}Wc+V_qPd;FYMoM`CoReDalr|mmqjx0T=Wm%_3evx}ld-}`s`#!Ut(+(`& zcl7Y&bJ~@|b21x8pVN~6c+=8*_&M!?uHW{|ia4iDoIb19hvsuyTXDdBX3Ik>ePF*$ zrDnKtR`c2X>ZphRIIDTQetcWMqi40fg>O7^_}jDEZ*Si7%H#XbYE%34IBfmotk!nK zyKP3idsgdSvotF7)w5dq@{oR=pE|2Oan|Tjp3}8J>bPpR$XY&#vi)=;%%oJv?q(lSNF6x zXcZ|D2LEq?{Z=Gj+25eG8hXb=mp*OKV!{n?dw$TMdF?p+Xy?}(wC7tN?-TocgZ8Rt z)r`Ey8niZ*rL8MV8?@vvUW~eYZ-aJg?-f-k`3+ic!*|Qx&u-A_A1$_ZpVgqfclRUr zJvX^Qdo*+`{u{Iz*7i?+tTt%BZhN|DT4aOPw{=B#L*E9i=t{R0A9rogPE1WKUJ~4( z9j=}mI3}P$Yi%~*zd^Hg-Epty#dXX>?rDs9A{N9(mu#`T|jzOG*Dvf`z; zy}zv2rrSGT?Y^g8>+}2Qm~sEA*N$y%n7i!VdhLmOI;L%TtzLV+mA!-E`FicymmVyh zyuM!hF}%E_a&5iVI%GwwkQMdXs_!~=SbKN9wj_Vl8t;Ymnqkn@lyw>PT2Sx8*|*H7 z*Y$MS|`?s8(Sg(bSiCouGtJhl9+=~Bt?XBwH*Oc|E*9Kee{4KRdz1A!7 zwGNh!kc*>UD>fNEz2XDzyl!${cWN*7eE;(A=bc*lvnLjuKjYL|SyxW=KJL_>82#`j z^N&t#`17|;i~q{0jrd{PguC`TwYy@=R=-y5)M}pVdFI5&PVK`p{qqKFc51Jgvi(6(^YYCL7vTdw^YZW^ly1@%*6m&XO(-mwkd>U7 zyC`o-LSCNy;urjZlgx#S3g>2Y$HI^fhOF~VvX+oFJEYTQ zM*mL`U#Hwxce7t1t);n{@n*U5|5AMZ5)Kv9+TU-(7P@JC6yS?<2iW z9zL^hVSZXxW(2Y^-L@oRalS2Y(fpZ3Ln3ER!l&TyRinSP(BGCZM-S^GT+m5NbenOG ziJOvym!B$?mobHe&qEc2=8Do+>2FZXkn3il7K>5~GaDiz&9FsMDg7;$^sKqq`wUJ?qy6J1O$kkni^Zj4X>N80nME}-8!PO^z$^qZ>2_=!*-LG1 zPq?){XB%Hn;T0%dHF2 zWSwx3J_HY4x^!vA9H>Cq@Br%|uOK~iY^?CFqM6wp!oN-KW>ciS%4TNLUKPwj@UTb! zA{lP&qXs2s3V5dEBY!i9ddT@Qh|-<{GoeeFSA)qco6MT>FOtmYTe(L);g_^Ggv=DD zL9rtf`%CW?d!s=q#lr#p=kU9(O&$upV+Z9-=s~e~C>3zlKQBKoJ=7u|L#Tk+1}w0$ znTQj4{a+mhZx6+LkcXv1dr!qT&(qez>S3|_8k8tFGWdHc{*m5_{~&Lh!RW0RGkg>y zxN%T`&ER2BJS?z-7d5rbz&XW7X$x7~K_<5A2fMzCaT4qX`zpa1eoF8ZV5E-{JgAku zo0o^;Rp6~S&3IRLH?&!$2Jx)~cW&@BD4uilc=#&*lMoN`tH2+A!9VyPJgJpkm>mZ% zaQW{P{%3eA^nJE6PO9H@#1`P&7C3dz`H<2|=oxxrJ?rk* z!|r=He`EJw;reGcE_5{t-+Jiit#phuDjoCM+1uLMSjjzw7>o^`*KoE7FbEXkP4Y-F zAg_Jl&fsTI{9L*YQvCCvYrIrYFB1m5ATTJ>PYD|2o#IFN(j5zH?Dsv`r0spLq6~xI zgraPu0I6){c~}g=UeL!@CD>4vmtt%k;L@L=bD+{W!=!YcVpKXuwp2Rj zg*cIl+Sb)3n}?x=;?Yj=Ho!Ke$NlsRGAKbvgB~9*JY>=q=S0M3D9|9v8r~S~=b`uw z^0LTq5Z06cgyXMt9^@8|ho{m4;dodLHW3D;mGq-y2Y;nQfuGU=WxfN-dt0WUyn6B($qnH1>sxBJ?B ztllYxE`dsyf&isUhQHDU<*f_KTbDr{obBzw)dr)dtBe>z{FRW5KqUm}2|;>7Cbf08 zwxb@x?*Qa!tIkMc#$R=+>ub=nin97SMR|_n;>T@*E!T=3q~AObl;Nhh>3$@f9{7LkGc6{5P4=q zzO+Q11tD(&l@5;v+hzOaBigqP{h{BC-O%warHkQHrKLU47J#x!ZK2%@=@otizz^gz z@}dLsqQfNkLAs4>t8{)Z*xAP3s@7N?WDB$gaNY&MPvjx;r3><<%Osh19eVm9uZJmZ z@Y1ZN+?HWcp=%}DT^XE2UkeNokkY+G(=4tVWEj zdfVM0+(+qHa1L$3S*4@Fspx63`M^J_f6#$3PnNU4%Zn9Nin11`u4h?i1K`dd?$D+S zeL$B;Uk9YG1I#<*1>0NQRCea?!?$Q~{?73>bVi*kXpi#P4)rfs>dw$w3AQ6%qWwf0 z?$&|e|M&;w5IK(04F2E_;Uvy};L_)2KA*0 zHu#x=Q%^64Yt!|=q*hTL#u=mg;np|mcH+Ll_j+*Zb_~JPC!y`j@I-&r0&Sp&NN0zx zUP_RmRPnZZR(o(6Q#|plpfG|BXr{$`aDQgFXw%2=)VMn0faeur=Fe2?z~KP>x5 zcW!9!t+a>!+Yf5vY-Kmvx&@=(+3l|cp}+M)8MS|_C>L=Sv0HcEp$*!$mt?t%QJ{a3 zCV$cPcZdkOwQE6JrBg;5rF~>;rOn`$@A*4@?cTLbaYod+EpLT#VN#4=1=!$jYBP6} z|LQK4+_lA60r{+t8D!syex1e%h&TFm(RNZUhaSVeT%39tYSos;94+BCP-&ZIa#CHT zJn(?sjVBcB??FCrKF!1RWt{oV@=cB<^nAPTH}s7-A7nd*mL5vWLH-s)h&S3)AGE2! zL2a#~ubhLj_BZWY?rBA-!TG8lPA7lpE>P(d8K86;)ZQ6vZ&TZ<+UP1z4>c&tr#QFk zVYc^&p4%(!-xKMn^{POw?l-V(rHS$N2kb#JUSWHdWd$* z%6Zxr@__+L*C|hUbd6l^(be#fM^j57?O0)l4ugLS#XlQkOq2(iK8*DS1-RmS{VMJ` zuPMrRdVGC76yHZZEggFKDIwX&3&SmnpWVmiZS}Hva+$6rf2loajWIw#3nd`iOYzyM z`!C0ldL9HD49ZlTy8c9eyAtlH-}L}?@>M#a-|d8cw-d%|od&f{@e|_+9%s76^-;75 zPvQInaV7Noo4T3{{Z-&JW9&dE!fB0ggf`?4%_Y#)hUe&O6XI5kZpV~H+zUiKX;6xu z0Wo1b4|gd*OB-y40os8UGQ-1^c8uXG+M!JV#sn+al!T!^&G2@KEX~$WO zvlwRuPAg7RM{H=rY3=|&aawU!c7_?S8mEHOgtM0H;Nd|VP7~xYFiXK%j0fV%yThyx zuA^c9PPm(k>oKr13D<)VF6`JsVLu%H#KP_zoY>Y~o&+;&doT@!yRN{VIQzj}9Neb^ z=`Qv*_>l@8g*d|>OAq*gu$$CRQR7+Y(-aQUVydncYAN<^V;qC0VlMh23Q}VRK6W0|}S_ zK|l(oY=+ZPpF-jOU(IK*W98mhpSbt*UXvP>el?y42~XPSatG z#YW$yv^$5`7hx~Q{t4yO89Io*bHFjwJsn<6--WcbW6z}Tqv-QgxSSZ~vL`$yvMSp1!VZ|0;Q|4pZ0GbdK&!BGa*5*M-g zR$%i^t!Wmxxgfv+3&u`eBSi%!6kkHe(!O z9(+gRmw0^qklj&0e~inQi$CJ=Iq=E++lpwjjCv9$^PUXy-Xt01eNHm;PNRQo^2bK% z|1;LfVq8{ow3{5YV*9Y;*gkAK<8>U$nz)%?UVWn0l*4m4g`g8#vy_X93_T@Lj(} zoel!vUGS3@i@E@80(-Su)Jb3?7y#1(7PSiaz^mYZphYbL8^9glLvVP=qRPMxU@O?a z&7#f*w}E%SL1AJ6zXxA{f`~<34xRDQE?6gTwz|QEu=UnEFSHIu|?vrafsu3H!Klt9W7IhW~g7?7e=Pc?x@Dw=UdDaHBfOkOd z79Il+f{d*eRRV4WZ-FCTu&6q4AINx-^#E6bH^E^8i~;n3FF@f-JO;La>}?iR4ekP; zf&7;(>N4;w$bN-+0XKlx!S`RasMTN-_||rdS_p0cTfu&>F=lWzcnKU3XFb4W;4z?H zXCHud;5P6cnEnQP3fuw)!2WL%H@FDg1>Oe-@35#-!PVe#VEL0p9Sb&q`@zQ`=PiqJ zfE&POknuMCDOgQXlhqz-Pqi1H1MiLg=e}rj?uQQRw|IH-ZL~=D=d;T1qW}3lmCXx= z1JzWtL#L@9@T6{42dN*af8)E9L)4*aI+|WTR)?v>(M>x7HS{A<7@mn%@N6{)1=F9Z zpYgfiQ7EMyqmEU_spHiN%BJRWEw_B0f(y8Y+=*OQZ2_8di?~MLlEn8kcCH|~lqbVw ze50{~tGJbLrM1)4>FNw#h@7QLl|z;B*LbVAx~h}EL0iM$IaTo2k!$&@GWi=rH?MKe zRidsZ%ERmUDOa&?>SlEd+NZZFpYp2~)v5w2s6wcohE+thtEh^p z4%Nx0_uc9?b-TJl-Kp;4GyQv1kNUm3SKX)XR}ZKM)kCURJ*+mVN7SS0G4;55LiMRX zs6VPF)n@e+nyJsIe)X(+PCc)-sIBS+)Kdr4OKO{XS-qlORom5TDz08vZ>Trb4)rJX zmU>$as&~|%)w}9F^}hN*eW-@iN9tqspXx8_uj&)^H#MyOOZ{DasyZ>mHUpEqn16WpB$qeDE{HvY+K&EZ?#u`!Zujd1a+q$oEsF)y}%o$};cF^7?XT zsjjNO_9$JR_!4BUd{I&+X>RkLpB0L8Vi^Nvka_EuDQ@+8m|gYki$_TtxFG z98pp)DTI^nDytb6PX0v0N$w?uaOS(~`Sx*KK=UUW(60QX5K>{KyR2?pM1>QLXcul$ z2xvj|_;5JDCbl<{I!Pgz#qR1g<0fa}M59UWC53Q`UGAFkvr|0Lcy{4tq5;+DFJF_L zLlcT<#Lv!~J{2e9wrVO)l5DS3+>GB7sd(8rl~eICE&)?wvZ&IwJ7G|COhiWl=4C|=BGpm;H#fraKXu<+~1z(Pi6 z{tOf^<}*;dn9o4*Vm<@Ki}?%`FXl5)yqM3x1?Dqw!Pk+23mBdG3=}WsGf=#k&p`2F zJ_E&z`3w{<<}*;dn9sn4<}+~N*O7q>8J+nI6ffp8P`sGWK=EQe1I3H^3=}WsGf=#k z&%k2y8Cd*vWMDC)GoOLt#e4>e7xNh?Ud(5pcrl-W;>COhiWd_ZSX{G;x6-B-XvBqy z)fsVNVrfQPm{^w)7bX^E#D&=vN%E%7{2C>7YIfC;TM zUGvMWy_j8J?ZxbZYAG+Li5K&0Bwoy~k$5q`M)Em=`85(R=J%0!F~3IQ#rztH7xQZ* zUd*qNywf(nM&iZ%8i^P4Yb0LGuaS5$zeeK4{2Ix7QS)mgUd*qNcrm|5;>G+Li5K&0 zBwoy~k-S?ozeeK4{2GZD^J^qt%&(DnF~3IQ#l#vp%k|g7rj|%Mk!MB|E2N#6d@|Bb zOrCSviODUbous}x%d5-edwX${@<$b8eWbQFV|}EycgFfiZRd>jk=ni)>m#*YGs;KO z_ra;1bpJcArq?cMtfp5psaMnMo7Ai66;JBbbPnh@)}|L-yD`1W+KuUD)ox6$qjqC@ z;k27HtW=6Wej2qmO418=P@-lZI53Xws01;wBBLnBwoE#!O7wei*fr z*R-UfyfIBfDvFylq@uVO41yX|pPoQ71CXws01DgHoe%!tzV3#pyFrX>~SK54(vXVcCJm{W;xDDfBu(0WDz%f>w4|bZNS20F6gO!|MRAjc zR1`O9NJVjzhEx8#E zB`!`d@n&3&VB(GB@&glZmAKx(1e>jJ*3=>-v83!AR3LWinjv4V+ep)j>WMY2DqHKE zpHQY4xwgUXzADgNCuzT%+e5eK87qa9)2$|&a=O*TQ%<*=aLVas6HGbXXrd{nTj`YJ z3SOcSFmhY=0e03`_eaV{ShNG=w$b2DgEtwx-Qdp*&ib>if3U$egHJQqWALvH_8EM) z!GARP6@!Ni{@mbyeOLQG)Zm{Qe3HSd4ZhIekioYb+-vaD1`ingmchdY@AIDS=lcd9 zX0XlR6$V!te2KwV8GN(BVS{@Ne$?Org9i=%yTOy+*ZpQ0{C$IG7;H26G=u95{ zC}oS??zQ!v!usk}B6?F$U01VSsYB(F6%{pg^<|aItIw;b=BlV~OkQ5?DyuH9be4aq zkyBVvS?A;`m3K@ocGm6k;m0i}I_vW5YihVCn7zg=N;m51$;+HIRTb4`b7?fbV|LmX1(26v)Wx#RaU)$`g#TB)6MKnI zgH$)}fpWztUanR7WN3!it*OI*FmcO9TrN zWhb$nq-d_1LdGyh73KNva;Lp)jZ;-iCeF?0`n|`?7)~x&BDOb?pLR(gbw$E_vQNhxa z3Kq|vmAGEv$U*lF|F@ihr_QuKw|dJLU(9NG?T8z>j`+y6)8$z#0~~1`8}`WKBc)PD z%BH}`AbpKDtu&YHf8D8dm$$DmsQ-hm%g$a^?p(dbRdLSR%BpI&=Uk4v`gP}d*Z*7x zF?U}6{DQ(0ixw64zH2w@&o%1bP5ozDcC;L* z{?szq!UgSjx_#;YLVu#gDSMz_wC${IR#m#~oNcpqs*R?~^8?%C|E1K-3rAXxt1`iY zWIIBaX-B)<7S;)N^v_ZKpM0CdkJNgLa{kI~gm<hIQAbZlCiU zF73m{Iuz}b(IB~JmM=1HF~jd-!|y~HDG;t}u9Uw}VA!I0bNsh;9nr(N%CJQfXS-pGUe1i~=sKdIbD?32#?C?eqt}6d z(b;*{utjUH4B4^y7ciw&?x*!LUWwr{Z8;E_y1H=(B7A%kUY8&q9~w3~bS7`3{;jE^N`E8PV(%o|A)i3gyBJK>%B{fiixq z>x;J0Cc_r(p-a#f5`WpVvDv>1{ykIi-yrA!xl}QbJ5U|IT!t)0Fc;5YkrCr z=tl4;<-$QQAa&pwN9y=ROXy`VNV(|s+?cET^1+K{>T=O7%9v%u0N)3szGyJj%+}?i z8FV=MKvFJxNpAp&Su}%g`iU+VjijY$5lOjd67BmlT`oFJn}C#yCeit5GKnA2W}0=B zE*IUTav) z{fY)u%L%$%bdXNB>2e4Bow>T)3O@;?em{K4JY6n2OULBva?zXm7|6Ip>*-)1@r%Aw zCy@9>)9LgA!#})lp|(XcY7>yQqVIJ6iMm|$uVxkLa?x4(+^|KvDGDSW(XBcg%_eCp z+D%i@fs%63s(KDcxoAUOzF3!wUe>%Nx?HrOJ_S-=G_r07QeSkcb^wWAw5h63*71uT z)l|FTAAZuXMepj8Q*>L=raES+t|QuA9|Q3zT2oOVeTmN2*~@gfXh+Rhu5HnsdKpL^ z(b>9og)SFet3@kyxoCZ5l<0ENwYm>TebM)-IaQa7=2ieC_6R)VG$a4vmqEfmeEI3x z7VWNiXXv(~v-K&EI-)~%J8+4Ac?K1^uo$PBLCqJKqCL)o1D77XmTxDt!>dA%UGk^ibmLd zK>895wHlW$7tOE3D|ET&oxK4h2GRVw=^Vo+ymYND7frE!D|NZ(tZf2`nBl9cv@QB# z$5iV&qO^QvtI;9%14}ebr@;taq%7FM3KJ`4FPpNYT>;~e~1Mlml z4)zpyJ?O*U0KX5mU=P7Jug52LAN(eewmaZyKi9SuUS`M8B|IKjS2EJ#x3|%33zYEZhq<$7W2S^>^Qp5JZ_g;vWDE04$hk>kx z@SKaZod@61fL3741WT|=P-QOFLZ4G4%-Y{c&TA8gX;`i_?L$5gS&x4 z{KNKNDOHK>fW5$j-2h(<>ad&OYk(JfGkn~y(Zj}`53d3;KjrXkKw`TSzUVi4tsCHH zfz;Uoe`46f@bQhhz70Olu)Xj}mnjv)za9Q95TDKPcEgUthhDDBbKvzr=5Pc2Dv%tD z!{54s{J>8Zd=dy?d*EMyKI|s=t|r=I_rqD&@Vty|h1Y;Mb|d^b7{o>hNG%59-vPgW zoz9cbVApTi7nh^;1>Xh|^8j0~*Rd^zGn>gp>Ihc=sZ$BRaU<(T`3~6rAG*Hqf}5CU z$``{|0uOc*+zwI-i)>@eJ8*ut-Y&G?VQC-`(*8{7|MUE=VWeqK*f#{u63#ODt9)D~U; z40t<8)Q6|FD)krYTj2|V#MS`629{lcPxz1kuQRc8;5A?hwhImdFLoHN4=VK;e!Orq z5TC+VhB&XN(**wwB=#VDRGaSWShycZxv)E|*WCk0Kw|#krwzLw&W`A|bKtdx-3aGI zbv_GU0K{hlyw$J=;3HzXJQr>Tl4HVI9XiK^zW_HAGs05J38an-z7vrmg z;WHm%4zV5ZZ-B(p2%p%?o}|18{%{jHjXeZAAHhHN2G|dzegJNJlsu%o8!mWE_f-U! z1F7SIPk)>>yNc%{c;yqEz1Su2bs!UaBfLdGoWia??ML_?AnVc#BjuH-BRmI`&{lXo zh+%Jl+kqE*Gwj?<4A@QZRv`WdVC&O*-E-hmfvo8n@Rf$$1m6uL{vP|r?aD&xYA!F#>V8Z~jo!oLH6X&Kw^I2j|}@S@TG6)v0nkd0&;09eBGOz$zsFT z@6b8W4Da_R?I#O%8@3028_2p3!n5Dfb8dqVew*i3{0OfC@;ad${?|c1cDOL@LCnS7v2PH zFFw%C_yp0uyFg^vQ=lnb8%rchtF0!V$~UmCXXEru;DTJ%y!c#B~Riw?S!3-38a z+rpx6FXag~Y|)|@Ep#at79Di4g+=dNY+=#e7F$>}$;B2Hy>GFFMNeC7;RE;6w&-Wu z44V`4o7*=tzzk%FEV{CC)MmqZFf{6>_0;W2$}_0tN>aY}QBS%Accdljd+|1s|1^@_zxpLn-E?o|E}#rW8I2?b4GIl^>Y=AtxMXKmt-EHm{2l z|MQxYe-h*9n}Y(>j?pNsLA|tEt-)Ib3Z_mxSEFj`rt-0gI=Sem=Axh~d^Z2{`H9+# zw)xblLhH1Q`s<0NjC;;R7X{dB@a#krRcYTUBXYr+=}2-1M0C2ZD9+5ZQT3g32)XFN| z)z0IluXol?KjHZO_Bpn!w$@p7cIA324ytR9n_gd2eRSGk)Z*dlOejj`-q^OvX32|955}i`QQk-b1%oTWl>w zE%p{yi>Jlg5^m{k>1pY0>1*k48EA>~+n1r1VFZ^mTeDiTTdl1*t+}mvt+v*pR(oqn ztE1J`>S^`1HncXjHnldl`dY)S-K{;Xy{&z%{jCG7@z%lCq1IvKnll4gf$V@akQ2xa zp=i^>y`k z4Rpo32D^s3hPzmHE3f%w^?jMXEMKdW!v`tp1>Uy;x5EAcseF5fV6)S2O|up{gW zd&1suL%1>A6mAat!r^dtxF_5j?hE&a2g332V0b7zjC6HoBrB2~u|{$txskkxEm9P* zM@k}&h%4fWcq0vw#z<47IpT|iBi)hSNMEEsG7yPJ1|vg}VPvl}+q2rU+pX<6?YZrF z?Y8!!c6)nCyQAIJ?rHb7H?%jlH?=pn``W|p-R(W?z3qMN{p|zo@%F*?q4r@!vooVv z(d;N=A`vRdg+XRIlUdGThKrb87c<+)tcIDU`t)E62E4Tgq8nQhr^Ic<4uMQtT*t~PI5V_S1uxUHwHuWg`hux+?4Gn^gH3Fn22 z!X?a-mlzv@bdk9gGe~Gh^AYoLFA0C{_}4#k{db zG9w)8iS@+>VuP{aSY}6dM@~mxM^Q&fhpWTe(b&=45$@>e=<68h80;AC$n4DS%<0VQ zEb1)jbai?=8#|jj!<{{yeVqfHgPp^jnPgW^BC|@!DsNX~BBy%DrvY+_OtSI*fho@< zhjPfDB67#&^ZFWn&Aza&$Jgf@@D2KgeVP7je~v%TU*s?GyZl~%qrcf7_V@Vv`~&_$ z|FA!^CA%f3C6Aq3!p`-!G`2LecYD~k1MJ!1mP~f5jqG-i*$rJyT|V-;NR`+9x-zPN7)sr4+s)t~FP`R#s(-{WuaH~D@3Zhx=8 z-yio6A;g}=>5SK&0O}SojvJcKQ^%!WheHt3y0W&S?s=C zcAlMG=V8Y+vD>=YY5nZ7A$C|+)Edo=+M@QTBkGAZM4O_%Xm_+X+8>QahY+pLidkd1 zFyO1_LrB_Zbyz!cJ8T{H4o8QlLpAW;TXH9Hj$#b)IUM9| wX<~N{2ea9iCG1EaJF=VII26iaw^`Y5x$HO_d(NKNbz{#a9DH;8|855UCl6GWu>b%7 literal 0 HcmV?d00001 diff --git a/desktopRuntime/UnsafeMemcpy.jar b/desktopRuntime/UnsafeMemcpy.jar new file mode 100644 index 0000000000000000000000000000000000000000..59fa35975f1c5356331cddda98bf6ab2138a1987 GIT binary patch literal 5842 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 Dkzp=5 literal 0 HcmV?d00001 diff --git a/desktopRuntime/eclipseProject/deps_fix/UnsafeMemcpy.jar b/desktopRuntime/eclipseProject/deps_fix/UnsafeMemcpy.jar new file mode 100644 index 0000000000000000000000000000000000000000..59fa35975f1c5356331cddda98bf6ab2138a1987 GIT binary patch literal 5842 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 Dkzp=5 literal 0 HcmV?d00001 diff --git a/desktopRuntime/libUnsafeMemcpy.so b/desktopRuntime/libUnsafeMemcpy.so new file mode 100644 index 0000000000000000000000000000000000000000..61ec5569ba8fcf05a39e3a51955b4bcef5f55652 GIT binary patch literal 127880 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

Y8+nTRU-Uz6uj4_iT99dH1VEN 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 aP30lV6&QQ(wO0OzzvC$nii9Nn^Z!4Qj*#d8 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/01.minecon_2011.png b/desktopRuntime/resources/assets/eagler/capes/01.minecon_2011.png new file mode 100644 index 0000000000000000000000000000000000000000..77e0ccc3a85baf085f4bdc7b9839e1ce177039a2 GIT binary patch literal 343 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfv^#Gp`S0D`p!VC;*j0}#93?593 z@ytvm%#0J+ST;&CAJgVI%gK7pg2%$;U?@->V@Z%-FoVOh8)+a;lDE4HLkFv@2av;A z;1OBOz`zYOiCdVFVb&Z8pdfpRr>`sf3l=68VGhP}n+l-NN>3NZ5RLQ64?K8zd9#C< zm{{2iI%Z6qcJXEw50gOShI4m!r!P_BY-w*>+B!{%(`8B9vgr#smMkyb!g$u8kvnC{ zVoo2k{B15`9QJQ6CNT>Yv~hkBnLR(l)U1)aB~(J%U*A=1g-PMOxGW~2jD}rTKA+%O z(7+v&;P;$!Lj!k+Le068#_C>;HR6w%1saXj&(CoY>tNvA(!?@HF=_%sVk74ZCUy=k co;(HyR{@W|Z)BbR10Bua>FVdQ&MBb@0MI62*Z=?k literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/02.minecon_2012.png b/desktopRuntime/resources/assets/eagler/capes/02.minecon_2012.png new file mode 100644 index 0000000000000000000000000000000000000000..639066225121e01e4099f040385a83ba4de607a1 GIT binary patch literal 347 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnF3?v&v(vJfvg8-ipS0D`pjC?YTV%m(dmW;|S zj7Eu!W|@rcos4lC8FSC_^}WxDFxl21^>erA|Ns9({!ds2(ohoQ7tG-B>_!@hljQC0 z!qCAg>jC6&7I;J!Gca%qgD@k*tT_@uLG}_)Usv`QEKDrII<_S@Rsw~Vc)B=-Xq-=e z;K9qwn;pc&#L8yS5ixPv#j9C7OahG?*3C2yU!ug>(%!bTb(#{V%aXQb(-(3qc|I?L zc~&Bm_=(!@@1(j8?6pq6uf*N5f2D0HpUMLs;S(=*U%i)=!z9kJ`o-?Odqg4^aH%9P z31u|w+VcJz*MbJ_n1ruZ9Sz-uOh+zU-Cg!xgZ0xxrrqUl@3ra(FbZX`a#}c_abRj; g74i_5xWmA3wb9RONBAWlpnDlSUHx3vIVCg!0H|MZ?EnA( literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/03.minecon_2013.png b/desktopRuntime/resources/assets/eagler/capes/03.minecon_2013.png new file mode 100644 index 0000000000000000000000000000000000000000..1cd6a125b9b2e910b38d66cccfeaa02649249611 GIT binary patch literal 408 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dynE^f_t_%!eKqi+sAHR}_u&}U* zzKn#0lB}zyqK}@EzkzDFsak}owzjrTx}9Nxi)BlI!{kV(8PP5-E?%qBysecI5)#q_ zv`V9lnp2EAv+O73+s~@>THEZkWkS@RzM!*b&z?JX?*04s|NsAgW*@5ww284K$S;_| z;n|He5GTpo-G!lpRn`N@;VkfoEM{Qf76xHPhFNnYfP(BLp1!W^FIbqEjU{@x<*b21 zD?D8sLo80eJ@3oiY{1iycypGJhi9aHiu%X@|4*s9#+uJQEV29T(yPtY0a+fk`Gw2G()#@E(!XQ$uP-( zGs7*$J@J!gyem%0az4b+BH}bDw|Uko9o7xZRkn^t`4U({mZ%Fn{2gr}uJT;u0LPIz tsZTQ)&q+UEcCbIZ<9*|Q+aKQx`41)Xa;UG~91V0cgQu&X%Q~loCIG7cir@eM literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/04.minecon_2015.png b/desktopRuntime/resources/assets/eagler/capes/04.minecon_2015.png new file mode 100644 index 0000000000000000000000000000000000000000..a272284d7c05466029beb4eaf4b9f7212e406265 GIT binary patch literal 384 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy9sxcfu0R?B7^TEm6=iv~)P#+6 z6&!5TJzPw}0xhG%+%r=`%Znmi%#vE_n+r2Kh4tt5x366|>%hX!<7;PLxpL*k{Yh7ML)4fb^HlvI%U^z**MbZmOqg8qcCF7>6)SYH@3)M+Yx{iRdMxksM;J?jh68L|pe%7Ki(c!WL+ zSYBlNA}1jo({pYiLu|uZM-IjM@C~Lb)E6*V?qG~21szhGfvHsLb({BsLXXr-r%V~EE29VA4+4O}ROO}^zVLWTl zn0?Yi-&@;NsAEs@+HY?{Qbdidt#1q&0iiR2dF9a%u3lb$Y)Ar`0KUf4LvS&@VF!u5rV8$1sD|9{!_{<&k*eRqjy z7IDw2F1hengEh=+rH*z?zwX69OgD-crv#nTyvRL)@fVA%f<3#W*Oa{uaSbmRRTPfg z=AEc;c3)W4jfKgFJr37>^UhKDbS@JEt}zVX`#UZ#VpMv||A5b= z;rE=4-2Mk^Shb$zEn=Kusn?+?zJM{tS5@lR&CPcm=Y+@~KKqBY;Ig2h^rm0+2{8wE s9%j2GyJhR+nxlO4o(ng~+}~quzi)@g#}qdcP)IO%y85}Sb4q9e06&eFJ^%m! literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/07.mapmaker.png b/desktopRuntime/resources/assets/eagler/capes/07.mapmaker.png new file mode 100644 index 0000000000000000000000000000000000000000..58a217a4d27be6f9a7c64af545c010bd176a41a7 GIT binary patch literal 580 zcmV-K0=xZ*P)ib!pYNt04aaF9!KlS`FVOmmb>mRC)3kxq7)Pj{J5c$-pupi_RM zRDYyZfu~-GtY3+(Vog6{i>_l&L1a%sWKcq7QA1~sv3#}SeYWI&x8;7g=7^`lp}Nnn zsFtv*nXs#w%)L|1zEjV^SklE_)5c!q>+j~*Pv+QA=Gjo@>+t66@#oo5=k4L;#2d9Y_EG010qNS#tmY3ljhU3ljkV znw%H_000McNliru=mY`-G%0Od(UK~y-)?a^(Ef}J+f zCvvxT*>S+itf>G0r#g-hno0CA=;nO$;$c9;*tP0as@~dduNj#lj4i8Hv)VC6=Cv$v z64AC|bRrWfX*nS5=ALTWA~NY46aadkw(azUR|?QYL?IA0&>|0%LM2on-Eu$^r(-Fg zZC4)7rxZX1;0Aa~{Yxo>KtB?o2u7o?;gC)Pc4uMr_r3h3BLIx2Z)lVP1`KXMXB~#g zZ3cP)IERmWAWQ(GIE~~$w=*8o_4@=kMI^s4S^W5O-}h(J%0GFW?A5 zf=)mr07ODwoZQ|Z#N*Ay&Yi)*oyRRuBdgrR!Q09s*ugD0iAQL%fcR7% z;pq~JbA%+9ODL`26aC`<^)rq&`(bn#}JFtZ_h{jw-^YpCM+sho4R7hu2l2gEbC8u^$H*1{{Me^W!r%Me$B`bIqo}eeb~=!iPL3`*_L+X-Ya;yiQ74)fayW^ zS?f)jdro&~v>Grzc(qXDlyp3&$B9J>ISKdP&)l2-PWpt9YVm`ezu8{yVLbAi@d3Zr zA;}LC6S){QBYgxLR!KK0ew3SeMuB1fmxeQk7|uu)#BXMh&c4~SX*K7HNHNh38&3Hh z$i05D_U-%MY}M=DW-`d7w)yigE_f7?nfjRFj_F|`hN$_OOTTzB@U54B>wSBlt^Lk7 lMJFWw%&}+u_xW`VV{evr(991^HfBWW31N%2_!Eb;4`yU_kf7y~f)9$+fH87S0`2{mLJiCzw;v{*y zyD)UH%6b4foCO|{#S9GG!XV7ZFl&wkP>{XE)7O>#1q&0ism7mOq>FZbJN4- z?qd{-U=Vx3$~DJDEP~tQ@ekdU##6@Wamw6p_Li1keS6!3$)iDviIc|}7+UEY{f}O; S*8)0`fx*+&&t;ucLK6Vbh-(x8 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/10.jira_mod.png b/desktopRuntime/resources/assets/eagler/capes/10.jira_mod.png new file mode 100644 index 0000000000000000000000000000000000000000..f3d4fe8f8205eaf72de27495c615822ba19ce599 GIT binary patch literal 474 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy6#+gWu0R?Hq{PH!C8bp56*QGq zw3HaMR8)<%b!-e7Y>Z57jZN)M&7Cc+Tr90UZS8$so&B6$0-a^U+!?|=Ji|P_q5}Nl zd>JyMqf6o$+6x$`Rx>VWVOZM1xOpJl>segED7=pW^j0RBMrn!@^*J&=wOxg0CG4BJR*x37`TN&n2}-D90{Nxdx@v7 zEBgx;CT3I9`F&4M0EKRQx;TbdoPK-$VAo*<0k#JMrR86YytSmaa$HL}^Lzh8DdDDR zzTWw^U)cTY&e&frm2=_zv0gcL>P7Yz8J@Z+f8`>XUms>MV9ob$5PoFk8?JcgM44h_ z@WyuxUI#4$7MMz%u-@?J^zV5m#S~t7@He>mZuHR*{j={-W{*n;`-ATa|Cj63d9%hl zMkg9BoATn@<8uv4Ufixz&+o}`FuLt?VT%s;L$(UWeQdV^q_`&BXDv|6EpAnmnxxtA ze!;v4JW?_|ueK&JzvZi&_k4q0eS`Pj!~Zv)KVa?i;UgFKyry_`e5TtmEFLcQHWeOyC*+`@d^!+kx%{X8Q4JR|+RA_Kgl1AX$t zJo3Xm3nGBXt1!~LD9Wce%C{uiuO!B=G{(OyHlQpnpgbQMhbF#eWX86v{@|m0EJ1^UBUXJg)93bgGKQ~~0Uf};LARlqR+o1#W8)He3 zUoeBivm0q3PLj8~3quF1tOt<8S>O>_%)r1c48n{Iv*t(u1=&kHeO=jKurM*32??%b zP5|l&_jGX#u{iy9!rh=l1_Ex93l%dnyhQ(KZwYd}n24x=h^!NKF9cN*6Gw&^OUkaG-q|x z{&hTyebg3~dsM}?^vf<>V^*5^YOd)Wm5v9>SKgN|?^9TM>T{Q&w$@Bn1Bvg4ChX7_ z3%NOsD?&3!h=t|1^9;*F-CO1dl*+kSeDLVdyW3LBz;GbSGx*J6Mb3o$XVX&N?wMDd zFxAsgDv{^6b2+Q-+N(itc@q3Jk2DunpWMzjC2F^k*Lv~PQc;;7a!oBe4i(*RH0O`@ zo^I&!w%68v)&%`V&JTqw0XAw2`wJQtUlD9schK5v&zuF{c$J+Jo^dQ&(UbNnN<;VD zE%V0$!bPt*dIMHXXuXiS(eKbh1*aJmc}-f`dS}|qqZeLEvGUv$Ic?XW^M5!W&X51h Y79L}+AzPJn7Z~acp00i_>zopr0IG-*MF0Q* literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/12.scrolls.png b/desktopRuntime/resources/assets/eagler/capes/12.scrolls.png new file mode 100644 index 0000000000000000000000000000000000000000..25e144743680c78108ed9bddb2c6f13862da774b GIT binary patch literal 737 zcmV<70v`Q|P)vi46$(Wc3P>9ZNgE4EA`nd}6jnF`SS$coE)`-j z0cu7HYd;`sNeXRUT5dZ4ZbS-pTmpMqPJTuMesz0-aA}530f|Zhi(3wjUNe++6P9FE zoRE;AesiRAK&P6QtB886n*y(J1+j@yv!MjEb2qeoTD7O4xq)50mU_RjsKcWI$$>q} zb1cfCU&^}y&BX%GdIHdy2+*Ts(uN1pp=Q#_0Mg0<)3O57wF1+}0MxDv)qDfhwgJ_- z0oI@a*0KTDgb3KDWZ8!Z+Ij@qgag`%1lpAe+L;&IdIa05Z{2SR-Ejloa0%wMap$&s z?Yd^~zIN}!a`U`w_r`kn#*6u12!q3qUuBd z00A*cL_t(I%k7bCGs8d>hBIW{8^sbd!78VSL2DAEdeOSI?!|N`He&z(pKubLO!ia9 zHy=EopMB4J_GlVSnM=_!P}c?4?E-UMYNRNF5CTAOo(LpC5de4<5x`I&_m{8lZ+j#w z$S+6`k{aY?-89X$b47?COn^^1`tUe5H9fQOtOyWV)>64#3W1WF+vSN|ZhTV_Sl_bj zgQHR(sG(n7?_))^BCjYCSi&of?$x~`)8fb-4iiD z8BxXeo+q&6WIjJ%DBv8X{3IrDEVMR)0M@VHzOlL_=ZRdV5)6dtGIFYkPZe ze0)+}d}3;SQe1srWPM<2ePC;SVrzY3Zhlx_epzOITVj4-Y<^^Ie^p<9TV#J;WPny= zfLC6CSZ9D;XnUV{L<2VS`(1gI{Tc zS7L-$V}w^_gjr*RS!9G;WQ1R9gko)lTWp10WrkQ^hFN2VU~q?9X^2^4h+AQZTx5t{ zZHZfAiCk%kU1o}1YKmWMk7;m_TxgVQahGm(sO0mg<@Bj}iK*uHtLXTzevYq$kg$4- zuz-uOfRV6(lCgl1vVe`Uf{(I?l(T+|vwx4Ye~z?+mbHVHwu6+peUiF@mAr_Wy@ipz zh?TyHnZJRZzk-;*f||dDm%oUZzlfQ?iNQm&A&o#FnPVlc30y zsLGS3%A2msmZ!^_u*{XF&YG{)@blI2^w#nA*Yo$-^!Qr0ix2<+00DGTPE!Ct=GbNc z0004EOGiWihy@);00009a7bBm000XU000XU0RWnu7ytkO2XskIMF;2v0s}Vy`wK&9 z0002sNkl7!G5WsPioQK;gOUKzuEf!Cfk~tsk)NEOrR|2^&1k`UA>?96J zg;+B7FR}du#|dGum_oCd6Hx{C%{yY#^js|GVu0*_L!L1K%JF&(@02Nk#ha8=ViFKh z07O>+&w!=W)@mY70e03}Z00000NkvXXu0mjf{6c{F literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/14.translator.png b/desktopRuntime/resources/assets/eagler/capes/14.translator.png new file mode 100644 index 0000000000000000000000000000000000000000..b681c269353cfbafe5c2f2fb674575f425e20f80 GIT binary patch literal 774 zcmV+h1Nr=kP)o(PK;nqjbTlVVNZ=>PmW_yj$~4gWKrjLgy-OQ z?dEvy>7eiL@AB@U|NsAAxJrru0004WQchC^0Xh}ptR5;7+&|6c2Ko|yK zr$S`Kb?t1Dl^vldrNq)&gpF;9GEif4`v3o8x!Xi}WHLxQUI3JIW z4C6RWIOiG!OIoow&!qyT&RX^LrMm4T)UB!dih>X{a{@DFr4l!Y5McHZRTiFT*Wjhn z%y2xmuYVS_%bXA%R{5;DmkI%t)hyFhMHZrxu zA|dFYW^-8>rD2#7!rnirL$C~?DhtW*JZW^;Nuv>ymUuHj0K!&IU~EW-B#wlDP^G2; zxF8EG8ex)*@#L8>+p-QUx9!@leCN06|5W%3!he39Hy9*N?re1LRsaA107*qoM6N<$ Ef(Z&XCjbBd literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/15.millionth_account.png b/desktopRuntime/resources/assets/eagler/capes/15.millionth_account.png new file mode 100644 index 0000000000000000000000000000000000000000..c2f0a02d8878c76af6743cdaab449e0270465b17 GIT binary patch literal 859 zcmV-h1El27Fed^rCj&7l0yHTDG%Er%D*`tw12rrH zHY@@+Edw|$1UN1PIWGe{F9bO+1UfJSJ1_)0F$6p^1U)kZKQseCGz3641wu9kK{o|M zI0ZyH1x7mtMmz;bJO)TT21z~!NMQVd>H4PaFaVO0%bR}W)Y4rEyn zWm*tsT@h(s5o%r%YF`m+U=nO;6?JMAcW)MaaTkGf7lCybgLW5(cNc|s7>IZnig_1{ zd>D>>7>s=xkA4}Ee;AU38kU3^mxURbg<P8=s9Ep^kD`}r9B`7QkVEByLB|NVFW{e=JhkN^Fd|NXT8{lQUIy4(N&00DGTPE!Ct=GbNc z0004EOGiWihy@);00009a7bBm000XU000XU0RWnu7ytkO2XskIMF;2v0s}WHAh3$R z0003(Nkl|?y~(v0ux&-@Mzs6t<9RKaaAKwE3e&ee5NK>WT?9MHzn^oZH!+9ZH{mri}Wr_w1I zgSr03TEpZD0bcF;k9YgvBHX5QqRD?oN*Ycyt$pCS^TCN z?E93wUf&*m)6!9nZ lsye5fYVdP^0{r*uJ^{s4b_>o1w*~+J002ovPDHLkV1mO9JmvrZ literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/16.prismarine.png b/desktopRuntime/resources/assets/eagler/capes/16.prismarine.png new file mode 100644 index 0000000000000000000000000000000000000000..3ee69b2ed641cd3ea5459a25c4c198a27147bb82 GIT binary patch literal 1007 zcmVpa4S(i^XP)Qz z&1(RB`SZ=#r6wOAD-CyULBPZZMP* z*$Dt>&9?A-pZ8ZTv$3{LduyA9=b$r255jX1o{MQ)Xf;HuAw{M!YzyH%Y^iBG3L5K)$B9jz~glq%m=tVi*RYjFE}LaYZSgcn6Gnl}qowM~aEC1O*n|aKQOj&U5aymq!P}gMc`c zU|5)zjS53Nzf#HzT}(cLl`AX!_}j0{%soYJ+9XkgQWB+7UV8Bbe*fv0qZWum3rsZL z+&tA*c6AN-GL(02v2bK^fJB$yMqp$KI{g49M2$%2PF&SP(5OS!u9<_3%bGaEHG>f@|@l9 zfTen!n&;DMoI>NUwS5<@RM`T{Cy!%r1hrEwqHciWd$e4KJdP)_V6+1|HwpSN{dSM} z`5AJ#i6v%m{5naTQDpkzU64p93Mz(47{w%sqGlE(kwmA8itDo7?lRE`mgg79$k`e6 z*zfkq^NhUMq1kGc4ul5*X#rlfN}=5`D+WE z>C#Q dgcD9U;cxJ!+Ts?@*Cqe}002ovPDHLkV1mWU(z*Zu literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/17.snowman.png b/desktopRuntime/resources/assets/eagler/capes/17.snowman.png new file mode 100644 index 0000000000000000000000000000000000000000..f4ad55259cb1afad3413da8bb51bdb3e499ec1a9 GIT binary patch literal 578 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyEdf3uu0R?H6crUMEG(Q|oLyX9 zT-{t<-Q3(g+&w%!JiI(Sy}UdFJ-vLqyn?*Eg1x$ zqe8=D!XslNBI6>X5~89LqGJ|NsB|Po7hOj$kYa@(X5gcy=QV#7XjYcVXyYmGuB}I14-?iy0WWg+Z8+ zVb&Z8pdfpRr>`sf3l=68LH@O>rz3%S%spKkLo80eop>33jXkZcmQ~oqBPVEq8hKhF!KC3O{?b!nsZ7 zT%2|C)1LD0niX-zg2q|g(SAkW+1F+4U3uYC=KNj9GJxK8ef^zHJ}uWG`S!uONn*>3 zq7S&9VVJv7Ml?Iou~H*^@2}K!i{~s0?y3YY`C`;FyD_Qa`7BAs8?i@B4}X=gbNQ6s zGB0}5g&jJpmdQAIDaJD?K9ak8aN(98kzdz0wu?=7cUbrD>-Aqueh*dGF4TXQ3=CBU MPgg&ebxsLQ0A}9fegFUf literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/capes/18.spade.png b/desktopRuntime/resources/assets/eagler/capes/18.spade.png new file mode 100644 index 0000000000000000000000000000000000000000..7cf8e8bfacb5f535db2f9aca34bd0d4cc2d83faf GIT binary patch literal 557 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dy#{zspT!AzY@Ue6AbMWwU^6+!< z3IGu|uZW1SsHljT7K1pikT}1vgrKM_zqq`dth~IOf`Xii7lWD)gGMlemX?NI9D`*E zgLMUiO%;Q4JEPZBM&CIMK}#8Fdh=f`y4iQ0c|5={i862c9mDAr`0K zobI>b_Wz<2Nh}u6>A3-YzG!?2N!S$7-R9a|s-N2_Aw99CZpDdI}tS z3LR| zkP|MG6E2z)FPs!Fk`ynL6fl$&FqsrGmK8CU6*H6-GoKcHBo{WG7k(rdHklYVoEU~B z88(+0IG`Cgq8U1-8HObqI;R>tr5ih?8$6~PJf|Byr5in`8$GBTJf$2xryM@19fv9* zkuD*UE+Qv2Bb6~Jo;WHpOe&u^E1)_np*mk~pL>b4gOb68lfa6TuZ(XqlbpJm5eu87 zy`ZSUp{c~A7Z0b{t*DAZwGHq)#n#3qR00001bW%=J06^y0 zW&i*H0b)x>L;#2d9Y_EG010qNS#tmY3ljhU3ljkVnw%H_000McNliru=mY`;5*P*B z9bEtb0Ub$1K~y-)V_-0b0|_`_Kmx{&VQJ~<=>-|iuEu$AfUF=Osk=G7ur4>m$~Z3@ z3Q!b8v`%PmF09LsF~^}Gs-wTFIj1no&>n{Z-^P}v+Vo6I4A)=gXAYpY(r7ND^%uF8ttya zAqF%7B9CeU6Khd*O0vHUI~&M~iEVA@Rawy5vy?5r<0Q$tdKY=V(zY&j65 zdgz^hMqyDzG1e3VUCeym9b^DiB+wMb)BhogQ-oUnO%#yU8{wCo25gi zrTY|1k7-t()2%#bSbG7{ENidXHeR!BedgHu%(L~GZ|A$v&UcZ$?_vkPr7azvt)1Sj zoj$EyzHME8?cM$z6Cye$Ms-e%?wkZfF?NMQ zuIw*Zm{^3&Zt@CD0_xHCba4!^IQ@3QS--;u0xjA(?`KV!w2Sdp&MTe5ADmN;`M#d= zz23M-;Ly~nhaE?boO=1WCtXcgzOA5VzWjI9^|OAbp0)8bVUho}(f$peUCDaa>HBSF zztdzi`+MNctF~=_*EttgqZEBrnAlflQ z{lKId{p;%Zqc^cJKDxNcqhVQ8VS?4I18+?;8eS~O^OLFJ=;KQaj$~FaZ4&8bNsy{6 z`RbwQ)^JKmxl}4JEI+x2<6v>N$^#QK%Sz{&TXwW^3wSBbWBOwn;%PQrt4w6U^GECp zUR7)46}tooR7(}st*HTDTRAHmJzwO<4-8EPPgg&ebxsLQ0J_8RhyVZp literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/charles.fallback.png b/desktopRuntime/resources/assets/eagler/mesh/charles.fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..f1d90ca587b3997b7fee5848a5cd92c9fbef9b53 GIT binary patch literal 59749 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 #?ousdTxYsykUMuw#}%3w!ErvmQ2|FA@$M<01A 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/charles.png b/desktopRuntime/resources/assets/eagler/mesh/charles.png new file mode 100644 index 0000000000000000000000000000000000000000..a23587f5673e4aa8a93d2c67dade4e0cb5ec21eb GIT binary patch literal 123138 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 TO|qKo7OBaaV7KsKB75aObIRM0 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/laxativedude.fallback.png b/desktopRuntime/resources/assets/eagler/mesh/laxativedude.fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..27b1f9ce54dfcc7b81164e817a7c94dae77956fa GIT binary patch literal 30405 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 XZhS}ZJ+yoP`Mj4^c~>TF68e7t&85+D literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/laxativedude.png b/desktopRuntime/resources/assets/eagler/mesh/laxativedude.png new file mode 100644 index 0000000000000000000000000000000000000000..ece3e4a3e3689c1a12fd98353709944b9f44b7e5 GIT binary patch literal 53774 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

tN@6jg^kC5kk4#9<0G!ES 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/laxativedude1.mdl b/desktopRuntime/resources/assets/eagler/mesh/laxativedude1.mdl new file mode 100644 index 0000000000000000000000000000000000000000..3f4d94fc760c6ecf839206817d022134eb1778af GIT binary patch literal 4017 zcmZvec~Dfx7RFnGh(ux7MOI~x5?K@#W;iz>7(q4x1!a{PWEl_`1QB1EL?ZCqt<*Cy z?lHc^C6HiJF${B!S&ZhXN8oCjZIx?nZc)|Ot13^Dh~DujhqxZZBlq>c({+gXla;siB>n!r%12&sV!Sn zT4(U7)fsfP^*XJM4P&gHF^iy(_w*FJNhMAF?wma8fA6rF^D61cPwncY>|%0Aagh+e=?-+GV?U-54`e5_1YyzdV0* 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/laxativedude2.mdl b/desktopRuntime/resources/assets/eagler/mesh/laxativedude2.mdl new file mode 100644 index 0000000000000000000000000000000000000000..1dffcbce842af3234dbd8677203b7861eaec1c88 GIT binary patch literal 4017 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/laxativedude3.mdl b/desktopRuntime/resources/assets/eagler/mesh/laxativedude3.mdl new file mode 100644 index 0000000000000000000000000000000000000000..56dee1c72243947b0fa3260b6df41910d4548bd6 GIT binary patch literal 705 zcmX|*O-NL66vfYs^U-_bjPv2^xqM<+Vc;}LhQTm3e#9)=1sQ>e^UQ%a5HrqT1VM{j zxF}k*h?t6uQqjVN+XrndFo+N-gO)*VS|pOR^4$MpW^wN2{?7g1|LGpNGlKL66awpGBhi?7tYbMv|Td$-o|s}J7N-@tx- z)${rO(I>R_|Giu0{sQjqK6J1C9aZ;l4+7hrPraG<%-$OG#bq_ie=7rp)-3l|1~yvz za?k8tfaE=CUh(qY1B{P**+Mj*D_>t!`8PitWP38hxi8;esQl~aeyQ1c-%$CR{@%AY zD*yQ559P~y$=}>B`@H;LpB!fYM@H3s$$#g@A2rK8$$$CtPc_SblD|32eaYY4mwS?5 z@@}Wcyu8d0_~562Hp-6xYXCvkAc>C(DL+i=$1&0XG}0h+x*>!~!{h-;C~-oF zkcL?`_6VuQ8e)&29Z|%nc63lN#98A=uqH^NR8sjV(il2P<1k1QI8HZ-6lsb)P8p;I Zc?Ts<5+-Si)nGSC4b~*PiHV_X-w_a3$}<1} literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/longarms.fallback.png b/desktopRuntime/resources/assets/eagler/mesh/longarms.fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..b5065341a6a5537ea935e8a0cbb2ce1f395e5a0c GIT binary patch literal 20604 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 Pb#a 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 z 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 AjsO4v literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/longarms0.mdl b/desktopRuntime/resources/assets/eagler/mesh/longarms0.mdl new file mode 100644 index 0000000000000000000000000000000000000000..29895c1ce3ae88bfc9139373612efa8f9a3030d4 GIT binary patch literal 23817 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/longarms1.mdl b/desktopRuntime/resources/assets/eagler/mesh/longarms1.mdl new file mode 100644 index 0000000000000000000000000000000000000000..a72acfa5b61cd400270d9cd6704275a43020f6ea GIT binary patch literal 4425 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 U9L?4|op;uR&+0%38-fG=59{(=Z2$lO literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/weirdclimber1.mdl b/desktopRuntime/resources/assets/eagler/mesh/weirdclimber1.mdl new file mode 100644 index 0000000000000000000000000000000000000000..933d3c81a872dc0575afac7334e1a3136668c14f GIT binary patch literal 7785 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/weirdclimber2.mdl b/desktopRuntime/resources/assets/eagler/mesh/weirdclimber2.mdl new file mode 100644 index 0000000000000000000000000000000000000000..728db6a27c5be259822e82168dec491053d184b9 GIT binary patch literal 705 zcmW-bZAep57{?#?>R#PT>sAEa!J^E-wY0=_Zzs+C6f)6Dtju$^>F5@vPYC|Nn4)|L4Qc-*lika3-oWLcP_R z?oFh`ctVMZ+gYU;+*2K_s}2Q2AyMhh?uuTB#&(L`iXtWxJ-z9an2e=j$xJM2wF1Bf zOm_0v2e}+5d9VVOr#(`?WZJiH!cmYEc5%fYm{`pi%6x$Td>%*Do>wcWYRDuo%2^gY5t>p?FS`O zXQw0~ABQ<*Nw#lcnTf6ccjM9Gc90QUzd104oHkI{hv+WH#lOFLD>ght!9>0;4S+5RiJYefSDUeb^p+1?Z}m GtNsJ&gT&+j literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/winston.fallback.png b/desktopRuntime/resources/assets/eagler/mesh/winston.fallback.png new file mode 100644 index 0000000000000000000000000000000000000000..b0da89c65dc316addaa706dded5a4a0583d62e4b GIT binary patch literal 37932 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 IM6N<$f=~GgtpET3 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/winston.png b/desktopRuntime/resources/assets/eagler/mesh/winston.png new file mode 100644 index 0000000000000000000000000000000000000000..fceadbb2eb2ab263182c8f654d2bc07af1791d67 GIT binary patch literal 73074 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

@yknmeLTy;%dxgQ5Tem}fmdpw`C^-k@3qt|Os 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 literal 0 HcmV?d00001 diff --git a/desktopRuntime/resources/assets/eagler/mesh/winston0.mdl b/desktopRuntime/resources/assets/eagler/mesh/winston0.mdl new file mode 100644 index 0000000000000000000000000000000000000000..f66da49ebd6497e7585b493444a91602feb3562c GIT binary patch literal 19989 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 'Other...' to disable FNAW skins) +eaglercraft.editProfile.enableFNAW=(Note: go to 'Video Settings...' > 'Other...' to enable FNAW skins) + +eaglercraft.editCape.title=Edit Cape +eaglercraft.editCape.playerCape=Player Cape +eaglercraft.editCape.addCape=Add Cape +eaglercraft.editCape.clearCape=Clear List + eaglercraft.editProfile.importExport=Import/Export eaglercraft.settingsBackup.importExport.title=What do you wanna do? @@ -599,6 +608,60 @@ eaglercraft.updateList.refresh=Refresh eaglercraft.updateList.note.0=Note: Updates are digitally signed, EaglercraftX will block any eaglercraft.updateList.note.1=updates that were not created by lax1dude or ayunami2000 +eaglercraft.voice.title=Voice Channel +eaglercraft.voice.titleNoVoice=Voice is disabled on this server +eaglercraft.voice.titleVoiceUnavailable=Voice is unavailable +eaglercraft.voice.titleVoiceBrowserError=(browser issue) +eaglercraft.voice.ptt=Press '%s' to speak +eaglercraft.voice.pttChangeDesc=(Press Any Key) +eaglercraft.voice.changeKey=Change +eaglercraft.voice.off=OFF +eaglercraft.voice.radius=NEARBY +eaglercraft.voice.global=GLOBAL +eaglercraft.voice.volumeTitle=Change Volume +eaglercraft.voice.volumeListen=Speakers Volume: +eaglercraft.voice.volumeSpeak=Microphone Volume: +eaglercraft.voice.radiusTitle=Change Listener Radius +eaglercraft.voice.radiusLabel=Players Within: +eaglercraft.voice.radiusChange=change +eaglercraft.voice.notConnected=Not Connected +eaglercraft.voice.connecting=Connecting... +eaglercraft.voice.unavailable=Could not connect! +eaglercraft.voice.connectedGlobal=Connected - Global +eaglercraft.voice.connectedRadius=Connected - $f$Within $radius$m +eaglercraft.voice.playersListening=Players Listening: +eaglercraft.voice.muted=Players Muted: +eaglercraft.voice.unmute=unmute +eaglercraft.voice.mute=mute +eaglercraft.voice.apply=Apply +eaglercraft.voice.volumeSpeakerLabel=Speakers: +eaglercraft.voice.volumeMicrophoneLabel=Microphone: + +eaglercraft.voice.unsupportedWarning1=Voice Warning +eaglercraft.voice.unsupportedWarning2=Your network's firewall may not support +eaglercraft.voice.unsupportedWarning3=eaglercraft's voice chat. +eaglercraft.voice.unsupportedWarning4=If your game doesn't work it's your issue +eaglercraft.voice.unsupportedWarning5=to solve, not ayunami2000's or lax1dude's. +eaglercraft.voice.unsupportedWarning6=Don't ask them to 'fix' it for you because +eaglercraft.voice.unsupportedWarning7=they won't help you fix a problem that only +eaglercraft.voice.unsupportedWarning8=you or your network's administrator has the +eaglercraft.voice.unsupportedWarning9=ability to correctly resolve. +eaglercraft.voice.unsupportedWarning10=Continue +eaglercraft.voice.unsupportedWarning11=Cancel + +eaglercraft.voice.ipGrabWarning1=IP Logger Warning +eaglercraft.voice.ipGrabWarning2=Using Eaglercraft voice chat may allow your +eaglercraft.voice.ipGrabWarning3=IP address to be logged by other players +eaglercraft.voice.ipGrabWarning4=also using voice on the server. +eaglercraft.voice.ipGrabWarning5=This issue will not be fixed, it is an +eaglercraft.voice.ipGrabWarning6=internal browser issue, not a mistake in the +eaglercraft.voice.ipGrabWarning7=game. Fortunately, this can only be done if +eaglercraft.voice.ipGrabWarning8=the other player uses a hacked web browser +eaglercraft.voice.ipGrabWarning9=or has Wireshark to capture the voice +eaglercraft.voice.ipGrabWarning10=packets, as there exists no real javascript +eaglercraft.voice.ipGrabWarning11=method to log IPs using a normal skidded +eaglercraft.voice.ipGrabWarning12=eaglercraft hacked client. + selectServer.title=Select Server selectServer.empty=empty selectServer.select=Join Server @@ -799,6 +862,7 @@ options.chat.height.focused=Focused Height options.chat.height.unfocused=Unfocused Height options.skinCustomisation=Skin Customization... options.skinCustomisation.title=Skin Customization +options.skinCustomisation.enableFNAWSkins=Show FNAW Skins options.modelPart.cape=Cape options.modelPart.hat=Hat options.modelPart.jacket=Jacket 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 ba16a63..03785ec 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 @@ -60,6 +60,9 @@ public class PlatformAssets { public static final ImageData loadImageFile(InputStream data) { try { BufferedImage img = ImageIO.read(data); + if(img == null) { + throw new IOException("Data is not a supported image format!"); + } int w = img.getWidth(); int h = img.getHeight(); boolean a = img.getColorModel().hasAlpha(); diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java index 9adf74c..6cab7cc 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java @@ -21,10 +21,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; public class PlatformBufferFunctions { public static void put(ByteBuffer newBuffer, ByteBuffer flip) { - int len = flip.remaining(); - for(int i = 0; i < len; ++i) { - newBuffer.put(flip.get()); - } + newBuffer.put(flip); } public static void put(IntBuffer intBuffer, int index, int[] data) { diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java index ece3fff..55bd718 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java @@ -1,13 +1,11 @@ package net.lax1dude.eaglercraft.v1_8.internal; import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; -import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException; -import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2.BreakLoop; +import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.DebugFilesystem; +import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.JDBCFilesystem; +import net.lax1dude.eaglercraft.v1_8.internal.lwjgl.JDBCFilesystemConverter; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; @@ -30,183 +28,104 @@ public class PlatformFilesystem { public static final Logger logger = LogManager.getLogger("PlatformFilesystem"); - public static final File filesystemRoot = (new File("filesystem/sp")).getAbsoluteFile(); + public static final File debugFilesystemRoot = (new File("filesystem/sp")).getAbsoluteFile(); + + private static IFilesystemProvider provider = null; + + public static String jdbcUri = null; + public static String jdbcDriver = null; public static void initialize() { - if(!filesystemRoot.isDirectory() && !filesystemRoot.mkdirs()) { - throw new EaglerFileSystemException("Could not create directory for virtual filesystem: " + filesystemRoot.getAbsolutePath()); + if(provider == null) { + if(jdbcUri != null && jdbcDriver != null) { + provider = JDBCFilesystem.initialize(jdbcUri, jdbcDriver); + if(((JDBCFilesystem)provider).isNewFilesystem() && debugFilesystemRoot.isDirectory() && debugFilesystemRoot.list().length > 0) { + JDBCFilesystemConverter.convertFilesystem("Converting filesystem, please wait...", debugFilesystemRoot, provider, true); + } + }else { + provider = DebugFilesystem.initialize(debugFilesystemRoot); + } } } + public static void setUseJDBC(String uri) { + jdbcUri = uri; + } + + public static void setJDBCDriverClass(String driver) { + jdbcDriver = driver; + } + + public static interface IFilesystemProvider { + + boolean eaglerDelete(String pathName); + + ByteBuffer eaglerRead(String pathName); + + void eaglerWrite(String pathName, ByteBuffer data); + + boolean eaglerExists(String pathName); + + boolean eaglerMove(String pathNameOld, String pathNameNew); + + int eaglerCopy(String pathNameOld, String pathNameNew); + + int eaglerSize(String pathName); + + void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive); + + } + + private static void throwNotInitialized() { + throw new UnsupportedOperationException("Filesystem has not been initialized!"); + } + public static boolean eaglerDelete(String pathName) { - File f = getJREFile(pathName); - if(!f.exists()) { - logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName); - return false; - } - if(f.delete()) { - deleteParentIfEmpty(f); - return true; - } - return false; + if(provider == null) throwNotInitialized(); + return provider.eaglerDelete(pathName); } public static ByteBuffer eaglerRead(String pathName) { - File f = getJREFile(pathName); - if(f.isFile()) { - long fileSize = f.length(); - if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath()); - ByteBuffer buf = PlatformRuntime.allocateByteBuffer((int)fileSize); - try(FileInputStream is = new FileInputStream(f)) { - byte[] copyBuffer = new byte[4096]; - int i; - while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) { - buf.put(copyBuffer, 0, i); - } - if(buf.remaining() > 0) { - throw new EaglerFileSystemException("ERROR: " + buf.remaining() + " bytes are remaining after reading: " + f.getAbsolutePath()); - } - buf.flip(); - ByteBuffer tmp = buf; - buf = null; - return tmp; - }catch (IOException e) { - throw new EaglerFileSystemException("Failed to read: " + f.getAbsolutePath(), e); - }catch(ArrayIndexOutOfBoundsException ex) { - throw new EaglerFileSystemException("ERROR: Expected " + fileSize + " bytes, buffer overflow reading: " + f.getAbsolutePath(), ex); - }finally { - if(buf != null) { - PlatformRuntime.freeByteBuffer(buf); - } - } - }else { - logger.warn("Tried to read file that doesn't exist: \"{}\"", f.getAbsolutePath()); - return null; - } + if(provider == null) throwNotInitialized(); + return provider.eaglerRead(pathName); } public static void eaglerWrite(String pathName, ByteBuffer data) { - File f = getJREFile(pathName); - File p = f.getParentFile(); - if(!p.isDirectory()) { - if(!p.mkdirs()) { - throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath()); - } - } - try(FileOutputStream fos = new FileOutputStream(f)) { - byte[] copyBuffer = new byte[Math.min(4096, data.remaining())]; - int i; - while((i = data.remaining()) > 0) { - if(i > copyBuffer.length) { - i = copyBuffer.length; - } - data.get(copyBuffer, 0, i); - fos.write(copyBuffer, 0, i); - } - }catch (IOException e) { - throw new EaglerFileSystemException("Failed to write: " + f.getAbsolutePath(), e); - } + if(provider == null) throwNotInitialized(); + provider.eaglerWrite(pathName, data); } public static boolean eaglerExists(String pathName) { - return getJREFile(pathName).isFile(); + if(provider == null) throwNotInitialized(); + return provider.eaglerExists(pathName); } public static boolean eaglerMove(String pathNameOld, String pathNameNew) { - File f1 = getJREFile(pathNameOld); - File f2 = getJREFile(pathNameNew); - if(f2.exists()) { - logger.warn("Tried to rename file \"{}\" to \"{}\" which already exists! File will be replaced"); - if(!f2.delete()) { - return false; - } - } - if(f1.renameTo(f2)) { - deleteParentIfEmpty(f1); - return true; - } - return false; + if(provider == null) throwNotInitialized(); + return provider.eaglerMove(pathNameOld, pathNameNew); } public static int eaglerCopy(String pathNameOld, String pathNameNew) { - File f1 = getJREFile(pathNameOld); - File f2 = getJREFile(pathNameNew); - if(!f1.isFile()) { - return -1; - } - if(f2.isDirectory()) { - throw new EaglerFileSystemException("Destination file is a directory: " + f2.getAbsolutePath()); - } - File p = f2.getParentFile(); - if(!p.isDirectory()) { - if(!p.mkdirs()) { - throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath()); - } - } - int sz = 0; - try(FileInputStream is = new FileInputStream(f1)) { - try(FileOutputStream os = new FileOutputStream(f2)) { - byte[] copyBuffer = new byte[4096]; - int i; - while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) { - os.write(copyBuffer, 0, i); - sz += i; - } - } - }catch (IOException e) { - throw new EaglerFileSystemException("Failed to copy \"" + f1.getAbsolutePath() + "\" to file \"" + f2.getAbsolutePath() + "\"", e); - } - return sz; + if(provider == null) throwNotInitialized(); + return provider.eaglerCopy(pathNameOld, pathNameNew); } public static int eaglerSize(String pathName) { - File f = getJREFile(pathName); - if(f.isFile()) { - long fileSize = f.length(); - if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath()); - return (int)fileSize; - }else { - return -1; - } + if(provider == null) throwNotInitialized(); + return provider.eaglerSize(pathName); } public static void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) { - try { - iterateFile(pathName, getJREFile(pathName), itr, recursive); - }catch(BreakLoop ex) { - } + if(provider == null) throwNotInitialized(); + provider.eaglerIterate(pathName, itr, recursive); } - private static void iterateFile(String pathName, File f, VFSFilenameIterator itr, boolean recursive) { - if(!f.exists()) { - return; - } - if(!f.isDirectory()) { - itr.next(pathName); - return; - } - File[] fa = f.listFiles(); - for(int i = 0; i < fa.length; ++i) { - File ff = fa[i]; - String fn = pathName + "/" + ff.getName(); - if(ff.isDirectory()) { - if(recursive) { - iterateFile(fn, ff, itr, true); - } - }else { - itr.next(fn); + public static void platformShutdown() { + if(provider != null) { + if(provider instanceof JDBCFilesystem) { + ((JDBCFilesystem)provider).shutdown(); } + provider = null; } } - - private static File getJREFile(String path) { - return new File(filesystemRoot, path); - } - - private static void deleteParentIfEmpty(File f) { - String[] s; - while((f = f.getParentFile()) != null && (s = f.list()) != null && s.length == 0) { - f.delete(); - } - } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java index 074cace..ce8d776 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformInput.java @@ -58,6 +58,9 @@ public class PlatformInput { private static final List keyboardCharList = new LinkedList(); + private static boolean vsync = true; + private static boolean glfwVSyncState = false; + private static class KeyboardEvent { protected final int key; @@ -213,9 +216,17 @@ public class PlatformInput { public static boolean isCloseRequested() { return glfwWindowShouldClose(win); } + + public static void setVSync(boolean enable) { + vsync = enable; + } public static void update() { glfwPollEvents(); + if(vsync != glfwVSyncState) { + glfwSwapInterval(vsync ? 1 : 0); + glfwVSyncState = vsync; + } glfwSwapBuffers(win); } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java index 7b65703..acaee45 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java @@ -8,6 +8,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; import static org.lwjgl.opengles.GLES30.*; import org.lwjgl.opengles.GLES31; +import org.lwjgl.opengles.GLESCapabilities; /** * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. @@ -25,6 +26,12 @@ import org.lwjgl.opengles.GLES31; * */ public class PlatformOpenGL { + + private static boolean hasLinearHDR32FSupport = false; + + static void setCurrentContext(GLESCapabilities caps) { + hasLinearHDR32FSupport = caps.GL_OES_texture_float_linear; + } public static final void _wglEnable(int glEnum) { glEnable(glEnum); @@ -270,6 +277,12 @@ public class PlatformOpenGL { nglTexImage2D(target, level, internalFormat, width, height, border, format, type, data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); } + + public static final void _wglTexImage2Df32(int target, int level, int internalFormat, int width, int height, + int border, int format, int type, ByteBuffer data) { + nglTexImage2D(target, level, internalFormat, width, height, border, format, type, + data == null ? 0l : EaglerLWJGLAllocator.getAddress(data)); + } public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer data) { @@ -532,5 +545,9 @@ public class PlatformOpenGL { public static int _wglGetTexLevelParameteri(int glTexture2d, int i, int glTextureWidth) { return GLES31.glGetTexLevelParameteri(glTexture2d, i, glTextureWidth); } + + public static final boolean checkLinearHDR32FSupport() { + return hasLinearHDR32FSupport; + } } 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 0538934..43eb008 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 @@ -171,7 +171,7 @@ public class PlatformRuntime { EGL.createDisplayCapabilities(glfw_eglHandle, major[0], minor[0]); glfwMakeContextCurrent(windowHandle); - GLES.createCapabilities(); + PlatformOpenGL.setCurrentContext(GLES.createCapabilities()); logger.info("OpenGL Version: {}", (glVersion = GLES30.glGetString(GLES30.GL_VERSION))); logger.info("OpenGL Renderer: {}", (glRenderer = GLES30.glGetString(GLES30.GL_RENDERER))); @@ -245,6 +245,7 @@ public class PlatformRuntime { public static void destroy() { PlatformAudio.platformShutdown(); + PlatformFilesystem.platformShutdown(); GLES.destroy(); EGL.destroy(); glfwDestroyWindow(windowHandle); @@ -340,15 +341,27 @@ public class PlatformRuntime { public static class NativeNIO { public static java.nio.ByteBuffer allocateByteBuffer(int length) { - return MemoryUtil.memByteBuffer(JEmalloc.nje_malloc(length), length); + long ret = JEmalloc.nje_malloc(length); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return MemoryUtil.memByteBuffer(ret, length); } public static java.nio.IntBuffer allocateIntBuffer(int length) { - return MemoryUtil.memIntBuffer(JEmalloc.nje_malloc(length << 2), length); + long ret = JEmalloc.nje_malloc(length << 2); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return MemoryUtil.memIntBuffer(ret, length); } public static java.nio.FloatBuffer allocateFloatBuffer(int length) { - return MemoryUtil.memFloatBuffer(JEmalloc.nje_malloc(length << 2), length); + long ret = JEmalloc.nje_malloc(length << 2); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return MemoryUtil.memFloatBuffer(ret, length); } public static java.nio.IntBuffer getIntBuffer(java.nio.ByteBuffer byteBuffer) { diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java new file mode 100644 index 0000000..0e676e0 --- /dev/null +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java @@ -0,0 +1,116 @@ +package net.lax1dude.eaglercraft.v1_8.internal; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState; + +/** + * Copyright (c) 2022-2024 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 PlatformVoiceClient { + + public static void initialize() { + + } + + public static void initializeDevices() { + + } + + public static boolean isSupported() { + return false; + } + + public static void setVoiceListenVolume(float f) { + + } + + public static void setVoiceSpeakVolume(float f) { + + } + + public static void activateVoice(boolean talk) { + + } + + public static void setICEServers(String[] servs) { + + } + + public static void signalConnect(EaglercraftUUID user, boolean offer) { + + } + + public static void signalDisconnect(EaglercraftUUID user, boolean b) { + + } + + public static void signalICECandidate(EaglercraftUUID user, String ice) { + + } + + public static void signalDescription(EaglercraftUUID user, String desc) { + + } + + public static void tickVoiceClient() { + + } + + public static void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) { + + } + + public static void resetPeerStates() { + + } + + public static void setVoiceProximity(int prox) { + + } + + public static void setMicVolume(float f) { + + } + + public static void mutePeer(EaglercraftUUID uuid, boolean mute) { + + } + + public static EnumVoiceChannelPeerState getPeerState() { + return EnumVoiceChannelPeerState.LOADING; + } + + public static EnumVoiceChannelReadyState getReadyState() { + return EnumVoiceChannelReadyState.NONE; + } + + public static EnumVoiceChannelPeerState getPeerStateConnect() { + return EnumVoiceChannelPeerState.LOADING; + } + + public static EnumVoiceChannelPeerState getPeerStateInitial() { + return EnumVoiceChannelPeerState.LOADING; + } + + public static EnumVoiceChannelPeerState getPeerStateDesc() { + return EnumVoiceChannelPeerState.LOADING; + } + + public static EnumVoiceChannelPeerState getPeerStateIce() { + return EnumVoiceChannelPeerState.LOADING; + } + +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLAllocator.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLAllocator.java index 8167730..7b06078 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLAllocator.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLAllocator.java @@ -3,7 +3,7 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; import org.lwjgl.system.jemalloc.JEmalloc; /** - * Copyright (c) 2022-2024 lax1dude, ayunami2000. All Rights Reserved. + * 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 @@ -26,19 +26,35 @@ public class EaglerLWJGLAllocator { } public static ByteBuffer allocByteBuffer(int len) { - return new EaglerLWJGLByteBuffer(JEmalloc.nje_malloc(len), len, true); + long ret = JEmalloc.nje_malloc(len); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return new EaglerLWJGLByteBuffer(ret, len, true); } public static ShortBuffer allocShortBuffer(int len) { - return new EaglerLWJGLShortBuffer(JEmalloc.nje_malloc(len << 1), len, true); + long ret = JEmalloc.nje_malloc(len << 1); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return new EaglerLWJGLShortBuffer(ret, len, true); } public static IntBuffer allocIntBuffer(int len) { - return new EaglerLWJGLIntBuffer(JEmalloc.nje_malloc(len << 2), len, true); + long ret = JEmalloc.nje_malloc(len << 2); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return new EaglerLWJGLIntBuffer(ret, len, true); } public static FloatBuffer allocFloatBuffer(int len) { - return new EaglerLWJGLFloatBuffer(JEmalloc.nje_malloc(len << 2), len, true); + long ret = JEmalloc.nje_malloc(len << 2); + if(ret == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + return new EaglerLWJGLFloatBuffer(ret, len, true); } public static void freeByteBuffer(ByteBuffer buffer) { @@ -145,4 +161,4 @@ public class EaglerLWJGLAllocator { return new WrongBufferClassType("Tried to pass a " + clazz.getClass().getSimpleName() + " which is not a native eagler buffer"); } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLByteBuffer.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLByteBuffer.java index d21926f..fed5de4 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLByteBuffer.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLByteBuffer.java @@ -1,10 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.jemalloc.JEmalloc; +import net.lax1dude.unsafememcpy.UnsafeMemcpy; +import net.lax1dude.unsafememcpy.UnsafeUtils; + /** - * Copyright (c) 2022 lax1dude. All Rights Reserved. + * 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 @@ -104,35 +106,33 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public byte get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return MemoryUtil.memGetByte(address + position++); + return UnsafeUtils.getMemByte(address + position++); } @Override public ByteBuffer put(byte b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutByte(address + position++, b); + UnsafeUtils.setMemByte(address + position++, b); return this; } @Override public byte get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetByte(address + index); + return UnsafeUtils.getMemByte(address + index); } @Override public ByteBuffer put(int index, byte b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutByte(address + index, b); + UnsafeUtils.setMemByte(address + index, b); return this; } @Override public ByteBuffer get(byte[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = MemoryUtil.memGetByte(address + position + i); - } + UnsafeMemcpy.memcpy(dst, offset, address + position, length); position += length; return this; } @@ -140,9 +140,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer get(byte[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[position + i] = MemoryUtil.memGetByte(address + position + i); - } + UnsafeMemcpy.memcpy(dst, 0, address + position, dst.length); position += dst.length; return this; } @@ -153,14 +151,14 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { EaglerLWJGLByteBuffer c = (EaglerLWJGLByteBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - MemoryUtil.memCopy(c.address + c.position, address + position, l); + UnsafeMemcpy.memcpy(address + position, c.address + c.position, l); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - MemoryUtil.memPutByte(address + position + l, src.get()); + UnsafeUtils.setMemByte(address + position + l, src.get()); } position += l; } @@ -170,9 +168,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer put(byte[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - MemoryUtil.memPutByte(address + position + i, src[offset + i]); - } + UnsafeMemcpy.memcpy(address + position, src, offset, length); position += length; return this; } @@ -180,9 +176,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer put(byte[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - MemoryUtil.memPutByte(address + position + i, src[i]); - } + UnsafeMemcpy.memcpy(address + position, src, 0, src.length); position += src.length; return this; } @@ -203,7 +197,10 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { int newLen = limit - position; long newAlloc = JEmalloc.nje_malloc(newLen); - MemoryUtil.memCopy(address + position, newAlloc, newLen); + if(newAlloc == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + UnsafeMemcpy.memcpy(newAlloc, address + position, newLen); return new EaglerLWJGLByteBuffer(newAlloc, newLen, true); } @@ -211,7 +208,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public char getChar() { if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position); - char c = (char)MemoryUtil.memGetShort(address + position); + char c = UnsafeUtils.getMemChar(address + position); position += 2; return c; } @@ -219,7 +216,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer putChar(char value) { if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutShort(address + position, (short)value); + UnsafeUtils.setMemChar(address + position, value); position += 2; return this; } @@ -227,20 +224,20 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public char getChar(int index) { if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index); - return (char)MemoryUtil.memGetShort(address + index); + return UnsafeUtils.getMemChar(address + index); } @Override public ByteBuffer putChar(int index, char value) { if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutShort(address + index, (short)value); + UnsafeUtils.setMemChar(address + index, value); return this; } @Override public short getShort() { if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position); - short s = MemoryUtil.memGetShort(address + position); + short s = UnsafeUtils.getMemShort(address + position); position += 2; return s; } @@ -248,7 +245,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer putShort(short value) { if(position + 2 > limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutShort(address + position, value); + UnsafeUtils.setMemShort(address + position, value); position += 2; return this; } @@ -256,13 +253,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public short getShort(int index) { if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetShort(address + index); + return UnsafeUtils.getMemShort(address + index); } @Override public ByteBuffer putShort(int index, short value) { if(index + 2 > limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutShort(address + index, value); + UnsafeUtils.setMemShort(address + index, value); return this; } @@ -274,7 +271,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public int getInt() { if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position); - int i = MemoryUtil.memGetInt(address + position); + int i = UnsafeUtils.getMemInt(address + position); position += 4; return i; } @@ -282,7 +279,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer putInt(int value) { if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutInt(address + position, value); + UnsafeUtils.setMemInt(address + position, value); position += 4; return this; } @@ -290,13 +287,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public int getInt(int index) { if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetInt(address + index); + return UnsafeUtils.getMemInt(address + index); } @Override public ByteBuffer putInt(int index, int value) { if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutInt(address + index, value); + UnsafeUtils.setMemInt(address + index, value); return this; } @@ -308,7 +305,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public long getLong() { if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position); - long l = MemoryUtil.memGetLong(address + position); + long l = UnsafeUtils.getMemLong(address + position); position += 8; return l; } @@ -316,7 +313,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer putLong(long value) { if(position + 8 > limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutLong(address + position, value); + UnsafeUtils.setMemLong(address + position, value); position += 8; return this; } @@ -324,20 +321,20 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public long getLong(int index) { if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetLong(address + index); + return UnsafeUtils.getMemLong(address + index); } @Override public ByteBuffer putLong(int index, long value) { if(index + 8 > limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutLong(address + index, value); + UnsafeUtils.setMemLong(address + index, value); return this; } @Override public float getFloat() { if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position); - float f = MemoryUtil.memGetFloat(address + position); + float f = UnsafeUtils.getMemFloat(address + position); position += 4; return f; } @@ -345,7 +342,7 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public ByteBuffer putFloat(float value) { if(position + 4 > limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutFloat(address + position, value); + UnsafeUtils.setMemFloat(address + position, value); position += 4; return this; } @@ -353,13 +350,13 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { @Override public float getFloat(int index) { if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetFloat(address + index); + return UnsafeUtils.getMemFloat(address + index); } @Override public ByteBuffer putFloat(int index, float value) { if(index + 4 > limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutFloat(address + index, value); + UnsafeUtils.setMemFloat(address + index, value); return this; } @@ -419,4 +416,4 @@ public class EaglerLWJGLByteBuffer implements ByteBuffer { return this; } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLFloatBuffer.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLFloatBuffer.java index 5110c17..9ca315b 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLFloatBuffer.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLFloatBuffer.java @@ -1,10 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.jemalloc.JEmalloc; +import net.lax1dude.unsafememcpy.UnsafeMemcpy; +import net.lax1dude.unsafememcpy.UnsafeUtils; + /** - * Copyright (c) 2022 lax1dude. All Rights Reserved. + * 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 @@ -106,47 +108,45 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { @Override public float get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return MemoryUtil.memGetFloat(address + ((position++) << SHIFT)); + return UnsafeUtils.getMemFloat(address + ((position++) << SHIFT)); } @Override public FloatBuffer put(float b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutFloat(address + ((position++) << SHIFT), b); + UnsafeUtils.setMemFloat(address + ((position++) << SHIFT), b); return this; } @Override public float get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetFloat(address + (index << SHIFT)); + return UnsafeUtils.getMemFloat(address + (index << SHIFT)); } @Override public FloatBuffer put(int index, float b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutFloat(address + (index << SHIFT), b); + UnsafeUtils.setMemFloat(address + (index << SHIFT), b); return this; } @Override public float getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetFloat(address + (index << SHIFT)); + return UnsafeUtils.getMemFloat(address + (index << SHIFT)); } @Override public void putElement(int index, float value) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutFloat(address + ((position++) << SHIFT), value); + UnsafeUtils.setMemFloat(address + ((position++) << SHIFT), value); } @Override public FloatBuffer get(float[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = MemoryUtil.memGetFloat(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length); position += length; return this; } @@ -154,9 +154,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { @Override public FloatBuffer get(float[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = MemoryUtil.memGetFloat(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length); position += dst.length; return this; } @@ -167,14 +165,14 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { EaglerLWJGLFloatBuffer c = (EaglerLWJGLFloatBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT); + UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.position << SHIFT), l << SHIFT); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - MemoryUtil.memPutFloat(address + ((position + l) << SHIFT), src.get()); + UnsafeUtils.setMemFloat(address + ((position + l) << SHIFT), src.get()); } position += l; } @@ -184,9 +182,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { @Override public FloatBuffer put(float[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - MemoryUtil.memPutFloat(address + ((position + i) << SHIFT), src[offset + i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length); position += length; return this; } @@ -194,9 +190,7 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { @Override public FloatBuffer put(float[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - MemoryUtil.memPutFloat(address + ((position + i) << SHIFT), src[i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length); position += src.length; return this; } @@ -217,7 +211,10 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { int newLen = limit - position; long newAlloc = JEmalloc.nje_malloc(newLen); - MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT); + if(newAlloc == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT); return new EaglerLWJGLFloatBuffer(newAlloc, newLen, true); } @@ -278,4 +275,4 @@ public class EaglerLWJGLFloatBuffer implements FloatBuffer { return this; } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLIntBuffer.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLIntBuffer.java index 6471eed..2068099 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLIntBuffer.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLIntBuffer.java @@ -1,10 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.jemalloc.JEmalloc; +import net.lax1dude.unsafememcpy.UnsafeMemcpy; +import net.lax1dude.unsafememcpy.UnsafeUtils; + /** - * Copyright (c) 2022 lax1dude. All Rights Reserved. + * 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 @@ -106,47 +108,45 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { @Override public int get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return MemoryUtil.memGetInt(address + ((position++) << SHIFT)); + return UnsafeUtils.getMemInt(address + ((position++) << SHIFT)); } @Override public IntBuffer put(int b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutInt(address + ((position++) << SHIFT), b); + UnsafeUtils.setMemInt(address + ((position++) << SHIFT), b); return this; } @Override public int get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetInt(address + (index << SHIFT)); + return UnsafeUtils.getMemInt(address + (index << SHIFT)); } @Override public IntBuffer put(int index, int b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutInt(address + (index << SHIFT), b); + UnsafeUtils.setMemInt(address + (index << SHIFT), b); return this; } @Override public int getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetInt(address + (index << SHIFT)); + return UnsafeUtils.getMemInt(address + (index << SHIFT)); } @Override public void putElement(int index, int value) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutInt(address + (index << SHIFT), value); + UnsafeUtils.setMemInt(address + (index << SHIFT), value); } @Override public IntBuffer get(int[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = MemoryUtil.memGetInt(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length); position += length; return this; } @@ -154,9 +154,7 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { @Override public IntBuffer get(int[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = MemoryUtil.memGetInt(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length); position += dst.length; return this; } @@ -167,14 +165,14 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { EaglerLWJGLIntBuffer c = (EaglerLWJGLIntBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT); + UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.position << SHIFT), l << SHIFT); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - MemoryUtil.memPutInt(address + ((position + l) << SHIFT), src.get()); + UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get()); } position += l; } @@ -184,9 +182,7 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { @Override public IntBuffer put(int[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[offset + i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length); position += length; return this; } @@ -194,9 +190,7 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { @Override public IntBuffer put(int[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - MemoryUtil.memPutInt(address + ((position + i) << SHIFT), src[i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length); position += src.length; return this; } @@ -217,7 +211,10 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { int newLen = limit - position; long newAlloc = JEmalloc.nje_malloc(newLen); - MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT); + if(newAlloc == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT); return new EaglerLWJGLIntBuffer(newAlloc, newLen, true); } @@ -278,4 +275,4 @@ public class EaglerLWJGLIntBuffer implements IntBuffer { return this; } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLShortBuffer.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLShortBuffer.java index 01e0198..59f4eb8 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLShortBuffer.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerLWJGLShortBuffer.java @@ -1,10 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.jemalloc.JEmalloc; +import net.lax1dude.unsafememcpy.UnsafeMemcpy; +import net.lax1dude.unsafememcpy.UnsafeUtils; + /** - * Copyright (c) 2022 lax1dude. All Rights Reserved. + * 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 @@ -106,47 +108,45 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { @Override public short get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return MemoryUtil.memGetShort(address + ((position++) << SHIFT)); + return UnsafeUtils.getMemShort(address + ((position++) << SHIFT)); } @Override public ShortBuffer put(short b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - MemoryUtil.memPutShort(address + ((position++) << SHIFT), b); + UnsafeUtils.setMemShort(address + ((position++) << SHIFT), b); return this; } @Override public short get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetShort(address + (index << SHIFT)); + return UnsafeUtils.getMemShort(address + (index << SHIFT)); } @Override public ShortBuffer put(int index, short b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutShort(address + (index << SHIFT), b); + UnsafeUtils.setMemShort(address + (index << SHIFT), b); return this; } @Override public short getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return MemoryUtil.memGetShort(address + (index << SHIFT)); + return UnsafeUtils.getMemShort(address + (index << SHIFT)); } @Override public void putElement(int index, short value) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - MemoryUtil.memPutShort(address + (index << SHIFT), value); + UnsafeUtils.setMemShort(address + (index << SHIFT), value); } @Override public ShortBuffer get(short[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = MemoryUtil.memGetShort(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, offset << SHIFT, address + (position << SHIFT), length); position += length; return this; } @@ -154,9 +154,7 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { @Override public ShortBuffer get(short[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = MemoryUtil.memGetShort(address + ((position + i) << SHIFT)); - } + UnsafeMemcpy.memcpyAlignDst(dst, 0, address + (position << SHIFT), dst.length); position += dst.length; return this; } @@ -167,14 +165,14 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { EaglerLWJGLShortBuffer c = (EaglerLWJGLShortBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - MemoryUtil.memCopy(c.address + (c.position << SHIFT), address + (position << SHIFT), l << SHIFT); + UnsafeMemcpy.memcpy(address + (position << SHIFT), c.address + (c.position << SHIFT), l << SHIFT); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - MemoryUtil.memPutShort(address + ((position + l) << SHIFT), src.get()); + UnsafeUtils.setMemInt(address + ((position + l) << SHIFT), src.get()); } position += l; } @@ -184,9 +182,7 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { @Override public ShortBuffer put(short[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[offset + i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, offset << SHIFT, length); position += length; return this; } @@ -194,9 +190,7 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { @Override public ShortBuffer put(short[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - MemoryUtil.memPutShort(address + ((position + i) << SHIFT), src[i]); - } + UnsafeMemcpy.memcpyAlignSrc(address + (position << SHIFT), src, 0, src.length); position += src.length; return this; } @@ -217,7 +211,10 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { int newLen = limit - position; long newAlloc = JEmalloc.nje_malloc(newLen); - MemoryUtil.memCopy(address + (position << SHIFT), newAlloc, newLen << SHIFT); + if(newAlloc == 0l) { + throw new OutOfMemoryError("Native je_malloc call returned null pointer!"); + } + UnsafeMemcpy.memcpy(newAlloc, address + (position << SHIFT), newLen << SHIFT); return new EaglerLWJGLShortBuffer(newAlloc, newLen, true); } @@ -278,4 +275,4 @@ public class EaglerLWJGLShortBuffer implements ShortBuffer { return this; } -} +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DebugFilesystem.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DebugFilesystem.java new file mode 100644 index 0000000..41afa22 --- /dev/null +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/DebugFilesystem.java @@ -0,0 +1,224 @@ +package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; + +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException; +import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2.BreakLoop; + +/** + * 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 DebugFilesystem implements PlatformFilesystem.IFilesystemProvider { + + public static DebugFilesystem initialize(File filesystemRoot) { + if(!filesystemRoot.isDirectory() && !filesystemRoot.mkdirs()) { + throw new EaglerFileSystemException("Could not create directory for virtual filesystem: " + filesystemRoot.getAbsolutePath()); + } + return new DebugFilesystem(filesystemRoot); + } + + private final File filesystemRoot; + + private DebugFilesystem(File root) { + this.filesystemRoot = root; + } + + @Override + public boolean eaglerDelete(String pathName) { + File f = getJREFile(pathName); + if(!f.exists()) { + PlatformFilesystem.logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName); + return false; + } + if(f.delete()) { + deleteParentIfEmpty(f); + return true; + } + return false; + } + + @Override + public ByteBuffer eaglerRead(String pathName) { + File f = getJREFile(pathName); + if(f.isFile()) { + long fileSize = f.length(); + if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath()); + ByteBuffer buf = PlatformRuntime.allocateByteBuffer((int)fileSize); + try(FileInputStream is = new FileInputStream(f)) { + byte[] copyBuffer = new byte[4096]; + int i; + while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) { + buf.put(copyBuffer, 0, i); + } + if(buf.remaining() > 0) { + throw new EaglerFileSystemException("ERROR: " + buf.remaining() + " bytes are remaining after reading: " + f.getAbsolutePath()); + } + buf.flip(); + ByteBuffer tmp = buf; + buf = null; + return tmp; + }catch (IOException e) { + throw new EaglerFileSystemException("Failed to read: " + f.getAbsolutePath(), e); + }catch(ArrayIndexOutOfBoundsException ex) { + throw new EaglerFileSystemException("ERROR: Expected " + fileSize + " bytes, buffer overflow reading: " + f.getAbsolutePath(), ex); + }finally { + if(buf != null) { + PlatformRuntime.freeByteBuffer(buf); + } + } + }else { + PlatformFilesystem.logger.warn("Tried to read file that doesn't exist: \"{}\"", f.getAbsolutePath()); + return null; + } + } + + @Override + public void eaglerWrite(String pathName, ByteBuffer data) { + File f = getJREFile(pathName); + File p = f.getParentFile(); + if(!p.isDirectory()) { + if(!p.mkdirs()) { + throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath()); + } + } + try(FileOutputStream fos = new FileOutputStream(f)) { + byte[] copyBuffer = new byte[Math.min(4096, data.remaining())]; + int i; + while((i = data.remaining()) > 0) { + if(i > copyBuffer.length) { + i = copyBuffer.length; + } + data.get(copyBuffer, 0, i); + fos.write(copyBuffer, 0, i); + } + }catch (IOException e) { + throw new EaglerFileSystemException("Failed to write: " + f.getAbsolutePath(), e); + } + } + + @Override + public boolean eaglerExists(String pathName) { + return getJREFile(pathName).isFile(); + } + + @Override + public boolean eaglerMove(String pathNameOld, String pathNameNew) { + File f1 = getJREFile(pathNameOld); + File f2 = getJREFile(pathNameNew); + if(f2.exists()) { + PlatformFilesystem.logger.warn("Tried to rename file \"{}\" to \"{}\" which already exists! File will be replaced"); + if(!f2.delete()) { + return false; + } + } + if(f1.renameTo(f2)) { + deleteParentIfEmpty(f1); + return true; + } + return false; + } + + @Override + public int eaglerCopy(String pathNameOld, String pathNameNew) { + File f1 = getJREFile(pathNameOld); + File f2 = getJREFile(pathNameNew); + if(!f1.isFile()) { + return -1; + } + if(f2.isDirectory()) { + throw new EaglerFileSystemException("Destination file is a directory: " + f2.getAbsolutePath()); + } + File p = f2.getParentFile(); + if(!p.isDirectory()) { + if(!p.mkdirs()) { + throw new EaglerFileSystemException("Could not create parent directory: " + p.getAbsolutePath()); + } + } + int sz = 0; + try(FileInputStream is = new FileInputStream(f1)) { + try(FileOutputStream os = new FileOutputStream(f2)) { + byte[] copyBuffer = new byte[4096]; + int i; + while((i = is.read(copyBuffer, 0, copyBuffer.length)) != -1) { + os.write(copyBuffer, 0, i); + sz += i; + } + } + }catch (IOException e) { + throw new EaglerFileSystemException("Failed to copy \"" + f1.getAbsolutePath() + "\" to file \"" + f2.getAbsolutePath() + "\"", e); + } + return sz; + } + + @Override + public int eaglerSize(String pathName) { + File f = getJREFile(pathName); + if(f.isFile()) { + long fileSize = f.length(); + if(fileSize > 2147483647L) throw new EaglerFileSystemException("Too large: " + fileSize + " @ " + f.getAbsolutePath()); + return (int)fileSize; + }else { + return -1; + } + } + + @Override + public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) { + try { + iterateFile(pathName, getJREFile(pathName), itr, recursive); + }catch(BreakLoop ex) { + } + } + + private void iterateFile(String pathName, File f, VFSFilenameIterator itr, boolean recursive) { + if(!f.exists()) { + return; + } + if(!f.isDirectory()) { + itr.next(pathName); + return; + } + File[] fa = f.listFiles(); + for(int i = 0; i < fa.length; ++i) { + File ff = fa[i]; + String fn = pathName + "/" + ff.getName(); + if(ff.isDirectory()) { + if(recursive) { + iterateFile(fn, ff, itr, true); + } + }else { + itr.next(fn); + } + } + } + + private File getJREFile(String path) { + return new File(filesystemRoot, path); + } + + private void deleteParentIfEmpty(File f) { + String[] s; + while((f = f.getParentFile()) != null && (s = f.list()) != null && s.length == 0) { + f.delete(); + } + } +} \ No newline at end of file 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 26b1be6..7f02c9a 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 @@ -123,5 +123,10 @@ public class DesktopClientConfigAdapter implements IClientConfigAdapter { public boolean isEnableSignatureBadge() { return false; } + + @Override + public boolean isAllowVoiceClient() { + return false; + } } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/FilesystemConvertingDialog.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/FilesystemConvertingDialog.java new file mode 100644 index 0000000..fe34b6d --- /dev/null +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/FilesystemConvertingDialog.java @@ -0,0 +1,78 @@ +package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.border.EmptyBorder; +import java.awt.Color; +import java.awt.BorderLayout; +import javax.swing.JProgressBar; +import java.awt.Dimension; +import java.awt.Toolkit; + +import javax.swing.JLabel; +import javax.swing.SwingConstants; +import javax.swing.UIManager; + +/** + * 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 FilesystemConvertingDialog extends JFrame { + + private static final long serialVersionUID = 1L; + private JPanel contentPane; + private JProgressBar progressBar; + + public FilesystemConvertingDialog(String title) { + setIconImage(Toolkit.getDefaultToolkit().getImage("icon32.png")); + setResizable(false); + setAlwaysOnTop(true); + setTitle("EaglercraftX 1.8"); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + setBounds(100, 100, 420, 100); + contentPane = new JPanel(); + contentPane.setBackground(new Color(255, 255, 255)); + contentPane.setBorder(null); + + setContentPane(contentPane); + contentPane.setLayout(new BorderLayout(0, 0)); + + JPanel panel = new JPanel(); + panel.setBorder(new EmptyBorder(10, 10, 10, 10)); + panel.setBackground(new Color(255, 255, 255)); + contentPane.add(panel, BorderLayout.SOUTH); + panel.setLayout(new BorderLayout(0, 0)); + + progressBar = new JProgressBar(); + progressBar.setIndeterminate(true); + progressBar.setPreferredSize(new Dimension(146, 20)); + progressBar.setMinimum(0); + progressBar.setMaximum(512); + panel.add(progressBar, BorderLayout.CENTER); + + JLabel lblNewLabel = new JLabel(title); + lblNewLabel.setFont(UIManager.getFont("PopupMenu.font")); + lblNewLabel.setHorizontalAlignment(SwingConstants.CENTER); + contentPane.add(lblNewLabel, BorderLayout.CENTER); + } + + public void setProgressIndeterminate(boolean itr) { + progressBar.setIndeterminate(itr); + } + + public void setProgressValue(int val) { + progressBar.setValue(val); + } + +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystem.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystem.java new file mode 100644 index 0000000..bafb146 --- /dev/null +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystem.java @@ -0,0 +1,441 @@ +package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; + +import java.sql.Connection; +import java.sql.Driver; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collection; +import java.util.Enumeration; +import java.util.LinkedList; +import java.util.Map.Entry; +import java.util.Properties; + +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.IFilesystemProvider; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem; +import net.lax1dude.eaglercraft.v1_8.internal.VFSFilenameIterator; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException; +import net.lax1dude.eaglercraft.v1_8.internal.vfs2.VFSIterator2; +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 JDBCFilesystem implements IFilesystemProvider { + + public static final Logger logger = LogManager.getLogger("JDBCFilesystem"); + + private boolean newFilesystem = true; + + private static volatile boolean cleanupThreadStarted = false; + private static final Collection jdbcFilesystems = new LinkedList(); + + private final String jdbcUri; + private final String jdbcDriver; + + private final Connection conn; + private final PreparedStatement createStatement; + private final PreparedStatement updateStatement; + private final PreparedStatement readStatement; + private final PreparedStatement existsStatement; + private final PreparedStatement sizeStatement; + private final PreparedStatement deleteStatement; + private final PreparedStatement renameStatement; + private final PreparedStatement iterateNonRecursive; + private final PreparedStatement iterateRecursive; + private boolean hasClosed = false; + + private final Object mutex = new Object(); + + public static IFilesystemProvider initialize(String jdbcUri, String jdbcDriver) { + Class driver; + try { + driver = Class.forName(jdbcDriver); + } catch (ClassNotFoundException e) { + throw new EaglerFileSystemException("JDBC driver class not found in JRE: " + jdbcDriver, e); + } + Driver driverObj = null; + Enumeration registeredDriversItr = DriverManager.getDrivers(); + while(registeredDriversItr.hasMoreElements()) { + Driver drv = registeredDriversItr.nextElement(); + if(drv.getClass().equals(driver)) { + driverObj = drv; + break; + } + } + if(driverObj == null) { + logger.warn("The class \"{}\" is not a registered JDBC driver, eaglercraft will try all registered drivers...", jdbcDriver); + } + Properties props = new Properties(); + for(Entry etr : System.getProperties().entrySet()) { + if(etr.getKey() instanceof String) { + String str = (String)etr.getKey(); + if(str.startsWith("eagler.jdbc.opts.")) { + props.put(str.substring(17), etr.getValue()); + } + } + } + logger.info("Connecting to database: \"{}\"", jdbcUri); + Connection conn; + try { + if(driverObj != null) { + conn = driverObj.connect(jdbcUri, props); + }else { + conn = DriverManager.getConnection(jdbcUri, props); + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("Failed to connect to database: \"" + jdbcUri + "\"", ex); + } + try { + return new JDBCFilesystem(conn, jdbcUri, jdbcDriver); + } catch (SQLException ex) { + try { + conn.close(); + }catch(SQLException ex2) { + } + throw new EaglerFileSystemException("Failed to initialize database: \"" + jdbcUri + "\"", ex); + } + } + + private JDBCFilesystem(Connection conn, String jdbcUri, String jdbcDriver) throws SQLException { + this.conn = conn; + this.jdbcUri = jdbcUri; + this.jdbcDriver = jdbcDriver; + try(Statement stmt = conn.createStatement()) { + stmt.execute("CREATE TABLE IF NOT EXISTS " + + "\"eaglercraft_desktop_runtime_filesystem\" (" + + "\"FileName\" VARCHAR(1024) NOT NULL," + + "\"FileSize\" INT NOT NULL," + + "\"FileData\" BLOB NOT NULL," + + "PRIMARY KEY(\"FileName\"))"); + + int totalFiles = 0; + try(ResultSet resultSet = stmt.executeQuery("SELECT COUNT(*) AS total_files FROM eaglercraft_desktop_runtime_filesystem")) { + if(resultSet.next()) { + totalFiles = resultSet.getInt(1); + } + } + logger.info("Loaded JDBC filesystem with {} files: \"{}\"", totalFiles, jdbcUri); + if(totalFiles > 0) { + newFilesystem = false; + } + } + this.createStatement = conn.prepareStatement("INSERT INTO eaglercraft_desktop_runtime_filesystem (FileName, FileSize, FileData) VALUES(?,?,?)"); + this.updateStatement = conn.prepareStatement("UPDATE eaglercraft_desktop_runtime_filesystem SET FileSize = ?, FileData = ? WHERE FileName = ?"); + this.readStatement = conn.prepareStatement("SELECT FileData FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1"); + this.existsStatement = conn.prepareStatement("SELECT COUNT(FileName) AS has_object FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1"); + this.sizeStatement = conn.prepareStatement("SELECT FileSize FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ? LIMIT 1"); + this.deleteStatement = conn.prepareStatement("DELETE FROM eaglercraft_desktop_runtime_filesystem WHERE FileName = ?"); + this.renameStatement = conn.prepareStatement("UPDATE eaglercraft_desktop_runtime_filesystem SET FileName = ? WHERE FileName = ?"); + this.iterateNonRecursive = conn.prepareStatement("SELECT FileName FROM eaglercraft_desktop_runtime_filesystem WHERE FileName LIKE ? AND NOT FileName LIKE ?"); + this.iterateRecursive = conn.prepareStatement("SELECT FileName FROM eaglercraft_desktop_runtime_filesystem WHERE FileName LIKE ?"); + startCleanupThread(); + synchronized(jdbcFilesystems) { + jdbcFilesystems.add(this); + } + } + + public boolean isNewFilesystem() { + return newFilesystem; + } + + private static void startCleanupThread() { + if(!cleanupThreadStarted) { + cleanupThreadStarted = true; + Runtime.getRuntime().addShutdownHook(new Thread(() -> { + synchronized(jdbcFilesystems) { + if(!jdbcFilesystems.isEmpty()) { + for(JDBCFilesystem fs : jdbcFilesystems) { + fs.shutdown0(); + } + jdbcFilesystems.clear(); + } + } + }, "JDBCFilesystemCleanup")); + } + } + + public void shutdown() { + shutdown0(); + synchronized(jdbcFilesystems) { + jdbcFilesystems.remove(this); + } + } + + private void shutdown0() { + synchronized(mutex) { + if(!hasClosed) { + hasClosed = true; + logger.info("Disconnecting from database: \"{}\"", jdbcUri); + try { + shutdown1(); + }catch(Throwable t) { + logger.error("Failed to disconnect from database: \"{}\""); + logger.error(t); + } + } + } + } + + private void shutdown1() throws SQLException { + if(!conn.isClosed()) { + quietClose(createStatement); + quietClose(updateStatement); + quietClose(readStatement); + quietClose(existsStatement); + quietClose(sizeStatement); + quietClose(deleteStatement); + quietClose(renameStatement); + quietClose(iterateNonRecursive); + quietClose(iterateRecursive); + conn.close(); + } + } + + private static void quietClose(Statement stmt) { + try { + stmt.close(); + }catch(Throwable t) { + } + } + + @Override + public boolean eaglerDelete(String pathName) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + deleteStatement.setString(1, pathName); + int ret = deleteStatement.executeUpdate(); + if(ret == 0) { + PlatformFilesystem.logger.warn("Tried to delete file that doesn't exist: \"{}\"", pathName); + } + return ret > 0; + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing delete!", ex); + } + } + + @Override + public ByteBuffer eaglerRead(String pathName) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + readStatement.setString(1, pathName); + byte[] has = null; + try(ResultSet resultSet = readStatement.executeQuery()) { + if(resultSet.next()) { + has = resultSet.getBytes(1); + } + } + if(has == null) { + PlatformFilesystem.logger.warn("Tried to read file that doesn't exist: \"{}\"", pathName); + return null; + } + ByteBuffer byteBuf = PlatformRuntime.allocateByteBuffer(has.length); + byteBuf.put(has); + byteBuf.flip(); + return byteBuf; + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing read!", ex); + } + } + + @Override + public void eaglerWrite(String pathName, ByteBuffer data) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + existsStatement.setString(1, pathName); + boolean exists; + try(ResultSet resultSet = existsStatement.executeQuery()) { + if(resultSet.next()) { + exists = resultSet.getInt(1) > 0; + }else { + exists = false; + } + } + byte[] cp = new byte[data.remaining()]; + data.get(cp); + if(exists) { + updateStatement.setInt(1, cp.length); + updateStatement.setBytes(2, cp); + updateStatement.setString(3, pathName); + if(updateStatement.executeUpdate() == 0) { + throw new EaglerFileSystemException("SQL file update query did not update any rows!"); + } + }else { + createStatement.setString(1, pathName); + createStatement.setInt(2, cp.length); + createStatement.setBytes(3, cp); + createStatement.executeUpdate(); + } + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing write!", ex); + } + } + + @Override + public boolean eaglerExists(String pathName) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + existsStatement.setString(1, pathName); + try(ResultSet resultSet = existsStatement.executeQuery()) { + if(resultSet.next()) { + return resultSet.getInt(1) > 0; + }else { + return false; + } + } + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing exists!", ex); + } + } + + @Override + public boolean eaglerMove(String pathNameOld, String pathNameNew) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + renameStatement.setString(1, pathNameNew); + renameStatement.setString(2, pathNameOld); + return renameStatement.executeUpdate() > 0; + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing move!", ex); + } + } + + @Override + public int eaglerCopy(String pathNameOld, String pathNameNew) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + readStatement.setString(1, pathNameOld); + try(ResultSet resultSet = readStatement.executeQuery()) { + byte[] has = null; + if(resultSet.next()) { + has = resultSet.getBytes(1); + } + if(has == null) { + return -1; + } + existsStatement.setString(1, pathNameNew); + boolean exists; + try(ResultSet resultSet2 = existsStatement.executeQuery()) { + if(resultSet2.next()) { + exists = resultSet2.getInt(1) > 0; + }else { + exists = false; + } + } + if(exists) { + updateStatement.setInt(1, has.length); + updateStatement.setBytes(2, has); + updateStatement.setString(3, pathNameNew); + if(updateStatement.executeUpdate() == 0) { + throw new EaglerFileSystemException("SQL file update query did not update any rows!"); + } + }else { + createStatement.setString(1, pathNameNew); + createStatement.setInt(2, has.length); + createStatement.setBytes(3, has); + createStatement.executeUpdate(); + } + return has.length; + } + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing copy!", ex); + } + } + + @Override + public int eaglerSize(String pathName) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + sizeStatement.setString(1, pathName); + try(ResultSet resultSet = sizeStatement.executeQuery()) { + if(resultSet.next()) { + return resultSet.getInt(1); + }else { + return -1; + } + } + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing size!", ex); + } + } + + @Override + public void eaglerIterate(String pathName, VFSFilenameIterator itr, boolean recursive) { + try { + synchronized(mutex) { + if(hasClosed || conn.isClosed()) { + throw new SQLException("Filesystem database connection is closed!"); + } + PreparedStatement stmt; + if(recursive) { + stmt = iterateRecursive; + stmt.setString(1, pathName + (!pathName.endsWith("/") ? "/%" : "%"));; + }else { + stmt = iterateNonRecursive; + if(!pathName.endsWith("/")) { + pathName += "/"; + } + stmt.setString(1, pathName + "%"); + stmt.setString(2, pathName + "%/%"); + } + try(ResultSet resultSet = stmt.executeQuery()) { + while(resultSet.next()) { + try { + itr.next(resultSet.getString(1)); + }catch(VFSIterator2.BreakLoop exx) { + break; + } + } + } + } + }catch(SQLException ex) { + throw new EaglerFileSystemException("JDBC exception thrown while executing iterate!", ex); + } + } + +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystemConverter.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystemConverter.java new file mode 100644 index 0000000..ea9034f --- /dev/null +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/JDBCFilesystemConverter.java @@ -0,0 +1,130 @@ +package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem.IFilesystemProvider; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; +import net.lax1dude.eaglercraft.v1_8.internal.vfs2.EaglerFileSystemException; +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 JDBCFilesystemConverter { + + private static final Logger logger = LogManager.getLogger("JDBCFilesystemConverter"); + + public static void convertFilesystem(String title, File oldFS, IFilesystemProvider newFS, boolean deleteOld) { + FilesystemConvertingDialog progressDialog = new FilesystemConvertingDialog(title); + try { + progressDialog.setProgressIndeterminate(true); + progressDialog.setLocationRelativeTo(null); + progressDialog.setVisible(true); + + String slug = oldFS.getAbsolutePath(); + List filesToCopy = new ArrayList(); + logger.info("Discovering files to convert..."); + iterateFolder(slug.length(), oldFS, filesToCopy); + logger.info("Found {} files in the old directory", filesToCopy.size()); + + progressDialog.setProgressIndeterminate(false); + progressDialog.setProgressValue(0); + + int progCounter = 0; + int lastProgUpdate = 0; + byte[] copyArray = new byte[4096]; + + int l = filesToCopy.size(); + for(int i = 0; i < l; ++i) { + String str = filesToCopy.get(i); + File f = new File(oldFS, str); + try(InputStream is = new FileInputStream(f)) { + ByteBuffer copyBuffer = PlatformRuntime.allocateByteBuffer((int)f.length()); + try { + int j; + while(copyBuffer.hasRemaining() && (j = is.read(copyArray, 0, copyArray.length)) != -1) { + copyBuffer.put(copyArray, 0, j); + } + copyBuffer.flip(); + progCounter += copyBuffer.remaining(); + newFS.eaglerWrite(str, copyBuffer); + }finally { + PlatformRuntime.freeByteBuffer(copyBuffer); + } + if(progCounter - lastProgUpdate > 25000) { + lastProgUpdate = progCounter; + logger.info("Converted {}/{} files, {} bytes to JDBC format...", (i + 1), l, progCounter); + } + }catch(IOException ex) { + throw new EaglerFileSystemException("Failed to convert file: \"" + f.getAbsolutePath() + "\"", ex); + } + progressDialog.setProgressValue(i * 512 / (l - 1)); + } + + logger.info("Converted {}/{} files successfully!", l, l); + + if(deleteOld) { + logger.info("Deleting old filesystem..."); + progressDialog.setProgressIndeterminate(true); + deleteOldFolder(oldFS); + logger.info("Delete complete!"); + } + }finally { + progressDialog.setVisible(false); + progressDialog.dispose(); + } + } + + private static void iterateFolder(int slug, File file, List ret) { + File[] f = file.listFiles(); + if(f == null) { + return; + } + for(int i = 0; i < f.length; ++i) { + File ff = f[i]; + if(ff.isDirectory()) { + iterateFolder(slug, ff, ret); + }else { + String str = ff.getAbsolutePath(); + if(str.length() > slug) { + str = str.substring(slug).replace('\\', '/'); + if(str.startsWith("/")) { + str = str.substring(1); + } + ret.add(str); + } + } + } + } + + private static void deleteOldFolder(File file) { + File[] f = file.listFiles(); + for(int i = 0; i < f.length; ++i) { + if(f[i].isDirectory()) { + deleteOldFolder(f[i]); + }else { + f[i].delete(); + } + } + file.delete(); + } +} \ No newline at end of file diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java index 23af40b..849e836 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/LWJGLEntryPoint.java @@ -6,6 +6,7 @@ import javax.swing.UnsupportedLookAndFeelException; import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.EagUtils; import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformANGLE; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformFilesystem; import net.lax1dude.eaglercraft.v1_8.internal.PlatformInput; import net.lax1dude.eaglercraft.v1_8.internal.PlatformRuntime; import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.program.ShaderSource; @@ -43,15 +44,9 @@ public class LWJGLEntryPoint { boolean hideRenderDocDialog = false; for(int i = 0; i < args.length; ++i) { - if(args[i].equalsIgnoreCase("highp")) { - ShaderSource.setHighP(true); - } if(args[i].equalsIgnoreCase("hide-renderdoc")) { hideRenderDocDialog = true; } - if(args[i].equalsIgnoreCase("fullscreen")) { - PlatformInput.setStartupFullscreen(true); - } } if(!hideRenderDocDialog) { @@ -66,7 +61,7 @@ public class LWJGLEntryPoint { lr.dispose(); } - getANGLEPlatformFromArgs(args); + getPlatformOptionsFromArgs(args); RelayManager.relayManager.load(EagRuntime.getStorage("r")); @@ -81,12 +76,22 @@ public class LWJGLEntryPoint { } - private static void getANGLEPlatformFromArgs(String[] args) { + private static void getPlatformOptionsFromArgs(String[] args) { for(int i = 0; i < args.length; ++i) { - EnumPlatformANGLE angle = EnumPlatformANGLE.fromId(args[i]); - if(angle != EnumPlatformANGLE.DEFAULT) { - PlatformRuntime.requestANGLE(angle); - break; + if(args[i].equalsIgnoreCase("fullscreen")) { + PlatformInput.setStartupFullscreen(true); + }else if(args[i].equalsIgnoreCase("highp")) { + ShaderSource.setHighP(true); + }else if(args[i].startsWith("jdbc:")) { + if(i < args.length - 1) { + PlatformFilesystem.setUseJDBC(args[i]); + PlatformFilesystem.setJDBCDriverClass(args[++i]); + } + }else { + EnumPlatformANGLE angle = EnumPlatformANGLE.fromId(args[i]); + if(angle != EnumPlatformANGLE.DEFAULT) { + PlatformRuntime.requestANGLE(angle); + } } } } diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/TestProgram.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/TestProgram.java deleted file mode 100644 index 26f348e..0000000 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/internal/lwjgl/TestProgram.java +++ /dev/null @@ -1,37 +0,0 @@ -package net.lax1dude.eaglercraft.v1_8.internal.lwjgl; - -import net.lax1dude.eaglercraft.v1_8.Display; -import net.lax1dude.eaglercraft.v1_8.EagRuntime; -import net.lax1dude.eaglercraft.v1_8.EagUtils; -import net.lax1dude.eaglercraft.v1_8.Keyboard; -import net.lax1dude.eaglercraft.v1_8.Mouse; -import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants; - -public class TestProgram { - - private static boolean grab = false; - - public static void main_(String[] args) { - - while(!Display.isCloseRequested()) { - - Keyboard.enableRepeatEvents(true); - Display.update(); - - while(Keyboard.next()) { - if(Keyboard.getEventKey() == KeyboardConstants.KEY_E && Keyboard.getEventKeyState()) { - grab = !grab; - Mouse.setGrabbed(grab); - } - } - - System.out.println("" + Mouse.getDX() + ", " + Mouse.getDY()); - - EagUtils.sleep(100l); - } - - EagRuntime.destroy(); - - } - -} diff --git a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java index b231677..a51779a 100644 --- a/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java +++ b/src/lwjgl/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java @@ -11,7 +11,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * 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 @@ -982,6 +982,30 @@ public class GlStateManager { Matrix4f.mul(modeMatrix, paramMatrix, modeMatrix); } + + public static final void multMatrix(Matrix4f matrix) { + Matrix4f modeMatrix; + + switch(stateMatrixMode) { + case GL_MODELVIEW: + default: + modeMatrix = modelMatrixStack[modelMatrixStackPointer]; + modelMatrixStackAccessSerial[modelMatrixStackPointer] = ++modelMatrixAccessSerial; + break; + case GL_PROJECTION: + modeMatrix = projectionMatrixStack[projectionMatrixStackPointer]; + projectionMatrixStackAccessSerial[projectionMatrixStackPointer] = ++projectionMatrixAccessSerial; + break; + case GL_TEXTURE: + int ptr = textureMatrixStackPointer[activeTexture]; + modeMatrix = textureMatrixStack[activeTexture][ptr]; + textureMatrixStackAccessSerial[activeTexture][textureMatrixStackPointer[activeTexture]] = + ++textureMatrixAccessSerial[activeTexture]; + break; + } + + Matrix4f.mul(modeMatrix, matrix, modeMatrix); + } public static final void color(float colorRed, float colorGreen, float colorBlue, float colorAlpha) { stateColorR = colorRed; diff --git a/src/lwjgl/java/net/minecraft/client/Minecraft.java b/src/lwjgl/java/net/minecraft/client/Minecraft.java index 7b64380..028195b 100644 --- a/src/lwjgl/java/net/minecraft/client/Minecraft.java +++ b/src/lwjgl/java/net/minecraft/client/Minecraft.java @@ -39,6 +39,7 @@ 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.minecraft.EaglerFontRenderer; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader; import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; @@ -67,6 +68,8 @@ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenSingleplayerConnecting; import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController; import net.lax1dude.eaglercraft.v1_8.update.RelayUpdateChecker; +import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceOverlay; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.audio.MusicTicker; @@ -307,6 +310,8 @@ public class Minecraft implements IThreadListener { private boolean isLANOpen = false; public SkullCommand eagskullCommand; + + public GuiVoiceOverlay voiceOverlay; public Minecraft(GameConfiguration gameConfig) { theMinecraft = this; @@ -421,6 +426,7 @@ public class Minecraft implements IThreadListener { this.mcResourceManager.registerReloadListener(new MetalsLUT()); this.mcResourceManager.registerReloadListener(new EmissiveItems()); this.mcResourceManager.registerReloadListener(new BlockVertexIDs()); + this.mcResourceManager.registerReloadListener(new EaglerMeshLoader()); AchievementList.openInventory.setStatStringFormatter(new IStatStringFormat() { public String formatString(String parString1) { try { @@ -471,6 +477,9 @@ public class Minecraft implements IThreadListener { this.checkGLError("Post startup"); this.ingameGUI = new GuiIngame(this); this.eagskullCommand = new SkullCommand(this); + this.voiceOverlay = new GuiVoiceOverlay(this); + ScaledResolution voiceRes = new ScaledResolution(this); + this.voiceOverlay.setResolution(voiceRes.getScaledWidth(), voiceRes.getScaledHeight()); ServerList.initServerList(this); EaglerProfile.read(); @@ -868,6 +877,7 @@ public class Minecraft implements IThreadListener { public void updateDisplay() { this.mcProfiler.startSection("display_update"); + Display.setVSync(this.gameSettings.enableVsync); Display.update(); this.mcProfiler.endSection(); this.checkWindowResize(); @@ -1214,12 +1224,14 @@ public class Minecraft implements IThreadListener { private void resize(int width, int height) { this.displayWidth = Math.max(1, width); this.displayHeight = Math.max(1, height); + ScaledResolution scaledresolution = new ScaledResolution(this); if (this.currentScreen != null) { - ScaledResolution scaledresolution = new ScaledResolution(this); this.currentScreen.onResize(this, scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight()); } this.loadingScreen = new LoadingScreenRenderer(this); + + this.voiceOverlay.setResolution(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight()); } public MusicTicker func_181535_r() { @@ -1257,6 +1269,9 @@ public class Minecraft implements IThreadListener { if (!this.isGamePaused) { this.ingameGUI.updateTick(); } + + this.mcProfiler.endStartSection("eaglerVoice"); + VoiceClientController.tickVoiceClient(this); this.mcProfiler.endSection(); this.entityRenderer.getMouseOver(1.0F); @@ -1764,6 +1779,7 @@ public class Minecraft implements IThreadListener { */ public void launchIntegratedServer(String folderName, String worldName, WorldSettings worldSettingsIn) { this.loadWorld((WorldClient) null); + Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins(this.gameSettings.enableFNAWSkins); session.reset(); SingleplayerServerController.launchEaglercraftServer(folderName, gameSettings.difficulty.getDifficultyId(), Math.max(gameSettings.renderDistanceChunks, 2), worldSettingsIn); @@ -2308,4 +2324,12 @@ public class Minecraft implements IThreadListener { public void clearTitles() { ingameGUI.displayTitle(null, null, -1, -1, -1); } + + public boolean getEnableFNAWSkins() { + boolean ret = this.gameSettings.enableFNAWSkins; + if (this.thePlayer != null) { + ret &= this.thePlayer.sendQueue.currentFNAWSkinAllowedState; + } + return ret; + } } \ No newline at end of file diff --git a/src/lwjgl/java/net/minecraft/client/gui/GuiIngame.java b/src/lwjgl/java/net/minecraft/client/gui/GuiIngame.java index a3a9b19..1f3c13a 100644 --- a/src/lwjgl/java/net/minecraft/client/gui/GuiIngame.java +++ b/src/lwjgl/java/net/minecraft/client/gui/GuiIngame.java @@ -287,6 +287,10 @@ public class GuiIngame extends Gui { if (scoreobjective1 != null) { this.renderScoreboard(scoreobjective1, scaledresolution); } + + if (this.mc.currentScreen == null) { + this.mc.voiceOverlay.drawOverlay(); + } GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0); diff --git a/src/lwjgl/java/net/minecraft/client/gui/GuiIngameMenu.java b/src/lwjgl/java/net/minecraft/client/gui/GuiIngameMenu.java index 420cabc..1b17165 100644 --- a/src/lwjgl/java/net/minecraft/client/gui/GuiIngameMenu.java +++ b/src/lwjgl/java/net/minecraft/client/gui/GuiIngameMenu.java @@ -1,5 +1,6 @@ package net.minecraft.client.gui; +import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.Mouse; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController; @@ -8,6 +9,8 @@ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenLANNotSupported; import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiShareToLan; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController; import net.lax1dude.eaglercraft.v1_8.update.GuiUpdateCheckerOverlay; +import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceMenu; +import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.achievement.GuiAchievements; import net.minecraft.client.gui.achievement.GuiStats; @@ -44,9 +47,13 @@ public class GuiIngameMenu extends GuiScreen { boolean hasSentAutoSave = !SingleplayerServerController.isWorldRunning(); private GuiUpdateCheckerOverlay updateCheckerOverlay; + private GuiVoiceMenu voiceMenu; public GuiIngameMenu() { updateCheckerOverlay = new GuiUpdateCheckerOverlay(true, this); + if (EagRuntime.getConfiguration().isAllowVoiceClient()) { + voiceMenu = new GuiVoiceMenu(this); + } } /**+ @@ -75,6 +82,10 @@ public class GuiIngameMenu extends GuiScreen { I18n.format("gui.achievements", new Object[0]))); this.buttonList.add(new GuiButton(6, this.width / 2 + 2, this.height / 4 + 48 + b0, 98, 20, I18n.format("gui.stats", new Object[0]))); + GuiButton mods; + this.buttonList.add(mods = new GuiButton(69420, this.width / 2 - 100, this.height / 4 + 73 + b0, + I18n.format("EaglerForge Mods", new Object[0]))); + mods.enabled = false; lanButton.enabled = SingleplayerServerController.isWorldRunning(); if (!hasSentAutoSave) { hasSentAutoSave = true; @@ -139,6 +150,10 @@ public class GuiIngameMenu extends GuiScreen { */ public void updateScreen() { super.updateScreen(); + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.updateScreen(); + } if (Mouse.isActuallyGrabbed()) { Mouse.setGrabbed(false); } @@ -156,37 +171,67 @@ public class GuiIngameMenu extends GuiScreen { this.updateCheckerOverlay.drawScreen(i, j, f); if (LANServerController.isLANOpen()) { + int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset(); String str = I18n.format("lanServer.pauseMenu0"); - drawString(fontRendererObj, str, 6, 32, 0xFFFF55); + drawString(fontRendererObj, str, 6, 10 + offset, 0xFFFF55); if (mc.gameSettings.hideJoinCode) { GlStateManager.pushMatrix(); - GlStateManager.translate(7.0f, 47.0f, 0.0f); + GlStateManager.translate(7.0f, 25.0f + offset, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); str = I18n.format("lanServer.showCode"); int w = fontRendererObj.getStringWidth(str); - boolean hover = i > 6 && i < 8 + w * 3 / 4 && j > 46 && j < 47 + 8; + boolean hover = i > 4 && i < 8 + w * 3 / 4 && j > 24 + offset && j < 25 + offset + 8; drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55); GlStateManager.popMatrix(); } else { int w = fontRendererObj.getStringWidth(str); GlStateManager.pushMatrix(); - GlStateManager.translate(6 + w + 3, 33, 0.0f); + GlStateManager.translate(6 + w + 3, 11 + offset, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); str = I18n.format("lanServer.hideCode"); int w2 = fontRendererObj.getStringWidth(str); - boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 33 - 1 && j < 33 + 6; + boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 11 + offset - 1 + && j < 11 + offset + 6; drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55); GlStateManager.popMatrix(); - drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " " - + EnumChatFormatting.RESET + LANServerController.getCurrentURI(), 6, 47, 0xFFFFFF); - drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " " - + EnumChatFormatting.RESET + LANServerController.getCurrentCode(), 6, 57, 0xFFFFFF); + drawString( + fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " " + + EnumChatFormatting.RESET + LANServerController.getCurrentURI(), + 6, 25 + offset, 0xFFFFFF); + drawString( + fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " " + + EnumChatFormatting.RESET + LANServerController.getCurrentCode(), + 6, 35 + offset, 0xFFFFFF); } } - super.drawScreen(i, j, f); + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + if (voiceMenu.isBlockingInput()) { + super.drawScreen(0, 0, f); + } else { + super.drawScreen(i, j, f); + } + voiceMenu.drawScreen(i, j, f); + } else { + super.drawScreen(i, j, f); + } + } catch (GuiVoiceMenu.AbortedException ex) { + } + } + + protected void keyTyped(char par1, int par2) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.keyTyped(par1, par2); + } + super.keyTyped(par1, par2); + } catch (GuiVoiceMenu.AbortedException ex) { + } } public void confirmClicked(boolean par1, int par2) { @@ -201,11 +246,20 @@ public class GuiIngameMenu extends GuiScreen { } protected void mouseClicked(int par1, int par2, int par3) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.mouseClicked(par1, par2, par3); + } + } catch (GuiVoiceMenu.AbortedException ex) { + return; + } if (par3 == 0) { + int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset(); if (mc.gameSettings.hideJoinCode) { String str = I18n.format("lanServer.showCode"); int w = fontRendererObj.getStringWidth(str); - if (par1 > 6 && par1 < 8 + w * 3 / 4 && par2 > 46 && par2 < 47 + 8) { + if (par1 > 4 && par1 < 8 + w * 3 / 4 && par2 > 24 + offset && par2 < 25 + offset + 8) { mc.gameSettings.hideJoinCode = false; this.mc.getSoundHandler() .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); @@ -216,7 +270,8 @@ public class GuiIngameMenu extends GuiScreen { int w = fontRendererObj.getStringWidth(str); str = I18n.format("lanServer.hideCode"); int w2 = fontRendererObj.getStringWidth(str); - if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 33 - 1 && par2 < 33 + 6) { + if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 11 + offset - 1 + && par2 < 11 + offset + 6) { mc.gameSettings.hideJoinCode = true; this.mc.getSoundHandler() .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); @@ -228,4 +283,22 @@ public class GuiIngameMenu extends GuiScreen { this.updateCheckerOverlay.mouseClicked(par1, par2, par3); super.mouseClicked(par1, par2, par3); } + + public void setWorldAndResolution(Minecraft par1Minecraft, int par2, int par3) { + super.setWorldAndResolution(par1Minecraft, par2, par3); + if (EagRuntime.getConfiguration().isAllowVoiceClient()) { + voiceMenu.setResolution(par1Minecraft, par2, par3); + } + } + + protected void mouseReleased(int par1, int par2, int par3) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.mouseReleased(par1, par2, par3); + } + super.mouseReleased(par1, par2, par3); + } catch (GuiVoiceMenu.AbortedException ex) { + } + } } \ No newline at end of file diff --git a/src/lwjgl/java/net/minecraft/client/gui/GuiScreen.java b/src/lwjgl/java/net/minecraft/client/gui/GuiScreen.java index 837f008..5bc126e 100644 --- a/src/lwjgl/java/net/minecraft/client/gui/GuiScreen.java +++ b/src/lwjgl/java/net/minecraft/client/gui/GuiScreen.java @@ -673,4 +673,8 @@ public abstract class GuiScreen extends Gui implements GuiYesNoCallback { public boolean shouldHangupIntegratedServer() { return true; } + + public boolean blockPTTKey() { + return false; + } } \ No newline at end of file diff --git a/src/lwjgl/java/net/minecraft/client/network/NetHandlerPlayClient.java b/src/lwjgl/java/net/minecraft/client/network/NetHandlerPlayClient.java index 88b4c48..e888bb9 100644 --- a/src/lwjgl/java/net/minecraft/client/network/NetHandlerPlayClient.java +++ b/src/lwjgl/java/net/minecraft/client/network/NetHandlerPlayClient.java @@ -13,12 +13,15 @@ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; import com.google.common.collect.Maps; import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.lax1dude.eaglercraft.v1_8.profile.CapePackets; +import net.lax1dude.eaglercraft.v1_8.profile.ServerCapeCache; import net.lax1dude.eaglercraft.v1_8.profile.ServerSkinCache; import net.lax1dude.eaglercraft.v1_8.profile.SkinPackets; import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANClientNetworkManager; import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager; import net.lax1dude.eaglercraft.v1_8.update.UpdateService; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack; @@ -242,6 +245,8 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { */ private final EaglercraftRandom avRandomizer = new EaglercraftRandom(); private final ServerSkinCache skinCache; + private final ServerCapeCache capeCache; + public boolean currentFNAWSkinAllowedState = true; public NetHandlerPlayClient(Minecraft mcIn, GuiScreen parGuiScreen, EaglercraftNetworkManager parNetworkManager, GameProfile parGameProfile) { @@ -250,6 +255,7 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { this.netManager = parNetworkManager; this.profile = parGameProfile; this.skinCache = new ServerSkinCache(parNetworkManager, mcIn.getTextureManager()); + this.capeCache = new ServerCapeCache(parNetworkManager, mcIn.getTextureManager()); this.isIntegratedServer = (parNetworkManager instanceof ClientIntegratedServerNetworkManager) || (parNetworkManager instanceof LANClientNetworkManager); } @@ -261,12 +267,17 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { public void cleanup() { this.clientWorldController = null; this.skinCache.destroy(); + this.capeCache.destroy(); } public ServerSkinCache getSkinCache() { return this.skinCache; } + public ServerCapeCache getCapeCache() { + return this.capeCache; + } + /**+ * Registers some server properties * (gametype,hardcore-mode,terraintype,difficulty,player limit), @@ -290,6 +301,10 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { this.gameController.gameSettings.sendSettingsToServer(); this.netManager.sendPacket(new C17PacketCustomPayload("MC|Brand", (new PacketBuffer(Unpooled.buffer())).writeString(ClientBrandRetriever.getClientModName()))); + if (VoiceClientController.isClientSupported()) { + VoiceClientController.initializeVoiceClient((pkt) -> this.netManager + .sendPacket(new C17PacketCustomPayload(VoiceClientController.SIGNAL_CHANNEL, pkt))); + } } /**+ @@ -712,6 +727,9 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { * describing the reason for termination */ public void onDisconnect(IChatComponent ichatcomponent) { + VoiceClientController.handleServerDisconnect(); + Minecraft.getMinecraft().getRenderManager() + .setEnableFNAWSkins(this.gameController.gameSettings.enableFNAWSkins); if (this.gameController.theWorld != null) { this.gameController.loadWorld((WorldClient) null); } @@ -1419,6 +1437,7 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { EaglercraftUUID uuid = s38packetplayerlistitem$addplayerdata.getProfile().getId(); this.playerInfoMap.remove(uuid); this.skinCache.evictSkin(uuid); + this.capeCache.evictCape(uuid); } else { NetworkPlayerInfo networkplayerinfo = (NetworkPlayerInfo) this.playerInfoMap .get(s38packetplayerlistitem$addplayerdata.getProfile().getId()); @@ -1600,6 +1619,13 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { logger.error("Couldn't read EAG|Skins-1.8 packet!"); logger.error(e); } + } else if ("EAG|Capes-1.8".equals(packetIn.getChannelName())) { + try { + CapePackets.readPluginMessage(packetIn.getBufferData(), capeCache); + } catch (IOException e) { + logger.error("Couldn't read EAG|Capes-1.8 packet!"); + logger.error(e); + } } else if ("EAG|UpdateCert-1.8".equals(packetIn.getChannelName())) { if (EagRuntime.getConfiguration().allowUpdateSvc()) { try { @@ -1612,6 +1638,14 @@ public class NetHandlerPlayClient implements INetHandlerPlayClient { logger.error(e); } } + } else if (VoiceClientController.SIGNAL_CHANNEL.equals(packetIn.getChannelName())) { + if (VoiceClientController.isClientSupported()) { + VoiceClientController.handleVoiceSignalPacket(packetIn.getBufferData()); + } + } else if ("EAG|FNAWSEn-1.8".equals(packetIn.getChannelName())) { + this.currentFNAWSkinAllowedState = packetIn.getBufferData().readBoolean(); + Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins( + this.currentFNAWSkinAllowedState && Minecraft.getMinecraft().gameSettings.enableFNAWSkins); } } diff --git a/src/lwjgl/java/net/minecraft/client/settings/GameSettings.java b/src/lwjgl/java/net/minecraft/client/settings/GameSettings.java index 87660d2..6f1ead7 100644 --- a/src/lwjgl/java/net/minecraft/client/settings/GameSettings.java +++ b/src/lwjgl/java/net/minecraft/client/settings/GameSettings.java @@ -9,6 +9,7 @@ import java.util.Map; import java.util.Set; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import org.json.JSONArray; import com.google.common.collect.ImmutableSet; @@ -33,6 +34,7 @@ import net.lax1dude.eaglercraft.v1_8.EaglerZLIB; import net.lax1dude.eaglercraft.v1_8.HString; import net.lax1dude.eaglercraft.v1_8.Keyboard; import net.lax1dude.eaglercraft.v1_8.Mouse; +import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType; import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; @@ -110,7 +112,7 @@ public class GameSettings { public boolean chatLinksPrompt = true; public float chatOpacity = 1.0F; public boolean snooperEnabled = true; - public boolean enableVsync = true; + public boolean enableVsync = EagRuntime.getPlatformType() != EnumPlatformType.DESKTOP; public boolean allowBlockAlternatives = true; public boolean reducedDebugInfo = false; public boolean hideServerAddress; @@ -265,6 +267,12 @@ public class GameSettings { public boolean ofSmoothBiomes = true; public boolean ofCustomColors = true; public boolean hidePassword = true; + + public boolean enableFNAWSkins = true; + public int voiceListenRadius = 16; + public float voiceListenVolume = 0.5f; + public float voiceSpeakVolume = 0.5f; + public int voicePTTKey = 47; // V public GameSettings(Minecraft mcIn) { this.keyBindings = (KeyBinding[]) ArrayUtils.addAll(new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, @@ -896,6 +904,15 @@ public class GameSettings { if (parOptions == GameSettings.Options.HIDE_PASSWORD) { hidePassword =! hidePassword; } + + if (parOptions == GameSettings.Options.FNAW_SKINS) { + this.enableFNAWSkins = !this.enableFNAWSkins; + this.mc.getRenderManager().setEnableFNAWSkins(this.mc.getEnableFNAWSkins()); + } + + if (parOptions == GameSettings.Options.EAGLER_VSYNC) { + this.enableVsync = !this.enableVsync; + } this.saveOptions(); } @@ -1019,6 +1036,10 @@ public class GameSettings { return this.ofCustomColors; case HIDE_PASSWORD: return hidePassword; + case FNAW_SKINS: + return this.enableFNAWSkins; + case EAGLER_VSYNC: + return this.enableVsync; default: return false; } @@ -1474,7 +1495,7 @@ public class GameSettings { this.snooperEnabled = astring[1].equals("true"); } - if (astring[0].equals("enableVsync")) { + if (astring[0].equals("enableVsyncEag")) { this.enableVsync = astring[1].equals("true"); } @@ -1869,7 +1890,21 @@ public class GameSettings { hidePassword = Boolean.valueOf(astring[1]).booleanValue(); } - Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + if (astring[0].equals("voiceListenRadius")) { + voiceListenRadius = Integer.parseInt(astring[1]); + } + + if (astring[0].equals("voiceListenVolume")) { + voiceListenVolume = this.parseFloat(astring[1]); + } + + if (astring[0].equals("voiceSpeakVolume")) { + voiceSpeakVolume = this.parseFloat(astring[1]); + } + + if (astring[0].equals("voicePTTKey")) { + voicePTTKey = Integer.parseInt(astring[1]); + } for (SoundCategory soundcategory : SoundCategory._VALUES) { if (astring[0].equals("soundCategory_" + soundcategory.getCategoryName())) { @@ -1882,6 +1917,10 @@ public class GameSettings { this.setModelPartEnabled(enumplayermodelparts, astring[1].equals("true")); } } + + if (astring[0].equals("enableFNAWSkins")) { + this.enableFNAWSkins = astring[1].equals("true"); + } deferredShaderConf.readOption(astring[0], astring[1]); } catch (Exception var8) { @@ -1890,8 +1929,16 @@ public class GameSettings { } KeyBinding.resetKeyBindingArrayAndHash(); + + Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + VoiceClientController.setVoiceListenVolume(voiceListenVolume); + VoiceClientController.setVoiceSpeakVolume(voiceSpeakVolume); + VoiceClientController.setVoiceProximity(voiceListenRadius); + if (this.mc.getRenderManager() != null) + this.mc.getRenderManager().setEnableFNAWSkins(this.enableFNAWSkins); } catch (Exception exception) { - logger.error("Failed to load options", exception); + logger.error("Failed to load options"); + logger.error(exception); } } @@ -1958,7 +2005,7 @@ public class GameSettings { printwriter.println("chatLinksPrompt:" + this.chatLinksPrompt); printwriter.println("chatOpacity:" + this.chatOpacity); printwriter.println("snooperEnabled:" + this.snooperEnabled); - printwriter.println("enableVsync:" + this.enableVsync); + printwriter.println("enableVsyncEag:" + this.enableVsync); printwriter.println("hideServerAddress:" + this.hideServerAddress); printwriter.println("advancedItemTooltips:" + this.advancedItemTooltips); printwriter.println("pauseOnLostFocus:" + this.pauseOnLostFocus); @@ -2047,6 +2094,11 @@ public class GameSettings { printwriter.println("ofSmoothBiomes:" + this.ofSmoothBiomes); printwriter.println("ofCustomColors:" + this.ofCustomColors); printwriter.println("hidePassword:" + hidePassword); + printwriter.println("voiceListenRadius:" + this.voiceListenRadius); + printwriter.println("voiceListenVolume:" + this.voiceListenVolume); + printwriter.println("voiceSpeakVolume:" + this.voiceSpeakVolume); + printwriter.println("voicePTTKey:" + this.voicePTTKey); + printwriter.println("enableFNAWSkins:" + this.enableFNAWSkins); for (KeyBinding keybinding : this.keyBindings) { printwriter.println("key_" + keybinding.getKeyDescription() + ":" + keybinding.getKeyCode()); @@ -2069,7 +2121,8 @@ public class GameSettings { printwriter.close(); return bao.toByteArray(); } catch (Exception exception) { - logger.error("Failed to save options", exception); + logger.error("Failed to save options"); + logger.error(exception); return null; } @@ -2255,7 +2308,9 @@ public class GameSettings { SWAMP_COLORS("Swamp Colors", false, false), SMOOTH_BIOMES("Smooth Biomes", false, false), CUSTOM_COLORS("Custom Colors", false, false), - HIDE_PASSWORD("Hide Password", false, false); + HIDE_PASSWORD("Hide Password", false, false), + FNAW_SKINS("options.skinCustomisation.enableFNAWSkins", false, true), + EAGLER_VSYNC("options.vsync", false, true); private final boolean enumFloat; private final boolean enumBoolean; diff --git a/src/main/java/net/PeytonPlayz585/shadow/GuiOtherSettingsOF.java b/src/main/java/net/PeytonPlayz585/shadow/GuiOtherSettingsOF.java index 098d6fd..02b0851 100644 --- a/src/main/java/net/PeytonPlayz585/shadow/GuiOtherSettingsOF.java +++ b/src/main/java/net/PeytonPlayz585/shadow/GuiOtherSettingsOF.java @@ -12,7 +12,7 @@ public class GuiOtherSettingsOF extends GuiScreen implements GuiYesNoCallback { private GuiScreen prevScreen; protected String title; private GameSettings settings; - private static GameSettings.Options[] enumOptions = new GameSettings.Options[] {GameSettings.Options.LAGOMETER, GameSettings.Options.PROFILER, GameSettings.Options.WEATHER, GameSettings.Options.TIME, GameSettings.Options.FULLSCREEN, GameSettings.Options.HUD_FPS, GameSettings.Options.AUTOSAVE_TICKS, GameSettings.Options.ANAGLYPH, GameSettings.Options.HUD_COORDS, GameSettings.Options.HUD_PLAYER, GameSettings.Options.HUD_STATS, GameSettings.Options.HUD_WORLD, GameSettings.Options.HUD_24H}; + private static GameSettings.Options[] enumOptions = new GameSettings.Options[] {GameSettings.Options.LAGOMETER, GameSettings.Options.PROFILER, GameSettings.Options.WEATHER, GameSettings.Options.TIME, GameSettings.Options.FULLSCREEN, GameSettings.Options.FNAW_SKINS, GameSettings.Options.HUD_FPS, GameSettings.Options.AUTOSAVE_TICKS, GameSettings.Options.ANAGLYPH, GameSettings.Options.HUD_COORDS, GameSettings.Options.HUD_PLAYER, GameSettings.Options.HUD_STATS, GameSettings.Options.HUD_WORLD, GameSettings.Options.HUD_24H}; public GuiOtherSettingsOF(GuiScreen p_i51_1_, GameSettings p_i51_2_) { this.prevScreen = p_i51_1_; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java index 2f46e14..33569cd 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/Display.java @@ -44,6 +44,10 @@ public class Display { public static boolean isCloseRequested() { return PlatformInput.isCloseRequested(); } + + public static void setVSync(boolean enable) { + PlatformInput.setVSync(enable); + } public static void update() { PlatformInput.update(); 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 f6d71a1..1e1f4ea 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/EaglercraftVersion.java @@ -35,7 +35,7 @@ public class EaglercraftVersion { public static final boolean enableUpdateService = false; public static final String updateBundlePackageName = "net.lax1dude.eaglercraft.v1_8.client"; - public static final int updateBundlePackageVersionInt = 27; + public static final int updateBundlePackageVersionInt = 29; public static final String updateLatestLocalStorageKey = "latestUpdate_" + updateBundlePackageName; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java index dc519b1..684275c 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/internal/IClientConfigAdapter.java @@ -67,4 +67,6 @@ public interface IClientConfigAdapter { boolean isCheckRelaysForUpdates(); boolean isEnableSignatureBadge(); + + boolean isAllowVoiceClient(); } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglerMeshLoader.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglerMeshLoader.java new file mode 100644 index 0000000..7f4f258 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglerMeshLoader.java @@ -0,0 +1,172 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import java.io.DataInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.IResourceManager; +import net.minecraft.client.resources.IResourceManagerReloadListener; +import net.minecraft.util.ResourceLocation; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; +import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; + +/** + * 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 EaglerMeshLoader implements IResourceManagerReloadListener { + + private static final Logger logger = LogManager.getLogger("EaglerMeshLoader"); + + private static final Map meshCache = new HashMap(); + + public static HighPolyMesh getEaglerMesh(ResourceLocation meshLoc) { + if(meshLoc.cachedPointerType == ResourceLocation.CACHED_POINTER_EAGLER_MESH) { + return (HighPolyMesh)meshLoc.cachedPointer; + } + HighPolyMesh theMesh = meshCache.get(meshLoc); + if(theMesh == null) { + theMesh = new HighPolyMesh(); + reloadMesh(meshLoc, theMesh, Minecraft.getMinecraft().getResourceManager()); + } + meshLoc.cachedPointerType = ResourceLocation.CACHED_POINTER_EAGLER_MESH; + meshLoc.cachedPointer = theMesh; + return theMesh; + } + + private static void reloadMesh(ResourceLocation meshLoc, HighPolyMesh meshStruct, IResourceManager resourceManager) { + IntBuffer up1 = null; + try { + int intsOfVertex, intsOfIndex, intsTotal, stride; + try(DataInputStream dis = new DataInputStream(resourceManager.getResource(meshLoc).getInputStream())) { + byte[] header = new byte[8]; + dis.read(header); + if(!Arrays.equals(header, new byte[] { (byte) 33, (byte) 69, (byte) 65, (byte) 71, (byte) 36, + (byte) 109, (byte) 100, (byte) 108 })) { + throw new IOException("File is not an eaglercraft high-poly mesh!"); + } + + char CT = (char)dis.read(); + + if(CT == 'C') { + meshStruct.hasTexture = false; + }else if(CT == 'T') { + meshStruct.hasTexture = true; + }else { + throw new IOException("Unsupported mesh type '" + CT + "'!"); + } + + dis.skipBytes(dis.readUnsignedShort()); + + meshStruct.vertexCount = dis.readInt(); + meshStruct.indexCount = dis.readInt(); + int byteIndexCount = meshStruct.indexCount; + if(byteIndexCount % 2 != 0) { // must round up to int + byteIndexCount += 1; + } + stride = meshStruct.hasTexture ? 24 : 16; + + intsOfVertex = meshStruct.vertexCount * stride / 4; + intsOfIndex = byteIndexCount / 2; + intsTotal = intsOfIndex + intsOfVertex; + up1 = EagRuntime.allocateIntBuffer(intsTotal); + + for(int i = 0; i < intsTotal; ++i) { + int ch1 = dis.read(); + int ch2 = dis.read(); + int ch3 = dis.read(); + int ch4 = dis.read(); + if ((ch1 | ch2 | ch3 | ch4) < 0) throw new EOFException(); // rip + up1.put((ch4 << 24) + (ch3 << 16) + (ch2 << 8) + (ch1 << 0)); + } + + } + + if(meshStruct.vertexArray == null) { + meshStruct.vertexArray = _wglGenVertexArrays(); + } + if(meshStruct.vertexBuffer == null) { + meshStruct.vertexBuffer = _wglGenBuffers(); + } + if(meshStruct.indexBuffer == null) { + meshStruct.indexBuffer = _wglGenBuffers(); + } + + up1.position(0).limit(intsOfVertex); + + EaglercraftGPU.bindGLArrayBuffer(meshStruct.vertexBuffer); + _wglBufferData(GL_ARRAY_BUFFER, up1, GL_STATIC_DRAW); + + EaglercraftGPU.bindGLBufferArray(meshStruct.vertexArray); + + up1.position(intsOfVertex).limit(intsTotal); + + _wglBindBuffer(GL_ELEMENT_ARRAY_BUFFER, meshStruct.indexBuffer); + _wglBufferData(GL_ELEMENT_ARRAY_BUFFER, up1, GL_STATIC_DRAW); + + _wglEnableVertexAttribArray(0); + _wglVertexAttribPointer(0, 3, GL_FLOAT, false, stride, 0); + + if(meshStruct.hasTexture) { + _wglEnableVertexAttribArray(1); + _wglVertexAttribPointer(1, 2, GL_FLOAT, false, stride, 16); + } + + _wglEnableVertexAttribArray(meshStruct.hasTexture ? 2 : 1); + _wglVertexAttribPointer(meshStruct.hasTexture ? 2 : 1, 4, GL_BYTE, true, stride, 12); + }catch(Throwable ex) { + if(meshStruct.vertexArray != null) { + _wglDeleteVertexArrays(meshStruct.vertexArray); + meshStruct.vertexArray = null; + } + if(meshStruct.vertexBuffer != null) { + _wglDeleteBuffers(meshStruct.vertexBuffer); + meshStruct.vertexBuffer = null; + } + if(meshStruct.indexBuffer != null) { + _wglDeleteBuffers(meshStruct.indexBuffer); + meshStruct.indexBuffer = null; + } + + meshStruct.vertexCount = 0; + meshStruct.indexCount = 0; + meshStruct.hasTexture = false; + + logger.error("Failed to load eaglercraft high-poly mesh: \"{}\"", meshLoc); + logger.error(ex); + }finally { + if(up1 != null) { + EagRuntime.freeIntBuffer(up1); + } + } + } + + @Override + public void onResourceManagerReload(IResourceManager var1) { + for(Entry meshEntry : meshCache.entrySet()) { + reloadMesh(meshEntry.getKey(), meshEntry.getValue(), var1); + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java index ed06b8c..26801df 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/EaglercraftGPU.java @@ -23,7 +23,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * 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 @@ -152,7 +152,7 @@ public class EaglercraftGPU { currentList = null; } - public static void glCallList(int displayList) { + public static final void glCallList(int displayList) { DisplayList dp = mapDisplayListsGL.get(displayList); if(dp == null) { throw new NullPointerException("Tried to call a display list that does not exist: " + displayList); @@ -491,11 +491,21 @@ public class EaglercraftGPU { public static final ITextureGL getNativeTexture(int tex) { return mapTexturesGL.get(tex); } + + public static final void drawHighPoly(HighPolyMesh mesh) { + if(mesh.vertexCount == 0 || mesh.indexCount == 0 || mesh.vertexArray == null) { + return; + } + FixedFunctionPipeline p = FixedFunctionPipeline.setupRenderDisplayList(mesh.getAttribBits()).update(); + EaglercraftGPU.bindGLBufferArray(mesh.vertexArray); + p.drawElements(GL_TRIANGLES, mesh.indexCount, GL_UNSIGNED_SHORT, 0); + } static boolean hasFramebufferHDR16FSupport = false; static boolean hasFramebufferHDR32FSupport = false; + static boolean hasLinearHDR32FSupport = false; - public static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) { + public static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback) { createFramebufferHDR16FTexture(target, level, w, h, format, allow32bitFallback, null); } @@ -503,7 +513,7 @@ public class EaglercraftGPU { createFramebufferHDR16FTexture(target, level, w, h, format, false, pixelData); } - private static void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback, ByteBuffer pixelData) { + private static final void createFramebufferHDR16FTexture(int target, int level, int w, int h, int format, boolean allow32bitFallback, ByteBuffer pixelData) { if(hasFramebufferHDR16FSupport) { int internalFormat; switch(format) { @@ -534,15 +544,15 @@ public class EaglercraftGPU { } } - public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback) { + public static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback) { createFramebufferHDR32FTexture(target, level, w, h, format, allow16bitFallback, null); } - public static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) { + public static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, ByteBuffer pixelData) { createFramebufferHDR32FTexture(target, level, w, h, format, false, pixelData); } - private static void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback, ByteBuffer pixelData) { + private static final void createFramebufferHDR32FTexture(int target, int level, int w, int h, int format, boolean allow16bitFallback, ByteBuffer pixelData) { if(hasFramebufferHDR32FSupport) { int internalFormat; switch(format) { @@ -559,7 +569,7 @@ public class EaglercraftGPU { default: throw new UnsupportedOperationException("Unknown format: " + format); } - _wglTexImage2D(target, level, internalFormat, w, h, 0, format, GL_FLOAT, pixelData); + _wglTexImage2Df32(target, level, internalFormat, w, h, 0, format, GL_FLOAT, pixelData); }else { if(allow16bitFallback) { if(hasFramebufferHDR16FSupport) { @@ -589,7 +599,13 @@ public class EaglercraftGPU { }else { logger.error("32-bit HDR render target support: false"); } - if(!checkHasHDRFramebufferSupport()) { + hasLinearHDR32FSupport = PlatformOpenGL.checkLinearHDR32FSupport(); + if(hasLinearHDR32FSupport) { + logger.info("32-bit HDR linear filter support: true"); + }else { + logger.error("32-bit HDR linear filter support: false"); + } + if(!checkHasHDRFramebufferSupportWithFilter()) { logger.error("No HDR render target support was detected! Shaders will be disabled."); } DrawUtils.init(); @@ -620,4 +636,12 @@ public class EaglercraftGPU { public static int glGetTexLevelParameteri(int glTexture2d, int i, int glTextureWidth) { return PlatformOpenGL._wglGetTexLevelParameteri(glTexture2d, i, glTextureWidth); } + + public static final boolean checkHasHDRFramebufferSupportWithFilter() { + return hasFramebufferHDR16FSupport || (hasFramebufferHDR32FSupport && hasLinearHDR32FSupport); + } + + public static final boolean checkLinearHDR32FSupport() { + return hasLinearHDR32FSupport; + } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/HighPolyMesh.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/HighPolyMesh.java new file mode 100644 index 0000000..5cbc430 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/HighPolyMesh.java @@ -0,0 +1,66 @@ +package net.lax1dude.eaglercraft.v1_8.opengl; + +import net.lax1dude.eaglercraft.v1_8.internal.IBufferArrayGL; +import net.lax1dude.eaglercraft.v1_8.internal.IBufferGL; +import net.lax1dude.eaglercraft.v1_8.opengl.FixedFunctionShader.FixedFunctionState; + +/** + * 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 HighPolyMesh { + + IBufferArrayGL vertexArray; + IBufferGL vertexBuffer; + IBufferGL indexBuffer; + + int vertexCount; + int indexCount; + + boolean hasTexture; + + public HighPolyMesh(IBufferArrayGL vertexArray, IBufferGL vertexBuffer, IBufferGL indexBuffer, int vertexCount, + int indexCount, boolean hasTexture) { + this.vertexArray = vertexArray; + this.vertexBuffer = vertexBuffer; + this.indexBuffer = indexBuffer; + this.vertexCount = vertexCount; + this.indexCount = indexCount; + this.hasTexture = hasTexture; + } + + HighPolyMesh() { + + } + + public boolean isNull() { + return vertexArray == null; + } + + public int getVertexCount() { + return vertexCount; + } + + public int getIndexCount() { + return indexCount; + } + + public boolean getHasTexture() { + return hasTexture; + } + + public int getAttribBits() { + return hasTexture ? (FixedFunctionState.STATE_HAS_ATTRIB_TEXTURE | FixedFunctionState.STATE_HAS_ATTRIB_NORMAL) : FixedFunctionState.STATE_HAS_ATTRIB_NORMAL; + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java index a1c2254..f08117f 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/opengl/ext/deferred/EaglerDeferredPipeline.java @@ -3984,11 +3984,11 @@ public class EaglerDeferredPipeline { } public static final boolean isSupported() { - return EaglercraftGPU.checkHasHDRFramebufferSupport(); + return EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter(); } public static final String getReasonUnsupported() { - if(!EaglercraftGPU.checkHasHDRFramebufferSupport()) { + if(!EaglercraftGPU.checkHasHDRFramebufferSupportWithFilter()) { return I18n.format("shaders.gui.unsupported.reason.hdrFramebuffer"); }else { return null; 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 new file mode 100644 index 0000000..ae93e41 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CapePackets.java @@ -0,0 +1,83 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import java.io.IOException; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.minecraft.network.PacketBuffer; + +/** + * 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 CapePackets { + + public static final int PACKET_MY_CAPE_PRESET = 0x01; + public static final int PACKET_MY_CAPE_CUSTOM = 0x02; + public static final int PACKET_GET_OTHER_CAPE = 0x03; + public static final int PACKET_OTHER_CAPE_PRESET = 0x04; + public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05; + + public static void readPluginMessage(PacketBuffer buffer, ServerCapeCache capeCache) throws IOException { + try { + int type = (int)buffer.readByte() & 0xFF; + switch(type) { + case PACKET_OTHER_CAPE_PRESET: { + EaglercraftUUID responseUUID = buffer.readUuid(); + int responsePreset = buffer.readInt(); + if(buffer.isReadable()) { + throw new IOException("PACKET_OTHER_CAPE_PRESET had " + buffer.readableBytes() + " remaining bytes!"); + } + capeCache.cacheCapePreset(responseUUID, responsePreset); + break; + } + case PACKET_OTHER_CAPE_CUSTOM: { + EaglercraftUUID responseUUID = buffer.readUuid(); + byte[] readCape = new byte[1173]; + buffer.readBytes(readCape); + if(buffer.isReadable()) { + throw new IOException("PACKET_OTHER_CAPE_CUSTOM had " + buffer.readableBytes() + " remaining bytes!"); + } + capeCache.cacheCapeCustom(responseUUID, readCape); + break; + } + default: + throw new IOException("Unknown skin packet type: " + type); + } + }catch(IOException ex) { + throw ex; + }catch(Throwable t) { + throw new IOException("Failed to parse cape packet!", t); + } + } + + 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) }; + } + + public static byte[] writeMyCapeCustom(CustomCape customCape) { + byte[] packet = new byte[1 + customCape.texture.length]; + packet[0] = (byte) PACKET_MY_CAPE_CUSTOM; + System.arraycopy(customCape.texture, 0, packet, 1, customCape.texture.length); + return packet; + } + + public static PacketBuffer writeGetOtherCape(EaglercraftUUID playerId) throws IOException { + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17)); + ret.writeByte(PACKET_GET_OTHER_CAPE); + ret.writeUuid(playerId); + return ret; + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CustomCape.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CustomCape.java new file mode 100644 index 0000000..76b8cf0 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/CustomCape.java @@ -0,0 +1,58 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import net.minecraft.client.Minecraft; +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 class CustomCape { + + public final String name; + public final byte[] texture; + + private EaglerSkinTexture textureInstance; + private ResourceLocation resourceLocation; + + private static int texId = 0; + + public CustomCape(String name, byte[] texture) { + this.name = name; + this.texture = texture; + byte[] texture2 = new byte[4096]; + SkinConverter.convertCape23x17RGBto32x32RGBA(texture, texture2); + this.textureInstance = new EaglerSkinTexture(texture2, 32, 32); + this.resourceLocation = null; + } + + public void load() { + if(resourceLocation == null) { + resourceLocation = new ResourceLocation("eagler:capes/custom/tex_" + texId++); + Minecraft.getMinecraft().getTextureManager().loadTexture(resourceLocation, textureInstance); + } + } + + public ResourceLocation getResource() { + return resourceLocation; + } + + public void delete() { + if(resourceLocation != null) { + Minecraft.getMinecraft().getTextureManager().deleteTexture(resourceLocation); + resourceLocation = null; + } + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..2f53813 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultCapes.java @@ -0,0 +1,75 @@ +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]; + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultSkins.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultSkins.java index 5c67d07..8f88b24 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultSkins.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/DefaultSkins.java @@ -42,9 +42,14 @@ public enum DefaultSkins { CREEPER(20, "Creeper", new ResourceLocation("eagler:skins/21.creeper.png"), SkinModel.STEVE), ZOMBIE(21, "Zombie", new ResourceLocation("eagler:skins/22.zombie.png"), SkinModel.ZOMBIE), PIG(22, "Pig", new ResourceLocation("eagler:skins/23.pig.png"), SkinModel.STEVE), - MOOSHROOM(23, "Mooshroom", new ResourceLocation("eagler:skins/24.mooshroom.png"), SkinModel.STEVE); + MOOSHROOM(23, "Mooshroom", new ResourceLocation("eagler:skins/24.mooshroom.png"), SkinModel.STEVE), + LONG_ARMS(24, "Long Arms", new ResourceLocation("eagler:mesh/longarms.fallback.png"), SkinModel.LONG_ARMS), + WEIRD_CLIMBER_DUDE(25, "Weird Climber Dude", new ResourceLocation("eagler:mesh/weirdclimber.fallback.png"), SkinModel.WEIRD_CLIMBER_DUDE), + LAXATIVE_DUDE(26, "Laxative Dude", new ResourceLocation("eagler:mesh/laxativedude.fallback.png"), SkinModel.LAXATIVE_DUDE), + BABY_CHARLES(27, "Baby Charles", new ResourceLocation("eagler:mesh/charles.fallback.png"), SkinModel.BABY_CHARLES), + BABY_WINSTON(28, "Baby Winston", new ResourceLocation("eagler:mesh/winston.fallback.png"), SkinModel.BABY_WINSTON); - public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[24]; + public static final DefaultSkins[] defaultSkinsMap = new DefaultSkins[29]; public final int id; public final String name; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerProfile.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerProfile.java index 2a6e212..4e8c4f2 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerProfile.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/EaglerProfile.java @@ -16,7 +16,7 @@ import net.minecraft.nbt.NBTTagList; import net.minecraft.util.ResourceLocation; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * Copyright (c) 2022-2024 lax1dude, 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 @@ -37,7 +37,11 @@ public class EaglerProfile { public static int presetSkinId; public static int customSkinId; + public static int presetCapeId; + public static int customCapeId; + public static final List customSkins = new ArrayList(); + public static final List customCapes = new ArrayList(); public static final EaglercraftRandom rand; @@ -78,6 +82,25 @@ public class EaglerProfile { } } } + + public static ResourceLocation getActiveCapeResourceLocation() { + if(presetCapeId == -1) { + if(customCapeId >= 0 && customCapeId < customCapes.size()) { + return customCapes.get(customCapeId).getResource(); + }else { + customCapeId = -1; + presetCapeId = 0; + return DefaultCapes.defaultCapesMap[0].location; + } + }else { + if(presetCapeId >= 0 && presetCapeId < DefaultCapes.defaultCapesMap.length) { + return DefaultCapes.defaultCapesMap[presetCapeId].location; + }else { + presetCapeId = 0; + return DefaultCapes.defaultCapesMap[0].location; + } + } + } public static EaglercraftUUID getPlayerUUID() { return Minecraft.getMinecraft().getSession().getProfile().getId(); @@ -113,6 +136,25 @@ public class EaglerProfile { } } } + + public static byte[] getCapePacket() { + if(presetCapeId == -1) { + if(customCapeId >= 0 && customCapeId < customCapes.size()) { + return CapePackets.writeMyCapeCustom(customCapes.get(customCapeId)); + }else { + customCapeId = -1; + presetCapeId = 0; + return CapePackets.writeMyCapePreset(0); + } + }else { + if(presetCapeId >= 0 && presetCapeId < DefaultCapes.defaultCapesMap.length) { + return CapePackets.writeMyCapePreset(presetCapeId); + }else { + presetCapeId = 0; + return CapePackets.writeMyCapePreset(0); + } + } + } private static boolean doesSkinExist(String name) { for(int i = 0, l = customSkins.size(); i < l; ++i) { @@ -122,6 +164,15 @@ public class EaglerProfile { } return false; } + + private static boolean doesCapeExist(String name) { + for(int i = 0, l = customCapes.size(); i < l; ++i) { + if(customCapes.get(i).name.equalsIgnoreCase(name)) { + return true; + } + } + return false; + } public static int addCustomSkin(String fileName, byte[] rawSkin) { if(doesSkinExist(fileName)) { @@ -138,6 +189,22 @@ public class EaglerProfile { customSkins.add(newSkin); return r; } + + public static int addCustomCape(String fileName, byte[] rawCape23x17RGB) { + if(doesCapeExist(fileName)) { + String newName; + int i = 2; + while(doesCapeExist(newName = fileName + " (" + i + ")")) { + ++i; + } + fileName = newName; + } + CustomCape newCape = new CustomCape(fileName, rawCape23x17RGB); + newCape.load(); + int r = customCapes.size(); + customCapes.add(newCape); + return r; + } public static void clearCustomSkins() { for(int i = 0, l = customSkins.size(); i < l; ++i) { @@ -145,6 +212,13 @@ public class EaglerProfile { } customSkins.clear(); } + + public static void clearCustomCapes() { + for(int i = 0, l = customCapes.size(); i < l; ++i) { + customCapes.get(i).delete(); + } + customCapes.clear(); + } public static void read() { read(EagRuntime.getStorage("p")); @@ -168,6 +242,9 @@ public class EaglerProfile { presetSkinId = profile.getInteger("presetSkin"); customSkinId = profile.getInteger("customSkin"); + + if(profile.hasKey("presetCape", 99)) presetCapeId = profile.getInteger("presetCape"); + if(profile.hasKey("customCape", 99)) customCapeId = profile.getInteger("customCape"); String loadUsername = profile.getString("username").trim(); @@ -194,6 +271,20 @@ public class EaglerProfile { customSkins.add(newSkin); } + if(profile.hasKey("capes", 9)) { + clearCustomCapes(); + NBTTagList capesList = profile.getTagList("capes", 10); + for(int i = 0, l = capesList.tagCount(); i < l; ++i) { + NBTTagCompound cape = capesList.getCompoundTagAt(i); + String capeName = cape.getString("name"); + byte[] capeData = cape.getByteArray("data"); + if(capeData.length != 1173) continue; + CustomCape newCape = new CustomCape(capeName, capeData); + newCape.load(); + customCapes.add(newCape); + } + } + if(presetSkinId == -1) { if(customSkinId < 0 || customSkinId >= customSkins.size()) { presetSkinId = 0; @@ -205,6 +296,18 @@ public class EaglerProfile { presetSkinId = 0; } } + + if(presetCapeId == -1) { + if(customCapeId < 0 || customCapeId >= customCapes.size()) { + presetCapeId = 0; + customCapeId = -1; + } + }else { + customCapeId = -1; + if(presetCapeId < 0 || presetCapeId >= DefaultCapes.defaultCapesMap.length) { + presetCapeId = 0; + } + } } @@ -212,6 +315,8 @@ public class EaglerProfile { NBTTagCompound profile = new NBTTagCompound(); profile.setInteger("presetSkin", presetSkinId); profile.setInteger("customSkin", customSkinId); + profile.setInteger("presetCape", presetCapeId); + profile.setInteger("customCape", customCapeId); profile.setString("username", username); NBTTagList skinsList = new NBTTagList(); for(int i = 0, l = customSkins.size(); i < l; ++i) { @@ -223,6 +328,15 @@ public class EaglerProfile { skinsList.appendTag(skin); } profile.setTag("skins", skinsList); + NBTTagList capesList = new NBTTagList(); + for(int i = 0, l = customCapes.size(); i < l; ++i) { + CustomCape cp = customCapes.get(i); + NBTTagCompound cape = new NBTTagCompound(); + cape.setString("name", cp.name); + cape.setByteArray("data", cp.texture); + capesList.appendTag(cape); + } + profile.setTag("capes", capesList); EaglerOutputStream bao = new EaglerOutputStream(); try { CompressedStreamTools.writeCompressed(profile, bao); @@ -253,9 +367,14 @@ public class EaglerProfile { setName(username); - presetSkinId = rand.nextInt(DefaultSkins.defaultSkinsMap.length); + do { + presetSkinId = rand.nextInt(DefaultSkins.defaultSkinsMap.length); + }while(DefaultSkins.defaultSkinsMap[presetSkinId].model.highPoly != null); customSkinId = -1; + presetCapeId = 0; + customCapeId = -1; + } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditCape.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditCape.java new file mode 100644 index 0000000..f9a6837 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/GuiScreenEditCape.java @@ -0,0 +1,359 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.Keyboard; +import net.lax1dude.eaglercraft.v1_8.Mouse; +import net.lax1dude.eaglercraft.v1_8.internal.EnumCursorType; +import net.lax1dude.eaglercraft.v1_8.internal.FileChooserResult; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.ResourceLocation; + +import java.io.IOException; + +/** + * 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 GuiScreenEditCape extends GuiScreen { + + private final GuiScreenEditProfile parent; + + private boolean dropDownOpen = false; + private String[] dropDownOptions; + private int slotsVisible = 0; + protected int selectedSlot = 0; + private int scrollPos = -1; + private int skinsHeight = 0; + private boolean dragging = false; + private int mousex = 0; + private int mousey = 0; + + private static final ResourceLocation eaglerGui = new ResourceLocation("eagler:gui/eagler_gui.png"); + + protected String screenTitle = "Edit Cape"; + + public GuiScreenEditCape(GuiScreenEditProfile parent) { + this.parent = parent; + updateOptions(); + } + + public void initGui() { + Keyboard.enableRepeatEvents(true); + screenTitle = I18n.format("editCape.title"); + selectedSlot = EaglerProfile.presetCapeId == -1 ? EaglerProfile.customCapeId : (EaglerProfile.presetCapeId + EaglerProfile.customCapes.size()); + buttonList.add(new GuiButton(0, width / 2 - 100, height / 6 + 168, I18n.format("gui.done"))); + buttonList.add(new GuiButton(1, width / 2 - 21, height / 6 + 80, 71, 20, I18n.format("editCape.addCape"))); + buttonList.add(new GuiButton(2, width / 2 - 21 + 71, height / 6 + 80, 72, 20, I18n.format("editCape.clearCape"))); + } + + private void updateOptions() { + int numCustom = EaglerProfile.customCapes.size(); + String[] n = new String[numCustom + DefaultCapes.defaultCapesMap.length]; + for(int i = 0; i < numCustom; ++i) { + n[i] = EaglerProfile.customCapes.get(i).name; + } + int numDefault = DefaultCapes.defaultCapesMap.length; + for(int j = 0; j < numDefault; ++j) { + n[numCustom + j] = DefaultCapes.defaultCapesMap[j].name; + } + dropDownOptions = n; + } + + public void drawScreen(int mx, int my, float partialTicks) { + drawDefaultBackground(); + drawCenteredString(fontRendererObj, screenTitle, width / 2, 15, 16777215); + drawString(fontRendererObj, I18n.format("editCape.playerCape"), width / 2 - 20, height / 6 + 36, 10526880); + + mousex = mx; + mousey = my; + + int skinX = width / 2 - 120; + int skinY = height / 6 + 8; + int skinWidth = 80; + int skinHeight = 130; + + drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xFFA0A0A0); + drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, 0xFF000015); + + int skid = selectedSlot - EaglerProfile.customCapes.size(); + if(skid < 0) { + skid = 0; + } + + if(dropDownOpen) { + super.drawScreen(0, 0, partialTicks); + }else { + super.drawScreen(mx, my, partialTicks); + } + + int numberOfCustomSkins = EaglerProfile.customSkins.size(); + int numberOfCustomCapes = EaglerProfile.customCapes.size(); + ResourceLocation skinTexture; + SkinModel model; + if(parent.selectedSlot < numberOfCustomSkins) { + CustomSkin customSkin = EaglerProfile.customSkins.get(parent.selectedSlot); + skinTexture = customSkin.getResource(); + model = customSkin.model; + }else { + DefaultSkins defaultSkin = DefaultSkins.getSkinFromId(parent.selectedSlot - numberOfCustomSkins); + skinTexture = defaultSkin.location; + model = defaultSkin.model; + } + + if(model.highPoly != null) { + drawCenteredString(fontRendererObj, I18n.format(this.mc.gameSettings.enableFNAWSkins ? "editProfile.disableFNAW" : "editProfile.enableFNAW"), width / 2, height / 6 + 150, 10526880); + } + + skinX = width / 2 - 20; + skinY = height / 6 + 52; + skinWidth = 140; + skinHeight = 22; + + drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336); + drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 21, skinY + skinHeight - 1, -16777216); + drawRect(skinX + skinWidth - 20, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216); + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + + mc.getTextureManager().bindTexture(eaglerGui); + drawTexturedModalRect(skinX + skinWidth - 18, skinY + 3, 0, 0, 16, 16); + + drawString(fontRendererObj, dropDownOptions[selectedSlot], skinX + 5, skinY + 7, 14737632); + + skinX = width / 2 - 20; + skinY = height / 6 + 73; + skinWidth = 140; + skinHeight = (height - skinY - 10); + slotsVisible = (skinHeight / 10); + if(slotsVisible > dropDownOptions.length) slotsVisible = dropDownOptions.length; + skinHeight = slotsVisible * 10 + 7; + skinsHeight = skinHeight; + if(scrollPos == -1) { + scrollPos = selectedSlot - 2; + } + if(scrollPos > (dropDownOptions.length - slotsVisible)) { + scrollPos = (dropDownOptions.length - slotsVisible); + } + if(scrollPos < 0) { + scrollPos = 0; + } + if(dropDownOpen) { + drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, -6250336); + drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, -16777216); + for(int i = 0; i < slotsVisible; i++) { + if(i + scrollPos < dropDownOptions.length) { + if(selectedSlot == i + scrollPos) { + drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x77ffffff); + }else if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i*10 + 5) && my < (skinY + i*10 + 15)) { + drawRect(skinX + 1, skinY + i*10 + 4, skinX + skinWidth - 1, skinY + i*10 + 14, 0x55ffffff); + } + drawString(fontRendererObj, dropDownOptions[i + scrollPos], skinX + 5, skinY + 5 + i*10, 14737632); + } + } + int scrollerSize = skinHeight * slotsVisible / dropDownOptions.length; + int scrollerPos = skinHeight * scrollPos / dropDownOptions.length; + drawRect(skinX + skinWidth - 4, skinY + scrollerPos + 1, skinX + skinWidth - 1, skinY + scrollerPos + scrollerSize, 0xff888888); + } + + if(!EagRuntime.getConfiguration().isDemo()) { + GlStateManager.pushMatrix(); + GlStateManager.scale(0.75f, 0.75f, 0.75f); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + String text = I18n.format("editProfile.importExport"); + + int w = mc.fontRendererObj.getStringWidth(text); + boolean hover = mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12; + if(hover) { + Mouse.showCursor(EnumCursorType.HAND); + } + + drawString(mc.fontRendererObj, EnumChatFormatting.UNDERLINE + text, 5, 5, hover ? 0xFFEEEE22 : 0xFFCCCCCC); + + GlStateManager.popMatrix(); + } + + int xx = width / 2 - 80; + int yy = height / 6 + 130; + + skinX = this.width / 2 - 120; + skinY = this.height / 6 + 8; + skinWidth = 80; + skinHeight = 130; + + ResourceLocation capeTexture; + if(selectedSlot < numberOfCustomCapes) { + capeTexture = EaglerProfile.customCapes.get(selectedSlot).getResource(); + }else { + capeTexture = DefaultCapes.getCapeFromId(selectedSlot - numberOfCustomCapes).location; + } + + SkinPreviewRenderer.renderPreview(xx, yy, mx, my, true, model, skinTexture, capeTexture); + } + + public void handleMouseInput() throws IOException { + super.handleMouseInput(); + if(dropDownOpen) { + int var1 = Mouse.getEventDWheel(); + if(var1 < 0) { + scrollPos += 3; + } + if(var1 > 0) { + scrollPos -= 3; + if(scrollPos < 0) { + scrollPos = 0; + } + } + } + } + + protected void actionPerformed(GuiButton par1GuiButton) { + if(!dropDownOpen) { + if(par1GuiButton.id == 0) { + safeProfile(); + this.mc.displayGuiScreen((GuiScreen) parent); + }else if(par1GuiButton.id == 1) { + EagRuntime.displayFileChooser("image/png", "png"); + }else if(par1GuiButton.id == 2) { + EaglerProfile.clearCustomCapes(); + safeProfile(); + updateOptions(); + selectedSlot = 0; + } + } + } + + public void updateScreen() { + if(EagRuntime.fileChooserHasResult()) { + FileChooserResult result = EagRuntime.getFileChooserResult(); + if(result != null) { + ImageData loadedCape = ImageData.loadImageFile(result.fileData); + if(loadedCape != null) { + if((loadedCape.width == 32 || loadedCape.width == 64) && loadedCape.height == 32) { + byte[] resized = new byte[1173]; + SkinConverter.convertCape32x32RGBAto23x17RGB(loadedCape, resized); + int k; + if((k = EaglerProfile.addCustomCape(result.fileName, resized)) != -1) { + selectedSlot = k; + updateOptions(); + safeProfile(); + } + }else { + EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 32x32 or 64x32 capes"); + } + }else { + EagRuntime.showPopup("The selected file '" + result.fileName + "' is not a PNG file!"); + } + } + } + if(dropDownOpen) { + if(Mouse.isButtonDown(0)) { + int skinX = width / 2 - 20; + int skinY = height / 6 + 73; + int skinWidth = 140; + if(mousex >= (skinX + skinWidth - 10) && mousex < (skinX + skinWidth) && mousey >= skinY && mousey < (skinY + skinsHeight)) { + dragging = true; + } + if(dragging) { + int scrollerSize = skinsHeight * slotsVisible / dropDownOptions.length; + scrollPos = (mousey - skinY - (scrollerSize / 2)) * dropDownOptions.length / skinsHeight; + } + }else { + dragging = false; + } + }else { + dragging = false; + } + } + + public void onGuiClosed() { + Keyboard.enableRepeatEvents(false); + } + + protected void keyTyped(char c, int k) { + if(k == 200 && selectedSlot > 0) { + --selectedSlot; + scrollPos = selectedSlot - 2; + } + if(k == 208 && selectedSlot < (dropDownOptions.length - 1)) { + ++selectedSlot; + scrollPos = selectedSlot - 2; + } + } + + protected void mouseClicked(int mx, int my, int button) { + if (button == 0) { + if(!EagRuntime.getConfiguration().isDemo()) { + int w = mc.fontRendererObj.getStringWidth(I18n.format("editProfile.importExport")); + if(mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12) { + safeProfile(); + mc.displayGuiScreen(new GuiScreenImportExportProfile(parent)); + mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + return; + } + } + + int skinX = width / 2 + 140 - 40; + int skinY = height / 6 + 52; + + if(mx >= skinX && mx < (skinX + 20) && my >= skinY && my < (skinY + 22)) { + dropDownOpen = !dropDownOpen; + return; + } + + skinX = width / 2 - 20; + skinY = height / 6 + 52; + int skinWidth = 140; + int skinHeight = skinsHeight; + + if(!(mx >= skinX && mx < (skinX + skinWidth) && my >= skinY && my < (skinY + skinHeight + 22))) { + dragging = false; + if(dropDownOpen) { + dropDownOpen = false; + return; + } + }else if(dropDownOpen && !dragging) { + skinY += 21; + for(int i = 0; i < slotsVisible; i++) { + if(i + scrollPos < dropDownOptions.length) { + if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15) && selectedSlot != i + scrollPos) { + selectedSlot = i + scrollPos; + dropDownOpen = false; + dragging = false; + return; + } + } + } + } + } + super.mouseClicked(mx, my, button); + } + + protected void safeProfile() { + int customLen = EaglerProfile.customCapes.size(); + if(selectedSlot < customLen) { + EaglerProfile.presetCapeId = -1; + EaglerProfile.customCapeId = selectedSlot; + }else { + EaglerProfile.presetCapeId = selectedSlot - customLen; + EaglerProfile.customCapeId = -1; + } + } + +} \ 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 ac9f393..947e701 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 @@ -20,7 +20,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import java.io.IOException; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * Copyright (c) 2022-2024 lax1dude, 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 @@ -42,7 +42,7 @@ public class GuiScreenEditProfile extends GuiScreen { private boolean dropDownOpen = false; private String[] dropDownOptions; private int slotsVisible = 0; - private int selectedSlot = 0; + protected int selectedSlot = 0; private int scrollPos = -1; private int skinsHeight = 0; private boolean dragging = false; @@ -102,11 +102,25 @@ public class GuiScreenEditProfile extends GuiScreen { drawRect(skinX, skinY, skinX + skinWidth, skinY + skinHeight, 0xFFA0A0A0); drawRect(skinX + 1, skinY + 1, skinX + skinWidth - 1, skinY + skinHeight - 1, 0xFF000015); - int skid = selectedSlot - EaglerProfile.customSkins.size(); - if(skid < 0) { - skid = 0; + GlStateManager.pushMatrix(); + GlStateManager.translate(skinX + 2, skinY - 9, 0.0f); + GlStateManager.scale(0.75f, 0.75f, 0.75f); + + int numberOfCustomSkins = EaglerProfile.customSkins.size(); + int skid = selectedSlot - numberOfCustomSkins; + SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model; + if(selectedSkinModel == SkinModel.STEVE || selectedSkinModel == SkinModel.ALEX || (selectedSkinModel.highPoly != null && !this.mc.gameSettings.enableFNAWSkins)) { + String capesText = I18n.format("editProfile.capes"); + int color = 10526880; + if(mx > skinX - 10 && my > skinY - 16 && mx < skinX + (fontRendererObj.getStringWidth(capesText) * 0.75f) + 10 && my < skinY + 7) { + color = 0xFFCCCC44; + Mouse.showCursor(EnumCursorType.HAND); + } + this.drawString(this.fontRendererObj, EnumChatFormatting.UNDERLINE + capesText, 0, 0, color); } + GlStateManager.popMatrix(); + usernameField.drawTextBox(); if(dropDownOpen || newSkinWaitSteveOrAlex) { super.drawScreen(0, 0, partialTicks); @@ -114,6 +128,10 @@ public class GuiScreenEditProfile extends GuiScreen { super.drawScreen(mx, my, partialTicks); } + if(selectedSkinModel.highPoly != null) { + drawCenteredString(fontRendererObj, I18n.format(this.mc.gameSettings.enableFNAWSkins ? "editProfile.disableFNAW" : "editProfile.enableFNAW"), width / 2, height / 6 + 150, 10526880); + } + skinX = width / 2 - 20; skinY = height / 6 + 82; skinWidth = 140; @@ -184,7 +202,6 @@ public class GuiScreenEditProfile extends GuiScreen { int xx = width / 2 - 80; int yy = height / 6 + 130; - int numberOfCustomSkins = EaglerProfile.customSkins.size(); if(newSkinWaitSteveOrAlex && selectedSlot < numberOfCustomSkins) { skinWidth = 70; @@ -217,8 +234,8 @@ public class GuiScreenEditProfile extends GuiScreen { drawCenteredString(fontRendererObj, "Steve", skinX + skinWidth / 2, skinY + skinHeight + 6, cc); } - mc.getTextureManager().bindTexture(newSkin.getResource()); - SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.STEVE); + SkinPreviewRenderer.renderPreview(xx, yy, mx, my, false, SkinModel.STEVE, newSkin.getResource(), + EaglerProfile.getActiveCapeResourceLocation()); skinX = width / 2 + 20; skinY = height / 4; @@ -242,8 +259,8 @@ public class GuiScreenEditProfile extends GuiScreen { drawCenteredString(fontRendererObj, "Alex", skinX + skinWidth / 2, skinY + skinHeight + 8, cc); } - mc.getTextureManager().bindTexture(newSkin.getResource()); - SkinPreviewRenderer.renderBiped(xx, yy, mx, my, SkinModel.ALEX); + SkinPreviewRenderer.renderPreview(xx, yy, mx, my, false, SkinModel.ALEX, newSkin.getResource(), + EaglerProfile.getActiveCapeResourceLocation()); }else { skinX = this.width / 2 - 120; skinY = this.height / 6 + 8; @@ -251,19 +268,15 @@ public class GuiScreenEditProfile extends GuiScreen { skinHeight = 130; ResourceLocation texture; - SkinModel model; - if(selectedSlot < numberOfCustomSkins) { - CustomSkin customSkin = EaglerProfile.customSkins.get(selectedSlot); - texture = customSkin.getResource(); - model = customSkin.model; + if(skid < 0) { + texture = EaglerProfile.customSkins.get(selectedSlot).getResource(); }else { - DefaultSkins defaultSkin = DefaultSkins.defaultSkinsMap[selectedSlot - numberOfCustomSkins]; - texture = defaultSkin.location; - model = defaultSkin.model; + texture = DefaultSkins.getSkinFromId(skid).location; } - mc.getTextureManager().bindTexture(texture); - SkinPreviewRenderer.renderBiped(xx, yy, newSkinWaitSteveOrAlex ? width / 2 : mx, newSkinWaitSteveOrAlex ? height / 2 : my, model); + SkinPreviewRenderer.renderPreview(xx, yy, newSkinWaitSteveOrAlex ? width / 2 : mx, + newSkinWaitSteveOrAlex ? height / 2 : my, false, selectedSkinModel, texture, + EaglerProfile.getActiveCapeResourceLocation()); } } @@ -293,6 +306,7 @@ public class GuiScreenEditProfile extends GuiScreen { }else if(par1GuiButton.id == 2) { EaglerProfile.clearCustomSkins(); safeProfile(); + EaglerProfile.save(); updateOptions(); selectedSlot = 0; } @@ -335,6 +349,7 @@ public class GuiScreenEditProfile extends GuiScreen { newSkinWaitSteveOrAlex = true; updateOptions(); safeProfile(); + EaglerProfile.save(); } }else { EagRuntime.showPopup("The selected image '" + result.fileName + "' is not the right size!\nEaglercraft only supports 64x32 or 64x64 skins"); @@ -387,21 +402,37 @@ public class GuiScreenEditProfile extends GuiScreen { } protected void mouseClicked(int mx, int my, int button) { - super.mouseClicked(mx, my, button); usernameField.mouseClicked(mx, my, button); if (button == 0) { if(!EagRuntime.getConfiguration().isDemo()) { int w = mc.fontRendererObj.getStringWidth(I18n.format("editProfile.importExport")); if(mx > 1 && my > 1 && mx < (w * 3 / 4) + 7 && my < 12) { + safeProfile(); + EaglerProfile.save(); mc.displayGuiScreen(new GuiScreenImportExportProfile(this)); mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); return; } } + int skinX, skinY; + int skid = selectedSlot - EaglerProfile.customSkins.size(); + SkinModel selectedSkinModel = skid < 0 ? EaglerProfile.customSkins.get(selectedSlot).model : DefaultSkins.getSkinFromId(skid).model; + if(selectedSkinModel == SkinModel.STEVE || selectedSkinModel == SkinModel.ALEX || (selectedSkinModel.highPoly != null && !this.mc.gameSettings.enableFNAWSkins)) { + skinX = this.width / 2 - 120; + skinY = this.height / 6 + 8; + String capesText = I18n.format("editProfile.capes"); + if(mx > skinX - 10 && my > skinY - 16 && mx < skinX + (fontRendererObj.getStringWidth(capesText) * 0.75f) + 10 && my < skinY + 7) { + safeProfile(); + this.mc.displayGuiScreen(new GuiScreenEditCape(this)); + mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + return; + } + } + if(newSkinWaitSteveOrAlex) { - int skinX = width / 2 - 90; - int skinY = height / 4; + skinX = width / 2 - 90; + skinY = height / 4; int skinWidth = 70; int skinHeight = 120; if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) { @@ -423,8 +454,8 @@ public class GuiScreenEditProfile extends GuiScreen { } return; }else if(selectedSlot < EaglerProfile.customSkins.size()) { - int skinX = width / 2 - 120; - int skinY = height / 6 + 18; + skinX = width / 2 - 120; + skinY = height / 6 + 18; int skinWidth = 80; int skinHeight = 120; if(mx >= skinX && my >= skinY && mx < skinX + skinWidth && my < skinY + skinHeight) { @@ -434,8 +465,8 @@ public class GuiScreenEditProfile extends GuiScreen { } } } - int skinX = width / 2 + 140 - 40; - int skinY = height / 6 + 82; + skinX = width / 2 + 140 - 40; + skinY = height / 6 + 82; if(mx >= skinX && mx < (skinX + 20) && my >= skinY && my < (skinY + 22)) { dropDownOpen = !dropDownOpen; @@ -448,27 +479,26 @@ public class GuiScreenEditProfile extends GuiScreen { int skinHeight = skinsHeight; if(!(mx >= skinX && mx < (skinX + skinWidth) && my >= skinY && my < (skinY + skinHeight + 22))) { - dropDownOpen = false; dragging = false; - return; - } - - skinY += 21; - - if(dropDownOpen && !dragging) { + if(dropDownOpen) { + dropDownOpen = false; + return; + } + }else if(dropDownOpen && !dragging) { + skinY += 21; for(int i = 0; i < slotsVisible; i++) { if(i + scrollPos < dropDownOptions.length) { - if(selectedSlot != i + scrollPos) { - if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15) && selectedSlot != i + scrollPos) { - selectedSlot = i + scrollPos; - dropDownOpen = false; - dragging = false; - } + if(mx >= skinX && mx < (skinX + skinWidth - 10) && my >= (skinY + i * 10 + 5) && my < (skinY + i * 10 + 15)) { + selectedSlot = i + scrollPos; + dropDownOpen = false; + dragging = false; + return; } } } } } + super.mouseClicked(mx, my, button); } protected void safeProfile() { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/HighPolySkin.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/HighPolySkin.java new file mode 100644 index 0000000..c7f6427 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/HighPolySkin.java @@ -0,0 +1,113 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import net.minecraft.util.ResourceLocation; + +/** + * 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 enum HighPolySkin { + + LONG_ARMS( + new ResourceLocation("eagler:mesh/longarms.png"), + new ResourceLocation("eagler:mesh/longarms0.mdl"), + null, + new ResourceLocation("eagler:mesh/longarms2.mdl"), + new ResourceLocation[] { + new ResourceLocation("eagler:mesh/longarms1.mdl") + }, + new float[] { + 1.325f + }, + 0.0f, + new ResourceLocation("eagler:mesh/longarms.fallback.png") + ), + + WEIRD_CLIMBER_DUDE( + new ResourceLocation("eagler:mesh/weirdclimber.png"), + new ResourceLocation("eagler:mesh/weirdclimber0.mdl"), + null, + new ResourceLocation("eagler:mesh/weirdclimber2.mdl"), + new ResourceLocation[] { + new ResourceLocation("eagler:mesh/weirdclimber1.mdl") + }, + new float[] { + 2.62f + }, + -90.0f, + new ResourceLocation("eagler:mesh/weirdclimber.fallback.png") + ), + + LAXATIVE_DUDE( + new ResourceLocation("eagler:mesh/laxativedude.png"), + new ResourceLocation("eagler:mesh/laxativedude0.mdl"), + null, + new ResourceLocation("eagler:mesh/laxativedude3.mdl"), + new ResourceLocation[] { + new ResourceLocation("eagler:mesh/laxativedude1.mdl"), + new ResourceLocation("eagler:mesh/laxativedude2.mdl") + }, + new float[] { + 2.04f + }, + 0.0f, + new ResourceLocation("eagler:mesh/laxativedude.fallback.png") + ), + + BABY_CHARLES( + new ResourceLocation("eagler:mesh/charles.png"), + new ResourceLocation("eagler:mesh/charles0.mdl"), + new ResourceLocation("eagler:mesh/charles1.mdl"), + new ResourceLocation("eagler:mesh/charles2.mdl"), + new ResourceLocation[] {}, + new float[] {}, + 0.0f, + new ResourceLocation("eagler:mesh/charles.fallback.png") + ), + + BABY_WINSTON( + new ResourceLocation("eagler:mesh/winston.png"), + new ResourceLocation("eagler:mesh/winston0.mdl"), + null, + new ResourceLocation("eagler:mesh/winston1.mdl"), + new ResourceLocation[] {}, + new float[] {}, + 0.0f, + new ResourceLocation("eagler:mesh/winston.fallback.png") + ); + + public static float highPolyScale = 0.5f; + + public final ResourceLocation texture; + public final ResourceLocation bodyModel; + public final ResourceLocation headModel; + public final ResourceLocation eyesModel; + public final ResourceLocation[] limbsModel; + public final float[] limbsOffset; + public final float limbsInitialRotation; + public final ResourceLocation fallbackTexture; + + HighPolySkin(ResourceLocation texture, ResourceLocation bodyModel, ResourceLocation headModel, ResourceLocation eyesModel, + ResourceLocation[] limbsModel, float[] limbsOffset, float limbsInitialRotation, ResourceLocation fallbackTexture) { + this.texture = texture; + this.bodyModel = bodyModel; + this.headModel = headModel; + this.eyesModel = eyesModel; + this.limbsModel = limbsModel; + this.limbsOffset = limbsOffset; + this.limbsInitialRotation = limbsInitialRotation; + this.fallbackTexture = fallbackTexture; + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java new file mode 100644 index 0000000..377c008 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/RenderHighPoly.java @@ -0,0 +1,471 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; +import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.AbstractClientPlayer; +import net.minecraft.client.model.ModelBase; +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.client.renderer.entity.RenderPlayer; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MathHelper; + +/** + * 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 RenderHighPoly extends RenderPlayer { + + private static final Logger logger = LogManager.getLogger("RenderHighPoly"); + + public RenderHighPoly(RenderManager renderManager, ModelBase fallbackModel, float fallbackScale) { + super(renderManager, fallbackModel, fallbackScale); + } + + private static final Matrix4f tmpMatrix = new Matrix4f(); + + public void doRender(AbstractClientPlayer abstractclientplayer, double d0, double d1, double d2, float f, + float f1) { + if (!abstractclientplayer.isUser() || this.renderManager.livingPlayer == abstractclientplayer) { + double nameY = d1; + HighPolySkin highPolySkin = abstractclientplayer.getEaglerSkinModel().highPoly; + + if(highPolySkin == null) { + super.doRender(abstractclientplayer, d0, d1, d2, f, f1); + return; + }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + nameY += 0.1; + }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + nameY -= 1.0; + } + + GlStateManager.pushMatrix(); + GlStateManager.disableCull(); + + try { + Minecraft mc = Minecraft.getMinecraft(); + float f2 = this.interpolateRotation(abstractclientplayer.prevRenderYawOffset, abstractclientplayer.renderYawOffset, + f1); + float f3 = this.interpolateRotation(abstractclientplayer.prevRotationYawHead, abstractclientplayer.rotationYawHead, + f1); + float f4 = f3 - f2; + if (abstractclientplayer.isRiding() && abstractclientplayer.ridingEntity instanceof EntityLivingBase) { + EntityLivingBase entitylivingbase1 = (EntityLivingBase) abstractclientplayer.ridingEntity; + f2 = this.interpolateRotation(entitylivingbase1.prevRenderYawOffset, entitylivingbase1.renderYawOffset, + f1); + f4 = f3 - f2; + float f5 = MathHelper.wrapAngleTo180_float(f4); + if (f5 < -85.0F) { + f5 = -85.0F; + } + + if (f5 >= 85.0F) { + f5 = 85.0F; + } + + f2 = f3 - f5; + if (f5 * f5 > 2500.0F) { + f2 += f5 * 0.2F; + } + } + + this.renderLivingAt(abstractclientplayer, d0, d1, d2); + float f10 = this.handleRotationFloat(abstractclientplayer, f1); + this.rotateCorpse(abstractclientplayer, f10, f2, f1); + GlStateManager.enableRescaleNormal(); + this.preRenderCallback(abstractclientplayer, f1); + float f6 = 0.0625F; + GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale); + mc.getTextureManager().bindTexture(highPolySkin.texture); + + if(abstractclientplayer.isPlayerSleeping()) { + if(highPolySkin == HighPolySkin.LAXATIVE_DUDE || highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + GlStateManager.translate(0.0f, -3.7f, 0.0f); + }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + GlStateManager.translate(0.0f, -2.4f, 0.0f); + }else { + GlStateManager.translate(0.0f, -3.0f, 0.0f); + } + } + + float var15 = abstractclientplayer.prevLimbSwingAmount + (abstractclientplayer.limbSwingAmount - abstractclientplayer.prevLimbSwingAmount) * f1; + float var16 = abstractclientplayer.limbSwing - abstractclientplayer.limbSwingAmount * (1.0F - f1); + + if(highPolySkin == HighPolySkin.LONG_ARMS) { + GlStateManager.rotate(MathHelper.sin(var16) * 20f * var15, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(MathHelper.cos(var16) * 7f * var15, 0.0f, 0.0f, 1.0f); + }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + GlStateManager.rotate(MathHelper.sin(var16) * 7f * var15, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(MathHelper.cos(var16) * 3f * var15, 0.0f, 0.0f, 1.0f); + GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f); + float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX); + GlStateManager.rotate(xd * 70.0f * var15, 0.0f, 0.0f, 1.0f); + float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ); + GlStateManager.rotate(zd * 70.0f * var15, 1.0f, 0.0f, 0.0f); + GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f); + }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + GlStateManager.rotate(-f3, 0.0f, 1.0f, 0.0f); + float xd = (float)(abstractclientplayer.posX - abstractclientplayer.prevPosX); + GlStateManager.rotate(-xd * 40.0f * var15, 0.0f, 0.0f, 1.0f); + float zd = (float)(abstractclientplayer.posZ - abstractclientplayer.prevPosZ); + GlStateManager.rotate(-zd * 40.0f * var15, 1.0f, 0.0f, 0.0f); + GlStateManager.rotate(f3, 0.0f, 1.0f, 0.0f); + }else if(highPolySkin == HighPolySkin.BABY_WINSTON) { + GlStateManager.translate(0.0f, (MathHelper.cos(f10 % 100000.0f) + 1.0f) * var15 * 0.2f, 0.0f); + GlStateManager.rotate(MathHelper.sin(var16) * 5f * var15, 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(MathHelper.cos(var16) * 5f * var15, 0.0f, 0.0f, 1.0f); + } + + if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) { + GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F); + } + + if(DeferredStateManager.isInDeferredPass()) { + DeferredStateManager.setDefaultMaterialConstants(); + DeferredStateManager.setRoughnessConstant(0.5f); + DeferredStateManager.setMetalnessConstant(0.05f); + } + + if(highPolySkin.bodyModel != null) { + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.bodyModel)); + } + float jumpFactor = 0.0f; + + if(highPolySkin.headModel != null) { + if(highPolySkin == HighPolySkin.BABY_CHARLES) { + long millis = System.currentTimeMillis(); + float partialTicks = (float) ((millis - abstractclientplayer.eaglerHighPolyAnimationTick) * 0.02); + //long l50 = millis / 50l * 50l; + //boolean runTick = par1EntityPlayer.eaglerHighPolyAnimationTick < l50 && millis >= l50; + abstractclientplayer.eaglerHighPolyAnimationTick = millis; + + if(partialTicks < 0.0f) { + partialTicks = 0.0f; + } + if(partialTicks > 1.0f) { + partialTicks = 1.0f; + } + + float jumpFac = (float)(abstractclientplayer.posY - abstractclientplayer.prevPosY); + if(jumpFac < 0.0f && !abstractclientplayer.isCollidedVertically) { + jumpFac = -jumpFac; + jumpFac *= 0.1f; + } + jumpFac -= 0.05f; + if(jumpFac > 0.1f && !abstractclientplayer.isCollidedVertically) { + jumpFac = 0.1f; + }else if(jumpFac < 0.0f) { + jumpFac = 0.0f; + }else if(jumpFac > 0.1f && abstractclientplayer.isCollidedVertically) { + jumpFac = 0.1f; + }else if(jumpFac > 0.4f) { + jumpFac = 0.4f; + } + jumpFac *= 10.0f; + + abstractclientplayer.eaglerHighPolyAnimationFloat3 += (jumpFac / (jumpFac + 1.0f)) * 6.0f * partialTicks; + + if(Float.isInfinite(abstractclientplayer.eaglerHighPolyAnimationFloat3)) { + abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f; + }else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 > 1.0f) { + abstractclientplayer.eaglerHighPolyAnimationFloat3 = 1.0f; + }else if(abstractclientplayer.eaglerHighPolyAnimationFloat3 < -1.0f) { + abstractclientplayer.eaglerHighPolyAnimationFloat3 = -1.0f; + } + + abstractclientplayer.eaglerHighPolyAnimationFloat2 += abstractclientplayer.eaglerHighPolyAnimationFloat3 * partialTicks; + + abstractclientplayer.eaglerHighPolyAnimationFloat5 += partialTicks; + while(abstractclientplayer.eaglerHighPolyAnimationFloat5 > 0.05f) { + abstractclientplayer.eaglerHighPolyAnimationFloat5 -= 0.05f; + abstractclientplayer.eaglerHighPolyAnimationFloat3 *= 0.99f; + abstractclientplayer.eaglerHighPolyAnimationFloat2 *= 0.9f; + } + + jumpFactor = abstractclientplayer.eaglerHighPolyAnimationFloat2; //(abstractclientplayer.eaglerHighPolyAnimationFloat1 - abstractclientplayer.eaglerHighPolyAnimationFloat2) * partialTicks + abstractclientplayer.eaglerHighPolyAnimationFloat2; + jumpFactor -= 0.12f; + if(jumpFactor < 0.0f) { + jumpFactor = 0.0f; + } + jumpFactor = jumpFactor / (jumpFactor + 2.0f); + if(jumpFactor > 1.0f) { + jumpFactor = 1.0f; + } + } + if(jumpFactor > 0.0f) { + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f); + } + + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.headModel)); + + if(jumpFactor > 0.0f) { + GlStateManager.popMatrix(); + } + } + + if(highPolySkin.limbsModel != null && highPolySkin.limbsModel.length > 0) { + for(int i = 0; i < highPolySkin.limbsModel.length; ++i) { + DeferredStateManager.setRoughnessConstant(0.023f); + DeferredStateManager.setMetalnessConstant(0.902f); + float offset = 0.0f; + if(highPolySkin.limbsOffset != null) { + if(highPolySkin.limbsOffset.length == 1) { + offset = highPolySkin.limbsOffset[0]; + }else { + offset = highPolySkin.limbsOffset[i]; + } + } + + GlStateManager.pushMatrix(); + + if(offset != 0.0f || highPolySkin.limbsInitialRotation != 0.0f) { + if(offset != 0.0f) { + GlStateManager.translate(0.0f, offset, 0.0f); + } + if(highPolySkin.limbsInitialRotation != 0.0f) { + GlStateManager.rotate(highPolySkin.limbsInitialRotation, 1.0f, 0.0f, 0.0f); + } + } + + if(highPolySkin == HighPolySkin.LONG_ARMS) { + if(abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + var17 *= var17; + GlStateManager.rotate(-var17 * 20.0f, 1.0f, 0.0f, 0.0f); + } + }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + if(abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + var17 *= var17; + GlStateManager.rotate(var17 * 60.0f, 1.0f, 0.0f, 0.0f); + } + GlStateManager.rotate(40.0f * var15, 1.0f, 0.0f, 0.0f); + }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + float fff = (i == 0) ? 1.0f : -1.0f; + float swing = (MathHelper.cos(f10 % 100000.0f) * fff + 0.2f) * var15; + float swing2 = (MathHelper.cos(f10 % 100000.0f) * fff * 0.5f + 0.0f) * var15; + GlStateManager.rotate(swing * 25.0f, 1.0f, 0.0f, 0.0f); + if(abstractclientplayer.isSwingInProgress) { + float var17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + var17 *= var17; + GlStateManager.rotate(-var17 * 25.0f, 1.0f, 0.0f, 0.0f); + } + + // shear matrix + tmpMatrix.setIdentity(); + tmpMatrix.m21 = swing2; + tmpMatrix.m23 = swing2 * -0.2f; + GlStateManager.multMatrix(tmpMatrix); + } + + if(i != 0) { + mc.getTextureManager().bindTexture(highPolySkin.texture); + if (abstractclientplayer.hurtTime > 0 || abstractclientplayer.deathTime > 0) { + GlStateManager.color(1.2f, 0.8F, 0.8F, 1.0F); + }else { + GlStateManager.color(1.0f, 1.0F, 1.0F, 1.0F); + } + } + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.limbsModel[i])); + + if(i == 0) { + GlStateManager.pushMatrix(); + + GlStateManager.translate(-0.287f, 0.05f, 0.0f); + + if(highPolySkin == HighPolySkin.LONG_ARMS) { + GlStateManager.translate(1.72f, 2.05f, -0.24f); + ItemStack stk = abstractclientplayer.getHeldItem(); + if(stk != null) { + Item itm = stk.getItem(); + if(itm != null) { + if(itm == Items.bow) { + GlStateManager.translate(-0.22f, 0.8f, 0.6f); + GlStateManager.rotate(-90.0f, 1.0f, 0.0f, 0.0f); + }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + GlStateManager.translate(0.0f, -0.1f, 0.13f); + }else if(!itm.isFull3D()) { + GlStateManager.translate(-0.08f, -0.1f, 0.16f); + } + } + } + }else if(highPolySkin == HighPolySkin.WEIRD_CLIMBER_DUDE) { + GlStateManager.translate(-0.029f, 1.2f, -3f); + GlStateManager.rotate(-5.0f, 0.0f, 1.0f, 0.0f); + float var17 = -1.2f * var15; + if(abstractclientplayer.isSwingInProgress) { + float vvar17 = MathHelper.cos(-abstractclientplayer.getSwingProgress(f1) * (float)Math.PI * 2.0f - 1.2f) - 0.362f; + var17 = vvar17 < var17 ? vvar17 : var17; + } + GlStateManager.translate(-0.02f * var17, 0.42f * var17, var17 * 0.35f); + GlStateManager.rotate(var17 * 30.0f, 1.0f, 0.0f, 0.0f); + GlStateManager.rotate(110.0f, 1.0f, 0.0f, 0.0f); + ItemStack stk = abstractclientplayer.getHeldItem(); + if(stk != null) { + Item itm = stk.getItem(); + if(itm != null) { + if(itm == Items.bow) { + GlStateManager.translate(-0.18f, 1.0f, 0.4f); + GlStateManager.rotate(-95.0f, 1.0f, 0.0f, 0.0f); + }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + GlStateManager.translate(0.0f, -0.1f, 0.13f); + }else if(!itm.isFull3D()) { + GlStateManager.translate(-0.08f, -0.1f, 0.16f); + } + } + } + }else if(highPolySkin == HighPolySkin.LAXATIVE_DUDE) { + GlStateManager.translate(1.291f, 2.44f, -2.18f); + GlStateManager.rotate(95.0f, 1.0f, 0.0f, 0.0f); + ItemStack stk = abstractclientplayer.getHeldItem(); + if(stk != null) { + Item itm = stk.getItem(); + if(itm != null) { + if(itm == Items.bow) { + GlStateManager.translate(-0.65f, 1.3f, -0.1f); + GlStateManager.rotate(180.0f, 0.0f, 0.0f, 1.0f); + GlStateManager.rotate(20.0f, 1.0f, 0.0f, 0.0f); + }else if(itm instanceof ItemBlock && !((ItemBlock)itm).getBlock().isNormalCube()) { + GlStateManager.translate(0.0f, -0.35f, 0.4f); + }else if(!itm.isFull3D()) { + GlStateManager.translate(-0.1f, -0.1f, 0.16f); + } + } + } + } + + DeferredStateManager.setDefaultMaterialConstants(); + renderHeldItem(abstractclientplayer, f1); + GlStateManager.popMatrix(); + } + + GlStateManager.popMatrix(); + } + } + + if(highPolySkin.eyesModel != null && !DeferredStateManager.isEnableShadowRender()) { + float ff = 0.00416f; + int brightness = abstractclientplayer.getBrightnessForRender(0.0f); + float blockLight = (brightness % 65536) * ff; + float skyLight = (brightness / 65536) * ff; + float sunCurve = (float)((abstractclientplayer.worldObj.getWorldTime() + 4000l) % 24000) / 24000.0f; + sunCurve = MathHelper.clamp_float(9.8f - MathHelper.abs(sunCurve * 5.0f + sunCurve * sunCurve * 45.0f - 14.3f) * 0.7f, 0.0f, 1.0f); + skyLight = skyLight * (sunCurve * 0.85f + 0.15f); + blockLight = blockLight * (sunCurve * 0.3f + 0.7f); + float eyeBrightness = blockLight; + if(skyLight > eyeBrightness) { + eyeBrightness = skyLight; + } + eyeBrightness += blockLight * 0.2f; + eyeBrightness = 1.0f - eyeBrightness; + eyeBrightness = MathHelper.clamp_float(eyeBrightness * 1.9f - 1.0f, 0.0f, 1.0f); + if(eyeBrightness > 0.1f) { + if(DeferredStateManager.isInDeferredPass()) { + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + DeferredStateManager.setDefaultMaterialConstants(); + DeferredStateManager.setEmissionConstant(eyeBrightness); + }else { + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_ONE, GL_ONE); + GlStateManager.color(eyeBrightness * 7.0f, eyeBrightness * 7.0f, eyeBrightness * 7.0f, 1.0f); + if(jumpFactor > 0.0f) { + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0f, jumpFactor * 3.0f, 0.0f); + } + } + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + GlStateManager.enableCull(); + + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(highPolySkin.eyesModel)); + + GlStateManager.enableTexture2D(); + GlStateManager.enableLighting(); + GlStateManager.disableCull(); + if(jumpFactor > 0.0f) { + GlStateManager.popMatrix(); + } + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + if(!DeferredStateManager.isInDeferredPass()) { + GlStateManager.disableBlend(); + } + } + } + }catch(Throwable t) { + logger.error("Couldn\'t render entity"); + logger.error(t); + } + GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); + GlStateManager.enableTexture2D(); + GlStateManager.setActiveTexture(OpenGlHelper.defaultTexUnit); + GlStateManager.enableCull(); + GlStateManager.popMatrix(); + if (!this.renderOutlines) { + this.renderName(abstractclientplayer, d0, nameY, d2); + } + } + } + + public void renderRightArm(AbstractClientPlayer clientPlayer) { + + } + + public void renderLeftArm(AbstractClientPlayer clientPlayer) { + + } + + protected void renderHeldItem(AbstractClientPlayer clientPlayer, float partialTicks) { + ItemStack itemstack = clientPlayer.getHeldItem(); + if (itemstack != null) { + GlStateManager.pushMatrix(); + GlStateManager.translate(-0.11F, 0.475F, 0.25F); + if (clientPlayer.fishEntity != null) { + itemstack = new ItemStack(Items.fishing_rod, 0); + } + + Item item = itemstack.getItem(); + Minecraft minecraft = Minecraft.getMinecraft(); + if (item instanceof ItemBlock && Block.getBlockFromItem(item).getRenderType() == 2) { + GlStateManager.translate(0.0F, 0.1875F, -0.3125F); + GlStateManager.rotate(20.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(45.0F, 0.0F, 1.0F, 0.0F); + float f1 = 0.375F; + GlStateManager.scale(-f1, -f1, f1); + } + + if (clientPlayer.isSneaking()) { + GlStateManager.translate(0.0F, 0.203125F, 0.0F); + } + + minecraft.getItemRenderer().renderItem(clientPlayer, itemstack, + ItemCameraTransforms.TransformType.THIRD_PERSON); + GlStateManager.popMatrix(); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerCapeCache.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerCapeCache.java new file mode 100644 index 0000000..7a7810d --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerCapeCache.java @@ -0,0 +1,242 @@ +package net.lax1dude.eaglercraft.v1_8.profile; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager; +import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.client.C17PacketCustomPayload; +import net.minecraft.util.ResourceLocation; + +/** + * 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 ServerCapeCache { + + private static final Logger logger = LogManager.getLogger("ServerCapeCache"); + + public class CapeCacheEntry { + + protected final boolean isPresetCape; + protected final int presetCapeId; + protected final CacheCustomCape customCape; + + protected long lastCacheHit = System.currentTimeMillis(); + + protected CapeCacheEntry(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation) { + this.isPresetCape = false; + this.presetCapeId = -1; + this.customCape = new CacheCustomCape(textureInstance, resourceLocation); + ServerCapeCache.this.textureManager.loadTexture(resourceLocation, textureInstance); + } + + /** + * Use only for the constant for the client player + */ + protected CapeCacheEntry(ResourceLocation resourceLocation) { + this.isPresetCape = false; + this.presetCapeId = -1; + this.customCape = new CacheCustomCape(null, resourceLocation); + } + + protected CapeCacheEntry(int presetSkinId) { + this.isPresetCape = true; + this.presetCapeId = presetSkinId; + this.customCape = null; + } + + public ResourceLocation getResourceLocation() { + if(isPresetCape) { + return DefaultCapes.getCapeFromId(presetCapeId).location; + }else { + if(customCape != null) { + return customCape.resourceLocation; + }else { + return null; + } + } + } + + protected void free() { + if(!isPresetCape && customCape.resourceLocation != null) { + ServerCapeCache.this.textureManager.deleteTexture(customCape.resourceLocation); + } + } + + } + + protected static class CacheCustomCape { + + protected final EaglerSkinTexture textureInstance; + protected final ResourceLocation resourceLocation; + + protected CacheCustomCape(EaglerSkinTexture textureInstance, ResourceLocation resourceLocation) { + this.textureInstance = textureInstance; + this.resourceLocation = resourceLocation; + } + + } + + private final CapeCacheEntry defaultCacheEntry = new CapeCacheEntry(0); + private final Map capesCache = new HashMap(); + private final Map waitingCapes = new HashMap(); + private final Map evictedCapes = new HashMap(); + + private final EaglercraftNetworkManager networkManager; + protected final TextureManager textureManager; + + private final EaglercraftUUID clientPlayerId; + private final CapeCacheEntry clientPlayerCacheEntry; + + private long lastFlush = System.currentTimeMillis(); + private long lastFlushReq = System.currentTimeMillis(); + private long lastFlushEvict = System.currentTimeMillis(); + + private static int texId = 0; + + public ServerCapeCache(EaglercraftNetworkManager networkManager, TextureManager textureManager) { + this.networkManager = networkManager; + this.textureManager = textureManager; + this.clientPlayerId = EaglerProfile.getPlayerUUID(); + this.clientPlayerCacheEntry = new CapeCacheEntry(EaglerProfile.getActiveCapeResourceLocation()); + } + + public CapeCacheEntry getClientPlayerCape() { + return clientPlayerCacheEntry; + } + + public CapeCacheEntry getCape(EaglercraftUUID player) { + if(player.equals(clientPlayerId)) { + return clientPlayerCacheEntry; + } + CapeCacheEntry etr = capesCache.get(player); + if(etr == null) { + if(!waitingCapes.containsKey(player) && !evictedCapes.containsKey(player)) { + waitingCapes.put(player, System.currentTimeMillis()); + PacketBuffer buffer; + try { + buffer = CapePackets.writeGetOtherCape(player); + }catch(IOException ex) { + logger.error("Could not write cape request packet!"); + logger.error(ex); + return defaultCacheEntry; + } + networkManager.sendPacket(new C17PacketCustomPayload("EAG|Capes-1.8", buffer)); + } + return defaultCacheEntry; + }else { + etr.lastCacheHit = System.currentTimeMillis(); + return etr; + } + } + + public void cacheCapePreset(EaglercraftUUID player, int presetId) { + if(waitingCapes.remove(player) != null) { + CapeCacheEntry etr = capesCache.remove(player); + if(etr != null) { + etr.free(); + } + capesCache.put(player, new CapeCacheEntry(presetId)); + }else { + logger.error("Unsolicited cape response recieved for \"{}\"! (preset {})", player, presetId); + } + } + + public void cacheCapeCustom(EaglercraftUUID player, byte[] pixels) { + if(waitingCapes.remove(player) != null) { + CapeCacheEntry etr = capesCache.remove(player); + if(etr != null) { + etr.free(); + } + byte[] pixels32x32 = new byte[4096]; + SkinConverter.convertCape23x17RGBto32x32RGBA(pixels, pixels32x32); + try { + etr = new CapeCacheEntry(new EaglerSkinTexture(pixels32x32, 32, 32), + new ResourceLocation("eagler:capes/multiplayer/tex_" + texId++)); + }catch(Throwable t) { + etr = new CapeCacheEntry(0); + logger.error("Could not process custom skin packet for \"{}\"!", player); + logger.error(t); + } + capesCache.put(player, etr); + }else { + logger.error("Unsolicited skin response recieved for \"{}\"!", player); + } + } + + public void flush() { + long millis = System.currentTimeMillis(); + if(millis - lastFlushReq > 5000l) { + lastFlushReq = millis; + if(!waitingCapes.isEmpty()) { + Iterator waitingItr = waitingCapes.values().iterator(); + while(waitingItr.hasNext()) { + if(millis - waitingItr.next().longValue() > 30000l) { + waitingItr.remove(); + } + } + } + } + if(millis - lastFlushEvict > 1000l) { + lastFlushEvict = millis; + if(!evictedCapes.isEmpty()) { + Iterator evictItr = evictedCapes.values().iterator(); + while(evictItr.hasNext()) { + if(millis - evictItr.next().longValue() > 3000l) { + evictItr.remove(); + } + } + } + } + if(millis - lastFlush > 60000l) { + lastFlush = millis; + if(!capesCache.isEmpty()) { + Iterator entryItr = capesCache.values().iterator(); + while(entryItr.hasNext()) { + CapeCacheEntry etr = entryItr.next(); + if(millis - etr.lastCacheHit > 900000l) { // 15 minutes + entryItr.remove(); + etr.free(); + } + } + } + } + } + + public void destroy() { + Iterator entryItr = capesCache.values().iterator(); + while(entryItr.hasNext()) { + entryItr.next().free(); + } + capesCache.clear(); + waitingCapes.clear(); + evictedCapes.clear(); + } + + public void evictCape(EaglercraftUUID uuid) { + evictedCapes.put(uuid, Long.valueOf(System.currentTimeMillis())); + CapeCacheEntry etr = capesCache.remove(uuid); + if(etr != null) { + etr.free(); + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerSkinCache.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerSkinCache.java index f2f6abd..5a88c28 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerSkinCache.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/ServerSkinCache.java @@ -321,6 +321,7 @@ public class ServerSkinCache { } skinsCache.clear(); waitingSkins.clear(); + evictedSkins.clear(); } public void evictSkin(EaglercraftUUID uuid) { 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 a91a05c..5242f8b 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 @@ -3,7 +3,7 @@ package net.lax1dude.eaglercraft.v1_8.profile; import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * Copyright (c) 2022-2024 lax1dude, 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 @@ -34,6 +34,56 @@ public class SkinConverter { copyRawPixels(skinIn.pixels, skinOut.pixels, 44, 52, 40, 64, 40, 20, 44, 32, 64, 64); copyRawPixels(skinIn.pixels, skinOut.pixels, 48, 52, 44, 64, 52, 20, 56, 32, 64, 64); } + + public static void convertCape32x32RGBAto23x17RGB(ImageData skinIn, byte[] skinOut) { + int i, j; + for(int y = 0; y < 17; ++y) { + 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 { + skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0; + } + } + } + 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 { + skinOut[i] = skinOut[i + 1] = skinOut[i + 2] = 0; + } + } + } + + public static void convertCape23x17RGBto32x32RGBA(byte[] skinIn, byte[] skinOut) { + int i, j; + for(int y = 0; y < 17; ++y) { + for(int x = 0; x < 22; ++x) { + i = (y * 32 + x) << 2; + j = (y * 23 + x) * 3; + skinOut[i] = (byte)0xFF; + skinOut[i + 1] = skinIn[j]; + skinOut[i + 2] = skinIn[j + 1]; + skinOut[i + 3] = skinIn[j + 2]; + } + } + for(int y = 0; y < 11; ++y) { + i = ((y + 11) * 32 + 22) << 2; + j = ((y + 6) * 23 + 22) * 3; + skinOut[i] = (byte)0xFF; + skinOut[i + 1] = skinIn[j]; + skinOut[i + 2] = skinIn[j + 1]; + skinOut[i + 3] = skinIn[j + 2]; + } + } private static void copyRawPixels(int[] imageIn, int[] imageOut, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, int imgSrcWidth, int imgDstWidth) { diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java index 7956881..8dbb655 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinModel.java @@ -19,15 +19,19 @@ import java.util.Map; * */ public enum SkinModel { - STEVE(0, 64, 64, "default", false), ALEX(1, 64, 64, "slim", false), ZOMBIE(2, 64, 64, "zombie", true); + STEVE(0, 64, 64, "default", false), ALEX(1, 64, 64, "slim", false), ZOMBIE(2, 64, 64, "zombie", true), + LONG_ARMS(3, HighPolySkin.LONG_ARMS), WEIRD_CLIMBER_DUDE(4, HighPolySkin.WEIRD_CLIMBER_DUDE), + LAXATIVE_DUDE(5, HighPolySkin.LAXATIVE_DUDE), BABY_CHARLES(6, HighPolySkin.BABY_CHARLES), + BABY_WINSTON(7, HighPolySkin.BABY_WINSTON); public final int id; public final int width; public final int height; public final String profileSkinType; public final boolean sanitize; + public final HighPolySkin highPoly; - public static final SkinModel[] skinModels = new SkinModel[3]; + public static final SkinModel[] skinModels = new SkinModel[8]; private static final Map skinModelsByName = new HashMap(); private SkinModel(int id, int w, int h, String profileSkinType, boolean sanitize) { @@ -36,6 +40,16 @@ public enum SkinModel { this.height = h; this.profileSkinType = profileSkinType; this.sanitize = sanitize; + this.highPoly = null; + } + + private SkinModel(int id, HighPolySkin highPoly) { + this.id = id; + this.width = 256; + this.height = 128; + this.profileSkinType = "eagler"; + this.sanitize = true; + this.highPoly = highPoly; } public static SkinModel getModelFromId(String str) { 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 93dc6b6..510bd89 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 @@ -58,6 +58,9 @@ public class SkinPackets { modelId = SkinModel.STEVE; } } + if(modelId.highPoly != null) { + modelId = SkinModel.STEVE; + } int bytesToRead = modelId.width * modelId.height * 4; byte[] readSkin = new byte[bytesToRead]; buffer.readBytes(readSkin); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPreviewRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPreviewRenderer.java index 1608c04..d7dcd47 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPreviewRenderer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/profile/SkinPreviewRenderer.java @@ -1,10 +1,14 @@ package net.lax1dude.eaglercraft.v1_8.profile; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.model.ModelPlayer; import net.minecraft.client.model.ModelZombie; import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.util.ResourceLocation; /** * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. @@ -36,7 +40,11 @@ public class SkinPreviewRenderer { playerModelZombie.isChild = false; } - public static void renderBiped(int x, int y, int mx, int my, SkinModel skinModel) { + public static void renderPreview(int x, int y, int mx, int my, SkinModel skinModel) { + renderPreview(x, y, mx, my, false, skinModel, null, null); + } + + public static void renderPreview(int x, int y, int mx, int my, boolean capeMode, SkinModel skinModel, ResourceLocation skinTexture, ResourceLocation capeTexture) { ModelBiped model; switch(skinModel) { case STEVE: @@ -49,6 +57,17 @@ public class SkinPreviewRenderer { case ZOMBIE: model = playerModelZombie; break; + case LONG_ARMS: + case WEIRD_CLIMBER_DUDE: + case LAXATIVE_DUDE: + case BABY_CHARLES: + case BABY_WINSTON: + if(skinModel.highPoly != null && Minecraft.getMinecraft().gameSettings.enableFNAWSkins) { + renderHighPoly(x, y, mx, my, skinModel.highPoly); + return; + } + model = playerModelSteve; + break; } GlStateManager.enableTexture2D(); @@ -65,12 +84,95 @@ public class SkinPreviewRenderer { RenderHelper.enableGUIStandardItemLighting(); GlStateManager.translate(0.0f, 1.0f, 0.0f); - GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f); + if(capeMode) { + GlStateManager.rotate(140.0f, 0.0f, 1.0f, 0.0f); + mx = x - (x - mx) - 20; + GlStateManager.rotate(((y - my) * -0.02f), 1.0f, 0.0f, 0.0f); + }else { + GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f); + } GlStateManager.rotate(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f); GlStateManager.translate(0.0f, -1.0f, 0.0f); + if(skinTexture != null) { + Minecraft.getMinecraft().getTextureManager().bindTexture(skinTexture); + } + model.render(null, 0.0f, 0.0f, (float)(System.currentTimeMillis() % 2000000) / 50f, ((x - mx) * 0.06f), ((y - my) * -0.1f), 0.0625f); + if(capeTexture != null && model instanceof ModelPlayer) { + Minecraft.getMinecraft().getTextureManager().bindTexture(capeTexture); + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0F, 0.0F, 0.125F); + GlStateManager.rotate(6.0F, 1.0F, 0.0F, 0.0F); + GlStateManager.rotate(180.0F, 0.0F, 1.0F, 0.0F); + ((ModelPlayer)model).renderCape(0.0625f); + GlStateManager.popMatrix(); + } + + GlStateManager.popMatrix(); + GlStateManager.disableLighting(); + } + + private static void renderHighPoly(int x, int y, int mx, int my, HighPolySkin msh) { + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.disableCull(); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + + GlStateManager.pushMatrix(); + GlStateManager.translate(x, y - 80.0f, 100.0f); + GlStateManager.scale(50.0f, 50.0f, 50.0f); + GlStateManager.rotate(180.0f, 1.0f, 0.0f, 0.0f); + GlStateManager.scale(1.0f, -1.0f, 1.0f); + + RenderHelper.enableGUIStandardItemLighting(); + + GlStateManager.translate(0.0f, 1.0f, 0.0f); + GlStateManager.rotate(((y - my) * -0.06f), 1.0f, 0.0f, 0.0f); + GlStateManager.rotate(((x - mx) * 0.06f), 0.0f, 1.0f, 0.0f); + GlStateManager.rotate(180.0f, 0.0f, 0.0f, 1.0f); + GlStateManager.translate(0.0f, -0.6f, 0.0f); + + GlStateManager.scale(HighPolySkin.highPolyScale, HighPolySkin.highPolyScale, HighPolySkin.highPolyScale); + Minecraft.getMinecraft().getTextureManager().bindTexture(msh.texture); + + if(msh.bodyModel != null) { + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.bodyModel)); + } + + if(msh.headModel != null) { + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.headModel)); + } + + if(msh.limbsModel != null && msh.limbsModel.length > 0) { + for(int i = 0; i < msh.limbsModel.length; ++i) { + float offset = 0.0f; + if(msh.limbsOffset != null) { + if(msh.limbsOffset.length == 1) { + offset = msh.limbsOffset[0]; + }else { + offset = msh.limbsOffset[i]; + } + } + if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) { + GlStateManager.pushMatrix(); + if(offset != 0.0f) { + GlStateManager.translate(0.0f, offset, 0.0f); + } + if(msh.limbsInitialRotation != 0.0f) { + GlStateManager.rotate(msh.limbsInitialRotation, 1.0f, 0.0f, 0.0f); + } + } + + EaglercraftGPU.drawHighPoly(EaglerMeshLoader.getEaglerMesh(msh.limbsModel[i])); + + if(offset != 0.0f || msh.limbsInitialRotation != 0.0f) { + GlStateManager.popMatrix(); + } + } + } + GlStateManager.popMatrix(); GlStateManager.disableLighting(); } 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 b51965b..318118d 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 @@ -293,6 +293,19 @@ public class ConnectionHandshake { d.write(packetSkin); PlatformNetworking.writePlayPacket(bao.toByteArray()); + bao.reset(); + d.writeByte(HandshakePacketTypes.PROTOCOL_CLIENT_PROFILE_DATA); + profileDataType = "cape_v1"; + d.writeByte(profileDataType.length()); + d.writeBytes(profileDataType); + byte[] packetCape = EaglerProfile.getCapePacket(); + if(packetCape.length > 0xFFFF) { + throw new IOException("Cape packet is too long: " + packetCape.length); + } + d.writeShort(packetCape.length); + d.write(packetCape); + PlatformNetworking.writePlayPacket(bao.toByteArray()); + byte[] packetSignatureData = UpdateService.getClientSignatureData(); if(packetSignatureData != null) { bao.reset(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenAddRelay.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenAddRelay.java index 7fa49f4..e66104a 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenAddRelay.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenAddRelay.java @@ -139,5 +139,9 @@ public class GuiScreenAddRelay extends GuiScreen { this.serverAddress.drawTextBox(); super.drawScreen(par1, par2, par3); } + + public boolean blockPTTKey() { + return this.serverName.isFocused() || this.serverAddress.isFocused(); + } } \ No newline at end of file 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 38b6ecb..6445e8d 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 @@ -117,7 +117,7 @@ public class GuiScreenLANConnecting extends GuiScreen { this.mc.clearTitles(); networkManager.setConnectionState(EnumConnectionState.LOGIN); networkManager.setNetHandler(new NetHandlerSingleplayerLogin(networkManager, mc, parent)); - networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket())); + networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket(), EaglerProfile.getCapePacket())); } } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenSingleplayerConnecting.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenSingleplayerConnecting.java index ff7d193..fb38a61 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenSingleplayerConnecting.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiScreenSingleplayerConnecting.java @@ -88,7 +88,7 @@ public class GuiScreenSingleplayerConnecting extends GuiScreen { this.mc.clearTitles(); this.networkManager.setConnectionState(EnumConnectionState.LOGIN); this.networkManager.setNetHandler(new NetHandlerSingleplayerLogin(this.networkManager, this.mc, this.menu)); - this.networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket())); + this.networkManager.sendPacket(new C00PacketLoginStart(this.mc.getSession().getProfile(), EaglerProfile.getSkinPacket(), EaglerProfile.getCapePacket())); } try { this.networkManager.processReceivedPackets(); diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java index 7ab3dc3..8b40fa2 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/gui/GuiShareToLan.java @@ -195,4 +195,8 @@ public class GuiShareToLan extends GuiScreen { super.updateScreen(); this.codeTextField.updateCursorCounter(); } + + public boolean blockPTTKey() { + return this.codeTextField.isFocused(); + } } \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java index f695ebe..c5d87ee 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerIntegratedServerWorker.java @@ -361,6 +361,9 @@ public class EaglerIntegratedServerWorker { case IPCPacket17ConfigureLAN.ID: { IPCPacket17ConfigureLAN pkt = (IPCPacket17ConfigureLAN)ipc; + if(!pkt.iceServers.isEmpty() && ServerPlatformSingleplayer.getClientConfigAdapter().isAllowVoiceClient()) { + currentProcess.enableVoice(pkt.iceServers.toArray(new String[pkt.iceServers.size()])); + } currentProcess.getConfigurationManager().configureLAN(pkt.gamemode, pkt.cheats); // don't use iceServers break; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java index 85a6969..656c7e5 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerMinecraftServer.java @@ -16,7 +16,9 @@ import net.minecraft.world.EnumDifficulty; import net.minecraft.world.WorldServer; import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldSettings.GameType; +import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedCapeService; import net.lax1dude.eaglercraft.v1_8.sp.server.skins.IntegratedSkinService; +import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService; /** * Copyright (c) 2023-2024 lax1dude, ayunami2000. All Rights Reserved. @@ -45,6 +47,8 @@ public class EaglerMinecraftServer extends MinecraftServer { protected boolean paused; protected EaglerSaveHandler saveHandler; protected IntegratedSkinService skinService; + protected IntegratedCapeService capeService; + protected IntegratedVoiceService voiceService; private long lastTPSUpdate = 0l; @@ -62,6 +66,8 @@ public class EaglerMinecraftServer extends MinecraftServer { Bootstrap.register(); this.saveHandler = new EaglerSaveHandler(savesDir, world); this.skinService = new IntegratedSkinService(new VFile2(saveHandler.getWorldDirectory(), "eagler/skulls")); + this.capeService = new IntegratedCapeService(); + this.voiceService = null; this.setServerOwner(owner); logger.info("server owner: " + owner); this.setDemo(demo); @@ -75,6 +81,27 @@ public class EaglerMinecraftServer extends MinecraftServer { public IntegratedSkinService getSkinService() { return skinService; } + + public IntegratedCapeService getCapeService() { + return capeService; + } + + public IntegratedVoiceService getVoiceService() { + return voiceService; + } + + public void enableVoice(String[] iceServers) { + if(iceServers != null) { + if(voiceService != null) { + voiceService.changeICEServers(iceServers); + }else { + voiceService = new IntegratedVoiceService(iceServers); + for(EntityPlayerMP player : getConfigurationManager().func_181057_v()) { + voiceService.handlePlayerLoggedIn(player); + } + } + } + } public void setBaseServerProperties(EnumDifficulty difficulty, GameType gamemode) { this.difficulty = difficulty; diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerPlayerList.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerPlayerList.java index 32e2b88..525110b 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerPlayerList.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/EaglerPlayerList.java @@ -43,6 +43,8 @@ public class EaglerPlayerList extends ServerConfigurationManager { public void playerLoggedOut(EntityPlayerMP playerIn) { super.playerLoggedOut(playerIn); - ((EaglerMinecraftServer)getServerInstance()).skinService.unregisterPlayer(playerIn.getUniqueID()); + EaglerMinecraftServer svr = (EaglerMinecraftServer)getServerInstance(); + svr.skinService.unregisterPlayer(playerIn.getUniqueID()); + svr.capeService.unregisterPlayer(playerIn.getUniqueID()); } } 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 new file mode 100644 index 0000000..90088cd --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapePackets.java @@ -0,0 +1,110 @@ +package net.lax1dude.eaglercraft.v1_8.sp.server.skins; + +import java.io.IOException; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.minecraft.entity.player.EntityPlayerMP; + +/** + * 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 IntegratedCapePackets { + + public static final int PACKET_MY_CAPE_PRESET = 0x01; + public static final int PACKET_MY_CAPE_CUSTOM = 0x02; + public static final int PACKET_GET_OTHER_CAPE = 0x03; + public static final int PACKET_OTHER_CAPE_PRESET = 0x04; + public static final int PACKET_OTHER_CAPE_CUSTOM = 0x05; + + public static void processPacket(byte[] data, EntityPlayerMP sender, IntegratedCapeService capeService) throws IOException { + if(data.length == 0) { + throw new IOException("Zero-length packet recieved"); + } + int packetId = (int)data[0] & 0xFF; + try { + switch(packetId) { + case PACKET_GET_OTHER_CAPE: + processGetOtherCape(data, sender, capeService); + break; + default: + throw new IOException("Unknown packet type " + packetId); + } + }catch(IOException ex) { + throw ex; + }catch(Throwable t) { + throw new IOException("Unhandled exception handling packet type " + packetId, t); + } + } + + private static void processGetOtherCape(byte[] data, EntityPlayerMP sender, IntegratedCapeService capeService) throws IOException { + if(data.length != 17) { + throw new IOException("Invalid length " + data.length + " for skin request packet"); + } + EaglercraftUUID searchUUID = IntegratedSkinPackets.bytesToUUID(data, 1); + capeService.processGetOtherCape(searchUUID, sender); + } + + public static void registerEaglerPlayer(EaglercraftUUID clientUUID, byte[] bs, IntegratedCapeService capeService) throws IOException { + if(bs.length == 0) { + throw new IOException("Zero-length packet recieved"); + } + byte[] generatedPacket; + int packetType = (int)bs[0] & 0xFF; + switch(packetType) { + case PACKET_MY_CAPE_PRESET: + if(bs.length != 5) { + throw new IOException("Invalid length " + bs.length + " for preset cape packet"); + } + generatedPacket = IntegratedCapePackets.makePresetResponse(clientUUID, (bs[1] << 24) | (bs[2] << 16) | (bs[3] << 8) | (bs[4] & 0xFF)); + break; + case PACKET_MY_CAPE_CUSTOM: + if(bs.length != 1174) { + throw new IOException("Invalid length " + bs.length + " for custom cape packet"); + } + generatedPacket = IntegratedCapePackets.makeCustomResponse(clientUUID, bs, 1, 1173); + break; + default: + throw new IOException("Unknown skin packet type: " + packetType); + } + capeService.registerEaglercraftPlayer(clientUUID, generatedPacket); + } + + public static void registerEaglerPlayerFallback(EaglercraftUUID clientUUID, IntegratedCapeService capeService) { + capeService.registerEaglercraftPlayer(clientUUID, IntegratedCapePackets.makePresetResponse(clientUUID, 0)); + } + + public static byte[] makePresetResponse(EaglercraftUUID uuid, int presetId) { + 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[20] = (byte)(presetId & 0xFF); + return ret; + } + + public static byte[] makeCustomResponse(EaglercraftUUID uuid, byte[] pixels) { + return makeCustomResponse(uuid, pixels, 0, pixels.length); + } + + public static byte[] makeCustomResponse(EaglercraftUUID uuid, byte[] pixels, int offset, int length) { + byte[] ret = new byte[1 + 16 + length]; + ret[0] = (byte)PACKET_OTHER_CAPE_CUSTOM; + IntegratedSkinPackets.UUIDToBytes(uuid, ret, 1); + System.arraycopy(pixels, offset, ret, 17, length); + return ret; + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapeService.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapeService.java new file mode 100644 index 0000000..21c7da3 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/skins/IntegratedCapeService.java @@ -0,0 +1,77 @@ +package net.lax1dude.eaglercraft.v1_8.sp.server.skins; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S3FPacketCustomPayload; + +/** + * 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 IntegratedCapeService { + + public static final Logger logger = LogManager.getLogger("IntegratedCapeService"); + + public static final int masterRateLimitPerPlayer = 250; + + public static final String CHANNEL = "EAG|Capes-1.8"; + + private final Map capesCache = new HashMap(); + + public void processPacket(byte[] packetData, EntityPlayerMP sender) { + try { + IntegratedCapePackets.processPacket(packetData, sender, this); + } catch (IOException e) { + logger.error("Invalid skin request packet recieved from player {}!", sender.getName()); + logger.error(e); + sender.playerNetServerHandler.kickPlayerFromServer("Invalid skin request packet recieved!"); + } + } + + public void processLoginPacket(byte[] packetData, EntityPlayerMP sender) { + try { + IntegratedCapePackets.registerEaglerPlayer(sender.getUniqueID(), packetData, this); + } catch (IOException e) { + logger.error("Invalid skin data packet recieved from player {}!", sender.getName()); + logger.error(e); + sender.playerNetServerHandler.kickPlayerFromServer("Invalid skin data packet recieved!"); + } + } + + public void registerEaglercraftPlayer(EaglercraftUUID playerUUID, byte[] capePacket) { + capesCache.put(playerUUID, capePacket); + } + + public void processGetOtherCape(EaglercraftUUID searchUUID, EntityPlayerMP sender) { + byte[] maybeCape = capesCache.get(searchUUID); + if(maybeCape == null) { + maybeCape = IntegratedCapePackets.makePresetResponse(searchUUID, 0); + } + sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer(Unpooled.buffer(maybeCape, maybeCape.length).writerIndex(maybeCape.length)))); + } + + public void unregisterPlayer(EaglercraftUUID playerUUID) { + synchronized(capesCache) { + capesCache.remove(playerUUID); + } + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceService.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceService.java new file mode 100644 index 0000000..7b9c682 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceService.java @@ -0,0 +1,255 @@ +package net.lax1dude.eaglercraft.v1_8.sp.server.voice; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.lax1dude.eaglercraft.v1_8.voice.ExpiringSet; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.server.S3FPacketCustomPayload; + +/** + * 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 IntegratedVoiceService { + + public static final Logger logger = LogManager.getLogger("IntegratedVoiceService"); + + public static final String CHANNEL = "EAG|Voice-1.8"; + + private byte[] iceServersPacket; + + private final Map voicePlayers = new HashMap<>(); + private final Map> voiceRequests = new HashMap<>(); + private final Set voicePairs = new HashSet<>(); + + public IntegratedVoiceService(String[] iceServers) { + iceServersPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketAllowed(true, iceServers); + } + + public void changeICEServers(String[] iceServers) { + iceServersPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketAllowed(true, iceServers); + } + + private static class VoicePair { + + private final EaglercraftUUID uuid1; + private final EaglercraftUUID uuid2; + + @Override + public int hashCode() { + return uuid1.hashCode() ^ uuid2.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VoicePair other = (VoicePair) obj; + return (uuid1.equals(other.uuid1) && uuid2.equals(other.uuid2)) + || (uuid1.equals(other.uuid2) && uuid2.equals(other.uuid1)); + } + + private VoicePair(EaglercraftUUID uuid1, EaglercraftUUID uuid2) { + this.uuid1 = uuid1; + this.uuid2 = uuid2; + } + + private boolean anyEquals(EaglercraftUUID uuid) { + return uuid1.equals(uuid) || uuid2.equals(uuid); + } + } + + public void handlePlayerLoggedIn(EntityPlayerMP player) { + player.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer( + Unpooled.buffer(iceServersPacket, iceServersPacket.length).writerIndex(iceServersPacket.length)))); + } + + public void handlePlayerLoggedOut(EntityPlayerMP player) { + removeUser(player.getUniqueID()); + } + + public void processPacket(PacketBuffer packetData, EntityPlayerMP sender) { + try { + IntegratedVoiceSignalPackets.processPacket(packetData, sender, this); + } catch (IOException e) { + logger.error("Invalid voice signal packet recieved from player {}!", sender.getName()); + logger.error(e); + sender.playerNetServerHandler.kickPlayerFromServer("Invalid voice signal packet recieved!"); + } + } + + void handleVoiceSignalPacketTypeRequest(EaglercraftUUID player, EntityPlayerMP sender) { + EaglercraftUUID senderUUID = sender.getUniqueID(); + if (senderUUID.equals(player)) + return; // prevent duplicates + if (!voicePlayers.containsKey(senderUUID)) + return; + EntityPlayerMP targetPlayerCon = voicePlayers.get(player); + if (targetPlayerCon == null) + return; + VoicePair newPair = new VoicePair(player, senderUUID); + if (voicePairs.contains(newPair)) + return; // already paired + ExpiringSet senderRequestSet = voiceRequests.get(senderUUID); + if (senderRequestSet == null) { + voiceRequests.put(senderUUID, senderRequestSet = new ExpiringSet<>(2000)); + } + if (!senderRequestSet.add(player)) { + return; + } + + // check if other has requested earlier + ExpiringSet theSet; + if ((theSet = voiceRequests.get(player)) != null && theSet.contains(senderUUID)) { + theSet.remove(senderUUID); + if (theSet.isEmpty()) + voiceRequests.remove(player); + senderRequestSet.remove(player); + if (senderRequestSet.isEmpty()) + voiceRequests.remove(senderUUID); + // send each other add data + voicePairs.add(newPair); + targetPlayerCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + IntegratedVoiceSignalPackets.makeVoiceSignalPacketConnect(senderUUID, false))); + sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + IntegratedVoiceSignalPackets.makeVoiceSignalPacketConnect(player, true))); + } + } + + void handleVoiceSignalPacketTypeConnect(EntityPlayerMP sender) { + if (voicePlayers.containsKey(sender.getUniqueID())) { + return; + } + boolean hasNoOtherPlayers = voicePlayers.isEmpty(); + voicePlayers.put(sender.getUniqueID(), sender); + if (hasNoOtherPlayers) { + return; + } + byte[] packetToBroadcast = IntegratedVoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values()); + for (EntityPlayerMP userCon : voicePlayers.values()) { + userCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, new PacketBuffer(Unpooled + .buffer(packetToBroadcast, packetToBroadcast.length).writerIndex(packetToBroadcast.length)))); + } + } + + void handleVoiceSignalPacketTypeICE(EaglercraftUUID player, String str, EntityPlayerMP sender) { + VoicePair pair = new VoicePair(player, sender.getUniqueID()); + EntityPlayerMP pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; + if (pass != null) { + pass.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + IntegratedVoiceSignalPackets.makeVoiceSignalPacketICE(sender.getUniqueID(), str))); + } + } + + void handleVoiceSignalPacketTypeDesc(EaglercraftUUID player, String str, EntityPlayerMP sender) { + VoicePair pair = new VoicePair(player, sender.getUniqueID()); + EntityPlayerMP pass = voicePairs.contains(pair) ? voicePlayers.get(player) : null; + if (pass != null) { + pass.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + IntegratedVoiceSignalPackets.makeVoiceSignalPacketDesc(sender.getUniqueID(), str))); + } + } + + void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID player, EntityPlayerMP sender) { + if (player != null) { + if (!voicePlayers.containsKey(player)) { + return; + } + byte[] userDisconnectPacket = null; + Iterator pairsItr = voicePairs.iterator(); + while (pairsItr.hasNext()) { + VoicePair voicePair = pairsItr.next(); + EaglercraftUUID target = null; + if (voicePair.uuid1.equals(player)) { + target = voicePair.uuid2; + } else if (voicePair.uuid2.equals(player)) { + target = voicePair.uuid1; + } + if (target != null) { + pairsItr.remove(); + EntityPlayerMP conn = voicePlayers.get(target); + if (conn != null) { + if (userDisconnectPacket == null) { + userDisconnectPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnect(player); + } + conn.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + new PacketBuffer(Unpooled.buffer(userDisconnectPacket, userDisconnectPacket.length) + .writerIndex(userDisconnectPacket.length)))); + } + sender.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnectPB(target))); + } + } + } else { + removeUser(sender.getUniqueID()); + } + } + + public void removeUser(EaglercraftUUID user) { + if (voicePlayers.remove(user) == null) { + return; + } + voiceRequests.remove(user); + if (voicePlayers.size() > 0) { + byte[] voicePlayersPkt = IntegratedVoiceSignalPackets.makeVoiceSignalPacketGlobal(voicePlayers.values()); + for (EntityPlayerMP userCon : voicePlayers.values()) { + if (!user.equals(userCon.getUniqueID())) { + userCon.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + new PacketBuffer(Unpooled.buffer(voicePlayersPkt, voicePlayersPkt.length) + .writerIndex(voicePlayersPkt.length)))); + } + } + } + byte[] userDisconnectPacket = null; + Iterator pairsItr = voicePairs.iterator(); + while (pairsItr.hasNext()) { + VoicePair voicePair = pairsItr.next(); + EaglercraftUUID target = null; + if (voicePair.uuid1.equals(user)) { + target = voicePair.uuid2; + } else if (voicePair.uuid2.equals(user)) { + target = voicePair.uuid1; + } + if (target != null) { + pairsItr.remove(); + if (voicePlayers.size() > 0) { + EntityPlayerMP conn = voicePlayers.get(target); + if (conn != null) { + if (userDisconnectPacket == null) { + userDisconnectPacket = IntegratedVoiceSignalPackets.makeVoiceSignalPacketDisconnect(user); + } + conn.playerNetServerHandler.sendPacket(new S3FPacketCustomPayload(CHANNEL, + new PacketBuffer(Unpooled.buffer(userDisconnectPacket, userDisconnectPacket.length) + .writerIndex(userDisconnectPacket.length)))); + } + } + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceSignalPackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceSignalPackets.java new file mode 100644 index 0000000..0422dc3 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/sp/server/voice/IntegratedVoiceSignalPackets.java @@ -0,0 +1,198 @@ +package net.lax1dude.eaglercraft.v1_8.sp.server.voice; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.Collection; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.netty.ByteBuf; +import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.network.PacketBuffer; + +/** + * 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 IntegratedVoiceSignalPackets { + + static final int VOICE_SIGNAL_ALLOWED = 0; + static final int VOICE_SIGNAL_REQUEST = 0; + static final int VOICE_SIGNAL_CONNECT = 1; + static final int VOICE_SIGNAL_DISCONNECT = 2; + static final int VOICE_SIGNAL_ICE = 3; + static final int VOICE_SIGNAL_DESC = 4; + static final int VOICE_SIGNAL_GLOBAL = 5; + + public static void processPacket(PacketBuffer buffer, EntityPlayerMP sender, IntegratedVoiceService voiceService) throws IOException { + int packetId = -1; + if(buffer.readableBytes() == 0) { + throw new IOException("Zero-length packet recieved"); + } + try { + packetId = buffer.readUnsignedByte(); + switch(packetId) { + case VOICE_SIGNAL_REQUEST: { + voiceService.handleVoiceSignalPacketTypeRequest(buffer.readUuid(), sender); + break; + } + case VOICE_SIGNAL_CONNECT: { + voiceService.handleVoiceSignalPacketTypeConnect(sender); + break; + } + case VOICE_SIGNAL_ICE: { + voiceService.handleVoiceSignalPacketTypeICE(buffer.readUuid(), buffer.readStringFromBuffer(32767), sender); + break; + } + case VOICE_SIGNAL_DESC: { + voiceService.handleVoiceSignalPacketTypeDesc(buffer.readUuid(), buffer.readStringFromBuffer(32767), sender); + break; + } + case VOICE_SIGNAL_DISCONNECT: { + voiceService.handleVoiceSignalPacketTypeDisconnect(buffer.readableBytes() > 0 ? buffer.readUuid() : null, sender); + break; + } + default: { + throw new IOException("Unknown packet type " + packetId); + } + } + if(buffer.readableBytes() > 0) { + throw new IOException("Voice packet is too long!"); + } + }catch(IOException ex) { + throw ex; + }catch(Throwable t) { + throw new IOException("Unhandled exception handling voice packet type " + packetId, t); + } + } + + static byte[] makeVoiceSignalPacketAllowed(boolean allowed, String[] iceServers) { + if (iceServers == null) { + byte[] ret = new byte[2]; + ByteBuf wrappedBuffer = Unpooled.buffer(ret, ret.length); + wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED); + wrappedBuffer.writeBoolean(allowed); + return ret; + } + byte[][] iceServersBytes = new byte[iceServers.length][]; + int totalLen = 2 + PacketBuffer.getVarIntSize(iceServers.length); + for(int i = 0; i < iceServers.length; ++i) { + byte[] b = iceServersBytes[i] = iceServers[i].getBytes(StandardCharsets.UTF_8); + totalLen += PacketBuffer.getVarIntSize(b.length) + b.length; + } + byte[] ret = new byte[totalLen]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_ALLOWED); + wrappedBuffer.writeBoolean(allowed); + wrappedBuffer.writeVarIntToBuffer(iceServersBytes.length); + for(int i = 0; i < iceServersBytes.length; ++i) { + byte[] b = iceServersBytes[i]; + wrappedBuffer.writeVarIntToBuffer(b.length); + wrappedBuffer.writeBytes(b); + } + return ret; + } + + static byte[] makeVoiceSignalPacketGlobal(Collection users) { + int cnt = users.size(); + byte[][] displayNames = new byte[cnt][]; + int i = 0; + for(EntityPlayerMP user : users) { + String name = user.getName(); + if(name.length() > 16) name = name.substring(0, 16); + displayNames[i++] = name.getBytes(StandardCharsets.UTF_8); + } + int totalLength = 1 + PacketBuffer.getVarIntSize(cnt) + (cnt << 4); + for(i = 0; i < cnt; ++i) { + totalLength += PacketBuffer.getVarIntSize(displayNames[i].length) + displayNames[i].length; + } + byte[] ret = new byte[totalLength]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_GLOBAL); + wrappedBuffer.writeVarIntToBuffer(cnt); + for(EntityPlayerMP user : users) { + wrappedBuffer.writeUuid(user.getUniqueID()); + } + for(i = 0; i < cnt; ++i) { + wrappedBuffer.writeVarIntToBuffer(displayNames[i].length); + wrappedBuffer.writeBytes(displayNames[i]); + } + return ret; + } + + static PacketBuffer makeVoiceSignalPacketConnect(EaglercraftUUID player, boolean offer) { + byte[] ret = new byte[18]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT); + wrappedBuffer.writeUuid(player); + wrappedBuffer.writeBoolean(offer); + return wrappedBuffer; + } + + static byte[] makeVoiceSignalPacketConnectAnnounce(EaglercraftUUID player) { + byte[] ret = new byte[17]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_CONNECT); + wrappedBuffer.writeUuid(player); + return ret; + } + + static byte[] makeVoiceSignalPacketDisconnect(EaglercraftUUID player) { + if(player == null) { + return new byte[] { (byte)VOICE_SIGNAL_DISCONNECT }; + } + byte[] ret = new byte[17]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT); + wrappedBuffer.writeUuid(player); + return ret; + } + + static PacketBuffer makeVoiceSignalPacketDisconnectPB(EaglercraftUUID player) { + if(player == null) { + byte[] ret = new byte[1]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT); + return wrappedBuffer; + } + byte[] ret = new byte[17]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_DISCONNECT); + wrappedBuffer.writeUuid(player); + return wrappedBuffer; + } + + static PacketBuffer makeVoiceSignalPacketICE(EaglercraftUUID player, String str) { + byte[] strBytes = str.getBytes(StandardCharsets.UTF_8); + byte[] ret = new byte[17 + PacketBuffer.getVarIntSize(strBytes.length) + strBytes.length]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_ICE); + wrappedBuffer.writeUuid(player); + wrappedBuffer.writeVarIntToBuffer(strBytes.length); + wrappedBuffer.writeBytes(strBytes); + return wrappedBuffer; + } + + static PacketBuffer makeVoiceSignalPacketDesc(EaglercraftUUID player, String str) { + byte[] strBytes = str.getBytes(StandardCharsets.UTF_8); + byte[] ret = new byte[17 + PacketBuffer.getVarIntSize(strBytes.length) + strBytes.length]; + PacketBuffer wrappedBuffer = new PacketBuffer(Unpooled.buffer(ret, ret.length)); + wrappedBuffer.writeByte(VOICE_SIGNAL_DESC); + wrappedBuffer.writeUuid(player); + wrappedBuffer.writeVarIntToBuffer(strBytes.length); + wrappedBuffer.writeBytes(strBytes); + return wrappedBuffer; + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateCheckerOverlay.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateCheckerOverlay.java index 0e1cc0c..caeac63 100644 --- a/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateCheckerOverlay.java +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/update/GuiUpdateCheckerOverlay.java @@ -41,6 +41,8 @@ public class GuiUpdateCheckerOverlay extends Gui { private int width; private int height; + private int totalHeightOffset = 0; + private boolean isIngame; private GuiScreen backScreen; @@ -61,10 +63,10 @@ public class GuiUpdateCheckerOverlay extends Gui { this.mc = mc; this.width = w; this.height = h; - checkForUpdatesButton = new GuiButton(0, w - 150, 0, 150, 20, I18n.format("update.button") + " " + I18n.format(mc.gameSettings.enableUpdateSvc ? "gui.yes" : "gui.no")); - startDownloadButton = new GuiButton(1, w - 115, 0, 115, 20, I18n.format("update.startDownload")); - viewAllUpdatesButton = new GuiButton(2, w - 115, 0, 115, 20, I18n.format("update.viewAll", 0)); - dismissUpdatesButton = new GuiButton(3, w - 115, 0, 115, 20, I18n.format("update.dismiss")); + checkForUpdatesButton = new GuiButton(0, 0, 0, 150, 20, I18n.format("update.button") + " " + I18n.format(mc.gameSettings.enableUpdateSvc ? "gui.yes" : "gui.no")); + startDownloadButton = new GuiButton(1, 1, 0, 115, 20, I18n.format("update.startDownload")); + viewAllUpdatesButton = new GuiButton(2, 1, 0, 115, 20, I18n.format("update.viewAll", 0)); + dismissUpdatesButton = new GuiButton(3, 1, 0, 115, 20, I18n.format("update.dismiss")); } public void drawScreen(int mx, int my, float partialTicks) { @@ -81,6 +83,7 @@ public class GuiUpdateCheckerOverlay extends Gui { startDownloadButton.visible = false; viewAllUpdatesButton.visible = false; dismissUpdatesButton.visible = false; + totalHeightOffset = 0; int i = UpdateService.getAvailableUpdates().size(); boolean shownSP = i > 0 || !mc.isSingleplayer() || LANServerController.isHostingLAN(); @@ -95,7 +98,7 @@ public class GuiUpdateCheckerOverlay extends Gui { dismissUpdatesButton.visible = true; viewAllUpdatesButton.displayString = I18n.format("update.viewAll", i); str = I18n.format("update.found"); - mc.fontRendererObj.drawStringWithShadow(str, width - mc.fontRendererObj.getStringWidth(str) - 3, 22, 0xFFFFAA); + mc.fontRendererObj.drawStringWithShadow(str, 3, 22, 0xFFFFAA); int embedY = 35; int embedWidth = 115; @@ -109,7 +112,7 @@ public class GuiUpdateCheckerOverlay extends Gui { } GlStateManager.pushMatrix(); - GlStateManager.translate(width - embedWidth - 1, embedY, 0.0f); + GlStateManager.translate(1.0f, embedY, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); int embedHeight2 = (int)(embedHeight / 0.75f); @@ -143,16 +146,20 @@ public class GuiUpdateCheckerOverlay extends Gui { startDownloadButton.yPosition = embedHeight + embedY + 5; viewAllUpdatesButton.yPosition = startDownloadButton.yPosition + 22; dismissUpdatesButton.yPosition = viewAllUpdatesButton.yPosition + 22; + totalHeightOffset = dismissUpdatesButton.yPosition + 20; GlStateManager.popMatrix(); }else if(isIngame) { if(shownSP) { str = I18n.format("update.noneNew"); - mc.fontRendererObj.drawString(str, width - mc.fontRendererObj.getStringWidth(str) - 3, 22, 0xDDDDDD); + mc.fontRendererObj.drawString(str, 3, 22, 0xDDDDDD); if(i > 0) { viewAllUpdatesButton.yPosition = 40; viewAllUpdatesButton.visible = true; viewAllUpdatesButton.displayString = I18n.format("update.viewAll", i); + totalHeightOffset = 60; + }else { + totalHeightOffset = 32; } } } @@ -173,23 +180,23 @@ public class GuiUpdateCheckerOverlay extends Gui { viewAllUpdatesButton.visible = false; dismissUpdatesButton.visible = false; GlStateManager.pushMatrix(); - GlStateManager.translate(width, isIngame ? 0.0f : 10.0f, 0.0f); + GlStateManager.translate(1.0f, isIngame ? 0.0f : 18.0f, 0.0f); String str = I18n.format("update.downloading"); - mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 2, 2, 0xFFFFAA); + mc.fontRendererObj.drawStringWithShadow(str, 2, 2, 0xFFFFAA); GlStateManager.translate(0.0f, 14.0f, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); if(!StringUtils.isAllBlank(progressState.statusString1)) { str = progressState.statusString1; - mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 3, 0, 0xFFFFFF); + mc.fontRendererObj.drawStringWithShadow(str, 3, 0, 0xFFFFFF); } int cc = isIngame ? 0xBBBBBB : 0xFFFFFF; if(!StringUtils.isAllBlank(progressState.statusString2)) { str = progressState.statusString2; - mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 3, 11, cc); + mc.fontRendererObj.drawStringWithShadow(str, 3, 11, cc); } - int progX1 = -135; + int progX1 = 3; int progY1 = 22; - int progX2 = -3; + int progX2 = 135; int progY2 = 32; float prog = progressState.progressBar; if(prog >= 0.0f) { @@ -202,6 +209,7 @@ public class GuiUpdateCheckerOverlay extends Gui { drawGradientRect(progX1, progY1 + 1, progX1 + 1, progY2 - 1, 0xFF000000, 0xFF000000); drawGradientRect(progX2 - 1, progY1 + 1, progX2, progY2 - 1, 0xFF000000, 0xFF000000); } + totalHeightOffset = 32; if(!StringUtils.isAllBlank(progressState.statusString3)) { GlStateManager.translate(0.0f, progY2 + 2, 0.0f); GlStateManager.scale(0.66f, 0.66f, 0.66f); @@ -209,8 +217,9 @@ public class GuiUpdateCheckerOverlay extends Gui { List wrappedURL = mc.fontRendererObj.listFormattedStringToWidth(str, (int)((progX2 - progX1) * 1.5f)); for(int i = 0, l = wrappedURL.size(); i < l; ++i) { str = wrappedURL.get(i); - mc.fontRendererObj.drawStringWithShadow(str, -mc.fontRendererObj.getStringWidth(str) - 5, i * 11, cc); + mc.fontRendererObj.drawStringWithShadow(str, 5, i * 11, cc); } + totalHeightOffset += (int)(wrappedURL.size() * 5.5f); } GlStateManager.popMatrix(); } @@ -244,4 +253,8 @@ public class GuiUpdateCheckerOverlay extends Gui { } } } + + public int getSharedWorldInfoYOffset() { + return totalHeightOffset; + } } diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelPeerState.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelPeerState.java new file mode 100644 index 0000000..86e9fdc --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelPeerState.java @@ -0,0 +1,20 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +/** + * Copyright (c) 2024 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 enum EnumVoiceChannelPeerState { + FAILED, SUCCESS, LOADING; +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelReadyState.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelReadyState.java new file mode 100644 index 0000000..bb29ba5 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelReadyState.java @@ -0,0 +1,20 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +/** + * Copyright (c) 2024 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 enum EnumVoiceChannelReadyState { + NONE, ABORTED, DEVICE_INITIALIZED; +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelStatus.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelStatus.java new file mode 100644 index 0000000..1d410bf --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelStatus.java @@ -0,0 +1,20 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +/** + * 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 enum EnumVoiceChannelStatus { + DISCONNECTED, CONNECTING, CONNECTED, UNAVAILABLE; +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelType.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelType.java new file mode 100644 index 0000000..c7300d9 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/EnumVoiceChannelType.java @@ -0,0 +1,20 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +/** + * 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 enum EnumVoiceChannelType { + NONE, GLOBAL, PROXIMITY; +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/ExpiringSet.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/ExpiringSet.java new file mode 100644 index 0000000..b23e3d6 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/ExpiringSet.java @@ -0,0 +1,84 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Map; + +/** + * Copyright (c) 2022 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 ExpiringSet extends HashSet { + private final long expiration; + private final ExpiringEvent event; + + private final Map timestamps = new HashMap<>(); + + public ExpiringSet(long expiration) { + this.expiration = expiration; + this.event = null; + } + + public ExpiringSet(long expiration, ExpiringEvent event) { + this.expiration = expiration; + this.event = event; + } + + public interface ExpiringEvent { + void onExpiration(T item); + } + + public void checkForExpirations() { + Iterator iterator = this.timestamps.keySet().iterator(); + long now = System.currentTimeMillis(); + while (iterator.hasNext()) { + T element = iterator.next(); + if (super.contains(element)) { + if (this.timestamps.get(element) + this.expiration < now) { + if (this.event != null) this.event.onExpiration(element); + iterator.remove(); + super.remove(element); + } + } else { + iterator.remove(); + super.remove(element); + } + } + } + + public boolean add(T o) { + checkForExpirations(); + boolean success = super.add(o); + if (success) timestamps.put(o, System.currentTimeMillis()); + return success; + } + + public boolean remove(Object o) { + checkForExpirations(); + boolean success = super.remove(o); + if (success) timestamps.remove(o); + return success; + } + + public void clear() { + this.timestamps.clear(); + super.clear(); + } + + public boolean contains(Object o) { + checkForExpirations(); + return super.contains(o); + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..cf5233b --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceMenu.java @@ -0,0 +1,772 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.List; +import java.util.Set; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.Keyboard; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiSlider2; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2022-2024 lax1dude, 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 GuiVoiceMenu extends Gui { + + public class AbortedException extends RuntimeException { + } + + private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png"); + + protected final GuiScreen parent; + + protected Minecraft mc; + protected FontRenderer fontRendererObj; + protected int width; + protected int height; + + protected int voiceButtonOFFposX; + protected int voiceButtonOFFposY; + protected int voiceButtonOFFposW; + protected int voiceButtonOFFposH; + + protected int voiceButtonRADIUSposX; + protected int voiceButtonRADIUSposY; + protected int voiceButtonRADIUSposW; + protected int voiceButtonRADIUSposH; + + protected int voiceButtonGLOBALposX; + protected int voiceButtonGLOBALposY; + protected int voiceButtonGLOBALposW; + protected int voiceButtonGLOBALposH; + + protected int voiceScreenButtonOFFposX; + protected int voiceScreenButtonOFFposY; + protected int voiceScreenButtonOFFposW; + protected int voiceScreenButtonOFFposH; + + protected int voiceScreenButtonRADIUSposX; + protected int voiceScreenButtonRADIUSposY; + protected int voiceScreenButtonRADIUSposW; + protected int voiceScreenButtonRADIUSposH; + + protected int voiceScreenButtonGLOBALposX; + protected int voiceScreenButtonGLOBALposY; + protected int voiceScreenButtonGLOBALposW; + protected int voiceScreenButtonGLOBALposH; + + protected int voiceScreenButtonChangeRadiusposX; + protected int voiceScreenButtonChangeRadiusposY; + protected int voiceScreenButtonChangeRadiusposW; + protected int voiceScreenButtonChangeRadiusposH; + + protected int voiceScreenVolumeIndicatorX; + protected int voiceScreenVolumeIndicatorY; + protected int voiceScreenVolumeIndicatorW; + protected int voiceScreenVolumeIndicatorH; + + protected boolean showSliderBlocks = false; + protected boolean showSliderVolume = false; + protected boolean showPTTKeyConfig = false; + protected int showNewPTTKey = 0; + protected GuiSlider2 sliderBlocks = null; + protected GuiSlider2 sliderListenVolume = null; + protected GuiSlider2 sliderSpeakVolume = null; + + protected GuiButton applyRadiusButton = null; + protected GuiButton applyVolumeButton = null; + protected GuiButton noticeContinueButton = null; + protected GuiButton noticeCancelButton = null; + + protected static boolean showingCompatWarning = false; + protected static boolean showCompatWarning = true; + + protected static boolean showingTrackingWarning = false; + protected static boolean showTrackingWarning = true; + + protected static EnumVoiceChannelType continueChannel = null; + + public GuiVoiceMenu(GuiScreen parent) { + this.parent = parent; + } + + public void setResolution(Minecraft mc, int w, int h) { + this.mc = mc; + this.fontRendererObj = mc.fontRendererObj; + this.width = w; + this.height = h; + initGui(); + } + + public void initGui() { + this.sliderBlocks = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 20, 150, 20, (VoiceClientController.getVoiceProximity() - 5) / 17.0f, 1.0f) { + public boolean mousePressed(Minecraft par1Minecraft, int par2, int par3) { + if(super.mousePressed(par1Minecraft, par2, par3)) { + this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks"; + return true; + }else { + return false; + } + } + public void mouseDragged(Minecraft par1Minecraft, int par2, int par3) { + super.mouseDragged(par1Minecraft, par2, par3); + this.displayString = "" + (int)((sliderValue * 17.0f) + 5.0f) + " Blocks"; + } + }; + sliderBlocks.displayString = "" + VoiceClientController.getVoiceProximity() + " Blocks"; + this.sliderListenVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 10, 150, 20, VoiceClientController.getVoiceListenVolume(), 1.0f); + this.sliderSpeakVolume = new GuiSlider2(-1, (width - 150) / 2, height / 3 + 56, 150, 20, VoiceClientController.getVoiceSpeakVolume(), 1.0f); + + applyRadiusButton = new GuiButton(2, (width - 150) / 2, height / 3 + 49, 150, 20, I18n.format("voice.apply")); + applyVolumeButton = new GuiButton(3, (width - 150) / 2, height / 3 + 90, 150, 20, I18n.format("voice.apply")); + noticeContinueButton = new GuiButton(5, (width - 150) / 2, height / 3 + 60, 150, 20, I18n.format("voice.unsupportedWarning10")); + noticeCancelButton = new GuiButton(6, (width - 150) / 2, height / 3 + 90, 150, 20, I18n.format("voice.unsupportedWarning11")); + applyRadiusButton.visible = applyVolumeButton.visible = noticeContinueButton.visible = noticeCancelButton.visible = false; + } + + private void drawButtons(int mx, int my, float partialTicks) { + applyRadiusButton.drawButton(mc, mx, my); + applyVolumeButton.drawButton(mc, mx, my); + noticeContinueButton.drawButton(mc, mx, my); + noticeCancelButton.drawButton(mc, mx, my); + } + + public void drawScreen(int mx, int my, float partialTicks) { + String txt = I18n.format("voice.title"); + drawString(fontRendererObj, txt, width - 5 - fontRendererObj.getStringWidth(txt), 5, 0xFFCC22); + + applyRadiusButton.visible = showSliderBlocks; + applyVolumeButton.visible = showSliderVolume; + + if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) { + + drawRect(0, 0, this.width, this.height, 0xB0101010); + + if(showSliderBlocks) { + + drawRect(width / 2 - 86, height / 4 - 1, this.width / 2 + 86, height / 3 + 64 + height / 16, 0xFFDDDDDD); + drawRect(width / 2 - 85, height / 4 + 0, this.width / 2 + 85, height / 3 + 63 + height / 16, 0xFF333333); + + drawCenteredString(this.fontRendererObj, I18n.format("voice.radiusTitle"), this.width / 2, height / 4 + 9, 16777215); + drawString(this.fontRendererObj, I18n.format("voice.radiusLabel"), (this.width - 150) / 2 + 3, height / 3 + 6, 0xCCCCCC); + sliderBlocks.drawButton(mc, mx, my); + + }else if(showSliderVolume) { + + drawRect(width / 2 - 86, height / 4 - 11, this.width / 2 + 86, height / 3 + 104 + height / 16, 0xFFDDDDDD); + drawRect(width / 2 - 85, height / 4 - 10, this.width / 2 + 85, height / 3 + 103 + height / 16, 0xFF333333); + + drawCenteredString(this.fontRendererObj, I18n.format("voice.volumeTitle"), this.width / 2, height / 4 - 1, 16777215); + drawString(this.fontRendererObj, I18n.format("voice.volumeListen"), (this.width - 150) / 2 + 3, height / 3 - 4, 0xCCCCCC); + sliderListenVolume.drawButton(mc, mx, my); + + drawString(this.fontRendererObj, I18n.format("voice.volumeSpeak"), (this.width - 150) / 2 + 3, height / 3 + 42, 0xCCCCCC); + sliderSpeakVolume.drawButton(mc, mx, my); + + }else if(showPTTKeyConfig) { + + drawRect(width / 2 - 86, height / 3 - 10, this.width / 2 + 86, height / 3 + 35, 0xFFDDDDDD); + drawRect(width / 2 - 85, height / 3 - 9, this.width / 2 + 85, height / 3 + 34, 0xFF333333); + + if(showNewPTTKey > 0) { + GlStateManager.pushMatrix(); + GlStateManager.translate(this.width / 2, height / 3 + 5, 0.0f); + GlStateManager.scale(2.0f, 2.0f, 2.0f); + drawCenteredString(this.fontRendererObj, Keyboard.getKeyName(mc.gameSettings.voicePTTKey), 0, 0, 0xFFCC11); + GlStateManager.popMatrix(); + }else { + drawCenteredString(this.fontRendererObj, I18n.format("voice.pttChangeDesc"), this.width / 2, height / 3 + 8, 16777215); + } + } + + drawButtons(mx, my, partialTicks); + throw new AbortedException(); + } + + GlStateManager.pushMatrix(); + + GlStateManager.translate(width - 6, 15, 0.0f); + GlStateManager.scale(0.75f, 0.75f, 0.75f); + + if(!VoiceClientController.isClientSupported()) { + txt = I18n.format("voice.titleVoiceUnavailable"); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 6, 0xFF7777); + txt = I18n.format("voice.titleVoiceBrowserError"); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 19, 0xAA4444); + GlStateManager.popMatrix(); + return; + } + + if(!VoiceClientController.isServerSupported()) { + txt = I18n.format("voice.titleNoVoice"); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xFF7777); + GlStateManager.popMatrix(); + return; + } + + int xo = 0; + // this feature is optional + //if(VoiceClientController.voiceRelayed()) { + // txt = I18n.format("voice.warning1"); + // drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 8, 0xBB9999); + // txt = I18n.format("voice.warning2"); + // drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 18, 0xBB9999); + // txt = I18n.format("voice.warning3"); + // drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 28, 0xBB9999); + // xo = 43; + // GlStateManager.translate(0.0f, xo, 0.0f); + //} + + EnumVoiceChannelStatus status = VoiceClientController.getVoiceStatus(); + EnumVoiceChannelType channel = VoiceClientController.getVoiceChannel(); + + boolean flag = false; + + if(channel == EnumVoiceChannelType.NONE) { + flag = true; + }else { + if(status == EnumVoiceChannelStatus.CONNECTED) { + + if(channel == EnumVoiceChannelType.PROXIMITY) { + txt = I18n.format("voice.connectedRadius").replace("$radius$", "" + VoiceClientController.getVoiceProximity()).replace("$f$", ""); + int w = fontRendererObj.getStringWidth(txt); + int xx = width - 5 - (w * 3 / 4); + int yy = 15 + (xo * 3 / 4); + voiceScreenButtonChangeRadiusposX = xx; + voiceScreenButtonChangeRadiusposY = yy; + voiceScreenButtonChangeRadiusposW = width - 3 - xx; + voiceScreenButtonChangeRadiusposH = 12; + if(mx >= xx && my >= yy && mx < xx + voiceScreenButtonChangeRadiusposW && my < yy + 12) { + txt = I18n.format("voice.connectedRadius").replace("$radius$", "" + VoiceClientController.getVoiceProximity()) + .replace("$f$", "" + EnumChatFormatting.UNDERLINE) + EnumChatFormatting.RESET; + } + }else { + txt = I18n.format("voice.connectedGlobal"); + } + + voiceScreenVolumeIndicatorX = width - 15 - (104 * 3 / 4); + voiceScreenVolumeIndicatorY = 15 + (xo * 3 / 4) + 30; + voiceScreenVolumeIndicatorW = width - voiceScreenVolumeIndicatorX - 4; + voiceScreenVolumeIndicatorH = 23; + + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0x66DD66); + + drawRect(-90, 42, 2, 52, 0xFFAAAAAA); + drawRect(-89, 43, 1, 51, 0xFF222222); + + float vol = VoiceClientController.getVoiceListenVolume(); + drawRect(-89, 43, -89 + (int)(vol * 90), 51, 0xFF993322); + + for(float f = 0.07f; f < vol; f += 0.08f) { + int ww = (int)(f * 90); + drawRect(-89 + ww, 43, -89 + ww + 1, 51, 0xFF999999); + } + + drawRect(-90, 57, 2, 67, 0xFFAAAAAA); + drawRect(-89, 58, 1, 66, 0xFF222222); + + vol = VoiceClientController.getVoiceSpeakVolume(); + drawRect(-89, 58, -89 + (int)(vol * 90), 66, 0xFF993322); + + for(float f = 0.07f; f < vol; f += 0.08f) { + int ww = (int)(f * 90); + drawRect(-89 + ww, 58, -89 + ww + 1, 66, 0xFF999999); + } + + mc.getTextureManager().bindTexture(voiceGuiIcons); + GlStateManager.color(0.7f, 0.7f, 0.7f, 1.0f); + + GlStateManager.pushMatrix(); + GlStateManager.translate(-104.0f, 41.5f, 0.0f); + GlStateManager.scale(0.7f, 0.7f, 0.7f); + drawTexturedModalRect(0, 0, 64, 144, 16, 16); + GlStateManager.popMatrix(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(-104.0f, 56.5f, 0.0f); + GlStateManager.scale(0.7f, 0.7f, 0.7f); + if((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey)) { + GlStateManager.color(0.9f, 0.4f, 0.4f, 1.0f); + drawTexturedModalRect(0, 0, 64, 64, 16, 16); + }else { + drawTexturedModalRect(0, 0, 64, 32, 16, 16); + } + GlStateManager.popMatrix(); + + txt = I18n.format("voice.ptt", Keyboard.getKeyName(mc.gameSettings.voicePTTKey)); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt) - 10, 76, 0x66DD66); + + mc.getTextureManager().bindTexture(voiceGuiIcons); + GlStateManager.color(0.4f, 0.9f, 0.4f, 1.0f); + GlStateManager.pushMatrix(); + GlStateManager.translate(-7.0f, 74.5f, 0.0f); + GlStateManager.scale(0.35f, 0.35f, 0.35f); + drawTexturedModalRect(0, 0, 32, 224, 32, 32); + GlStateManager.popMatrix(); + + txt = I18n.format("voice.playersListening"); + + GlStateManager.pushMatrix(); + GlStateManager.translate(0.0f, 98.0f, 0.0f); + GlStateManager.scale(1.2f, 1.2f, 1.2f); + drawString(fontRendererObj, txt, -fontRendererObj.getStringWidth(txt), 0, 0xFF7777); + GlStateManager.popMatrix(); + + List playersToRender = VoiceClientController.getVoiceRecent(); + + if(playersToRender.size() > 0) { + EaglercraftUUID uuid; + Set playersSpeaking = VoiceClientController.getVoiceSpeaking(); + Set playersMuted = VoiceClientController.getVoiceMuted(); + for(int i = 0, l = playersToRender.size(); i < l; ++i) { + uuid = playersToRender.get(i); + txt = VoiceClientController.getVoiceUsername(uuid); + + boolean muted = playersMuted.contains(uuid); + boolean speaking = !muted && playersSpeaking.contains(uuid); + + int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9; + boolean hovered = mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9; + float cm = hovered ? 1.5f : 1.0f; + mc.getTextureManager().bindTexture(voiceGuiIcons); + + GlStateManager.pushMatrix(); + GlStateManager.translate(-100.0f, 115.0f + i * 12.0f, 0.0f); + GlStateManager.scale(0.78f, 0.78f, 0.78f); + + if(muted) { + GlStateManager.color(1.0f * cm, 0.2f * cm, 0.2f * cm, 1.0f); + drawTexturedModalRect(0, 0, 64, 208, 16, 16); + }else if(speaking) { + GlStateManager.color(1.0f * cm, 1.0f * cm, 1.0f * cm, 1.0f); + drawTexturedModalRect(0, 0, 64, 176, 16, 16); + }else { + GlStateManager.color(0.65f * cm, 0.65f * cm, 0.65f * cm, 1.0f); + drawTexturedModalRect(0, 0, 64, 144, 16, 16); + } + + GlStateManager.popMatrix(); + + if(muted) { + drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0xCC4444, cm)); + }else if(speaking) { + drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0xCCCCCC, cm)); + }else { + drawString(fontRendererObj, txt, -84, 117 + i * 12, attenuate(0x999999, cm)); + } + + } + }else { + txt = "(none)"; + drawString(fontRendererObj, txt, -fontRendererObj.getStringWidth(txt), 112, 0xAAAAAA); + } + + }else if(status == EnumVoiceChannelStatus.CONNECTING) { + float fadeTimer = MathHelper.sin((float)((System.currentTimeMillis() % 700l) * 0.0014d) * 3.14159f) * 0.35f + 0.3f; + txt = I18n.format("voice.connecting"); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, (0xFFDD77 | ((int)(Math.pow(fadeTimer, 1.0d / 2.2d) * 255.0f) << 24))); + GlStateManager.disableBlend(); + }else if(status == EnumVoiceChannelStatus.UNAVAILABLE) { + txt = I18n.format("voice.unavailable"); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xFF3333); + }else { + flag = true; + } + } + + if(flag) { + txt = I18n.format("voice.notConnected"); + drawString(fontRendererObj, txt, 1 - fontRendererObj.getStringWidth(txt), 5, 0xBB9999); + } + + String OFFstring = I18n.format("voice.off"); + String RADIUSstring = I18n.format("voice.radius"); + String GLOBALstring = I18n.format("voice.global"); + + int OFFwidth = fontRendererObj.getStringWidth(OFFstring); + int RADIUSwidth = fontRendererObj.getStringWidth(RADIUSstring); + int GLOBALwidth = fontRendererObj.getStringWidth(GLOBALstring); + + voiceButtonOFFposX = 0 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth; + voiceButtonOFFposY = 20; + voiceButtonOFFposW = OFFwidth + 5; + voiceButtonOFFposH = 15; + + voiceScreenButtonOFFposX = voiceButtonOFFposX * 3 / 4 + width - 6; + voiceScreenButtonOFFposY = 15 + (voiceButtonOFFposY + xo) * 3 / 4; + voiceScreenButtonOFFposW = voiceButtonOFFposW * 3 / 4; + voiceScreenButtonOFFposH = voiceButtonOFFposH * 3 / 4; + + voiceButtonRADIUSposX = 0 - RADIUSwidth - 8 - GLOBALwidth; + voiceButtonRADIUSposY = 20; + voiceButtonRADIUSposW = RADIUSwidth + 5; + voiceButtonRADIUSposH = 15; + + voiceScreenButtonRADIUSposX = voiceButtonRADIUSposX * 3 / 4 + width - 6; + voiceScreenButtonRADIUSposY = 15 + (voiceButtonRADIUSposY + xo) * 3 / 4; + voiceScreenButtonRADIUSposW = voiceButtonRADIUSposW * 3 / 4; + voiceScreenButtonRADIUSposH = voiceButtonRADIUSposH * 3 / 4; + + voiceButtonGLOBALposX = 0 - GLOBALwidth; + voiceButtonGLOBALposY = 20; + voiceButtonGLOBALposW = GLOBALwidth + 5; + voiceButtonGLOBALposH = 15; + + voiceScreenButtonGLOBALposX = voiceButtonGLOBALposX * 3 / 4 + width - 6; + voiceScreenButtonGLOBALposY = 15 + (voiceButtonGLOBALposY + xo) * 3 / 4; + voiceScreenButtonGLOBALposW = voiceButtonGLOBALposW * 3 / 4; + voiceScreenButtonGLOBALposH = voiceButtonGLOBALposH * 3 / 4; + + if(channel == EnumVoiceChannelType.NONE) { + drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFFCCCCCC); + drawRect(voiceButtonOFFposX + 1, voiceButtonOFFposY + 1, voiceButtonOFFposX + voiceButtonOFFposW - 2, + voiceButtonOFFposY + voiceButtonOFFposH - 1, 0xFF222222); + }else if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX + + voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) { + drawOutline(voiceButtonOFFposX, voiceButtonOFFposY, voiceButtonOFFposW, voiceButtonOFFposH, 0xFF777777); + } + + if(channel == EnumVoiceChannelType.PROXIMITY) { + drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFFCCCCCC); + drawRect(voiceButtonRADIUSposX + 1, voiceButtonRADIUSposY + 1, voiceButtonRADIUSposX + voiceButtonRADIUSposW - 2, + voiceButtonRADIUSposY + voiceButtonRADIUSposH - 1, 0xFF222222); + }else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX + + voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) { + drawOutline(voiceButtonRADIUSposX, voiceButtonRADIUSposY, voiceButtonRADIUSposW, voiceButtonRADIUSposH, 0xFF777777); + } + + if(channel == EnumVoiceChannelType.GLOBAL) { + drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFFCCCCCC); + drawRect(voiceButtonGLOBALposX + 1, voiceButtonGLOBALposY + 1, voiceButtonGLOBALposX + voiceButtonGLOBALposW - 2, + voiceButtonGLOBALposY + voiceButtonGLOBALposH - 1, 0xFF222222); + }else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX + + voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) { + drawOutline(voiceButtonGLOBALposX, voiceButtonGLOBALposY, voiceButtonGLOBALposW, voiceButtonGLOBALposH, 0xFF777777); + } + + int enabledColor = (status == EnumVoiceChannelStatus.CONNECTED || channel == EnumVoiceChannelType.NONE) ? 0x66DD66 : 0xDDCC66; + int disabledColor = 0xDD4444; + + if(channel != EnumVoiceChannelType.NONE && status == EnumVoiceChannelStatus.UNAVAILABLE) { + enabledColor = disabledColor; + } + + drawString(fontRendererObj, OFFstring, 3 - OFFwidth - 8 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == EnumVoiceChannelType.NONE ? enabledColor : disabledColor); + drawString(fontRendererObj, RADIUSstring, 3 - RADIUSwidth - 8 - GLOBALwidth, 24, channel == EnumVoiceChannelType.PROXIMITY ? enabledColor : disabledColor); + drawString(fontRendererObj, GLOBALstring, 3 - GLOBALwidth, 24, channel == EnumVoiceChannelType.GLOBAL ? enabledColor : disabledColor); + + GlStateManager.popMatrix(); + + if(showingCompatWarning) { + + drawNotice(I18n.format("voice.unsupportedWarning1"), false, I18n.format("voice.unsupportedWarning2"), I18n.format("voice.unsupportedWarning3"), + "", I18n.format("voice.unsupportedWarning4"), I18n.format("voice.unsupportedWarning5"), I18n.format("voice.unsupportedWarning6"), + I18n.format("voice.unsupportedWarning7"), I18n.format("voice.unsupportedWarning8"), I18n.format("voice.unsupportedWarning9")); + + noticeContinueButton.visible = true; + noticeCancelButton.visible = false; + }else if(showingTrackingWarning) { + + drawNotice(I18n.format("voice.ipGrabWarning1"), true, I18n.format("voice.ipGrabWarning2"), I18n.format("voice.ipGrabWarning3"), + I18n.format("voice.ipGrabWarning4"), "", I18n.format("voice.ipGrabWarning5"), I18n.format("voice.ipGrabWarning6"), + I18n.format("voice.ipGrabWarning7"), I18n.format("voice.ipGrabWarning8"), I18n.format("voice.ipGrabWarning9"), + I18n.format("voice.ipGrabWarning10"), I18n.format("voice.ipGrabWarning11"), I18n.format("voice.ipGrabWarning12")); + + noticeContinueButton.visible = true; + noticeCancelButton.visible = true; + }else { + noticeContinueButton.visible = false; + noticeCancelButton.visible = false; + } + + drawButtons(mx, my, partialTicks); + + if(showingCompatWarning || showingTrackingWarning) { + throw new AbortedException(); + } + } + + private void drawNotice(String title, boolean showCancel, String... lines) { + + int widthAccum = 0; + + for(int i = 0; i < lines.length; ++i) { + int w = fontRendererObj.getStringWidth(lines[i]); + if(widthAccum < w) { + widthAccum = w; + } + } + + int margin = 15; + + int x = (width - widthAccum) / 2; + int y = (height - lines.length * 10 - 60 - margin) / 2; + + drawRect(x - margin - 1, y - margin - 1, x + widthAccum + margin + 1, + y + lines.length * 10 + 49 + margin, 0xFFCCCCCC); + drawRect(x - margin, y - margin, x + widthAccum + margin, + y + lines.length * 10 + 48 + margin, 0xFF111111); + + drawCenteredString(fontRendererObj, EnumChatFormatting.BOLD + title, width / 2, y, 0xFF7766); + + for(int i = 0; i < lines.length; ++i) { + drawString(fontRendererObj, lines[i], x, y + i * 10 + 18, 0xDDAAAA); + } + + if(!showCancel) { + noticeContinueButton.width = 150; + noticeContinueButton.xPosition = (width - 150) / 2; + noticeContinueButton.yPosition = y + lines.length * 10 + 29; + }else { + noticeContinueButton.width = widthAccum / 2 - 10; + noticeContinueButton.xPosition = (width - widthAccum) / 2 + widthAccum / 2 + 3; + noticeContinueButton.yPosition = y + lines.length * 10 + 28; + noticeCancelButton.width = widthAccum / 2 - 10; + noticeCancelButton.xPosition = (width - widthAccum) / 2 + 4; + noticeCancelButton.yPosition = y + lines.length * 10 + 28; + } + + } + + public static int attenuate(int cin, float f) { + return attenuate(cin, f, f, f, 1.0f); + } + + 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 var8 = (float) (cin & 255) / 255.0F; + var10 *= a; + var6 *= r; + var7 *= g; + var8 *= b; + if(var10 > 1.0f) { + var10 = 1.0f; + } + if(var6 > 1.0f) { + var6 = 1.0f; + } + if(var7 > 1.0f) { + var7 = 1.0f; + } + if(var8 > 1.0f) { + var8 = 1.0f; + } + return (((int)(var10 * 255.0f) << 24) | ((int)(var6 * 255.0f) << 16) | ((int)(var7 * 255.0f) << 8) | (int)(var8 * 255.0f)); + } + + private void drawOutline(int x, int y, int w, int h, int color) { + drawRect(x, y, x + w, y + 1, color); + drawRect(x + w - 1, y + 1, x + w, y + h - 1, color); + drawRect(x, y + h - 1, x + w, y + h, color); + drawRect(x, y + 1, x + 1, y + h - 1, color); + } + + public void mouseReleased(int par1, int par2, int par3) { + applyRadiusButton.mouseReleased(par1, par2); + applyVolumeButton.mouseReleased(par1, par2); + noticeContinueButton.mouseReleased(par1, par2); + noticeCancelButton.mouseReleased(par1, par2); + if(showSliderBlocks || showSliderVolume) { + if(showSliderBlocks) { + if(par3 == 0) { + sliderBlocks.mouseReleased(par1, par2); + } + }else if(showSliderVolume) { + if(par3 == 0) { + sliderListenVolume.mouseReleased(par1, par2); + sliderSpeakVolume.mouseReleased(par1, par2); + } + } + throw new AbortedException(); + } + } + + public void keyTyped(char par1, int par2) { + if(showSliderBlocks || showSliderVolume || showPTTKeyConfig) { + if(showPTTKeyConfig) { + if(par2 == 1) { + showPTTKeyConfig = false; + }else { + mc.gameSettings.voicePTTKey = par2; + showNewPTTKey = 10; + } + } + throw new AbortedException(); + } + } + + public void mouseClicked(int mx, int my, int button) { + if(showSliderBlocks || showSliderVolume || showPTTKeyConfig || showingCompatWarning || showingTrackingWarning) { + if(showSliderBlocks) { + sliderBlocks.mousePressed(mc, mx, my); + }else if(showSliderVolume) { + sliderListenVolume.mousePressed(mc, mx, my); + sliderSpeakVolume.mousePressed(mc, mx, my); + } + if(button == 0) { + if(applyRadiusButton.mousePressed(mc, mx, my)) actionPerformed(applyRadiusButton); + if(applyVolumeButton.mousePressed(mc, mx, my)) actionPerformed(applyVolumeButton); + if(noticeContinueButton.mousePressed(mc, mx, my)) actionPerformed(noticeContinueButton); + if(noticeCancelButton.mousePressed(mc, mx, my)) actionPerformed(noticeCancelButton); + } + throw new AbortedException(); + } + + EnumVoiceChannelStatus status = VoiceClientController.getVoiceStatus(); + EnumVoiceChannelType channel = VoiceClientController.getVoiceChannel(); + + if(button == 0) { + if(VoiceClientController.isSupported()) { + if(mx >= voiceScreenButtonOFFposX && my >= voiceScreenButtonOFFposY && mx < voiceScreenButtonOFFposX + + voiceScreenButtonOFFposW && my < voiceScreenButtonOFFposY + voiceScreenButtonOFFposH) { + VoiceClientController.setVoiceChannel(EnumVoiceChannelType.NONE); + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + }else if(mx >= voiceScreenButtonRADIUSposX && my >= voiceScreenButtonRADIUSposY && mx < voiceScreenButtonRADIUSposX + + voiceScreenButtonRADIUSposW && my < voiceScreenButtonRADIUSposY + voiceScreenButtonRADIUSposH) { + + if(showCompatWarning) { + continueChannel = EnumVoiceChannelType.PROXIMITY; + showingCompatWarning = true; + }else if(showTrackingWarning) { + continueChannel = EnumVoiceChannelType.PROXIMITY; + showingTrackingWarning = true; + }else { + VoiceClientController.setVoiceChannel(EnumVoiceChannelType.PROXIMITY); + } + + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + + }else if(mx >= voiceScreenButtonGLOBALposX && my >= voiceScreenButtonGLOBALposY && mx < voiceScreenButtonGLOBALposX + + voiceScreenButtonGLOBALposW && my < voiceScreenButtonGLOBALposY + voiceScreenButtonGLOBALposH) { + + if(showCompatWarning) { + continueChannel = EnumVoiceChannelType.GLOBAL; + showingCompatWarning = true; + }else if(showTrackingWarning) { + continueChannel = EnumVoiceChannelType.GLOBAL; + showingTrackingWarning = true; + }else { + VoiceClientController.setVoiceChannel(EnumVoiceChannelType.GLOBAL); + } + + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + }else if(channel == EnumVoiceChannelType.PROXIMITY && status == EnumVoiceChannelStatus.CONNECTED && mx >= voiceScreenButtonChangeRadiusposX && + my >= voiceScreenButtonChangeRadiusposY && mx < voiceScreenButtonChangeRadiusposX + voiceScreenButtonChangeRadiusposW && + my < voiceScreenButtonChangeRadiusposY + voiceScreenButtonChangeRadiusposH) { + showSliderBlocks = true; + sliderBlocks.sliderValue = (VoiceClientController.getVoiceProximity() - 5) / 17.0f; + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + }else if(status == EnumVoiceChannelStatus.CONNECTED && channel != EnumVoiceChannelType.NONE && mx >= voiceScreenVolumeIndicatorX && + my >= voiceScreenVolumeIndicatorY && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW && + my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH) { + showSliderVolume = true; + sliderListenVolume.sliderValue = VoiceClientController.getVoiceListenVolume(); + sliderSpeakVolume.sliderValue = VoiceClientController.getVoiceSpeakVolume(); + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + }else if(status == EnumVoiceChannelStatus.CONNECTED && channel != EnumVoiceChannelType.NONE && mx >= voiceScreenVolumeIndicatorX - 1 && + my >= voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 2 && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && + my < voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 12) { + showPTTKeyConfig = true; + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + }else if(status == EnumVoiceChannelStatus.CONNECTED) { + List playersToRender = VoiceClientController.getVoiceRecent(); + if(playersToRender.size() > 0) { + Set playersMuted = VoiceClientController.getVoiceMuted(); + for(int i = 0, l = playersToRender.size(); i < l; ++i) { + EaglercraftUUID uuid = playersToRender.get(i); + String txt = VoiceClientController.getVoiceUsername(uuid); + boolean muted = playersMuted.contains(uuid); + int mhy = voiceScreenVolumeIndicatorY + voiceScreenVolumeIndicatorH + 33 + i * 9; + if(mx >= voiceScreenVolumeIndicatorX - 3 && my >= mhy && mx < voiceScreenVolumeIndicatorX + voiceScreenVolumeIndicatorW + 2 && my < mhy + 9) { + VoiceClientController.setVoiceMuted(uuid, !muted); + this.mc.getSoundHandler().playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); + break; + } + } + } + } + } + } + + } + + private void actionPerformed(GuiButton btn) { + if(btn.id == 2) { + showSliderBlocks = false; + VoiceClientController.setVoiceProximity(mc.gameSettings.voiceListenRadius = (int)((sliderBlocks.sliderValue * 17.0f) + 5.0f)); + mc.gameSettings.saveOptions(); + }else if(btn.id == 3) { + showSliderVolume = false; + VoiceClientController.setVoiceListenVolume(mc.gameSettings.voiceListenVolume = sliderListenVolume.sliderValue); + VoiceClientController.setVoiceSpeakVolume(mc.gameSettings.voiceSpeakVolume = sliderSpeakVolume.sliderValue); + mc.gameSettings.saveOptions(); + }else if(btn.id == 4) { + showPTTKeyConfig = false; + mc.gameSettings.saveOptions(); + }else if(btn.id == 5) { + if(showingCompatWarning) { + showingCompatWarning = false; + showCompatWarning = false; + if(showTrackingWarning) { + showingTrackingWarning = true; + }else { + VoiceClientController.setVoiceChannel(continueChannel); + } + }else if(showingTrackingWarning) { + showingTrackingWarning = false; + showTrackingWarning = false; + VoiceClientController.setVoiceChannel(continueChannel); + } + }else if(btn.id == 6) { + if(showingTrackingWarning) { + showingTrackingWarning = false; + VoiceClientController.setVoiceChannel(EnumVoiceChannelType.NONE); + } + } + } + + public void updateScreen() { + if(showNewPTTKey > 0) { + --showNewPTTKey; + if(showNewPTTKey == 0) { + showPTTKeyConfig = false; + mc.gameSettings.saveOptions(); + } + } + } + + public boolean isBlockingInput() { + return showSliderBlocks || showSliderVolume || showPTTKeyConfig || showingCompatWarning || showingTrackingWarning; + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceOverlay.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceOverlay.java new file mode 100644 index 0000000..8d0e639 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/GuiVoiceOverlay.java @@ -0,0 +1,258 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.GL_GREATER; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.Keyboard; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiChat; +import net.minecraft.client.gui.GuiIngameMenu; +import net.minecraft.util.ResourceLocation; + +/** + * Copyright (c) 2022-2024 lax1dude, 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 GuiVoiceOverlay extends Gui { + + public final Minecraft mc; + public int width; + public int height; + + private long pttTimer = 0l; + + public GuiVoiceOverlay(Minecraft mc) { + this.mc = mc; + } + + public void setResolution(int w, int h) { + this.width = w; + this.height = h; + } + + private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png"); + + public void drawOverlay() { + if(mc.theWorld != null && VoiceClientController.getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED && VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.NONE && + !(mc.currentScreen != null && (mc.currentScreen instanceof GuiIngameMenu))) { + + if(mc.currentScreen != null && mc.currentScreen.doesGuiPauseGame()) { + return; + } + + GlStateManager.disableLighting(); + GlStateManager.disableBlend(); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL_GREATER, 0.1F); + GlStateManager.pushMatrix(); + + if(mc.currentScreen == null || (mc.currentScreen instanceof GuiChat)) { + GlStateManager.translate(width / 2 + 77, height - 56, 0.0f); + if(mc.thePlayer == null || mc.thePlayer.capabilities.isCreativeMode) { + GlStateManager.translate(0.0f, 16.0f, 0.0f); + } + }else { + GlStateManager.translate(width / 2 + 10, 4, 0.0f); + } + + GlStateManager.scale(0.75f, 0.75f, 0.75f); + + String txxt = "press '" + Keyboard.getKeyName(mc.gameSettings.voicePTTKey) + "'"; + drawString(mc.fontRendererObj, txxt, -3 - mc.fontRendererObj.getStringWidth(txxt), 9, 0xDDDDDD); + + GlStateManager.scale(0.66f, 0.66f, 0.66f); + + mc.getTextureManager().bindTexture(voiceGuiIcons); + + if((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey)) { + long millis = System.currentTimeMillis(); + if(pttTimer == 0l) { + pttTimer = millis; + } + GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f); + drawTexturedModalRect(0, 0, 0, 64, 32, 32); + GlStateManager.translate(-1.5f, -1.5f, 0.0f); + if(millis - pttTimer < 1050l) { + if((millis - pttTimer) % 300l < 150l) { + GlStateManager.color(0.9f, 0.2f, 0.2f, 1.0f); + }else { + GlStateManager.color(0.9f, 0.7f, 0.7f, 1.0f); + } + }else { + GlStateManager.color(0.9f, 0.3f, 0.3f, 1.0f); + } + drawTexturedModalRect(0, 0, 0, 64, 32, 32); + }else { + pttTimer = 0l; + GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f); + drawTexturedModalRect(0, 0, 0, 32, 32, 32); + GlStateManager.translate(-1.5f, -1.5f, 0.0f); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + drawTexturedModalRect(0, 0, 0, 32, 32, 32); + GlStateManager.translate(-0.5f, -0.5f, 0.0f); + drawTexturedModalRect(0, 0, 0, 32, 32, 32); + } + + GlStateManager.popMatrix(); + + if(VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) { + Set listeners = VoiceClientController.getVoiceListening(); + if(listeners.size() > 0) { + Set speakers = VoiceClientController.getVoiceSpeaking(); + Set muted = VoiceClientController.getVoiceMuted(); + + List listenerList = new ArrayList(); + listenerList.addAll(listeners); + listenerList.removeAll(muted); + + while(listenerList.size() > 5) { + boolean flag = false; + for(int i = 0, l = listenerList.size(); i < l; ++i) { + if(!speakers.contains(listenerList.get(i))) { + listenerList.remove(i); + flag = true; + break; + } + } + if(!flag) { + break; + } + } + + int more = listenerList.size() - 5; + + int ww = width; + int hh = height; + + if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) { + hh -= 15; + } + + List listenerListStr = new ArrayList(Math.min(5, listenerList.size())); + + int left = 50; + for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) { + String txt = VoiceClientController.getVoiceUsername(listenerList.get(i)); + listenerListStr.add(txt); + int j = mc.fontRendererObj.getStringWidth(txt) + 4; + if(j > left) { + left = j; + } + } + + if(more > 0) { + GlStateManager.pushMatrix(); + GlStateManager.translate(ww - left + 3, hh - 10, left); + GlStateManager.scale(0.75f, 0.75f, 0.75f); + drawString(mc.fontRendererObj, "(" + more + " more)", 0, 0, 0xBBBBBB); + GlStateManager.popMatrix(); + hh -= 9; + } + + for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) { + boolean speaking = speakers.contains(listenerList.get(i)); + float speakf = speaking ? 1.0f : 0.75f; + + drawString(mc.fontRendererObj, listenerListStr.get(i), ww - left, hh - 13 - i * 11, speaking ? 0xEEEEEE : 0xBBBBBB); + + mc.getTextureManager().bindTexture(voiceGuiIcons); + + GlStateManager.pushMatrix(); + GlStateManager.translate(ww - left - 14, hh - 14 - i * 11, 0.0f); + + GlStateManager.scale(0.75f, 0.75f, 0.75f); + GlStateManager.color(speakf * 0.2f, speakf * 0.2f, speakf * 0.2f, 1.0f); + drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16); + GlStateManager.translate(0.25f, 0.25f, 0.0f); + drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16); + + GlStateManager.translate(-1.25f, -1.25f, 0.0f); + GlStateManager.color(speakf, speakf, speakf, 1.0f); + drawTexturedModalRect(0, 0, 64, speaking ? 176 : 208, 16, 16); + + GlStateManager.popMatrix(); + + } + + } + }else if(VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.GLOBAL) { + Set speakers = VoiceClientController.getVoiceSpeaking(); + Set muted = VoiceClientController.getVoiceMuted(); + + List listenerList = new ArrayList(); + listenerList.addAll(speakers); + listenerList.removeAll(muted); + + int more = listenerList.size() - 5; + + int ww = width; + int hh = height; + + if(mc.currentScreen != null && (mc.currentScreen instanceof GuiChat)) { + hh -= 15; + } + + List listenerListStr = new ArrayList(Math.min(5, listenerList.size())); + + int left = 50; + for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) { + String txt = VoiceClientController.getVoiceUsername(listenerList.get(i)); + listenerListStr.add(txt); + int j = mc.fontRendererObj.getStringWidth(txt) + 4; + if(j > left) { + left = j; + } + } + + if(more > 0) { + GlStateManager.pushMatrix(); + GlStateManager.translate(ww - left + 3, hh - 10, left); + GlStateManager.scale(0.75f, 0.75f, 0.75f); + drawString(mc.fontRendererObj, "(" + more + " more)", 0, 0, 0xBBBBBB); + GlStateManager.popMatrix(); + hh -= 9; + } + + for(int i = 0, l = listenerList.size(); i < l && i < 5; ++i) { + drawString(mc.fontRendererObj, listenerListStr.get(i), ww - left, hh - 13 - i * 11, 0xEEEEEE); + + mc.getTextureManager().bindTexture(voiceGuiIcons); + + GlStateManager.pushMatrix(); + GlStateManager.translate(ww - left - 14, hh - 14 - i * 11, 0.0f); + + GlStateManager.scale(0.75f, 0.75f, 0.75f); + GlStateManager.color(0.2f, 0.2f, 0.2f, 1.0f); + drawTexturedModalRect(0, 0, 64, 176, 16, 16); + GlStateManager.translate(0.25f, 0.25f, 0.0f); + drawTexturedModalRect(0, 0, 64, 176, 16, 16); + + GlStateManager.translate(-1.25f, -1.25f, 0.0f); + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + drawTexturedModalRect(0, 0, 64, 176, 16, 16); + + GlStateManager.popMatrix(); + + } + } + } + } + +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceClientController.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceClientController.java new file mode 100644 index 0000000..08be439 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceClientController.java @@ -0,0 +1,367 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.Consumer; +import java.util.stream.Collectors; + +import net.lax1dude.eaglercraft.v1_8.EagRuntime; +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.Keyboard; +import net.lax1dude.eaglercraft.v1_8.internal.PlatformVoiceClient; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.profile.EaglerProfile; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.PacketBuffer; + +/** + * Copyright (c) 2022-2024 lax1dude, 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 VoiceClientController { + + public static final String SIGNAL_CHANNEL = "EAG|Voice-1.8"; + + static final Logger logger = LogManager.getLogger("VoiceClientController"); + + private static boolean clientSupport = false; + private static boolean serverSupport = false; + private static Consumer packetSendCallback = null; + private static EnumVoiceChannelType voiceChannel = EnumVoiceChannelType.NONE; + private static final HashSet nearbyPlayers = new HashSet<>(); + private static final ExpiringSet recentlyNearbyPlayers = new ExpiringSet<>(5000, uuid -> { + if (!nearbyPlayers.contains(uuid)) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + }); + private static final Map uuidToNameLookup = new HashMap<>(256); + + public static boolean isSupported() { + return isClientSupported() && isServerSupported(); + } + + private static boolean checked = false; + + public static boolean isClientSupported() { + if (!checked) { + checked = true; + clientSupport = EagRuntime.getConfiguration().isAllowVoiceClient() && PlatformVoiceClient.isSupported(); + } + return clientSupport; + } + + public static boolean isServerSupported() { + return serverSupport; + } + + public static void initializeVoiceClient(Consumer signalSendCallbackIn) { + packetSendCallback = signalSendCallbackIn; + uuidToNameLookup.clear(); + if (getVoiceChannel() != EnumVoiceChannelType.NONE) sendInitialVoice(); + } + + public static void handleVoiceSignalPacket(PacketBuffer packetData) { + VoiceSignalPackets.handleVoiceSignal(packetData); + } + + static void handleVoiceSignalPacketTypeGlobal(EaglercraftUUID[] voicePlayers, String[] voiceNames) { + uuidToNameLookup.clear(); + for (int i = 0; i < voicePlayers.length; i++) { + if(voiceNames != null) { + uuidToNameLookup.put(voicePlayers[i], voiceNames[i]); + } + sendPacketRequestIfNeeded(voicePlayers[i]); + } + } + + public static void handleServerDisconnect() { + if(!isClientSupported()) return; + serverSupport = false; + uuidToNameLookup.clear(); + for (EaglercraftUUID uuid : nearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + for (EaglercraftUUID uuid : recentlyNearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + nearbyPlayers.clear(); + recentlyNearbyPlayers.clear(); + Set antiConcurrentModificationUUIDs = new HashSet<>(listeningSet); + for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + activateVoice(false); + } + + static void handleVoiceSignalPacketTypeAllowed(boolean voiceAvailableStat, String[] servs) { + serverSupport = voiceAvailableStat; + PlatformVoiceClient.setICEServers(servs); + if(isSupported()) { + EnumVoiceChannelType ch = getVoiceChannel(); + setVoiceChannel(EnumVoiceChannelType.NONE); + setVoiceChannel(ch); + } + } + + static void handleVoiceSignalPacketTypeConnect(EaglercraftUUID user, boolean offer) { + PlatformVoiceClient.signalConnect(user, offer); + } + + static void handleVoiceSignalPacketTypeConnectAnnounce(EaglercraftUUID user) { + sendPacketRequest(user); + } + + static void handleVoiceSignalPacketTypeDisconnect(EaglercraftUUID user) { + PlatformVoiceClient.signalDisconnect(user, true); + } + + static void handleVoiceSignalPacketTypeICECandidate(EaglercraftUUID user, String ice) { + PlatformVoiceClient.signalICECandidate(user, ice); + } + + static void handleVoiceSignalPacketTypeDescription(EaglercraftUUID user, String desc) { + PlatformVoiceClient.signalDescription(user, desc); + } + + public static void tickVoiceClient(Minecraft mc) { + if(!isClientSupported()) return; + recentlyNearbyPlayers.checkForExpirations(); + speakingSet.clear(); + PlatformVoiceClient.tickVoiceClient(); + + if (getVoiceChannel() != EnumVoiceChannelType.NONE && (getVoiceStatus() == EnumVoiceChannelStatus.CONNECTING || getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED)) { + activateVoice((mc.currentScreen == null || !mc.currentScreen.blockPTTKey()) && Keyboard.isKeyDown(mc.gameSettings.voicePTTKey)); + + if (mc.theWorld != null && mc.thePlayer != null) { + HashSet seenPlayers = new HashSet<>(); + for (EntityPlayer player : mc.theWorld.playerEntities) { + if (player == mc.thePlayer) continue; + if (getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) updateVoicePosition(player.getUniqueID(), player.posX, player.posY + player.getEyeHeight(), player.posZ); + int prox = 22; + // cube + if (Math.abs(mc.thePlayer.posX - player.posX) <= prox && Math.abs(mc.thePlayer.posY - player.posY) <= prox && Math.abs(mc.thePlayer.posZ - player.posZ) <= prox) { + if (!uuidToNameLookup.containsKey(player.getUniqueID())) { + uuidToNameLookup.put(player.getUniqueID(), player.getName()); + } + if (addNearbyPlayer(player.getUniqueID())) { + seenPlayers.add(player.getUniqueID()); + } + } + } + cleanupNearbyPlayers(seenPlayers); + } + } + } + + public static final boolean addNearbyPlayer(EaglercraftUUID uuid) { + recentlyNearbyPlayers.remove(uuid); + if (nearbyPlayers.add(uuid)) { + sendPacketRequestIfNeeded(uuid); + return true; + } + return false; + } + + public static final void removeNearbyPlayer(EaglercraftUUID uuid) { + if (nearbyPlayers.remove(uuid)) { + if (getVoiceStatus() == EnumVoiceChannelStatus.DISCONNECTED || getVoiceStatus() == EnumVoiceChannelStatus.UNAVAILABLE) return; + if (voiceChannel == EnumVoiceChannelType.PROXIMITY) recentlyNearbyPlayers.add(uuid); + } + } + + public static final void cleanupNearbyPlayers(HashSet existingPlayers) { + nearbyPlayers.stream().filter(ud -> !existingPlayers.contains(ud)).collect(Collectors.toSet()).forEach(VoiceClientController::removeNearbyPlayer); + } + + public static final void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) { + PlatformVoiceClient.updateVoicePosition(uuid, x, y, z); + } + + public static void setVoiceChannel(EnumVoiceChannelType channel) { + if (voiceChannel == channel) return; + if (channel != EnumVoiceChannelType.NONE) PlatformVoiceClient.initializeDevices(); + PlatformVoiceClient.resetPeerStates(); + if (channel == EnumVoiceChannelType.NONE) { + for (EaglercraftUUID uuid : nearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + for (EaglercraftUUID uuid : recentlyNearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + nearbyPlayers.clear(); + recentlyNearbyPlayers.clear(); + Set antiConcurrentModificationUUIDs = new HashSet<>(listeningSet); + for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + sendPacketDisconnect(null); + activateVoice(false); + } else if (voiceChannel == EnumVoiceChannelType.PROXIMITY) { + for (EaglercraftUUID uuid : nearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + for (EaglercraftUUID uuid : recentlyNearbyPlayers) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + nearbyPlayers.clear(); + recentlyNearbyPlayers.clear(); + sendPacketDisconnect(null); + } else if(voiceChannel == EnumVoiceChannelType.GLOBAL) { + Set antiConcurrentModificationUUIDs = new HashSet<>(listeningSet); + antiConcurrentModificationUUIDs.removeAll(nearbyPlayers); + antiConcurrentModificationUUIDs.removeAll(recentlyNearbyPlayers); + for (EaglercraftUUID uuid : antiConcurrentModificationUUIDs) { + PlatformVoiceClient.signalDisconnect(uuid, false); + } + sendPacketDisconnect(null); + } + voiceChannel = channel; + if (channel != EnumVoiceChannelType.NONE) { + sendInitialVoice(); + } + } + + public static void sendInitialVoice() { + sendPacketConnect(); + for (EaglercraftUUID uuid : nearbyPlayers) { + sendPacketRequest(uuid); + } + } + + public static EnumVoiceChannelType getVoiceChannel() { + return voiceChannel; + } + + private static boolean voicePeerErrored() { + return PlatformVoiceClient.getPeerState() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateConnect() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateInitial() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateDesc() == EnumVoiceChannelPeerState.FAILED || PlatformVoiceClient.getPeerStateIce() == EnumVoiceChannelPeerState.FAILED; + } + public static EnumVoiceChannelStatus getVoiceStatus() { + return (!isClientSupported() || !isServerSupported()) ? EnumVoiceChannelStatus.UNAVAILABLE : + (PlatformVoiceClient.getReadyState() != EnumVoiceChannelReadyState.DEVICE_INITIALIZED ? + EnumVoiceChannelStatus.CONNECTING : (voicePeerErrored() ? EnumVoiceChannelStatus.UNAVAILABLE : EnumVoiceChannelStatus.CONNECTED)); + } + + private static boolean talkStatus = false; + + public static void activateVoice(boolean talk) { + if (talkStatus != talk) { + PlatformVoiceClient.activateVoice(talk); + talkStatus = talk; + } + } + + private static int proximity = 16; + + public static void setVoiceProximity(int prox) { + PlatformVoiceClient.setVoiceProximity(prox); + proximity = prox; + } + + public static int getVoiceProximity() { + return proximity; + } + + private static float volumeListen = 0.5f; + + public static void setVoiceListenVolume(float f) { + PlatformVoiceClient.setVoiceListenVolume(f); + volumeListen = f; + } + + public static float getVoiceListenVolume() { + return volumeListen; + } + + private static float volumeSpeak = 0.5f; + + public static void setVoiceSpeakVolume(float f) { + if (volumeSpeak != f) { + PlatformVoiceClient.setMicVolume(f); + } + volumeSpeak = f; + } + + public static float getVoiceSpeakVolume() { + return volumeSpeak; + } + + private static final Set listeningSet = new HashSet<>(); + private static final Set speakingSet = new HashSet<>(); + private static final Set mutedSet = new HashSet<>(); + + public static Set getVoiceListening() { + return listeningSet; + } + + public static Set getVoiceSpeaking() { + return speakingSet; + } + + public static void setVoiceMuted(EaglercraftUUID uuid, boolean mute) { + PlatformVoiceClient.mutePeer(uuid, mute); + if (mute) { + mutedSet.add(uuid); + } else { + mutedSet.remove(uuid); + } + } + + public static Set getVoiceMuted() { + return mutedSet; + } + + public static List getVoiceRecent() { + return new ArrayList<>(listeningSet); + } + + public static String getVoiceUsername(EaglercraftUUID uuid) { + if(uuid == null) { + return "null"; + } + String ret = uuidToNameLookup.get(uuid); + return ret == null ? uuid.toString() : ret; + } + + public static void sendPacketICE(EaglercraftUUID peerId, String candidate) { + packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketICE(peerId, candidate)); + } + + public static void sendPacketDesc(EaglercraftUUID peerId, String desc) { + packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketDesc(peerId, desc)); + } + + public static void sendPacketDisconnect(EaglercraftUUID peerId) { + packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketDisconnect(peerId)); + } + + public static void sendPacketConnect() { + packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketConnect()); + } + + public static void sendPacketRequest(EaglercraftUUID peerId) { + packetSendCallback.accept(VoiceSignalPackets.makeVoiceSignalPacketRequest(peerId)); + } + + private static void sendPacketRequestIfNeeded(EaglercraftUUID uuid) { + if (getVoiceStatus() == EnumVoiceChannelStatus.DISCONNECTED || getVoiceStatus() == EnumVoiceChannelStatus.UNAVAILABLE) return; + if(uuid.equals(EaglerProfile.getPlayerUUID())) return; + if (!getVoiceListening().contains(uuid)) sendPacketRequest(uuid); + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceSignalPackets.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceSignalPackets.java new file mode 100644 index 0000000..be36777 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceSignalPackets.java @@ -0,0 +1,142 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import java.nio.charset.StandardCharsets; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.minecraft.network.PacketBuffer; + +/** + * Copyright (c) 2024 lax1dude, 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 VoiceSignalPackets { + + static final int VOICE_SIGNAL_ALLOWED = 0; + static final int VOICE_SIGNAL_REQUEST = 0; + static final int VOICE_SIGNAL_CONNECT = 1; + static final int VOICE_SIGNAL_DISCONNECT = 2; + static final int VOICE_SIGNAL_ICE = 3; + static final int VOICE_SIGNAL_DESC = 4; + static final int VOICE_SIGNAL_GLOBAL = 5; + + static void handleVoiceSignal(PacketBuffer streamIn) { + try { + int sig = streamIn.readUnsignedByte(); + switch(sig) { + case VOICE_SIGNAL_ALLOWED: { + boolean voiceAvailableStat = streamIn.readUnsignedByte() == 1; + String[] servs = null; + if(voiceAvailableStat) { + servs = new String[streamIn.readVarIntFromBuffer()]; + for(int i = 0; i < servs.length; i++) { + servs[i] = streamIn.readStringFromBuffer(1024); + } + } + VoiceClientController.handleVoiceSignalPacketTypeAllowed(voiceAvailableStat, servs); + break; + } + case VOICE_SIGNAL_GLOBAL: { + if (VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.GLOBAL) return; + EaglercraftUUID[] voiceIds = new EaglercraftUUID[streamIn.readVarIntFromBuffer()]; + for(int i = 0; i < voiceIds.length; i++) { + voiceIds[i] = streamIn.readUuid(); + } + String[] voiceNames = null; + if (streamIn.isReadable()) { + voiceNames = new String[voiceIds.length]; + for(int i = 0; i < voiceNames.length; i++) { + voiceNames[i] = streamIn.readStringFromBuffer(16); + } + } + VoiceClientController.handleVoiceSignalPacketTypeGlobal(voiceIds, voiceNames); + break; + } + case VOICE_SIGNAL_CONNECT: { + EaglercraftUUID uuid = streamIn.readUuid(); + if (streamIn.isReadable()) { + VoiceClientController.handleVoiceSignalPacketTypeConnect(uuid, streamIn.readBoolean()); + } else if (VoiceClientController.getVoiceChannel() != EnumVoiceChannelType.PROXIMITY || VoiceClientController.getVoiceListening().contains(uuid)) { + VoiceClientController.handleVoiceSignalPacketTypeConnectAnnounce(uuid); + } + break; + } + case VOICE_SIGNAL_DISCONNECT: { + VoiceClientController.handleVoiceSignalPacketTypeDisconnect(streamIn.readableBytes() > 0 ? streamIn.readUuid() : null); + break; + } + case VOICE_SIGNAL_ICE: { + VoiceClientController.handleVoiceSignalPacketTypeICECandidate(streamIn.readUuid(), streamIn.readStringFromBuffer(32767)); + break; + } + case VOICE_SIGNAL_DESC: { + VoiceClientController.handleVoiceSignalPacketTypeDescription(streamIn.readUuid(), streamIn.readStringFromBuffer(32767)); + break; + } + default: { + VoiceClientController.logger.error("Unknown voice signal packet '{}'!", sig); + break; + } + } + }catch(Throwable ex) { + VoiceClientController.logger.error("Failed to handle signal packet!"); + VoiceClientController.logger.error(ex); + } + } + + static PacketBuffer makeVoiceSignalPacketRequest(EaglercraftUUID user) { + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17)); + ret.writeByte(VOICE_SIGNAL_REQUEST); + ret.writeUuid(user); + return ret; + } + + static PacketBuffer makeVoiceSignalPacketICE(EaglercraftUUID user, String icePacket) { + byte[] str = icePacket.getBytes(StandardCharsets.UTF_8); + int estLen = 17 + PacketBuffer.getVarIntSize(str.length) + str.length; + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(estLen, estLen)); + ret.writeByte(VOICE_SIGNAL_ICE); + ret.writeUuid(user); + ret.writeByteArray(str); + return ret; + } + + static PacketBuffer makeVoiceSignalPacketDesc(EaglercraftUUID user, String descPacket) { + byte[] str = descPacket.getBytes(StandardCharsets.UTF_8); + int estLen = 17 + PacketBuffer.getVarIntSize(str.length) + str.length; + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(estLen, estLen)); + ret.writeByte(VOICE_SIGNAL_DESC); + ret.writeUuid(user); + ret.writeByteArray(str); + return ret; + } + + static PacketBuffer makeVoiceSignalPacketDisconnect(EaglercraftUUID user) { + if (user == null) { + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(1, 1)); + ret.writeByte(VOICE_SIGNAL_DISCONNECT); + return ret; + } + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(17, 17)); + ret.writeByte(VOICE_SIGNAL_DISCONNECT); + ret.writeUuid(user); + return ret; + } + + public static PacketBuffer makeVoiceSignalPacketConnect() { + PacketBuffer ret = new PacketBuffer(Unpooled.buffer(1, 1)); + ret.writeByte(VOICE_SIGNAL_CONNECT); + return ret; + } +} \ No newline at end of file diff --git a/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceTagRenderer.java b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceTagRenderer.java new file mode 100644 index 0000000..17ba1c8 --- /dev/null +++ b/src/main/java/net/lax1dude/eaglercraft/v1_8/voice/VoiceTagRenderer.java @@ -0,0 +1,118 @@ +package net.lax1dude.eaglercraft.v1_8.voice; + +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + +import java.util.HashSet; +import java.util.Set; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; +import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.ResourceLocation; + +/** + * 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 VoiceTagRenderer { + + private static final ResourceLocation voiceGuiIcons = new ResourceLocation("eagler:gui/eagler_gui.png"); + + private static final Set voiceTagsDrawnThisFrame = new HashSet(); + + public static void renderVoiceNameTag(Minecraft mc, EntityOtherPlayerMP player, int offset) { + EaglercraftUUID uuid = player.getUniqueID(); + boolean mute = VoiceClientController.getVoiceMuted().contains(uuid); + if((mute || VoiceClientController.getVoiceSpeaking().contains(uuid)) && voiceTagsDrawnThisFrame.add(uuid)) { + GlStateManager.disableLighting(); + GlStateManager.disableTexture2D(); + GlStateManager.enableAlpha(); + GlStateManager.depthMask(false); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + + GlStateManager.pushMatrix(); + GlStateManager.translate(-8.0f, -18.0f + offset, 0.0f); + + GlStateManager.scale(16.0f, 16.0f, 16.0f); + + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + worldrenderer.begin(7, DefaultVertexFormats.POSITION_COLOR); + float a = 0.25F; + worldrenderer.pos(-0.02, -0.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex(); + worldrenderer.pos(-0.02, 1.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex(); + worldrenderer.pos(1.02, 1.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex(); + worldrenderer.pos(1.02, -0.02, 0.0).color(0.0F, 0.0F, 0.0F, a).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL_GREATER, 0.02f); + + mc.getTextureManager().bindTexture(voiceGuiIcons); + + int u = 0; + int v = mute ? 192 : 160; + + float var7 = 0.00390625F; + float var8 = 0.00390625F; + + if(mute) { + GlStateManager.color(0.9F, 0.3F, 0.3F, 0.125F); + }else { + GlStateManager.color(1.0F, 1.0F, 1.0F, 0.125F); + } + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(0, 1.0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex(); + worldrenderer.pos(1.0, 1.0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex(); + worldrenderer.pos(1.0, 0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex(); + worldrenderer.pos(0, 0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex(); + tessellator.draw(); + + GlStateManager.alphaFunc(GL_GREATER, 0.1f); + GlStateManager.enableDepth(); + GlStateManager.depthMask(true); + + if(mute) { + GlStateManager.color(0.9F, 0.3F, 0.3F, 1.0F); + }else { + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + } + + worldrenderer.begin(7, DefaultVertexFormats.POSITION_TEX); + worldrenderer.pos(0, 1.0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex(); + worldrenderer.pos(1.0, 1.0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 32 - 0.2f) * var8)).endVertex(); + worldrenderer.pos(1.0, 0, 0).tex((double) ((float) (u + 32 - 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex(); + worldrenderer.pos(0, 0, 0).tex((double) ((float) (u + 0.2f) * var7), (double) ((float) (v + 0.2f) * var8)).endVertex(); + tessellator.draw(); + + GlStateManager.enableLighting(); + GlStateManager.disableBlend(); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + GlStateManager.popMatrix(); + } + } + + public static void clearTagsDrawnSet() { + voiceTagsDrawnThisFrame.clear(); + } + +} \ No newline at end of file diff --git a/src/main/java/net/minecraft/block/BlockRedstoneWire.java b/src/main/java/net/minecraft/block/BlockRedstoneWire.java index 332db33..e9ea362 100644 --- a/src/main/java/net/minecraft/block/BlockRedstoneWire.java +++ b/src/main/java/net/minecraft/block/BlockRedstoneWire.java @@ -99,7 +99,7 @@ public class BlockRedstoneWire extends Block { BlockPos posTmp = new BlockPos(0, 0, 0); Block block = worldIn.getBlockState(blockpos).getBlock(); if (!canConnectTo(worldIn.getBlockState(blockpos), direction) && (block.isBlockNormalCube() - || !canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.UP, posTmp))))) { + || !canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.DOWN, posTmp))))) { Block block1 = worldIn.getBlockState(pos.up()).getBlock(); return !block1.isBlockNormalCube() && block.isBlockNormalCube() && canConnectUpwardsTo(worldIn.getBlockState(blockpos.offsetEvenFaster(EnumFacing.UP, posTmp))) @@ -177,11 +177,13 @@ public class BlockRedstoneWire extends Block { if (worldIn.getBlockState(blockpos).getBlock().isNormalCube() && !worldIn.getBlockState(pos1.up()).getBlock().isNormalCube()) { if (flag && pos1.getY() >= pos2.getY()) { - l = this.getMaxCurrentStrength(worldIn, blockpos.up(), l); + ++blockpos.y; + l = this.getMaxCurrentStrength(worldIn, blockpos, l); } } else if (!worldIn.getBlockState(blockpos).getBlock().isNormalCube() && flag && pos1.getY() <= pos2.getY()) { - l = this.getMaxCurrentStrength(worldIn, blockpos.down(), l); + --blockpos.y; + l = this.getMaxCurrentStrength(worldIn, blockpos, l); } } @@ -205,6 +207,7 @@ public class BlockRedstoneWire extends Block { this.blocksNeedingUpdate.add(pos1); + facings = EnumFacing._VALUES; for (int m = 0; m < facings.length; ++m) { this.blocksNeedingUpdate.add(pos1.offset(facings[m])); } diff --git a/src/main/java/net/minecraft/client/entity/AbstractClientPlayer.java b/src/main/java/net/minecraft/client/entity/AbstractClientPlayer.java index 9657182..f0042c9 100644 --- a/src/main/java/net/minecraft/client/entity/AbstractClientPlayer.java +++ b/src/main/java/net/minecraft/client/entity/AbstractClientPlayer.java @@ -1,6 +1,7 @@ package net.minecraft.client.entity; import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile; +import net.lax1dude.eaglercraft.v1_8.profile.SkinModel; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.client.resources.DefaultPlayerSkin; @@ -34,6 +35,14 @@ import net.minecraft.world.WorldSettings; */ public abstract class AbstractClientPlayer extends EntityPlayer { private NetworkPlayerInfo playerInfo; + + public long eaglerHighPolyAnimationTick = System.currentTimeMillis(); + public float eaglerHighPolyAnimationFloat1 = 0.0f; + public float eaglerHighPolyAnimationFloat2 = 0.0f; + public float eaglerHighPolyAnimationFloat3 = 0.0f; + public float eaglerHighPolyAnimationFloat4 = 0.0f; + public float eaglerHighPolyAnimationFloat5 = 0.0f; + public float eaglerHighPolyAnimationFloat6 = 0.0f; public AbstractClientPlayer(World worldIn, GameProfile playerProfile) { super(worldIn, playerProfile); @@ -91,6 +100,11 @@ public abstract class AbstractClientPlayer extends EntityPlayer { return networkplayerinfo == null ? DefaultPlayerSkin.getSkinType(this.getUniqueID()) : networkplayerinfo.getSkinType(); } + + public SkinModel getEaglerSkinModel() { + NetworkPlayerInfo networkplayerinfo = this.getPlayerInfo(); + return networkplayerinfo == null ? SkinModel.STEVE : networkplayerinfo.getEaglerSkinModel(); + } public float getFovModifier() { float f = 1.0F; diff --git a/src/main/java/net/minecraft/client/gui/GuiButton.java b/src/main/java/net/minecraft/client/gui/GuiButton.java index 39e831f..f7a6fbd 100644 --- a/src/main/java/net/minecraft/client/gui/GuiButton.java +++ b/src/main/java/net/minecraft/client/gui/GuiButton.java @@ -32,8 +32,8 @@ import net.minecraft.util.ResourceLocation; */ public class GuiButton extends Gui { protected static final ResourceLocation buttonTextures = new ResourceLocation("textures/gui/widgets.png"); - protected int width; - protected int height; + public int width; + public int height; public int xPosition; public int yPosition; public String displayString; diff --git a/src/main/java/net/minecraft/client/gui/GuiChat.java b/src/main/java/net/minecraft/client/gui/GuiChat.java index 6fea820..6d38229 100644 --- a/src/main/java/net/minecraft/client/gui/GuiChat.java +++ b/src/main/java/net/minecraft/client/gui/GuiChat.java @@ -341,4 +341,8 @@ public class GuiChat extends GuiScreen { public boolean doesGuiPauseGame() { return false; } + + public boolean blockPTTKey() { + return true; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/gui/GuiCommandBlock.java b/src/main/java/net/minecraft/client/gui/GuiCommandBlock.java index f6813d0..05a2bf0 100644 --- a/src/main/java/net/minecraft/client/gui/GuiCommandBlock.java +++ b/src/main/java/net/minecraft/client/gui/GuiCommandBlock.java @@ -189,4 +189,8 @@ public class GuiCommandBlock extends GuiScreen { } } + + public boolean blockPTTKey() { + return commandTextField.isFocused(); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/gui/GuiCustomizeSkin.java b/src/main/java/net/minecraft/client/gui/GuiCustomizeSkin.java index 92fa729..2ac38b7 100644 --- a/src/main/java/net/minecraft/client/gui/GuiCustomizeSkin.java +++ b/src/main/java/net/minecraft/client/gui/GuiCustomizeSkin.java @@ -26,6 +26,8 @@ import net.minecraft.entity.player.EnumPlayerModelParts; public class GuiCustomizeSkin extends GuiScreen { private final GuiScreen parentScreen; private String title; + + private GuiButton enableFNAWSkinsButton; public GuiCustomizeSkin(GuiScreen parentScreenIn) { this.parentScreen = parentScreenIn; @@ -53,7 +55,10 @@ public class GuiCustomizeSkin extends GuiScreen { ++i; } - this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 24 * (i >> 1), + this.buttonList.add(enableFNAWSkinsButton = new GuiButton(201, this.width / 2 - 100, + this.height / 6 + 10 + 24 * (i >> 1), I18n.format("options.skinCustomisation.enableFNAWSkins") + ": " + + I18n.format(mc.gameSettings.enableFNAWSkins ? "options.on" : "options.off"))); + this.buttonList.add(new GuiButton(200, this.width / 2 - 100, this.height / 6 + 40 + 24 * (i >> 1), I18n.format("gui.done", new Object[0]))); } @@ -66,6 +71,11 @@ public class GuiCustomizeSkin extends GuiScreen { if (parGuiButton.id == 200) { this.mc.gameSettings.saveOptions(); this.mc.displayGuiScreen(this.parentScreen); + } else if (parGuiButton.id == 201) { + mc.gameSettings.enableFNAWSkins = !mc.gameSettings.enableFNAWSkins; + mc.getRenderManager().setEnableFNAWSkins(mc.getEnableFNAWSkins()); + enableFNAWSkinsButton.displayString = I18n.format("options.skinCustomisation.enableFNAWSkins") + ": " + + I18n.format(mc.gameSettings.enableFNAWSkins ? "options.on" : "options.off"); } else if (parGuiButton instanceof GuiCustomizeSkin.ButtonPart) { EnumPlayerModelParts enumplayermodelparts = ((GuiCustomizeSkin.ButtonPart) parGuiButton).playerModelParts; this.mc.gameSettings.switchModelPartEnabled(enumplayermodelparts); diff --git a/src/main/java/net/minecraft/client/gui/GuiOptions.java b/src/main/java/net/minecraft/client/gui/GuiOptions.java index ba7084f..9044be0 100644 --- a/src/main/java/net/minecraft/client/gui/GuiOptions.java +++ b/src/main/java/net/minecraft/client/gui/GuiOptions.java @@ -133,7 +133,7 @@ public class GuiOptions extends GuiScreen implements GuiYesNoCallback { chatcomponenttext.appendText(": "); chatcomponenttext.appendSibling( new ChatComponentTranslation(parEnumDifficulty.getDifficultyResourceKey(), new Object[0])); - return chatcomponenttext.getFormattedText(); + return chatcomponenttext.getUnformattedText(); } public void confirmClicked(boolean flag, int i) { diff --git a/src/main/java/net/minecraft/client/gui/GuiRepair.java b/src/main/java/net/minecraft/client/gui/GuiRepair.java index a10a1e0..8a2b454 100644 --- a/src/main/java/net/minecraft/client/gui/GuiRepair.java +++ b/src/main/java/net/minecraft/client/gui/GuiRepair.java @@ -224,4 +224,8 @@ public class GuiRepair extends GuiContainer implements ICrafting { public void func_175173_a(Container parContainer, IInventory parIInventory) { } + + public boolean blockPTTKey() { + return nameField.isFocused(); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/gui/GuiScreenBook.java b/src/main/java/net/minecraft/client/gui/GuiScreenBook.java index 39f1564..51253e6 100644 --- a/src/main/java/net/minecraft/client/gui/GuiScreenBook.java +++ b/src/main/java/net/minecraft/client/gui/GuiScreenBook.java @@ -551,4 +551,8 @@ public class GuiScreenBook extends GuiScreen { } } } + + public boolean blockPTTKey() { + return this.bookIsUnsigned; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/gui/GuiVideoSettings.java b/src/main/java/net/minecraft/client/gui/GuiVideoSettings.java index 4908d29..6c69e95 100644 --- a/src/main/java/net/minecraft/client/gui/GuiVideoSettings.java +++ b/src/main/java/net/minecraft/client/gui/GuiVideoSettings.java @@ -49,7 +49,7 @@ public class GuiVideoSettings extends GuiScreen { GameSettings.Options.AO_LEVEL, GameSettings.Options.VIEW_BOBBING, GameSettings.Options.GUI_SCALE, - GameSettings.Options.USE_VBO, + GameSettings.Options.EAGLER_VSYNC, GameSettings.Options.GAMMA, GameSettings.Options.BLOCK_ALTERNATIVES, GameSettings.Options.FOG_FANCY, @@ -182,6 +182,7 @@ public class GuiVideoSettings extends GuiScreen { int j = scaledresolution.getScaledWidth(); int k = scaledresolution.getScaledHeight(); this.setWorldAndResolution(this.mc, j, k); + this.mc.voiceOverlay.setResolution(j, k); } } diff --git a/src/main/java/net/minecraft/client/gui/inventory/GuiContainerCreative.java b/src/main/java/net/minecraft/client/gui/inventory/GuiContainerCreative.java index 9cb035b..446e65c 100644 --- a/src/main/java/net/minecraft/client/gui/inventory/GuiContainerCreative.java +++ b/src/main/java/net/minecraft/client/gui/inventory/GuiContainerCreative.java @@ -854,4 +854,8 @@ public class GuiContainerCreative extends InventoryEffectRenderer { return this.slot.isHere(inv, slotIn); } } + + public boolean blockPTTKey() { + return searchField.isFocused(); + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/gui/inventory/GuiEditSign.java b/src/main/java/net/minecraft/client/gui/inventory/GuiEditSign.java index e4d0f13..247c32e 100644 --- a/src/main/java/net/minecraft/client/gui/inventory/GuiEditSign.java +++ b/src/main/java/net/minecraft/client/gui/inventory/GuiEditSign.java @@ -172,4 +172,8 @@ public class GuiEditSign extends GuiScreen { GlStateManager.popMatrix(); super.drawScreen(i, j, f); } + + public boolean blockPTTKey() { + return true; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/client/model/ModelPlayer.java b/src/main/java/net/minecraft/client/model/ModelPlayer.java index 7be4264..c3f2ec5 100644 --- a/src/main/java/net/minecraft/client/model/ModelPlayer.java +++ b/src/main/java/net/minecraft/client/model/ModelPlayer.java @@ -1,5 +1,7 @@ package net.minecraft.client.model; +import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; + import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.minecraft.entity.Entity; @@ -119,7 +121,14 @@ public class ModelPlayer extends ModelBiped { } public void renderCape(float parFloat1) { + GlStateManager.matrixMode(GL_TEXTURE); + GlStateManager.pushMatrix(); + GlStateManager.scale(2.0f, 1.0f, 1.0f); + GlStateManager.matrixMode(GL_MODELVIEW); this.bipedCape.render(parFloat1); + GlStateManager.matrixMode(GL_TEXTURE); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); } /**+ diff --git a/src/main/java/net/minecraft/client/multiplayer/PlayerControllerMP.java b/src/main/java/net/minecraft/client/multiplayer/PlayerControllerMP.java index 2d73c1f..de58e59 100644 --- a/src/main/java/net/minecraft/client/multiplayer/PlayerControllerMP.java +++ b/src/main/java/net/minecraft/client/multiplayer/PlayerControllerMP.java @@ -313,6 +313,7 @@ public class PlayerControllerMP { .closeChannel(new ChatComponentText("Exception thrown: " + ex.toString())); } this.netClientHandler.getSkinCache().flush(); + this.netClientHandler.getCapeCache().flush(); } else { this.netClientHandler.getNetworkManager().checkDisconnected(); } diff --git a/src/main/java/net/minecraft/client/network/NetworkPlayerInfo.java b/src/main/java/net/minecraft/client/network/NetworkPlayerInfo.java index 76b3ee3..5a1da5b 100644 --- a/src/main/java/net/minecraft/client/network/NetworkPlayerInfo.java +++ b/src/main/java/net/minecraft/client/network/NetworkPlayerInfo.java @@ -1,6 +1,7 @@ package net.minecraft.client.network; import net.lax1dude.eaglercraft.v1_8.mojang.authlib.GameProfile; +import net.lax1dude.eaglercraft.v1_8.profile.SkinModel; import net.minecraft.client.Minecraft; import net.minecraft.network.play.server.S38PacketPlayerListItem; import net.minecraft.scoreboard.ScorePlayerTeam; @@ -83,13 +84,17 @@ public class NetworkPlayerInfo { return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile) .getSkinModel().profileSkinType; } + + public SkinModel getEaglerSkinModel() { + return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getSkinModel(); + } public ResourceLocation getLocationSkin() { return Minecraft.getMinecraft().getNetHandler().getSkinCache().getSkin(this.gameProfile).getResourceLocation(); } public ResourceLocation getLocationCape() { - return null; + return Minecraft.getMinecraft().getNetHandler().getCapeCache().getCape(this.gameProfile.getId()).getResourceLocation(); } public ScorePlayerTeam getPlayerTeam() { diff --git a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java index 4e4092d..3c9693c 100644 --- a/src/main/java/net/minecraft/client/renderer/EntityRenderer.java +++ b/src/main/java/net/minecraft/client/renderer/EntityRenderer.java @@ -39,6 +39,7 @@ import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.ShadersRenderPassFuture import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.gui.GuiShaderConfig; import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.texture.EmissiveItems; import net.lax1dude.eaglercraft.v1_8.vector.Vector4f; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceTagRenderer; import net.lax1dude.eaglercraft.v1_8.vector.Matrix4f; import net.minecraft.block.Block; import net.minecraft.block.BlockBed; @@ -182,6 +183,8 @@ public class EntityRenderer implements IResourceManagerReloadListener { private boolean initialized = false; private DebugChunkRenderer chunkRenderer; private float clipDistance = 128.0F; + + public float currentProjMatrixFOV = 0.0f; public EntityRenderer(Minecraft mcIn, IResourceManager resourceManagerIn) { this.useShader = false; @@ -650,9 +653,9 @@ public class EntityRenderer implements IResourceManagerReloadListener { float farPlane = this.farPlaneDistance * 2.0f * MathHelper.SQRT_2; if(this.mc.gameSettings.renderDistanceChunks >= 2) { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); + GlStateManager.gluPerspective(currentProjMatrixFOV = this.getFOVModifier(partialTicks, true), (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); } else { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, farPlane); + GlStateManager.gluPerspective(currentProjMatrixFOV = this.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, farPlane); } DeferredStateManager.setGBufferNearFarPlanes(0.05f, farPlane); GlStateManager.matrixMode(GL_MODELVIEW); @@ -1081,6 +1084,8 @@ public class EntityRenderer implements IResourceManagerReloadListener { }); throw new ReportedException(crashreport); } + + this.mc.voiceOverlay.drawOverlay(); } } @@ -1158,6 +1163,8 @@ public class EntityRenderer implements IResourceManagerReloadListener { if (fxaa) { EffectPipelineFXAA.begin(this.mc.displayWidth, this.mc.displayHeight); } + + VoiceTagRenderer.clearTagsDrawnSet(); GlStateManager.enableDepth(); GlStateManager.enableAlpha(); @@ -1221,19 +1228,20 @@ public class EntityRenderer implements IResourceManagerReloadListener { this.mc.mcProfiler.endStartSection("sky"); GlStateManager.matrixMode(GL_PROJECTION); GlStateManager.loadIdentity(); + float vigg = this.getFOVModifier(partialTicks, true); if(this.mc.gameSettings.renderDistanceChunks >= 2) { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); + GlStateManager.gluPerspective(vigg, (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); } else { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * 4.0F); + GlStateManager.gluPerspective(vigg, (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * 4.0F); } GlStateManager.matrixMode(GL_MODELVIEW); renderglobal.renderSky(partialTicks, pass); GlStateManager.matrixMode(GL_PROJECTION); GlStateManager.loadIdentity(); if(this.mc.gameSettings.renderDistanceChunks >= 2) { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); + GlStateManager.gluPerspective(vigg, (float)this.mc.displayWidth / (float)this.mc.displayHeight, 0.05F, this.clipDistance); } else { - GlStateManager.gluPerspective(this.getFOVModifier(partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * MathHelper.SQRT_2); + GlStateManager.gluPerspective(vigg, (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * MathHelper.SQRT_2); } GlStateManager.matrixMode(GL_MODELVIEW); } else { diff --git a/src/main/java/net/minecraft/client/renderer/RenderGlobal.java b/src/main/java/net/minecraft/client/renderer/RenderGlobal.java index f4f9350..eadc01a 100644 --- a/src/main/java/net/minecraft/client/renderer/RenderGlobal.java +++ b/src/main/java/net/minecraft/client/renderer/RenderGlobal.java @@ -169,6 +169,7 @@ public class RenderGlobal implements IWorldAccess, IResourceManagerReloadListene private double lastViewEntityZ = Double.MIN_VALUE; private double lastViewEntityPitch = Double.MIN_VALUE; private double lastViewEntityYaw = Double.MIN_VALUE; + private float lastViewProjMatrixFOV = Float.MIN_VALUE; private final ChunkUpdateManager renderDispatcher = new ChunkUpdateManager(); private ChunkRenderContainer renderContainer; private int renderDistanceChunks = -1; @@ -894,12 +895,14 @@ public class RenderGlobal implements IWorldAccess, IResourceManagerReloadListene || viewEntity.posX != this.lastViewEntityX || viewEntity.posY != this.lastViewEntityY || viewEntity.posZ != this.lastViewEntityZ || (double) viewEntity.rotationPitch != this.lastViewEntityPitch - || (double) viewEntity.rotationYaw != this.lastViewEntityYaw; + || (double) viewEntity.rotationYaw != this.lastViewEntityYaw + || this.mc.entityRenderer.currentProjMatrixFOV != this.lastViewProjMatrixFOV; this.lastViewEntityX = viewEntity.posX; this.lastViewEntityY = viewEntity.posY; this.lastViewEntityZ = viewEntity.posZ; this.lastViewEntityPitch = (double) viewEntity.rotationPitch; this.lastViewEntityYaw = (double) viewEntity.rotationYaw; + this.lastViewProjMatrixFOV = this.mc.entityRenderer.currentProjMatrixFOV; boolean flag = this.debugFixedClippingHelper != null; Lagometer.timerVisibility.start(); if (!flag && this.displayListEntitiesDirty) { diff --git a/src/main/java/net/minecraft/client/renderer/entity/Render.java b/src/main/java/net/minecraft/client/renderer/entity/Render.java index d2f0ede..6a27da3 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/Render.java +++ b/src/main/java/net/minecraft/client/renderer/entity/Render.java @@ -8,8 +8,12 @@ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.NameTagRenderer; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelStatus; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceTagRenderer; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.culling.ICamera; @@ -126,6 +130,9 @@ public abstract class Render { * partialTickTime */ private void renderEntityOnFire(Entity entity, double x, double y, double z, float partialTicks) { + if (entity.width == 0 || entity.height == 0) { + return; + } GlStateManager.disableLighting(); TextureMap texturemap = Minecraft.getMinecraft().getTextureMapBlocks(); EaglerTextureAtlasSprite textureatlassprite = texturemap.getAtlasSprite("minecraft:blocks/fire_layer_0"); @@ -386,6 +393,13 @@ public abstract class Render { GlStateManager.enableLighting(); GlStateManager.disableBlend(); GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + if (entityIn instanceof EntityOtherPlayerMP) { + if (VoiceClientController.getVoiceStatus() == EnumVoiceChannelStatus.CONNECTED) { + VoiceTagRenderer.renderVoiceNameTag(Minecraft.getMinecraft(), (EntityOtherPlayerMP) entityIn, b0); + } + } + GlStateManager.popMatrix(); } } diff --git a/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java b/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java index dc23c21..fd7bcaf 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java +++ b/src/main/java/net/minecraft/client/renderer/entity/RenderManager.java @@ -8,9 +8,11 @@ import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.OpenGlHelper; import net.lax1dude.eaglercraft.v1_8.opengl.WorldRenderer; import net.lax1dude.eaglercraft.v1_8.opengl.ext.deferred.DeferredStateManager; +import net.lax1dude.eaglercraft.v1_8.profile.RenderHighPoly; import net.minecraft.block.Block; import net.minecraft.block.BlockBed; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.model.ModelChicken; @@ -128,6 +130,7 @@ public class RenderManager { private Map, Render> entityRenderMap = Maps.newHashMap(); private Map skinMap = Maps.newHashMap(); private RenderPlayer playerRenderer; + private RenderPlayer eaglerRenderer; private FontRenderer textRenderer; private double renderPosX; private double renderPosY; @@ -215,6 +218,14 @@ public class RenderManager { this.skinMap.put("default", this.playerRenderer); this.skinMap.put("slim", new RenderPlayer(this, true, false)); this.skinMap.put("zombie", new RenderPlayer(this, false, true)); + this.eaglerRenderer = new RenderHighPoly(this, this.playerRenderer.getMainModel(), + this.playerRenderer.shadowSize); + this.skinMap.put("eagler", + Minecraft.getMinecraft().gameSettings.enableFNAWSkins ? this.eaglerRenderer : this.playerRenderer); + } + + public void setEnableFNAWSkins(boolean en) { + this.skinMap.put("eagler", en ? this.eaglerRenderer : this.playerRenderer); } public void setRenderPosition(double renderPosXIn, double renderPosYIn, double renderPosZIn) { diff --git a/src/main/java/net/minecraft/client/renderer/entity/RenderPlayer.java b/src/main/java/net/minecraft/client/renderer/entity/RenderPlayer.java index 2c20a0f..ef92a0d 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/RenderPlayer.java +++ b/src/main/java/net/minecraft/client/renderer/entity/RenderPlayer.java @@ -3,6 +3,7 @@ package net.minecraft.client.renderer.entity; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.model.ModelBase; import net.minecraft.client.model.ModelBiped; import net.minecraft.client.model.ModelPlayer; import net.minecraft.client.model.ModelZombie; @@ -59,6 +60,10 @@ public class RenderPlayer extends RendererLivingEntity { this.addLayer(new LayerCape(this)); this.addLayer(new LayerCustomHead(this.getMainModel().bipedHead)); } + + protected RenderPlayer(RenderManager renderManager, ModelBase modelBase, float size) { + super(renderManager, modelBase, size); + } public ModelBiped getMainModel() { return (ModelBiped) super.getMainModel(); 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 90a6336..8528108 100644 --- a/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java +++ b/src/main/java/net/minecraft/client/renderer/entity/RendererLivingEntity.java @@ -193,7 +193,8 @@ public abstract class RendererLivingEntity extends R GlStateManager.disableRescaleNormal(); } catch (Exception exception) { - logger.error("Couldn\'t render entity", exception); + logger.error("Couldn\'t render entity"); + logger.error(exception); } GlStateManager.setActiveTexture(OpenGlHelper.lightmapTexUnit); diff --git a/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java b/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java index 66e4893..99ce6bc 100644 --- a/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java +++ b/src/main/java/net/minecraft/client/renderer/texture/TextureManager.java @@ -58,8 +58,8 @@ public class TextureManager implements ITickable, IResourceManagerReloadListener public void bindTexture(ResourceLocation resource) { int glTex; - if (resource.cachedPointer != null) { - TextureUtil.bindTexture(glTex = ((ITextureObject) resource.cachedPointer).getGlTextureId()); // unsafe, lol + if (resource.cachedPointerType == ResourceLocation.CACHED_POINTER_TEXTURE) { + TextureUtil.bindTexture(glTex = ((ITextureObject) resource.cachedPointer).getGlTextureId()); } else { Object object = (ITextureObject) this.mapTextureObjects.get(resource); if (object == null) { @@ -68,6 +68,7 @@ public class TextureManager implements ITickable, IResourceManagerReloadListener } resource.cachedPointer = object; + resource.cachedPointerType = ResourceLocation.CACHED_POINTER_TEXTURE; TextureUtil.bindTexture(glTex = ((ITextureObject) object).getGlTextureId()); } if (DeferredStateManager.isInDeferredPass()) { @@ -121,9 +122,10 @@ public class TextureManager implements ITickable, IResourceManagerReloadListener } public ITextureObject getTexture(ResourceLocation textureLocation) { - if (textureLocation.cachedPointer != null) { + if (textureLocation.cachedPointerType == ResourceLocation.CACHED_POINTER_TEXTURE) { return (ITextureObject) textureLocation.cachedPointer; } else { + textureLocation.cachedPointerType = ResourceLocation.CACHED_POINTER_TEXTURE; return (ITextureObject) (textureLocation.cachedPointer = this.mapTextureObjects.get(textureLocation)); } } diff --git a/src/main/java/net/minecraft/network/NetHandlerPlayServer.java b/src/main/java/net/minecraft/network/NetHandlerPlayServer.java index 5eb64d5..b8826a3 100644 --- a/src/main/java/net/minecraft/network/NetHandlerPlayServer.java +++ b/src/main/java/net/minecraft/network/NetHandlerPlayServer.java @@ -90,6 +90,7 @@ import net.minecraft.util.IntHashMap; import net.minecraft.util.ReportedException; import net.minecraft.world.WorldServer; import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager; +import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService; import org.apache.commons.lang3.StringUtils; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; @@ -1239,6 +1240,15 @@ public class NetHandlerPlayServer implements INetHandlerPlayServer, ITickable { byte[] r = new byte[c17packetcustompayload.getBufferData().readableBytes()]; c17packetcustompayload.getBufferData().readBytes(r); ((EaglerMinecraftServer) serverController).getSkinService().processPacket(r, playerEntity); + } else if ("EAG|Capes-1.8".equals(c17packetcustompayload.getChannelName())) { + byte[] r = new byte[c17packetcustompayload.getBufferData().readableBytes()]; + c17packetcustompayload.getBufferData().readBytes(r); + ((EaglerMinecraftServer) serverController).getCapeService().processPacket(r, playerEntity); + } else if ("EAG|Voice-1.8".equals(c17packetcustompayload.getChannelName())) { + IntegratedVoiceService vcs = ((EaglerMinecraftServer) serverController).getVoiceService(); + if (vcs != null) { + vcs.processPacket(c17packetcustompayload.getBufferData(), playerEntity); + } } else if ("EAG|MyUpdCert-1.8".equals(c17packetcustompayload.getChannelName())) { if (playerEntity.updateCertificate == null) { PacketBuffer pb = c17packetcustompayload.getBufferData(); diff --git a/src/main/java/net/minecraft/network/login/client/C00PacketLoginStart.java b/src/main/java/net/minecraft/network/login/client/C00PacketLoginStart.java index 8f862e5..6debecd 100644 --- a/src/main/java/net/minecraft/network/login/client/C00PacketLoginStart.java +++ b/src/main/java/net/minecraft/network/login/client/C00PacketLoginStart.java @@ -30,13 +30,15 @@ import net.minecraft.network.login.INetHandlerLoginServer; public class C00PacketLoginStart implements Packet { private GameProfile profile; private byte[] skin; + private byte[] cape; public C00PacketLoginStart() { } - public C00PacketLoginStart(GameProfile profileIn, byte[] skin) { + public C00PacketLoginStart(GameProfile profileIn, byte[] skin, byte[] cape) { this.profile = profileIn; this.skin = skin; + this.cape = cape; } /**+ @@ -45,6 +47,7 @@ public class C00PacketLoginStart implements Packet { public void readPacketData(PacketBuffer parPacketBuffer) throws IOException { this.profile = new GameProfile((EaglercraftUUID) null, parPacketBuffer.readStringFromBuffer(16)); this.skin = parPacketBuffer.readByteArray(); + this.cape = parPacketBuffer.readableBytes() > 0 ? parPacketBuffer.readByteArray() : null; } /**+ @@ -53,6 +56,7 @@ public class C00PacketLoginStart implements Packet { public void writePacketData(PacketBuffer parPacketBuffer) throws IOException { parPacketBuffer.writeString(this.profile.getName()); parPacketBuffer.writeByteArray(this.skin); + parPacketBuffer.writeByteArray(this.cape); } /**+ @@ -69,4 +73,8 @@ public class C00PacketLoginStart implements Packet { public byte[] getSkin() { return this.skin; } + + public byte[] getCape() { + return this.cape; + } } \ No newline at end of file diff --git a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java index 2285bd3..79b2181 100644 --- a/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java +++ b/src/main/java/net/minecraft/server/management/ServerConfigurationManager.java @@ -60,7 +60,9 @@ import net.minecraft.world.border.WorldBorder; import net.minecraft.world.demo.DemoWorldManager; import net.minecraft.world.storage.IPlayerFileData; import net.minecraft.world.storage.WorldInfo; +import net.lax1dude.eaglercraft.v1_8.sp.server.EaglerMinecraftServer; import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager; +import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; @@ -346,6 +348,13 @@ public abstract class ServerConfigurationManager { this.uuidToPlayerMap.remove(uuid); this.playerStatFiles.remove(entityplayermp.getName()); } + + ((EaglerMinecraftServer) mcServer).getSkinService().unregisterPlayer(uuid); + ((EaglerMinecraftServer) mcServer).getCapeService().unregisterPlayer(uuid); + IntegratedVoiceService vcs = ((EaglerMinecraftServer) mcServer).getVoiceService(); + if (vcs != null) { + vcs.handlePlayerLoggedOut(playerIn); + } this.sendPacketToAllPlayers(new S38PacketPlayerListItem(S38PacketPlayerListItem.Action.REMOVE_PLAYER, new EntityPlayerMP[] { playerIn })); diff --git a/src/main/java/net/minecraft/server/network/NetHandlerLoginServer.java b/src/main/java/net/minecraft/server/network/NetHandlerLoginServer.java index 7442874..43ef083 100644 --- a/src/main/java/net/minecraft/server/network/NetHandlerLoginServer.java +++ b/src/main/java/net/minecraft/server/network/NetHandlerLoginServer.java @@ -17,6 +17,7 @@ import net.minecraft.util.ChatComponentText; import net.minecraft.util.IChatComponent; import net.minecraft.util.ITickable; import net.lax1dude.eaglercraft.v1_8.sp.server.socket.IntegratedServerPlayerNetworkManager; +import net.lax1dude.eaglercraft.v1_8.sp.server.voice.IntegratedVoiceService; import org.apache.commons.lang3.Validate; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; @@ -52,6 +53,7 @@ public class NetHandlerLoginServer implements INetHandlerLoginServer, ITickable private int connectionTimer; private GameProfile loginGameProfile; private byte[] loginSkinPacket; + private byte[] loginCapePacket; private String serverId = ""; private EntityPlayerMP field_181025_l; @@ -77,6 +79,14 @@ public class NetHandlerLoginServer implements INetHandlerLoginServer, ITickable this.field_181025_l); ((EaglerMinecraftServer) field_181025_l.mcServer).getSkinService() .processLoginPacket(this.loginSkinPacket, field_181025_l); + if (this.loginCapePacket != null) { + ((EaglerMinecraftServer) field_181025_l.mcServer).getCapeService() + .processLoginPacket(this.loginCapePacket, field_181025_l); + } + IntegratedVoiceService svc = ((EaglerMinecraftServer) field_181025_l.mcServer).getVoiceService(); + if (svc != null) { + svc.handlePlayerLoggedIn(entityplayermp); + } this.field_181025_l = null; } } @@ -117,6 +127,14 @@ public class NetHandlerLoginServer implements INetHandlerLoginServer, ITickable this.server.getConfigurationManager().initializeConnectionToPlayer(this.networkManager, entityplayermp); ((EaglerMinecraftServer) entityplayermp.mcServer).getSkinService() .processLoginPacket(this.loginSkinPacket, entityplayermp); + if (this.loginCapePacket != null) { + ((EaglerMinecraftServer) entityplayermp.mcServer).getCapeService() + .processLoginPacket(this.loginCapePacket, entityplayermp); + } + IntegratedVoiceService svc = ((EaglerMinecraftServer) entityplayermp.mcServer).getVoiceService(); + if (svc != null) { + svc.handlePlayerLoggedIn(entityplayermp); + } } } @@ -141,6 +159,7 @@ public class NetHandlerLoginServer implements INetHandlerLoginServer, ITickable new Object[0]); this.loginGameProfile = this.getOfflineProfile(c00packetloginstart.getProfile()); this.loginSkinPacket = c00packetloginstart.getSkin(); + this.loginCapePacket = c00packetloginstart.getCape(); this.currentLoginState = NetHandlerLoginServer.LoginState.READY_TO_ACCEPT; } diff --git a/src/main/java/net/minecraft/util/ResourceLocation.java b/src/main/java/net/minecraft/util/ResourceLocation.java index d384748..0055cf5 100644 --- a/src/main/java/net/minecraft/util/ResourceLocation.java +++ b/src/main/java/net/minecraft/util/ResourceLocation.java @@ -28,6 +28,11 @@ public class ResourceLocation { public String resourceName; public Object cachedPointer = null; + public int cachedPointerType = 0; + + public static final int CACHED_POINTER_NONE = 0; + public static final int CACHED_POINTER_TEXTURE = 1; + public static final int CACHED_POINTER_EAGLER_MESH = 2; protected ResourceLocation(int parInt1, String... resourceName) { this.resourceName = resourceName[0]; diff --git a/src/main/java/net/minecraft/world/World.java b/src/main/java/net/minecraft/world/World.java index 12d5f88..c0f305e 100644 --- a/src/main/java/net/minecraft/world/World.java +++ b/src/main/java/net/minecraft/world/World.java @@ -2718,9 +2718,10 @@ public abstract class World implements IBlockAccess { int i = 0; EnumFacing[] facings = EnumFacing._VALUES; + BlockPos tmp = new BlockPos(0, 0, 0); for (int k = 0; k < facings.length; ++k) { EnumFacing enumfacing = facings[k]; - int j = this.getRedstonePower(pos.offset(enumfacing), enumfacing); + int j = this.getRedstonePower(pos.offsetEvenFaster(enumfacing, tmp), enumfacing); if (j >= 15) { return 15; } diff --git a/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java b/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java index bf722c8..cea4041 100644 --- a/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java +++ b/src/main/java/net/minecraft/world/gen/ChunkProviderServer.java @@ -172,7 +172,8 @@ public class ChunkProviderServer implements IChunkProvider { return chunk; } catch (Exception exception) { - logger.error("Couldn\'t load chunk", exception); + logger.error("Couldn\'t load chunk"); + logger.error(exception); return null; } } @@ -183,7 +184,8 @@ public class ChunkProviderServer implements IChunkProvider { try { this.chunkLoader.saveExtraChunkData(this.worldObj, parChunk); } catch (Exception exception) { - logger.error("Couldn\'t save entities", exception); + logger.error("Couldn\'t save entities"); + logger.error(exception); } } @@ -196,10 +198,11 @@ public class ChunkProviderServer implements IChunkProvider { this.chunkLoader.saveChunk(this.worldObj, parChunk); ++EaglerMinecraftServer.counterChunkWrite; } catch (IOException ioexception) { - logger.error("Couldn\'t save chunk", ioexception); + logger.error("Couldn\'t save chunk"); + logger.error(ioexception); } catch (MinecraftException minecraftexception) { - logger.error("Couldn\'t save chunk; already in use by another instance of Minecraft?", - minecraftexception); + logger.error("Couldn\'t save chunk; already in use by another instance of Minecraft?"); + logger.error(minecraftexception); } } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java index b0087b1..07d0c9c 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformAudio.java @@ -46,8 +46,8 @@ public class PlatformAudio { static final Logger logger = LogManager.getLogger("BrowserAudio"); - private static AudioContext audioctx = null; - private static MediaStreamAudioDestinationNode recDest = null; + static AudioContext audioctx = null; + static MediaStreamAudioDestinationNode recDest = null; private static final Map soundCache = new HashMap(); private static long cacheFreeTimer = 0l; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java index 17f28cc..c3b6593 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformBufferFunctions.java @@ -21,10 +21,7 @@ import net.lax1dude.eaglercraft.v1_8.internal.buffer.IntBuffer; public class PlatformBufferFunctions { public static void put(ByteBuffer newBuffer, ByteBuffer flip) { - int len = flip.remaining(); - for(int i = 0; i < len; ++i) { - newBuffer.put(flip.get()); - } + newBuffer.put(flip); } public static void put(IntBuffer intBuffer, int index, int[] data) { diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java index 813c779..5d948ae 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformFilesystem.java @@ -18,7 +18,7 @@ import org.teavm.jso.indexeddb.IDBRequest; import org.teavm.jso.indexeddb.IDBTransaction; import org.teavm.jso.indexeddb.IDBVersionChangeEvent; import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.typedarrays.DataView; +import org.teavm.jso.typedarrays.Int8Array; import net.lax1dude.eaglercraft.v1_8.internal.buffer.ByteBuffer; import net.lax1dude.eaglercraft.v1_8.internal.buffer.EaglerArrayBufferAllocator; @@ -85,11 +85,11 @@ public class PlatformFilesystem { if(ar == null) { return null; } - return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(DataView.create(ar)); + return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(Int8Array.create(ar)); } public static void eaglerWrite(String pathName, ByteBuffer data) { - if(!AsyncHandlers.writeWholeFile(database, pathName, EaglerArrayBufferAllocator.getDataViewStupid(data).getBuffer()).bool) { + if(!AsyncHandlers.writeWholeFile(database, pathName, EaglerArrayBufferAllocator.getDataView8Unsigned(data).getBuffer()).bool) { throw new RuntimeException("Failed to write " + data.remaining() + " byte file to indexeddb table: " + pathName); } } 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 55774fd..648772f 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 @@ -4,6 +4,9 @@ import java.util.LinkedList; import java.util.List; import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; + +import org.teavm.interop.Async; +import org.teavm.interop.AsyncCallback; import org.teavm.jso.JSBody; import org.teavm.jso.JSObject; import org.teavm.jso.browser.TimerHandler; @@ -100,6 +103,8 @@ public class PlatformInput { public static boolean keyboardLockSupported = false; public static boolean lockKeys = false; + private static boolean vsync = true; + @JSBody(params = { }, script = "window.onbeforeunload = () => {return false;};") private static native void onBeforeCloseRegister(); @@ -290,6 +295,10 @@ public class PlatformInput { public static boolean isCloseRequested() { return false; } + + public static void setVSync(boolean enable) { + vsync = enable; + } public static void update() { double r = win.getDevicePixelRatio(); @@ -304,7 +313,39 @@ public class PlatformInput { canvas.setHeight(h2); } flipBuffer(); - EagUtils.sleep(1l); + if (PlatformRuntime.recording) { + long t = System.currentTimeMillis(); + if(t - PlatformRuntime.lastFrame > (1000 / 30)) { + PlatformRuntime.recFrame(); + PlatformRuntime.lastFrame = t; + } + } + if(vsync) { + asyncRequestAnimationFrame(); + }else { + EagUtils.sleep(0l); + } + } + + @Async + private static native void asyncRequestAnimationFrame(); + + private static void asyncRequestAnimationFrame(AsyncCallback cb) { + final boolean[] hasCompleted = new boolean[1]; + final int[] timeout = new int[] { -1 }; + Window.requestAnimationFrame((d) -> { + if(!hasCompleted[0]) { + hasCompleted[0] = true; + Window.clearTimeout(timeout[0]); + cb.complete(null); + } + }); + timeout[0] = Window.setTimeout(() -> { + if(!hasCompleted[0]) { + hasCompleted[0] = true; + cb.complete(null); + } + }, 50); } static void initFramebuffer(WebGL2RenderingContext ctx, WebGLFramebuffer fbo, int sw, int sh) { @@ -593,7 +634,7 @@ public class PlatformInput { @JSBody(params = { }, script = "window.navigator.keyboard.unlock();") private static native void unlockKeys(); - @JSBody(params = { }, script = "return 'keyboard' in window.navigator && 'lock' in window.navigator.keyboard;") + @JSBody(params = { }, script = "return !!(window.navigator.keyboard && window.navigator.keyboard.lock);") private static native boolean checkKeyboardLockSupported(); @JSBody(params = { }, script = "document.exitFullscreen();") diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java index 01ed53f..9398c09 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformOpenGL.java @@ -38,12 +38,14 @@ public class PlatformOpenGL { static boolean hasDebugRenderInfoExt = false; static boolean hasFramebufferHDR16FSupport = false; static boolean hasFramebufferHDR32FSupport = false; + static boolean hasLinearHDR32FSupport = false; static void setCurrentContext(WebGL2RenderingContext context) { ctx = context; hasDebugRenderInfoExt = ctx.getExtension("WEBGL_debug_renderer_info") != null; hasFramebufferHDR16FSupport = ctx.getExtension("EXT_color_buffer_half_float") != null; hasFramebufferHDR32FSupport = ctx.getExtension("EXT_color_buffer_float") != null; + hasLinearHDR32FSupport = ctx.getExtension("OES_texture_float_linear") != null; _wglClearColor(1.0f, 1.0f, 1.0f, 1.0f); } @@ -193,15 +195,15 @@ public class PlatformOpenGL { } public static final void _wglBufferData(int target, ByteBuffer data, int usage) { - ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage); + ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView8(data), usage); } public static final void _wglBufferData(int target, IntBuffer data, int usage) { - ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage); + ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView32(data), usage); } public static final void _wglBufferData(int target, FloatBuffer data, int usage) { - ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView(data), usage); + ctx.bufferData(target, data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data), usage); } public static final void _wglBufferData(int target, int size, int usage) { @@ -209,15 +211,15 @@ public class PlatformOpenGL { } public static final void _wglBufferSubData(int target, int offset, ByteBuffer data) { - ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data)); + ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView8(data)); } public static final void _wglBufferSubData(int target, int offset, IntBuffer data) { - ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data)); + ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView32(data)); } public static final void _wglBufferSubData(int target, int offset, FloatBuffer data) { - ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView(data)); + ctx.bufferSubData(target, offset, data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data)); } public static final void _wglBindVertexArray(IBufferArrayGL obj) { @@ -260,55 +262,61 @@ public class PlatformOpenGL { public static final void _wglTexImage3D(int target, int level, int internalFormat, int width, int height, int depth, int border, int format, int type, ByteBuffer data) { ctx.texImage3D(target, level, internalFormat, width, height, depth, border, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) { ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexImage2Du16(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) { ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView16Unsigned(data)); + } + + public static final void _wglTexImage2Df32(int target, int level, int internalFormat, int width, + int height, int border, int format, int type, ByteBuffer data) { + ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, + data == null ? null : EaglerArrayBufferAllocator.getDataView32F(data)); } public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, IntBuffer data) { ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, FloatBuffer data) { ctx.texImage2D(target, level, internalFormat, width, height, border, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer data) { ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexSubImage2Du16(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, ByteBuffer data) { ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid16(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView16Unsigned(data)); } public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, IntBuffer data) { ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglTexSubImage2D(int target, int level, int xoffset, int yoffset, int width, int height, int format, int type, FloatBuffer data) { ctx.texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, - data == null ? null : EaglerArrayBufferAllocator.getDataViewStupid(data)); + data == null ? null : EaglerArrayBufferAllocator.getDataView8Unsigned(data)); } public static final void _wglCopyTexSubImage2D(int target, int level, int xoffset, int yoffset, @@ -457,32 +465,32 @@ public class PlatformOpenGL { public static final void _wglUniformMatrix2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglUniformMatrix3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglUniformMatrix3x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix3x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglUniformMatrix4fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix4fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglUniformMatrix4x2fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix4x2fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglUniformMatrix4x3fv(IUniformGL obj, boolean transpose, FloatBuffer mat) { if(obj != null) ctx.uniformMatrix4x3fv(((OpenGLObjects.UniformGL)obj).ptr, transpose, - mat == null ? null : EaglerArrayBufferAllocator.getFloatArrayStupid(mat)); + mat == null ? null : EaglerArrayBufferAllocator.getDataView32F(mat)); } public static final void _wglBindFramebuffer(int target, IFramebufferGL framebuffer) { @@ -576,7 +584,11 @@ public class PlatformOpenGL { public static final void _wglFinish() { ctx.finish(); } - + + public static final boolean checkLinearHDR32FSupport() { + return hasLinearHDR32FSupport; + } + private static final void checkErr(String name) { int i = ctx.getError(); if(i != 0) { @@ -600,3 +612,4 @@ public class PlatformOpenGL { return parameterValue; } } + 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 f2f6e97..91c7371 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 @@ -28,7 +28,6 @@ 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.typedarrays.DataView; import org.teavm.jso.typedarrays.Uint8Array; import org.teavm.jso.webaudio.MediaStream; import org.teavm.jso.webgl.WebGLFramebuffer; @@ -275,27 +274,27 @@ public class PlatformRuntime { } public static ByteBuffer castPrimitiveByteArray(byte[] array) { - return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array))); + return EaglerArrayBufferAllocator.wrapByteBufferTeaVM(TeaVMUtils.unwrapByteArray(array)); } public static IntBuffer castPrimitiveIntArray(int[] array) { - return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array))); + return EaglerArrayBufferAllocator.wrapIntBufferTeaVM(TeaVMUtils.unwrapIntArray(array)); } public static FloatBuffer castPrimitiveFloatArray(float[] array) { - return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(DataView.create(TeaVMUtils.unwrapArrayBuffer(array))); + return EaglerArrayBufferAllocator.wrapFloatBufferTeaVM(TeaVMUtils.unwrapFloatArray(array)); } public static byte[] castNativeByteBuffer(ByteBuffer buffer) { - return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataViewStupid(buffer)); + return TeaVMUtils.wrapUnsignedByteArray(EaglerArrayBufferAllocator.getDataView8Unsigned(buffer)); } public static int[] castNativeIntBuffer(IntBuffer buffer) { - return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataViewStupid32(buffer)); + return TeaVMUtils.wrapIntArray(EaglerArrayBufferAllocator.getDataView32(buffer)); } public static float[] castNativeFloatBuffer(FloatBuffer buffer) { - return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getFloatArrayStupid(buffer)); + return TeaVMUtils.wrapFloatArray(EaglerArrayBufferAllocator.getDataView32F(buffer)); } public static void freeByteBuffer(ByteBuffer byteBuffer) { @@ -500,12 +499,13 @@ public class PlatformRuntime { return TeaVMClientConfigAdapter.instance; } - private static boolean canRec = false; - private static boolean recording = false; - private static JSObject mediaRec = null; - private static HTMLCanvasElement recCanvas = null; - private static CanvasRenderingContext2D recCtx = null; - private static MediaStream recStream = null; + 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; @@ -534,7 +534,7 @@ public class PlatformRuntime { return recording ? "recording.stop" : "recording.start"; } - private static void recFrame() { + static void recFrame() { if (mediaRec != null) { int w = PlatformRuntime.canvas.getWidth(); int h = PlatformRuntime.canvas.getHeight(); @@ -546,21 +546,6 @@ public class PlatformRuntime { } } - private static void onRecFrame() { - if (recording) { - recFrame(); - long t = System.currentTimeMillis(); - Window.requestAnimationFrame(timestamp -> { - long d = (1000 / 30) - (System.currentTimeMillis() - t); - if (d <= 0) { - onRecFrame(); - } else { - Window.setTimeout(PlatformRuntime::onRecFrame, d); - } - }); - } - } - @JSFunctor private static interface MediaHandler extends JSObject { void onMedia(MediaStream stream); @@ -630,7 +615,6 @@ public class PlatformRuntime { }, logger::info); } }); - onRecFrame(); } else { stopRec(mediaRec); mediaRec = null; diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java new file mode 100644 index 0000000..0700c95 --- /dev/null +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/PlatformVoiceClient.java @@ -0,0 +1,439 @@ +package net.lax1dude.eaglercraft.v1_8.internal; + +import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; +import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; +import net.lax1dude.eaglercraft.v1_8.log4j.Logger; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelPeerState; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelReadyState; +import net.lax1dude.eaglercraft.v1_8.voice.EnumVoiceChannelType; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; +import org.json.JSONObject; +import org.json.JSONWriter; +import org.teavm.jso.JSBody; +import org.teavm.jso.JSObject; +import org.teavm.jso.dom.events.Event; +import org.teavm.jso.dom.events.EventListener; +import org.teavm.jso.dom.html.HTMLAudioElement; +import org.teavm.jso.dom.html.HTMLDocument; +import org.teavm.jso.json.JSON; +import org.teavm.jso.typedarrays.Uint8Array; +import org.teavm.jso.webaudio.*; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Copyright (c) 2022-2024 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 PlatformVoiceClient { + + private static final Logger logger = LogManager.getLogger("PlatformVoiceClient"); + + private static final HashMap voiceAnalysers = new HashMap<>(); + private static final HashMap voiceGains = new HashMap<>(); + private static final HashMap voicePanners = new HashMap<>(); + + @JSBody(params = {}, script = "return typeof window.RTCPeerConnection !== \"undefined\" && typeof navigator.mediaDevices !== \"undefined\" && typeof navigator.mediaDevices.getUserMedia !== \"undefined\";") + public static native boolean isSupported(); + + @JSBody(params = { "item" }, script = "return item.streams[0];") + static native MediaStream getFirstStream(JSObject item); + + @JSBody(params = { "aud", "stream" }, script = "return aud.srcObject = stream;") + static native void setSrcObject(HTMLAudioElement aud, MediaStream stream); + + @JSBody(params = { "aud" }, script = "return aud.remove();") + static native void removeAud(HTMLAudioElement aud); + + @JSBody(params = { "pc", "stream" }, script = "return stream.getTracks().forEach((track) => { pc.addTrack(track, stream); });") + static native void addStream(JSObject pc, MediaStream stream); + + @JSBody(params = { "rawStream", "muted" }, script = "return rawStream.getAudioTracks()[0].enabled = !muted;") + static native void mute(MediaStream rawStream, boolean muted); + + @JSBody(params = { "peerConnection", "str" }, script = "return peerConnection.addIceCandidate(new RTCIceCandidate(JSON.parse(str)));") + static native void addIceCandidate(JSObject peerConnection, String str); + + public static void disconnect(JSObject peerConnection) { + PlatformWebRTC.closeIt(peerConnection); + } + + public static void setVoiceProximity(int prox) { + for (PannerNode panner : voicePanners.values()) { + panner.setMaxDistance(VoiceClientController.getVoiceListenVolume() * 2 * prox + 0.1f); + } + } + + public static void updateVoicePosition(EaglercraftUUID uuid, double x, double y, double z) { + if (voicePanners.containsKey(uuid)) voicePanners.get(uuid).setPosition((float) x, (float) y, (float) z); + } + + public static class VoicePeer { + public final EaglercraftUUID peerId; + public final JSObject peerConnection; + public MediaStream rawStream; + public VoicePeer(EaglercraftUUID peerId, JSObject peerConnection, boolean offer) { + this.peerId = peerId; + this.peerConnection = peerConnection; + + TeaVMUtils.addEventListener(peerConnection, "icecandidate", (EventListener) evt -> { + if (PlatformWebRTC.hasCandidate(evt)) { + Map m = new HashMap<>(); + m.put("sdpMLineIndex", "" + PlatformWebRTC.getSdpMLineIndex(evt)); + m.put("candidate", PlatformWebRTC.getCandidate(evt)); + handleIceCandidate(peerId, JSONWriter.valueToString(m)); + } + }); + TeaVMUtils.addEventListener(peerConnection, "track", (EventListener) evt -> { + rawStream = getFirstStream(evt); + HTMLAudioElement aud = (HTMLAudioElement) HTMLDocument.current().createElement("audio"); + aud.setAutoplay(true); + aud.setMuted(true); + TeaVMUtils.addEventListener(aud, "ended", (EventListener) evt2 -> { + removeAud(aud); + }); + setSrcObject(aud, rawStream); + handlePeerTrack(peerId, rawStream); + }); + + addStream(peerConnection, localMediaStream.getStream()); + if (offer) { + PlatformWebRTC.createOffer(peerConnection, desc -> { + PlatformWebRTC.setLocalDescription(peerConnection, desc, () -> { + handleDescription(peerId, JSON.stringify(desc)); + }, err -> { + logger.error("Failed to set local description for \"{}\"! {}", peerId, err); + if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) { + peerStateInitial = EnumVoiceChannelPeerState.FAILED; + } + signalDisconnect(peerId, false); + }); + }, err -> { + logger.error("Failed to set create offer for \"{}\"! {}", peerId, err); + if (peerStateInitial == EnumVoiceChannelPeerState.LOADING) { + peerStateInitial = EnumVoiceChannelPeerState.FAILED; + } + signalDisconnect(peerId, false); + }); + } + + TeaVMUtils.addEventListener(peerConnection, "connectionstatechange", (EventListener) evt -> { + String cs = PlatformWebRTC.getConnectionState(peerConnection); + if ("disconnected".equals(cs)) { + signalDisconnect(peerId, false); + } else if ("connected".equals(cs)) { + if (peerState != EnumVoiceChannelPeerState.SUCCESS) { + peerState = EnumVoiceChannelPeerState.SUCCESS; + } + } else if ("failed".equals(cs)) { + if (peerState == EnumVoiceChannelPeerState.LOADING) { + peerState = EnumVoiceChannelPeerState.FAILED; + } + signalDisconnect(peerId, false); + } + }); + } + + public void disconnect() { + PlatformVoiceClient.disconnect(peerConnection); + } + + public void mute(boolean muted) { + PlatformVoiceClient.mute(rawStream, muted); + } + + public void setRemoteDescription(String descJSON) { + try { + JSONObject remoteDesc = new JSONObject(descJSON); + PlatformWebRTC.setRemoteDescription2(peerConnection, descJSON, () -> { + if (remoteDesc.has("type") && "offer".equals(remoteDesc.getString("type"))) { + PlatformWebRTC.createAnswer(peerConnection, desc -> { + PlatformWebRTC.setLocalDescription(peerConnection, desc, () -> { + handleDescription(peerId, JSON.stringify(desc)); + if (peerStateDesc != EnumVoiceChannelPeerState.SUCCESS) peerStateDesc = EnumVoiceChannelPeerState.SUCCESS; + }, err -> { + logger.error("Failed to set local description for \"{}\"! {}", peerId, err.getMessage()); + if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED; + signalDisconnect(peerId, false); + }); + }, err -> { + logger.error("Failed to create answer for \"{}\"! {}", peerId, err.getMessage()); + if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED; + signalDisconnect(peerId, false); + }); + } + }, err -> { + logger.error("Failed to set remote description for \"{}\"! {}", peerId, err.getMessage()); + if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED; + signalDisconnect(peerId, false); + }); + } catch (Throwable err) { + logger.error("Failed to parse remote description for \"{}\"! {}", peerId, err.getMessage()); + if (peerStateDesc == EnumVoiceChannelPeerState.LOADING) peerStateDesc = EnumVoiceChannelPeerState.FAILED; + signalDisconnect(peerId, false); + } + } + + public void addICECandidate(String candidate) { + try { + addIceCandidate(peerConnection, candidate); + if (peerStateIce != EnumVoiceChannelPeerState.SUCCESS) peerStateIce = EnumVoiceChannelPeerState.SUCCESS; + } catch (Throwable err) { + logger.error("Failed to parse ice candidate for \"{}\"! {}", peerId, err.getMessage()); + if (peerStateIce == EnumVoiceChannelPeerState.LOADING) peerStateIce = EnumVoiceChannelPeerState.FAILED; + signalDisconnect(peerId, false); + } + } + } + + public static Set> iceServers = new HashSet<>(); + public static boolean hasInit = false; + public static Map peerList = new HashMap<>(); + public static MediaStreamAudioDestinationNode localMediaStream; + public static GainNode localMediaStreamGain; + public static MediaStream localRawMediaStream; + public static EnumVoiceChannelReadyState readyState = EnumVoiceChannelReadyState.NONE; + public static EnumVoiceChannelPeerState peerState = EnumVoiceChannelPeerState.LOADING; + public static EnumVoiceChannelPeerState peerStateConnect = EnumVoiceChannelPeerState.LOADING; + public static EnumVoiceChannelPeerState peerStateInitial = EnumVoiceChannelPeerState.LOADING; + public static EnumVoiceChannelPeerState peerStateDesc = EnumVoiceChannelPeerState.LOADING; + public static EnumVoiceChannelPeerState peerStateIce = EnumVoiceChannelPeerState.LOADING; + public static AudioContext microphoneVolumeAudioContext = null; + + public static void setICEServers(String[] urls) { + iceServers.clear(); + if (urls == null) return; + for (String url : urls) { + String[] etr = url.split(";"); + if (etr.length == 1) { + Map m = new HashMap<>(); + m.put("urls", etr[0]); + iceServers.add(m); + } else if (etr.length == 3) { + Map m = new HashMap<>(); + m.put("urls", etr[0]); + m.put("username", etr[1]); + m.put("credential", etr[2]); + iceServers.add(m); + } + } + } + + public static void activateVoice(boolean talk) { + if (hasInit) { + PlatformVoiceClient.mute(localRawMediaStream, !talk); + } + } + + public static void initializeDevices() { + if (!hasInit) { + localRawMediaStream = PlatformRuntime.getMic(); + if (localRawMediaStream == null) { + readyState = EnumVoiceChannelReadyState.ABORTED; + return; + } + microphoneVolumeAudioContext = AudioContext.create(); + mute(localRawMediaStream, true); + localMediaStream = microphoneVolumeAudioContext.createMediaStreamDestination(); + localMediaStreamGain = microphoneVolumeAudioContext.createGain(); + microphoneVolumeAudioContext.createMediaStreamSource(localRawMediaStream).connect(localMediaStreamGain); + localMediaStreamGain.connect(localMediaStream); + localMediaStreamGain.getGain().setValue(1.0F); + readyState = EnumVoiceChannelReadyState.DEVICE_INITIALIZED; + hasInit = true; + } else { + readyState = EnumVoiceChannelReadyState.DEVICE_INITIALIZED; + } + } + + public static void tickVoiceClient() { + for (EaglercraftUUID uuid : voiceAnalysers.keySet()) { + AnalyserNode analyser = voiceAnalysers.get(uuid); + Uint8Array array = Uint8Array.create(analyser.getFrequencyBinCount()); + analyser.getByteFrequencyData(array); + int len = array.getLength(); + for (int i = 0; i < len; i++) { + if (array.get(i) >= 0.1f) { + VoiceClientController.getVoiceSpeaking().add(uuid); + break; + } + } + } + } + + public static void setMicVolume(float val) { + if (hasInit) { + if(val > 0.5F) val = 0.5F + (val - 0.5F) * 2.0F; + if(val > 1.5F) val = 1.5F; + if(val < 0.0F) val = 0.0F; + localMediaStreamGain.getGain().setValue(val * 2.0F); + } + } + + public static void resetPeerStates() { + peerState = peerStateConnect = peerStateInitial = peerStateDesc = peerStateIce = EnumVoiceChannelPeerState.LOADING; + } + + public static EnumVoiceChannelPeerState getPeerState() { + return peerState; + } + + public static EnumVoiceChannelPeerState getPeerStateConnect() { + return peerStateConnect; + } + + public static EnumVoiceChannelPeerState getPeerStateInitial() { + return peerStateInitial; + } + + public static EnumVoiceChannelPeerState getPeerStateDesc() { + return peerStateDesc; + } + + public static EnumVoiceChannelPeerState getPeerStateIce() { + return peerStateIce; + } + + public static EnumVoiceChannelReadyState getReadyState() { + return readyState; + } + + public static void signalConnect(EaglercraftUUID peerId, boolean offer) { + if (!hasInit) initializeDevices(); + try { + JSObject peerConnection = PlatformWebRTC.createRTCPeerConnection(JSONWriter.valueToString(iceServers)); + VoicePeer peerInstance = new VoicePeer(peerId, peerConnection, offer); + peerList.put(peerId, peerInstance); + if (peerStateConnect != EnumVoiceChannelPeerState.SUCCESS) peerStateConnect = EnumVoiceChannelPeerState.SUCCESS; + } catch (Throwable e) { + if (peerStateConnect == EnumVoiceChannelPeerState.LOADING) peerStateConnect = EnumVoiceChannelPeerState.FAILED; + } + } + + public static void signalDescription(EaglercraftUUID peerId, String descJSON) { + VoicePeer peer = peerList.get(peerId); + if (peer != null) { + peer.setRemoteDescription(descJSON); + } + } + + public static void signalDisconnect(EaglercraftUUID peerId, boolean quiet) { + VoicePeer peer = peerList.get(peerId); + if (peer != null) { + peerList.remove(peerId, peer); + try { + peer.disconnect(); + } catch (Throwable ignored) {} + handlePeerDisconnect(peerId, quiet); + } + } + + public static void mutePeer(EaglercraftUUID peerId, boolean muted) { + VoicePeer peer = peerList.get(peerId); + if (peer != null) { + peer.mute(muted); + } + } + + public static void signalICECandidate(EaglercraftUUID peerId, String candidate) { + VoicePeer peer = peerList.get(peerId); + if (peer != null) { + peer.addICECandidate(candidate); + } + } + + public static void handleIceCandidate(EaglercraftUUID peerId, String candidate) { + VoiceClientController.sendPacketICE(peerId, candidate); + } + + public static void handleDescription(EaglercraftUUID peerId, String desc) { + VoiceClientController.sendPacketDesc(peerId, desc); + } + + public static void handlePeerTrack(EaglercraftUUID peerId, MediaStream audioStream) { + if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.NONE) return; + MediaStreamAudioSourceNode audioNode = PlatformAudio.audioctx.createMediaStreamSource(audioStream); + AnalyserNode analyser = PlatformAudio.audioctx.createAnalyser(); + analyser.setSmoothingTimeConstant(0f); + analyser.setFftSize(32); + audioNode.connect(analyser); + voiceAnalysers.put(peerId, analyser); + if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.GLOBAL) { + GainNode gain = PlatformAudio.audioctx.createGain(); + gain.getGain().setValue(VoiceClientController.getVoiceListenVolume()); + analyser.connect(gain); + gain.connect(PlatformAudio.audioctx.getDestination()); + gain.connect(PlatformAudio.recDest); + voiceGains.put(peerId, gain); + VoiceClientController.getVoiceListening().add(peerId); + } else if (VoiceClientController.getVoiceChannel() == EnumVoiceChannelType.PROXIMITY) { + PannerNode panner = PlatformAudio.audioctx.createPanner(); + panner.setRolloffFactor(1f); + panner.setDistanceModel("linear"); + panner.setPanningModel("HRTF"); + panner.setConeInnerAngle(360f); + panner.setConeOuterAngle(0f); + panner.setConeOuterGain(0f); + panner.setOrientation(0f, 1f, 0f); + panner.setPosition(0, 0, 0); + float vol = VoiceClientController.getVoiceListenVolume(); + panner.setMaxDistance(vol * 2 * VoiceClientController.getVoiceProximity() + 0.1f); + GainNode gain = PlatformAudio.audioctx.createGain(); + gain.getGain().setValue(vol); + analyser.connect(gain); + gain.connect(panner); + panner.connect(PlatformAudio.audioctx.getDestination()); + panner.connect(PlatformAudio.recDest); + voiceGains.put(peerId, gain); + VoiceClientController.getVoiceListening().add(peerId); + voicePanners.put(peerId, panner); + } + if (VoiceClientController.getVoiceMuted().contains(peerId)) mutePeer(peerId, true); + } + + public static void handlePeerDisconnect(EaglercraftUUID peerId, boolean quiet) { + if (voiceAnalysers.containsKey(peerId)) { + voiceAnalysers.get(peerId).disconnect(); + voiceAnalysers.remove(peerId); + } + if (voiceGains.containsKey(peerId)) { + voiceGains.get(peerId).disconnect(); + voiceGains.remove(peerId); + VoiceClientController.getVoiceListening().remove(peerId); + } + if (voicePanners.containsKey(peerId)) { + voicePanners.get(peerId).disconnect(); + voicePanners.remove(peerId); + } + if (!quiet) { + VoiceClientController.sendPacketDisconnect(peerId); + } + } + + public static void setVoiceListenVolume(float f) { + for (EaglercraftUUID uuid : voiceGains.keySet()) { + GainNode gain = voiceGains.get(uuid); + float val = f; + if(val > 0.5f) val = 0.5f + (val - 0.5f) * 3.0f; + if(val > 2.0f) val = 2.0f; + if(val < 0.0f) val = 0.0f; + gain.getGain().setValue(val * 2.0f); + if (voicePanners.containsKey(uuid)) voicePanners.get(uuid).setMaxDistance(f * 2 * VoiceClientController.getVoiceProximity() + 0.1f); + } + } +} \ No newline at end of file diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java index fd2e3b6..755046a 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayBufferAllocator.java @@ -1,9 +1,9 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.DataView; import org.teavm.jso.typedarrays.Float32Array; import org.teavm.jso.typedarrays.Int32Array; +import org.teavm.jso.typedarrays.Int8Array; import org.teavm.jso.typedarrays.Uint16Array; import org.teavm.jso.typedarrays.Uint8Array; @@ -31,27 +31,31 @@ public class EaglerArrayBufferAllocator { } public static ByteBuffer allocateByteBuffer(int size) { - return new EaglerArrayByteBuffer(DataView.create(ArrayBuffer.create(size))); + return new EaglerArrayByteBuffer(Int8Array.create(size)); } public static ByteBuffer wrapByteBufferTeaVM(DataView dv) { return new EaglerArrayByteBuffer(dv); } - public static IntBuffer allocateIntBuffer(int size) { - return new EaglerArrayIntBuffer(DataView.create(ArrayBuffer.create(size << 2))); + public static ByteBuffer wrapByteBufferTeaVM(Int8Array typedArray) { + return new EaglerArrayByteBuffer(typedArray); } - public static IntBuffer wrapIntBufferTeaVM(DataView dv) { - return new EaglerArrayIntBuffer(dv); + public static IntBuffer allocateIntBuffer(int size) { + return new EaglerArrayIntBuffer(Int32Array.create(size)); + } + + public static IntBuffer wrapIntBufferTeaVM(Int32Array typedArray) { + return new EaglerArrayIntBuffer(typedArray); } public static FloatBuffer allocateFloatBuffer(int size) { - return new EaglerArrayFloatBuffer(DataView.create(ArrayBuffer.create(size << 2))); + return new EaglerArrayFloatBuffer(Float32Array.create(size)); } - public static FloatBuffer wrapFloatBufferTeaVM(DataView dv) { - return new EaglerArrayFloatBuffer(dv); + public static FloatBuffer wrapFloatBufferTeaVM(Float32Array typedArray) { + return new EaglerArrayFloatBuffer(typedArray); } public static DataView getDataView(ByteBuffer buffer) { @@ -63,121 +67,115 @@ public class EaglerArrayBufferAllocator { if(p == 0 && l == b.capacity) { return d; }else { - int i = d.getByteOffset(); - return DataView.create(d.getBuffer(), i + p, l - p); + return DataView.create(d.getBuffer(), d.getByteOffset() + p, l - p); } }else { throw notEagler(buffer); } } - public static Uint8Array getDataViewStupid(ByteBuffer buffer) { + public static Int8Array getDataView8(ByteBuffer buffer) { if(buffer instanceof EaglerArrayByteBuffer) { EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; - DataView d = b.dataView; - int p = b.position; - int l = b.limit; - int i = d.getByteOffset(); - return Uint8Array.create(d.getBuffer(), i + p, l - p); - }else { - throw notEagler(buffer); - } - } - - public static Uint16Array getDataViewStupid16(ByteBuffer buffer) { - if(buffer instanceof EaglerArrayByteBuffer) { - EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; - DataView d = b.dataView; - int p = b.position; - int l = b.limit; - int i = d.getByteOffset(); - return Uint16Array.create(d.getBuffer(), i + p, (l - p) >> 1); - }else { - throw notEagler(buffer); - } - } - - public static DataView getDataView(IntBuffer buffer) { - if(buffer instanceof EaglerArrayIntBuffer) { - EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; - DataView d = b.dataView; + Int8Array d = b.typedArray; int p = b.position; int l = b.limit; if(p == 0 && l == b.capacity) { return d; }else { int i = d.getByteOffset(); - return DataView.create(d.getBuffer(), i + (p << 2), (l - p) << 2); + return Int8Array.create(d.getBuffer(), d.getByteOffset() + p, l - p); } }else { throw notEagler(buffer); } } - public static Uint8Array getDataViewStupid(IntBuffer buffer) { - if(buffer instanceof EaglerArrayIntBuffer) { - EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; - DataView d = b.dataView; + public static Uint8Array getDataView8Unsigned(ByteBuffer buffer) { + if(buffer instanceof EaglerArrayByteBuffer) { + EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; + Int8Array d = b.typedArray; int p = b.position; - int l = b.limit; int i = d.getByteOffset(); - return Uint8Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2); + return Uint8Array.create(d.getBuffer(), i + p, b.limit - p); }else { throw notEagler(buffer); } } - public static Int32Array getDataViewStupid32(IntBuffer buffer) { - if(buffer instanceof EaglerArrayIntBuffer) { - EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; - DataView d = b.dataView; + public static Uint16Array getDataView16Unsigned(ByteBuffer buffer) { + if(buffer instanceof EaglerArrayByteBuffer) { + EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; + Int8Array d = b.typedArray; int p = b.position; - int l = b.limit; - int i = d.getByteOffset(); - return Int32Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2); + return Uint16Array.create(d.getBuffer(), d.getByteOffset() + p, (b.limit - p) >> 1); }else { throw notEagler(buffer); } } - public static DataView getDataView(FloatBuffer buffer) { - if(buffer instanceof EaglerArrayFloatBuffer) { - EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer; - DataView d = b.dataView; + public static Float32Array getDataView32F(ByteBuffer buffer) { + if(buffer instanceof EaglerArrayByteBuffer) { + EaglerArrayByteBuffer b = (EaglerArrayByteBuffer)buffer; + Int8Array d = b.typedArray; + int p = b.position; + return Float32Array.create(d.getBuffer(), d.getByteOffset() + p, (b.limit - p) >> 2); + }else { + throw notEagler(buffer); + } + } + + public static Int32Array getDataView32(IntBuffer buffer) { + if(buffer instanceof EaglerArrayIntBuffer) { + EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; + Int32Array d = b.typedArray; int p = b.position; int l = b.limit; if(p == 0 && l == b.capacity) { return d; }else { - int i = d.getByteOffset(); - return DataView.create(d.getBuffer(), i + (p << 2), (l - p) << 2); + return Int32Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), l - p); } }else { throw notEagler(buffer); } } - public static Uint8Array getDataViewStupid(FloatBuffer buffer) { - if(buffer instanceof EaglerArrayFloatBuffer) { - EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer; - DataView d = b.dataView; + public static Uint8Array getDataView8Unsigned(IntBuffer buffer) { + if(buffer instanceof EaglerArrayIntBuffer) { + EaglerArrayIntBuffer b = (EaglerArrayIntBuffer)buffer; + Int32Array d = b.typedArray; int p = b.position; int l = b.limit; - int i = d.getByteOffset(); - return Uint8Array.create(d.getBuffer(), i + (p << 2), (l - p) << 2); + return Uint8Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), (l - p) << 2); }else { throw notEagler(buffer); } } - public static Float32Array getFloatArrayStupid(FloatBuffer buffer) { + public static Float32Array getDataView32F(FloatBuffer buffer) { if(buffer instanceof EaglerArrayFloatBuffer) { EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer; - DataView d = b.dataView; + Float32Array d = b.typedArray; int p = b.position; int l = b.limit; - int i = d.getByteOffset(); - return Float32Array.create(d.getBuffer(), i + p, l - p); + if(p == 0 && l == b.capacity) { + return d; + }else { + return Float32Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), l - p); + } + }else { + throw notEagler(buffer); + } + } + + public static Uint8Array getDataView8Unsigned(FloatBuffer buffer) { + if(buffer instanceof EaglerArrayFloatBuffer) { + EaglerArrayFloatBuffer b = (EaglerArrayFloatBuffer)buffer; + Float32Array d = b.typedArray; + int p = b.position; + int l = b.limit; + return Uint8Array.create(d.getBuffer(), d.getByteOffset() + (p << 2), (l - p) << 2); }else { throw notEagler(buffer); } 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 5f2760c..adda4b2 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 @@ -1,8 +1,12 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.DataView; -import org.teavm.jso.typedarrays.Uint8Array; +import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.typedarrays.Int16Array; +import org.teavm.jso.typedarrays.Int32Array; +import org.teavm.jso.typedarrays.Int8Array; + +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -22,16 +26,18 @@ import org.teavm.jso.typedarrays.Uint8Array; public class EaglerArrayByteBuffer implements ByteBuffer { final DataView dataView; + final Int8Array typedArray; final int capacity; int position; int limit; int mark; - static final DataView ZERO_LENGTH_BUFFER = DataView.create(ArrayBuffer.create(0)); + static final Int8Array ZERO_LENGTH_BUFFER = Int8Array.create(0); EaglerArrayByteBuffer(DataView dataView) { this.dataView = dataView; + this.typedArray = Int8Array.create(dataView.getBuffer(), dataView.getByteOffset(), dataView.getByteLength()); this.capacity = dataView.getByteLength(); this.position = 0; this.limit = this.capacity; @@ -40,11 +46,30 @@ public class EaglerArrayByteBuffer implements ByteBuffer { EaglerArrayByteBuffer(DataView dataView, int position, int limit, int mark) { this.dataView = dataView; + this.typedArray = Int8Array.create(dataView.getBuffer(), dataView.getByteOffset(), dataView.getByteLength()); this.capacity = dataView.getByteLength(); this.position = position; this.limit = limit; this.mark = mark; } + + EaglerArrayByteBuffer(Int8Array typedArray) { + this.typedArray = typedArray; + this.dataView = DataView.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getByteLength()); + this.capacity = typedArray.getByteLength(); + this.position = 0; + this.limit = this.capacity; + this.mark = -1; + } + + EaglerArrayByteBuffer(Int8Array typedArray, int position, int limit, int mark) { + this.typedArray = typedArray; + this.dataView = DataView.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getByteLength()); + this.capacity = typedArray.getByteLength(); + this.position = position; + this.limit = limit; + this.mark = mark; + } @Override public int capacity() { @@ -93,8 +118,12 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer slice() { - int o = dataView.getByteOffset(); - return new EaglerArrayByteBuffer(DataView.create(dataView.getBuffer(), o + position, limit - position)); + if(position == limit) { + return new EaglerArrayByteBuffer(ZERO_LENGTH_BUFFER); + }else { + if(position > limit) throw new ArrayIndexOutOfBoundsException(position); + return new EaglerArrayByteBuffer(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, limit - position)); + } } @Override @@ -110,35 +139,33 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public byte get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return dataView.getInt8(position++); + return typedArray.get(position++); } @Override public ByteBuffer put(byte b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - dataView.setInt8(position++, b); + typedArray.set(position++, b); return this; } @Override public byte get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getInt8(index); + return typedArray.get(index); } @Override public ByteBuffer put(int index, byte b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setInt8(index, b); + typedArray.set(index, b); return this; } @Override public ByteBuffer get(byte[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = dataView.getInt8(position + i); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, length), offset); position += length; return this; } @@ -146,9 +173,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer get(byte[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[position + i] = dataView.getInt8(position + i); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, dst.length)); position += dst.length; return this; } @@ -159,10 +184,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { EaglerArrayByteBuffer c = (EaglerArrayByteBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - int o = c.dataView.getByteOffset(); - Uint8Array.create(dataView.getBuffer()).set( - Uint8Array.create(c.dataView.getBuffer(), o + c.position, c.limit - c.position), - dataView.getByteOffset() + position); + typedArray.set(Int8Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + c.position, l), position); position += l; c.position += l; }else { @@ -179,8 +201,10 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer put(byte[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dataView.setInt8(position + i, src[offset + i]); + if(offset == 0 && length == src.length) { + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); + }else { + typedArray.set(Int8Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset, length), position); } position += length; return this; @@ -189,10 +213,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ByteBuffer put(byte[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - //dataView.set(src, position); // doesn't work - for(int i = 0; i < src.length; ++i) { - dataView.setInt8(position + i, src[i]); - } + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); position += src.length; return this; } @@ -211,12 +232,10 @@ public class EaglerArrayByteBuffer implements ByteBuffer { return new EaglerArrayByteBuffer(ZERO_LENGTH_BUFFER); } - int o = dataView.getByteOffset(); + Int8Array dst = Int8Array.create(limit - position); + dst.set(Int8Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + position, limit - position)); - Uint8Array dst = Uint8Array.create(ArrayBuffer.create(limit - position)); - dst.set(Uint8Array.create(dataView.getBuffer(), o + position, limit - position)); - - return new EaglerArrayByteBuffer(DataView.create(dst.getBuffer())); + return new EaglerArrayByteBuffer(dst); } @Override @@ -279,7 +298,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public ShortBuffer asShortBuffer() { - return new EaglerArrayShortBuffer(dataView); + return new EaglerArrayShortBuffer(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 1)); } @Override @@ -313,7 +332,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public IntBuffer asIntBuffer() { - return new EaglerArrayIntBuffer(dataView); + return new EaglerArrayIntBuffer(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 2)); } @Override @@ -388,7 +407,7 @@ public class EaglerArrayByteBuffer implements ByteBuffer { @Override public FloatBuffer asFloatBuffer() { - return new EaglerArrayFloatBuffer(dataView); + return new EaglerArrayFloatBuffer(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset(), typedArray.getLength() >> 2)); } @Override diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayFloatBuffer.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayFloatBuffer.java index d69d580..4e9ffe9 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayFloatBuffer.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayFloatBuffer.java @@ -1,8 +1,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.typedarrays.DataView; -import org.teavm.jso.typedarrays.Uint8Array; +import org.teavm.jso.typedarrays.Float32Array; + +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array; */ public class EaglerArrayFloatBuffer implements FloatBuffer { - final DataView dataView; + final Float32Array typedArray; final int capacity; int position; @@ -30,17 +30,19 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { private static final int SHIFT = 2; - EaglerArrayFloatBuffer(DataView dataView) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + static final Float32Array ZERO_LENGTH_BUFFER = Float32Array.create(0); + + EaglerArrayFloatBuffer(Float32Array typedArray) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = 0; this.limit = this.capacity; this.mark = -1; } - EaglerArrayFloatBuffer(DataView dataView, int position, int limit, int mark) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + EaglerArrayFloatBuffer(Float32Array typedArray, int position, int limit, int mark) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = position; this.limit = limit; this.mark = mark; @@ -93,64 +95,66 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { @Override public FloatBuffer slice() { - int o = dataView.getByteOffset(); - return new EaglerArrayFloatBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); + if(position == limit) { + return new EaglerArrayFloatBuffer(ZERO_LENGTH_BUFFER); + }else { + if(position > limit) throw new ArrayIndexOutOfBoundsException(position); + return new EaglerArrayFloatBuffer(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); + } } @Override public FloatBuffer duplicate() { - return new EaglerArrayFloatBuffer(dataView, position, limit, mark); + return new EaglerArrayFloatBuffer(typedArray, position, limit, mark); } @Override public FloatBuffer asReadOnlyBuffer() { - return new EaglerArrayFloatBuffer(dataView, position, limit, mark); + return new EaglerArrayFloatBuffer(typedArray, position, limit, mark); } @Override public float get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return dataView.getFloat32((position++) << SHIFT, true); + return typedArray.get(position++); } @Override public FloatBuffer put(float b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - dataView.setFloat32((position++) << SHIFT, b, true); + typedArray.set(position++, b); return this; } @Override public float get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getFloat32(index << SHIFT, true); + return typedArray.get(index); } @Override public FloatBuffer put(int index, float b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setFloat32(index << SHIFT, b, true); + typedArray.set(index, b); return this; } @Override public float getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getFloat32(index << SHIFT, true); + return typedArray.get(index); } @Override public void putElement(int index, float value) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setFloat32(index << SHIFT, value, true); + typedArray.set(index, value); } @Override public FloatBuffer get(float[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = dataView.getFloat32((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset); position += length; return this; } @@ -158,9 +162,7 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { @Override public FloatBuffer get(float[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = dataView.getFloat32((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length)); position += dst.length; return this; } @@ -171,17 +173,14 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { EaglerArrayFloatBuffer c = (EaglerArrayFloatBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - int o = c.dataView.getByteOffset(); - Uint8Array.create(dataView.getBuffer()).set( - Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT), - dataView.getByteOffset() + (position << SHIFT)); + typedArray.set(Float32Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - dataView.setFloat32((position + l) << SHIFT, src.get(), true); + typedArray.set(position + l, src.get()); } position += l; } @@ -191,8 +190,10 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { @Override public FloatBuffer put(float[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dataView.setFloat32((position + i) << SHIFT, src[offset + i], true); + if(offset == 0 && length == src.length) { + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); + }else { + typedArray.set(Float32Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position); } position += length; return this; @@ -201,9 +202,7 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { @Override public FloatBuffer put(float[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - dataView.setFloat32((position + i) << SHIFT, src[i], true); - } + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); position += src.length; return this; } @@ -219,15 +218,13 @@ public class EaglerArrayFloatBuffer implements FloatBuffer { if(position > limit) throw new ArrayIndexOutOfBoundsException(position); if(position == limit) { - return new EaglerArrayFloatBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER); + return new EaglerArrayFloatBuffer(ZERO_LENGTH_BUFFER); } - int o = dataView.getByteOffset(); + Float32Array dst = Float32Array.create(limit - position); + dst.set(Float32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); - Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT)); - dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); - - return new EaglerArrayFloatBuffer(DataView.create(dst.getBuffer())); + return new EaglerArrayFloatBuffer(dst); } @Override diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayIntBuffer.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayIntBuffer.java index e2eaba8..7aee34a 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayIntBuffer.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayIntBuffer.java @@ -1,8 +1,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.typedarrays.DataView; -import org.teavm.jso.typedarrays.Uint8Array; +import org.teavm.jso.typedarrays.Int32Array; + +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array; */ public class EaglerArrayIntBuffer implements IntBuffer { - final DataView dataView; + final Int32Array typedArray; final int capacity; int position; @@ -30,17 +30,19 @@ public class EaglerArrayIntBuffer implements IntBuffer { private static final int SHIFT = 2; - EaglerArrayIntBuffer(DataView dataView) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + static final Int32Array ZERO_LENGTH_BUFFER = Int32Array.create(0); + + EaglerArrayIntBuffer(Int32Array typedArray) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = 0; this.limit = this.capacity; this.mark = -1; } - EaglerArrayIntBuffer(DataView dataView, int position, int limit, int mark) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + EaglerArrayIntBuffer(Int32Array typedArray, int position, int limit, int mark) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = position; this.limit = limit; this.mark = mark; @@ -93,64 +95,66 @@ public class EaglerArrayIntBuffer implements IntBuffer { @Override public IntBuffer slice() { - int o = dataView.getByteOffset(); - return new EaglerArrayIntBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); + if(position == limit) { + return new EaglerArrayIntBuffer(ZERO_LENGTH_BUFFER); + }else { + if(position > limit) throw new ArrayIndexOutOfBoundsException(position); + return new EaglerArrayIntBuffer(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); + } } @Override public IntBuffer duplicate() { - return new EaglerArrayIntBuffer(dataView, position, limit, mark); + return new EaglerArrayIntBuffer(typedArray, position, limit, mark); } @Override public IntBuffer asReadOnlyBuffer() { - return new EaglerArrayIntBuffer(dataView, position, limit, mark); + return new EaglerArrayIntBuffer(typedArray, position, limit, mark); } @Override public int get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return dataView.getInt32((position++) << SHIFT, true); + return typedArray.get(position++); } @Override public IntBuffer put(int b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - dataView.setInt32((position++) << SHIFT, b, true); + typedArray.set(position++, b); return this; } @Override public int get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getInt32(index << SHIFT, true); + return typedArray.get(index); } @Override public IntBuffer put(int index, int b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setInt32(index << SHIFT, b, true); + typedArray.set(index, b); return this; } @Override public int getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getInt32(index << SHIFT, true); + return typedArray.get(index); } @Override public void putElement(int index, int value) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setInt32(index << SHIFT, value, true); + typedArray.set(index, value); } @Override public IntBuffer get(int[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = dataView.getInt32((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset); position += length; return this; } @@ -158,9 +162,7 @@ public class EaglerArrayIntBuffer implements IntBuffer { @Override public IntBuffer get(int[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = dataView.getInt32((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length)); position += dst.length; return this; } @@ -171,17 +173,14 @@ public class EaglerArrayIntBuffer implements IntBuffer { EaglerArrayIntBuffer c = (EaglerArrayIntBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - int o = c.dataView.getByteOffset(); - Uint8Array.create(dataView.getBuffer()).set( - Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT), - dataView.getByteOffset() + (position << SHIFT)); + typedArray.set(Int32Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - dataView.setInt32((position + l) << SHIFT, src.get(), true); + typedArray.set(position + l, src.get()); } position += l; } @@ -191,8 +190,10 @@ public class EaglerArrayIntBuffer implements IntBuffer { @Override public IntBuffer put(int[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dataView.setInt32((position + i) << SHIFT, src[offset + i], true); + if(offset == 0 && length == src.length) { + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); + }else { + typedArray.set(Int32Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position); } position += length; return this; @@ -201,9 +202,7 @@ public class EaglerArrayIntBuffer implements IntBuffer { @Override public IntBuffer put(int[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - dataView.setInt32((position + i) << SHIFT, src[i], true); - } + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); position += src.length; return this; } @@ -219,15 +218,13 @@ public class EaglerArrayIntBuffer implements IntBuffer { if(position > limit) throw new ArrayIndexOutOfBoundsException(position); if(position == limit) { - return new EaglerArrayIntBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER); + return new EaglerArrayIntBuffer(ZERO_LENGTH_BUFFER); } - int o = dataView.getByteOffset(); + Int32Array dst = Int32Array.create(limit - position); + dst.set(Int32Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); - Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT)); - dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); - - return new EaglerArrayIntBuffer(DataView.create(dst.getBuffer())); + return new EaglerArrayIntBuffer(dst); } @Override diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayShortBuffer.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayShortBuffer.java index a21e63e..16eabb5 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayShortBuffer.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/buffer/EaglerArrayShortBuffer.java @@ -1,8 +1,8 @@ package net.lax1dude.eaglercraft.v1_8.internal.buffer; -import org.teavm.jso.typedarrays.ArrayBuffer; -import org.teavm.jso.typedarrays.DataView; -import org.teavm.jso.typedarrays.Uint8Array; +import org.teavm.jso.typedarrays.Int16Array; + +import net.lax1dude.eaglercraft.v1_8.internal.teavm.TeaVMUtils; /** * Copyright (c) 2022-2023 lax1dude. All Rights Reserved. @@ -21,7 +21,7 @@ import org.teavm.jso.typedarrays.Uint8Array; */ public class EaglerArrayShortBuffer implements ShortBuffer { - final DataView dataView; + final Int16Array typedArray; final int capacity; int position; @@ -30,17 +30,19 @@ public class EaglerArrayShortBuffer implements ShortBuffer { private static final int SHIFT = 1; - EaglerArrayShortBuffer(DataView dataView) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + static final Int16Array ZERO_LENGTH_BUFFER = Int16Array.create(0); + + EaglerArrayShortBuffer(Int16Array typedArray) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = 0; this.limit = this.capacity; this.mark = -1; } - EaglerArrayShortBuffer(DataView dataView, int position, int limit, int mark) { - this.dataView = dataView; - this.capacity = dataView.getByteLength() >> SHIFT; + EaglerArrayShortBuffer(Int16Array typedArray, int position, int limit, int mark) { + this.typedArray = typedArray; + this.capacity = typedArray.getLength(); this.position = position; this.limit = limit; this.mark = mark; @@ -93,64 +95,66 @@ public class EaglerArrayShortBuffer implements ShortBuffer { @Override public ShortBuffer slice() { - int o = dataView.getByteOffset(); - return new EaglerArrayShortBuffer(DataView.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); + if(position == limit) { + return new EaglerArrayShortBuffer(ZERO_LENGTH_BUFFER); + }else { + if(position > limit) throw new ArrayIndexOutOfBoundsException(position); + return new EaglerArrayShortBuffer(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); + } } @Override public ShortBuffer duplicate() { - return new EaglerArrayShortBuffer(dataView, position, limit, mark); + return new EaglerArrayShortBuffer(typedArray, position, limit, mark); } @Override public ShortBuffer asReadOnlyBuffer() { - return new EaglerArrayShortBuffer(dataView, position, limit, mark); + return new EaglerArrayShortBuffer(typedArray, position, limit, mark); } @Override public short get() { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - return dataView.getInt16((position++) << SHIFT, true); + return typedArray.get(position++); } @Override public ShortBuffer put(short b) { if(position >= limit) throw new ArrayIndexOutOfBoundsException(position); - dataView.setInt16((position++) << SHIFT, b, true); + typedArray.set(position++, b); return this; } @Override public short get(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getInt16(index << SHIFT, true); + return typedArray.get(index); } @Override public ShortBuffer put(int index, short b) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setInt16(index << SHIFT, b, true); + typedArray.set(index, b); return this; } @Override public short getElement(int index) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - return dataView.getInt16(index << SHIFT, true); + return typedArray.get(index); } @Override public void putElement(int index, short value) { if(index >= limit) throw new ArrayIndexOutOfBoundsException(index); - dataView.setInt16(index << SHIFT, value, true); + typedArray.set(index, value); } @Override public ShortBuffer get(short[] dst, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dst[offset + i] = dataView.getInt16((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), length), offset); position += length; return this; } @@ -158,9 +162,7 @@ public class EaglerArrayShortBuffer implements ShortBuffer { @Override public ShortBuffer get(short[] dst) { if(position + dst.length > limit) throw new ArrayIndexOutOfBoundsException(position + dst.length - 1); - for(int i = 0; i < dst.length; ++i) { - dst[i] = dataView.getInt16((position + i) << SHIFT, true); - } + TeaVMUtils.unwrapArrayBufferView(dst).set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), dst.length)); position += dst.length; return this; } @@ -171,17 +173,14 @@ public class EaglerArrayShortBuffer implements ShortBuffer { EaglerArrayShortBuffer c = (EaglerArrayShortBuffer)src; int l = c.limit - c.position; if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); - int o = c.dataView.getByteOffset(); - Uint8Array.create(dataView.getBuffer()).set( - Uint8Array.create(c.dataView.getBuffer(), o + (c.position << SHIFT), (c.limit - c.position) << SHIFT), - dataView.getByteOffset() + (position << SHIFT)); + typedArray.set(Int16Array.create(c.typedArray.getBuffer(), c.typedArray.getByteOffset() + (c.position << SHIFT), l), position); position += l; c.position += l; }else { int l = src.remaining(); if(position + l > limit) throw new ArrayIndexOutOfBoundsException(position + l - 1); for(int i = 0; i < l; ++i) { - dataView.setInt16((position + l) << SHIFT, src.get(), true); + typedArray.set(position + l, src.get()); } position += l; } @@ -191,8 +190,10 @@ public class EaglerArrayShortBuffer implements ShortBuffer { @Override public ShortBuffer put(short[] src, int offset, int length) { if(position + length > limit) throw new ArrayIndexOutOfBoundsException(position + length - 1); - for(int i = 0; i < length; ++i) { - dataView.setInt16((position + i) << SHIFT, src[offset + i], true); + if(offset == 0 && length == src.length) { + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); + }else { + typedArray.set(Int16Array.create(TeaVMUtils.unwrapArrayBuffer(src), offset << SHIFT, length), position); } position += length; return this; @@ -201,9 +202,7 @@ public class EaglerArrayShortBuffer implements ShortBuffer { @Override public ShortBuffer put(short[] src) { if(position + src.length > limit) throw new ArrayIndexOutOfBoundsException(position + src.length - 1); - for(int i = 0; i < src.length; ++i) { - dataView.setInt16((position + i) << SHIFT, src[i], true); - } + typedArray.set(TeaVMUtils.unwrapArrayBufferView(src), position); position += src.length; return this; } @@ -219,15 +218,13 @@ public class EaglerArrayShortBuffer implements ShortBuffer { if(position > limit) throw new ArrayIndexOutOfBoundsException(position); if(position == limit) { - return new EaglerArrayShortBuffer(EaglerArrayByteBuffer.ZERO_LENGTH_BUFFER); + return new EaglerArrayShortBuffer(ZERO_LENGTH_BUFFER); } - int o = dataView.getByteOffset(); + Int16Array dst = Int16Array.create(limit - position); + dst.set(Int16Array.create(typedArray.getBuffer(), typedArray.getByteOffset() + (position << SHIFT), limit - position)); - Uint8Array dst = Uint8Array.create(ArrayBuffer.create((limit - position) << SHIFT)); - dst.set(Uint8Array.create(dataView.getBuffer(), o + (position << SHIFT), (limit - position) << SHIFT)); - - return new EaglerArrayShortBuffer(DataView.create(dst.getBuffer())); + return new EaglerArrayShortBuffer(dst); } @Override 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 e9ad8a2..b0f6e33 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 @@ -55,6 +55,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { private boolean logInvalidCerts = false; private boolean checkRelaysForUpdates = false; private boolean enableSignatureBadge = false; + private boolean allowVoiceClient = true; public void loadNative(JSObject jsObject) { integratedServerOpts = new JSONObject(); @@ -73,12 +74,14 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { useSpecialCursors = eaglercraftXOpts.getHtml5CursorSupport(false); logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftXOpts.getLogInvalidCerts(false); enableSignatureBadge = eaglercraftXOpts.getEnableSignatureBadge(false); + allowVoiceClient = eaglercraftXOpts.getAllowVoiceClient(true); integratedServerOpts.put("worldsDB", worldsDB); integratedServerOpts.put("demoMode", demoMode); integratedServerOpts.put("lang", defaultLocale); integratedServerOpts.put("allowUpdateSvc", isAllowUpdateSvc); integratedServerOpts.put("allowUpdateDL", isAllowUpdateDL); + integratedServerOpts.put("allowVoiceClient", allowVoiceClient); JSEaglercraftXOptsServersArray serversArray = eaglercraftXOpts.getServers(); if(serversArray != null) { @@ -158,6 +161,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { useSpecialCursors = eaglercraftOpts.optBoolean("html5CursorSupport", false); logInvalidCerts = EaglercraftVersion.enableUpdateService && !demoMode && eaglercraftOpts.optBoolean("logInvalidCerts", false); enableSignatureBadge = eaglercraftOpts.optBoolean("enableSignatureBadge", false); + allowVoiceClient = eaglercraftOpts.optBoolean("allowVoiceClient", true); JSONArray serversArray = eaglercraftOpts.optJSONArray("servers"); if(serversArray != null) { for(int i = 0, l = serversArray.length(); i < l; ++i) { @@ -299,6 +303,11 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { public boolean isEnableSignatureBadge() { return enableSignatureBadge; } + + @Override + public boolean isAllowVoiceClient() { + return allowVoiceClient; + } @Override public String toString() { @@ -317,6 +326,7 @@ public class TeaVMClientConfigAdapter implements IClientConfigAdapter { jsonObject.put("logInvalidCerts", logInvalidCerts); jsonObject.put("checkRelaysForUpdates", checkRelaysForUpdates); jsonObject.put("enableSignatureBadge", enableSignatureBadge); + jsonObject.put("allowVoiceClient", allowVoiceClient); 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/TeaVMUtils.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMUtils.java index 98a6963..0a8edf7 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMUtils.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/internal/teavm/TeaVMUtils.java @@ -9,6 +9,7 @@ import org.teavm.jso.browser.Window; import org.teavm.jso.typedarrays.ArrayBuffer; import org.teavm.jso.typedarrays.ArrayBufferView; import org.teavm.jso.typedarrays.Float32Array; +import org.teavm.jso.typedarrays.Int16Array; import org.teavm.jso.typedarrays.Int32Array; import org.teavm.jso.typedarrays.Int8Array; import org.teavm.jso.typedarrays.Uint8Array; @@ -57,6 +58,10 @@ public class TeaVMUtils { return ((TeaVMArrayObject)(Object)buf).getData().getBuffer(); } + public static ArrayBufferView unwrapArrayBufferView(byte[] buf) { + return ((TeaVMArrayObject)(Object)buf).getData(); + } + @JSBody(params = { "buf" }, script = "return $rt_createByteArray(buf.buffer)") private static native JSObject wrapByteArray0(JSObject buf); @@ -80,6 +85,10 @@ public class TeaVMUtils { return ((TeaVMArrayObject)(Object)buf).getData().getBuffer(); } + public static ArrayBufferView unwrapArrayBufferView(int[] buf) { + return ((TeaVMArrayObject)(Object)buf).getData(); + } + @JSBody(params = { "buf" }, script = "return $rt_createIntArray(buf.buffer)") private static native JSObject wrapIntArray0(JSObject buf); @@ -95,6 +104,10 @@ public class TeaVMUtils { return ((TeaVMArrayObject)(Object)buf).getData().getBuffer(); } + public static ArrayBufferView unwrapArrayBufferView(float[] buf) { + return ((TeaVMArrayObject)(Object)buf).getData(); + } + @JSBody(params = { "buf" }, script = "return $rt_createFloatArray(buf.buffer)") private static native JSObject wrapFloatArray0(JSObject buf); @@ -102,6 +115,25 @@ public class TeaVMUtils { return (float[])(Object)wrapFloatArray0(buf); } + public static Int16Array unwrapShortArray(short[] buf) { + return Int16Array.create(((TeaVMArrayObject)(Object)buf).getData().getBuffer()); + } + + public static ArrayBuffer unwrapArrayBuffer(short[] buf) { + return ((TeaVMArrayObject)(Object)buf).getData().getBuffer(); + } + + public static ArrayBufferView unwrapArrayBufferView(short[] buf) { + return ((TeaVMArrayObject)(Object)buf).getData(); + } + + @JSBody(params = { "buf" }, script = "return $rt_createShortArray(buf.buffer)") + private static native JSObject wrapShortArray0(JSObject buf); + + public static short[] wrapShortArray(Int16Array buf) { + return (short[])(Object)wrapShortArray0(buf); + } + @Async public static native void sleepSetTimeout(int millis); 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 7449bd8..9e335f4 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 @@ -79,5 +79,8 @@ public abstract class JSEaglercraftXOptsRoot implements JSObject { @JSBody(params = { "def" }, script = "return (typeof this.checkRelaysForUpdates === \"boolean\") ? this.checkRelaysForUpdates : def;") public native boolean getCheckRelaysForUpdates(boolean defaultValue); + + @JSBody(params = { "def" }, script = "return (typeof this.allowVoiceClient === \"boolean\") ? this.allowVoiceClient : def;") + public native boolean getAllowVoiceClient(boolean defaultValue); } diff --git a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java index 597592f..dde15a3 100644 --- a/src/teavm/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java +++ b/src/teavm/java/net/lax1dude/eaglercraft/v1_8/opengl/GlStateManager.java @@ -13,7 +13,7 @@ import static net.lax1dude.eaglercraft.v1_8.opengl.RealOpenGLEnums.*; import static net.lax1dude.eaglercraft.v1_8.internal.PlatformOpenGL.*; /** - * Copyright (c) 2022-2023 lax1dude, ayunami2000. All Rights Reserved. + * 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 @@ -984,6 +984,30 @@ public class GlStateManager extends ModData { Matrix4f.mul(modeMatrix, paramMatrix, modeMatrix); } + + public static final void multMatrix(Matrix4f matrix) { + Matrix4f modeMatrix; + + switch(stateMatrixMode) { + case GL_MODELVIEW: + default: + modeMatrix = modelMatrixStack[modelMatrixStackPointer]; + modelMatrixStackAccessSerial[modelMatrixStackPointer] = ++modelMatrixAccessSerial; + break; + case GL_PROJECTION: + modeMatrix = projectionMatrixStack[projectionMatrixStackPointer]; + projectionMatrixStackAccessSerial[projectionMatrixStackPointer] = ++projectionMatrixAccessSerial; + break; + case GL_TEXTURE: + int ptr = textureMatrixStackPointer[activeTexture]; + modeMatrix = textureMatrixStack[activeTexture][ptr]; + textureMatrixStackAccessSerial[activeTexture][textureMatrixStackPointer[activeTexture]] = + ++textureMatrixAccessSerial[activeTexture]; + break; + } + + Matrix4f.mul(modeMatrix, matrix, modeMatrix); + } public static final void color(float colorRed, float colorGreen, float colorBlue, float colorAlpha) { stateColorR = colorRed; diff --git a/src/teavm/java/net/minecraft/client/Minecraft.java b/src/teavm/java/net/minecraft/client/Minecraft.java index d42ae4f..01d4999 100644 --- a/src/teavm/java/net/minecraft/client/Minecraft.java +++ b/src/teavm/java/net/minecraft/client/Minecraft.java @@ -45,6 +45,7 @@ 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.minecraft.EaglerFontRenderer; +import net.lax1dude.eaglercraft.v1_8.opengl.EaglerMeshLoader; import net.lax1dude.eaglercraft.v1_8.opengl.EaglercraftGPU; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.opengl.ImageData; @@ -73,6 +74,8 @@ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenSingleplayerConnecting; import net.lax1dude.eaglercraft.v1_8.sp.internal.ClientPlatformSingleplayer; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController; import net.lax1dude.eaglercraft.v1_8.update.RelayUpdateChecker; +import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceOverlay; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.client.audio.MusicTicker; @@ -315,6 +318,8 @@ public class Minecraft extends ModData implements IThreadListener { public ModAPI modapi; public SkullCommand eagskullCommand; + + public GuiVoiceOverlay voiceOverlay; public Minecraft(GameConfiguration gameConfig) { theMinecraft = this; @@ -431,6 +436,7 @@ public class Minecraft extends ModData implements IThreadListener { this.mcResourceManager.registerReloadListener(new MetalsLUT()); this.mcResourceManager.registerReloadListener(new EmissiveItems()); this.mcResourceManager.registerReloadListener(new BlockVertexIDs()); + this.mcResourceManager.registerReloadListener(new EaglerMeshLoader()); AchievementList.openInventory.setStatStringFormatter(new IStatStringFormat() { public String formatString(String parString1) { try { @@ -481,6 +487,9 @@ public class Minecraft extends ModData implements IThreadListener { this.checkGLError("Post startup"); this.ingameGUI = new GuiIngame(this); this.eagskullCommand = new SkullCommand(this); + this.voiceOverlay = new GuiVoiceOverlay(this); + ScaledResolution voiceRes = new ScaledResolution(this); + this.voiceOverlay.setResolution(voiceRes.getScaledWidth(), voiceRes.getScaledHeight()); ServerList.initServerList(this); EaglerProfile.read(); @@ -888,6 +897,7 @@ public class Minecraft extends ModData implements IThreadListener { public void updateDisplay() { this.mcProfiler.startSection("display_update"); + Display.setVSync(this.gameSettings.enableVsync); Display.update(); this.mcProfiler.endSection(); this.checkWindowResize(); @@ -1234,12 +1244,14 @@ public class Minecraft extends ModData implements IThreadListener { private void resize(int width, int height) { this.displayWidth = Math.max(1, width); this.displayHeight = Math.max(1, height); + ScaledResolution scaledresolution = new ScaledResolution(this); if (this.currentScreen != null) { - ScaledResolution scaledresolution = new ScaledResolution(this); this.currentScreen.onResize(this, scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight()); } this.loadingScreen = new LoadingScreenRenderer(this); + + this.voiceOverlay.setResolution(scaledresolution.getScaledWidth(), scaledresolution.getScaledHeight()); } public MusicTicker func_181535_r() { @@ -1278,6 +1290,9 @@ public class Minecraft extends ModData implements IThreadListener { if (!this.isGamePaused) { this.ingameGUI.updateTick(); } + + this.mcProfiler.endStartSection("eaglerVoice"); + VoiceClientController.tickVoiceClient(this); this.mcProfiler.endSection(); this.entityRenderer.getMouseOver(1.0F); @@ -1794,6 +1809,7 @@ public class Minecraft extends ModData implements IThreadListener { */ public void launchIntegratedServer(String folderName, String worldName, WorldSettings worldSettingsIn) { this.loadWorld((WorldClient) null); + Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins(this.gameSettings.enableFNAWSkins); session.reset(); SingleplayerServerController.launchEaglercraftServer(folderName, gameSettings.difficulty.getDifficultyId(), Math.max(gameSettings.renderDistanceChunks, 2), worldSettingsIn); @@ -2338,4 +2354,12 @@ public class Minecraft extends ModData implements IThreadListener { public void clearTitles() { ingameGUI.displayTitle(null, null, -1, -1, -1); } + + public boolean getEnableFNAWSkins() { + boolean ret = this.gameSettings.enableFNAWSkins; + if (this.thePlayer != null) { + ret &= this.thePlayer.sendQueue.currentFNAWSkinAllowedState; + } + return ret; + } } \ No newline at end of file diff --git a/src/teavm/java/net/minecraft/client/gui/GuiIngame.java b/src/teavm/java/net/minecraft/client/gui/GuiIngame.java index b7ab960..c8aef88 100644 --- a/src/teavm/java/net/minecraft/client/gui/GuiIngame.java +++ b/src/teavm/java/net/minecraft/client/gui/GuiIngame.java @@ -289,6 +289,10 @@ public class GuiIngame extends Gui { if (scoreobjective1 != null) { this.renderScoreboard(scoreobjective1, scaledresolution); } + + if (this.mc.currentScreen == null) { + this.mc.voiceOverlay.drawOverlay(); + } GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0); diff --git a/src/teavm/java/net/minecraft/client/gui/GuiIngameMenu.java b/src/teavm/java/net/minecraft/client/gui/GuiIngameMenu.java index b436341..dd0c57f 100644 --- a/src/teavm/java/net/minecraft/client/gui/GuiIngameMenu.java +++ b/src/teavm/java/net/minecraft/client/gui/GuiIngameMenu.java @@ -1,5 +1,6 @@ package net.minecraft.client.gui; +import net.lax1dude.eaglercraft.v1_8.EagRuntime; import net.lax1dude.eaglercraft.v1_8.Mouse; import net.lax1dude.eaglercraft.v1_8.opengl.GlStateManager; import net.lax1dude.eaglercraft.v1_8.sp.SingleplayerServerController; @@ -8,6 +9,8 @@ import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiScreenLANNotSupported; import net.lax1dude.eaglercraft.v1_8.sp.gui.GuiShareToLan; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANServerController; import net.lax1dude.eaglercraft.v1_8.update.GuiUpdateCheckerOverlay; +import net.lax1dude.eaglercraft.v1_8.voice.GuiVoiceMenu; +import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.achievement.GuiAchievements; import net.minecraft.client.gui.achievement.GuiStats; @@ -45,9 +48,13 @@ public class GuiIngameMenu extends GuiScreen { boolean hasSentAutoSave = !SingleplayerServerController.isWorldRunning(); private GuiUpdateCheckerOverlay updateCheckerOverlay; + private GuiVoiceMenu voiceMenu; public GuiIngameMenu() { updateCheckerOverlay = new GuiUpdateCheckerOverlay(true, this); + if (EagRuntime.getConfiguration().isAllowVoiceClient()) { + voiceMenu = new GuiVoiceMenu(this); + } } /**+ @@ -146,6 +153,10 @@ public class GuiIngameMenu extends GuiScreen { */ public void updateScreen() { super.updateScreen(); + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.updateScreen(); + } if (Mouse.isActuallyGrabbed()) { Mouse.setGrabbed(false); } @@ -163,37 +174,67 @@ public class GuiIngameMenu extends GuiScreen { this.updateCheckerOverlay.drawScreen(i, j, f); if (LANServerController.isLANOpen()) { + int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset(); String str = I18n.format("lanServer.pauseMenu0"); - drawString(fontRendererObj, str, 6, 32, 0xFFFF55); + drawString(fontRendererObj, str, 6, 10 + offset, 0xFFFF55); if (mc.gameSettings.hideJoinCode) { GlStateManager.pushMatrix(); - GlStateManager.translate(7.0f, 47.0f, 0.0f); + GlStateManager.translate(7.0f, 25.0f + offset, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); str = I18n.format("lanServer.showCode"); int w = fontRendererObj.getStringWidth(str); - boolean hover = i > 6 && i < 8 + w * 3 / 4 && j > 46 && j < 47 + 8; + boolean hover = i > 4 && i < 8 + w * 3 / 4 && j > 24 + offset && j < 25 + offset + 8; drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55); GlStateManager.popMatrix(); } else { int w = fontRendererObj.getStringWidth(str); GlStateManager.pushMatrix(); - GlStateManager.translate(6 + w + 3, 33, 0.0f); + GlStateManager.translate(6 + w + 3, 11 + offset, 0.0f); GlStateManager.scale(0.75f, 0.75f, 0.75f); str = I18n.format("lanServer.hideCode"); int w2 = fontRendererObj.getStringWidth(str); - boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 33 - 1 && j < 33 + 6; + boolean hover = i > 6 + w + 2 && i < 6 + w + 3 + w2 * 3 / 4 && j > 11 + offset - 1 + && j < 11 + offset + 6; drawString(fontRendererObj, EnumChatFormatting.UNDERLINE + str, 0, 0, hover ? 0xEEEEAA : 0xCCCC55); GlStateManager.popMatrix(); - drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " " - + EnumChatFormatting.RESET + LANServerController.getCurrentURI(), 6, 47, 0xFFFFFF); - drawString(fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " " - + EnumChatFormatting.RESET + LANServerController.getCurrentCode(), 6, 57, 0xFFFFFF); + drawString( + fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu1") + " " + + EnumChatFormatting.RESET + LANServerController.getCurrentURI(), + 6, 25 + offset, 0xFFFFFF); + drawString( + fontRendererObj, EnumChatFormatting.GRAY + I18n.format("lanServer.pauseMenu2") + " " + + EnumChatFormatting.RESET + LANServerController.getCurrentCode(), + 6, 35 + offset, 0xFFFFFF); } } - super.drawScreen(i, j, f); + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + if (voiceMenu.isBlockingInput()) { + super.drawScreen(0, 0, f); + } else { + super.drawScreen(i, j, f); + } + voiceMenu.drawScreen(i, j, f); + } else { + super.drawScreen(i, j, f); + } + } catch (GuiVoiceMenu.AbortedException ex) { + } + } + + protected void keyTyped(char par1, int par2) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.keyTyped(par1, par2); + } + super.keyTyped(par1, par2); + } catch (GuiVoiceMenu.AbortedException ex) { + } } public void confirmClicked(boolean par1, int par2) { @@ -208,11 +249,20 @@ public class GuiIngameMenu extends GuiScreen { } protected void mouseClicked(int par1, int par2, int par3) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.mouseClicked(par1, par2, par3); + } + } catch (GuiVoiceMenu.AbortedException ex) { + return; + } if (par3 == 0) { + int offset = this.updateCheckerOverlay.getSharedWorldInfoYOffset(); if (mc.gameSettings.hideJoinCode) { String str = I18n.format("lanServer.showCode"); int w = fontRendererObj.getStringWidth(str); - if (par1 > 6 && par1 < 8 + w * 3 / 4 && par2 > 46 && par2 < 47 + 8) { + if (par1 > 4 && par1 < 8 + w * 3 / 4 && par2 > 24 + offset && par2 < 25 + offset + 8) { mc.gameSettings.hideJoinCode = false; this.mc.getSoundHandler() .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); @@ -223,7 +273,8 @@ public class GuiIngameMenu extends GuiScreen { int w = fontRendererObj.getStringWidth(str); str = I18n.format("lanServer.hideCode"); int w2 = fontRendererObj.getStringWidth(str); - if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 33 - 1 && par2 < 33 + 6) { + if (par1 > 6 + w + 2 && par1 < 6 + w + 3 + w2 * 3 / 4 && par2 > 11 + offset - 1 + && par2 < 11 + offset + 6) { mc.gameSettings.hideJoinCode = true; this.mc.getSoundHandler() .playSound(PositionedSoundRecord.create(new ResourceLocation("gui.button.press"), 1.0F)); @@ -235,4 +286,22 @@ public class GuiIngameMenu extends GuiScreen { this.updateCheckerOverlay.mouseClicked(par1, par2, par3); super.mouseClicked(par1, par2, par3); } + + public void setWorldAndResolution(Minecraft par1Minecraft, int par2, int par3) { + super.setWorldAndResolution(par1Minecraft, par2, par3); + if (EagRuntime.getConfiguration().isAllowVoiceClient()) { + voiceMenu.setResolution(par1Minecraft, par2, par3); + } + } + + protected void mouseReleased(int par1, int par2, int par3) { + try { + if (EagRuntime.getConfiguration().isAllowVoiceClient() + && (!mc.isSingleplayer() || LANServerController.isHostingLAN())) { + voiceMenu.mouseReleased(par1, par2, par3); + } + super.mouseReleased(par1, par2, par3); + } catch (GuiVoiceMenu.AbortedException ex) { + } + } } \ No newline at end of file diff --git a/src/teavm/java/net/minecraft/client/gui/GuiScreen.java b/src/teavm/java/net/minecraft/client/gui/GuiScreen.java index d512358..0165809 100644 --- a/src/teavm/java/net/minecraft/client/gui/GuiScreen.java +++ b/src/teavm/java/net/minecraft/client/gui/GuiScreen.java @@ -678,4 +678,8 @@ public abstract class GuiScreen extends Gui implements GuiYesNoCallback { public boolean shouldHangupIntegratedServer() { return true; } + + public boolean blockPTTKey() { + return false; + } } \ No newline at end of file diff --git a/src/teavm/java/net/minecraft/client/network/NetHandlerPlayClient.java b/src/teavm/java/net/minecraft/client/network/NetHandlerPlayClient.java index a15a956..8020d40 100644 --- a/src/teavm/java/net/minecraft/client/network/NetHandlerPlayClient.java +++ b/src/teavm/java/net/minecraft/client/network/NetHandlerPlayClient.java @@ -16,12 +16,15 @@ import net.lax1dude.eaglercraft.v1_8.EaglercraftUUID; import com.google.common.collect.Maps; import net.lax1dude.eaglercraft.v1_8.netty.Unpooled; +import net.lax1dude.eaglercraft.v1_8.profile.CapePackets; +import net.lax1dude.eaglercraft.v1_8.profile.ServerCapeCache; import net.lax1dude.eaglercraft.v1_8.profile.ServerSkinCache; import net.lax1dude.eaglercraft.v1_8.profile.SkinPackets; import net.lax1dude.eaglercraft.v1_8.socket.EaglercraftNetworkManager; import net.lax1dude.eaglercraft.v1_8.sp.lan.LANClientNetworkManager; import net.lax1dude.eaglercraft.v1_8.sp.socket.ClientIntegratedServerNetworkManager; import net.lax1dude.eaglercraft.v1_8.update.UpdateService; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; import net.lax1dude.eaglercraft.v1_8.minecraft.EaglerFolderResourcePack; @@ -245,6 +248,8 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie */ private final EaglercraftRandom avRandomizer = new EaglercraftRandom(); private final ServerSkinCache skinCache; + private final ServerCapeCache capeCache; + public boolean currentFNAWSkinAllowedState = true; public NetHandlerPlayClient(Minecraft mcIn, GuiScreen parGuiScreen, EaglercraftNetworkManager parNetworkManager, GameProfile parGameProfile) { @@ -253,6 +258,7 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie this.netManager = parNetworkManager; this.profile = parGameProfile; this.skinCache = new ServerSkinCache(parNetworkManager, mcIn.getTextureManager()); + this.capeCache = new ServerCapeCache(parNetworkManager, mcIn.getTextureManager()); this.isIntegratedServer = (parNetworkManager instanceof ClientIntegratedServerNetworkManager) || (parNetworkManager instanceof LANClientNetworkManager); } @@ -264,11 +270,16 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie public void cleanup() { this.clientWorldController = null; this.skinCache.destroy(); + this.capeCache.destroy(); } public ServerSkinCache getSkinCache() { return this.skinCache; } + + public ServerCapeCache getCapeCache() { + return this.capeCache; + } public void loadModData(BaseData data) { doneLoadingTerrain = data.getBoolean("doneLoadingTerrain"); @@ -441,6 +452,10 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie this.gameController.gameSettings.sendSettingsToServer(); this.netManager.sendPacket(new C17PacketCustomPayload("MC|Brand", (new PacketBuffer(Unpooled.buffer())).writeString(ClientBrandRetriever.getClientModName()))); + if (VoiceClientController.isClientSupported()) { + VoiceClientController.initializeVoiceClient((pkt) -> this.netManager + .sendPacket(new C17PacketCustomPayload(VoiceClientController.SIGNAL_CHANNEL, pkt))); + } } /**+ @@ -863,6 +878,9 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie * describing the reason for termination */ public void onDisconnect(IChatComponent ichatcomponent) { + VoiceClientController.handleServerDisconnect(); + Minecraft.getMinecraft().getRenderManager() + .setEnableFNAWSkins(this.gameController.gameSettings.enableFNAWSkins); if (this.gameController.theWorld != null) { this.gameController.loadWorld((WorldClient) null); } @@ -1975,6 +1993,7 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie EaglercraftUUID uuid = s38packetplayerlistitem$addplayerdata.getProfile().getId(); this.playerInfoMap.remove(uuid); this.skinCache.evictSkin(uuid); + this.capeCache.evictCape(uuid); } else { NetworkPlayerInfo networkplayerinfo = (NetworkPlayerInfo) this.playerInfoMap .get(s38packetplayerlistitem$addplayerdata.getProfile().getId()); @@ -2168,6 +2187,13 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie logger.error("Couldn't read EAG|Skins-1.8 packet!"); logger.error(e); } + } else if ("EAG|Capes-1.8".equals(packetIn.getChannelName())) { + try { + CapePackets.readPluginMessage(packetIn.getBufferData(), capeCache); + } catch (IOException e) { + logger.error("Couldn't read EAG|Capes-1.8 packet!"); + logger.error(e); + } } else if ("EAG|UpdateCert-1.8".equals(packetIn.getChannelName())) { if (EagRuntime.getConfiguration().allowUpdateSvc()) { try { @@ -2180,6 +2206,14 @@ public class NetHandlerPlayClient extends ModData implements INetHandlerPlayClie logger.error(e); } } + } else if (VoiceClientController.SIGNAL_CHANNEL.equals(packetIn.getChannelName())) { + if (VoiceClientController.isClientSupported()) { + VoiceClientController.handleVoiceSignalPacket(packetIn.getBufferData()); + } + } else if ("EAG|FNAWSEn-1.8".equals(packetIn.getChannelName())) { + this.currentFNAWSkinAllowedState = packetIn.getBufferData().readBoolean(); + Minecraft.getMinecraft().getRenderManager().setEnableFNAWSkins( + this.currentFNAWSkinAllowedState && Minecraft.getMinecraft().gameSettings.enableFNAWSkins); } } diff --git a/src/teavm/java/net/minecraft/client/settings/GameSettings.java b/src/teavm/java/net/minecraft/client/settings/GameSettings.java index 6935ded..ff6e6c4 100644 --- a/src/teavm/java/net/minecraft/client/settings/GameSettings.java +++ b/src/teavm/java/net/minecraft/client/settings/GameSettings.java @@ -20,6 +20,7 @@ import net.PeytonPlayz585.shadow.Lang; import net.eaglerforge.api.BaseData; import net.eaglerforge.api.ModData; import net.lax1dude.eaglercraft.v1_8.sp.relay.RelayManager; +import net.lax1dude.eaglercraft.v1_8.voice.VoiceClientController; import org.json.JSONArray; import com.google.common.collect.ImmutableSet; @@ -35,6 +36,7 @@ import net.lax1dude.eaglercraft.v1_8.EaglerZLIB; import net.lax1dude.eaglercraft.v1_8.HString; import net.lax1dude.eaglercraft.v1_8.Keyboard; import net.lax1dude.eaglercraft.v1_8.Mouse; +import net.lax1dude.eaglercraft.v1_8.internal.EnumPlatformType; import net.lax1dude.eaglercraft.v1_8.internal.KeyboardConstants; import net.lax1dude.eaglercraft.v1_8.log4j.LogManager; import net.lax1dude.eaglercraft.v1_8.log4j.Logger; @@ -112,7 +114,7 @@ public class GameSettings extends ModData { public boolean chatLinksPrompt = true; public float chatOpacity = 1.0F; public boolean snooperEnabled = true; - public boolean enableVsync = true; + public boolean enableVsync = EagRuntime.getPlatformType() != EnumPlatformType.DESKTOP; public boolean allowBlockAlternatives = true; public boolean reducedDebugInfo = false; public boolean hideServerAddress; @@ -267,6 +269,12 @@ public class GameSettings extends ModData { public boolean ofSmoothBiomes = true; public boolean ofCustomColors = true; public boolean hidePassword = true; + public boolean enableFNAWSkins = true; + + public int voiceListenRadius = 16; + public float voiceListenVolume = 0.5f; + public float voiceSpeakVolume = 0.5f; + public int voicePTTKey = 47; // V public GameSettings(Minecraft mcIn) { this.keyBindings = (KeyBinding[]) ArrayUtils.addAll(new KeyBinding[] { this.keyBindAttack, this.keyBindUseItem, @@ -1060,6 +1068,15 @@ public class GameSettings extends ModData { if (parOptions == GameSettings.Options.HIDE_PASSWORD) { hidePassword =! hidePassword; } + + if (parOptions == GameSettings.Options.FNAW_SKINS) { + this.enableFNAWSkins = !this.enableFNAWSkins; + this.mc.getRenderManager().setEnableFNAWSkins(this.mc.getEnableFNAWSkins()); + } + + if (parOptions == GameSettings.Options.EAGLER_VSYNC) { + this.enableVsync = !this.enableVsync; + } this.saveOptions(); } @@ -1181,6 +1198,10 @@ public class GameSettings extends ModData { return this.ofSmoothBiomes; case CUSTOM_COLORS: return this.ofCustomColors; + case FNAW_SKINS: + return this.enableFNAWSkins; + case EAGLER_VSYNC: + return this.enableVsync; default: return false; } @@ -1636,7 +1657,7 @@ public class GameSettings extends ModData { this.snooperEnabled = astring[1].equals("true"); } - if (astring[0].equals("enableVsync")) { + if (astring[0].equals("enableVsyncEag")) { this.enableVsync = astring[1].equals("true"); } @@ -2031,7 +2052,21 @@ public class GameSettings extends ModData { hidePassword = Boolean.valueOf(astring[1]).booleanValue(); } - Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + if (astring[0].equals("voiceListenRadius")) { + voiceListenRadius = Integer.parseInt(astring[1]); + } + + if (astring[0].equals("voiceListenVolume")) { + voiceListenVolume = this.parseFloat(astring[1]); + } + + if (astring[0].equals("voiceSpeakVolume")) { + voiceSpeakVolume = this.parseFloat(astring[1]); + } + + if (astring[0].equals("voicePTTKey")) { + voicePTTKey = Integer.parseInt(astring[1]); + } for (SoundCategory soundcategory : SoundCategory._VALUES) { if (astring[0].equals("soundCategory_" + soundcategory.getCategoryName())) { @@ -2044,6 +2079,10 @@ public class GameSettings extends ModData { this.setModelPartEnabled(enumplayermodelparts, astring[1].equals("true")); } } + + if (astring[0].equals("enableFNAWSkins")) { + this.enableFNAWSkins = astring[1].equals("true"); + } deferredShaderConf.readOption(astring[0], astring[1]); } catch (Exception var8) { @@ -2052,8 +2091,16 @@ public class GameSettings extends ModData { } KeyBinding.resetKeyBindingArrayAndHash(); + + Keyboard.setFunctionKeyModifier(keyBindFunction.getKeyCode()); + VoiceClientController.setVoiceListenVolume(voiceListenVolume); + VoiceClientController.setVoiceSpeakVolume(voiceSpeakVolume); + VoiceClientController.setVoiceProximity(voiceListenRadius); + if (this.mc.getRenderManager() != null) + this.mc.getRenderManager().setEnableFNAWSkins(this.enableFNAWSkins); } catch (Exception exception) { - logger.error("Failed to load options", exception); + logger.error("Failed to load options"); + logger.error(exception); } } @@ -2120,7 +2167,7 @@ public class GameSettings extends ModData { printwriter.println("chatLinksPrompt:" + this.chatLinksPrompt); printwriter.println("chatOpacity:" + this.chatOpacity); printwriter.println("snooperEnabled:" + this.snooperEnabled); - printwriter.println("enableVsync:" + this.enableVsync); + printwriter.println("enableVsyncEag:" + this.enableVsync); printwriter.println("hideServerAddress:" + this.hideServerAddress); printwriter.println("advancedItemTooltips:" + this.advancedItemTooltips); printwriter.println("pauseOnLostFocus:" + this.pauseOnLostFocus); @@ -2209,6 +2256,11 @@ public class GameSettings extends ModData { printwriter.println("ofSmoothBiomes:" + this.ofSmoothBiomes); printwriter.println("ofCustomColors:" + this.ofCustomColors); printwriter.println("hidePassword:" + hidePassword); + printwriter.println("voiceListenRadius:" + this.voiceListenRadius); + printwriter.println("voiceListenVolume:" + this.voiceListenVolume); + printwriter.println("voiceSpeakVolume:" + this.voiceSpeakVolume); + printwriter.println("voicePTTKey:" + this.voicePTTKey); + printwriter.println("enableFNAWSkins:" + this.enableFNAWSkins); for (KeyBinding keybinding : this.keyBindings) { printwriter.println("key_" + keybinding.getKeyDescription() + ":" + keybinding.getKeyCode()); @@ -2231,7 +2283,8 @@ public class GameSettings extends ModData { printwriter.close(); return bao.toByteArray(); } catch (Exception exception) { - logger.error("Failed to save options", exception); + logger.error("Failed to save options"); + logger.error(exception); return null; } @@ -2417,7 +2470,9 @@ public class GameSettings extends ModData { SWAMP_COLORS("Swamp Colors", false, false), SMOOTH_BIOMES("Smooth Biomes", false, false), CUSTOM_COLORS("Custom Colors", false, false), - HIDE_PASSWORD("Hide Password", false, false); + HIDE_PASSWORD("Hide Password", false, false), + FNAW_SKINS("options.skinCustomisation.enableFNAWSkins", false, true), + EAGLER_VSYNC("options.vsync", false, true); private final boolean enumFloat; private final boolean enumBoolean;