From 70b292cd1ddc6bd3a49f8beed06c7f882dbcab3e Mon Sep 17 00:00:00 2001 From: "TempleTerry[x64]" <123938029+PhilipPanda@users.noreply.github.com> Date: Fri, 12 Apr 2024 22:55:50 +0200 Subject: [PATCH] 1.8.8 Finally --- gradle.properties | 4 +- gradlew | 295 +++++--- .../templeclient/TempleClient.java | 39 +- .../templeclient/config/ConfigManager.java | 71 +- .../templeclient/event/EventCancellable.java | 3 +- .../templeclient/event/EventStageable.java | 3 +- .../templeclient/event/ForgeEventManager.java | 32 +- .../event/events/render/ArmorEvent.java | 6 + .../event/events/render/FireEvent.java | 6 + .../event/events/render/HeldItemEvent.java | 6 + .../event/events/render/NamePlateEvent.java | 12 + .../event/events/render/Render3DEvent.java | 12 + .../event/events/render/Render3DPreEvent.java | 11 + .../events/render/Render3DPrePreEvent.java | 11 + .../event/events/world/EntityEvent.java | 10 +- .../events/world/LiquidCollisionEvent.java | 10 +- .../command/commands/BindCommand.java | 5 +- .../command/commands/CoordsCommand.java | 2 +- .../command/commands/FriendCommand.java | 2 +- .../command/commands/HelpCommand.java | 5 +- .../features/command/commands/IpCommand.java | 2 +- .../command/commands/NameMcCommand.java | 35 + .../gui/clickgui/basic/ClickGuiScreen.java | 4 +- .../gui/clickgui/basic/ClientGuiScreen.java | 4 +- .../gui/clickgui/basic/panels/IContainer.java | 11 + .../clickgui/basic/{ => panels}/Panel.java | 78 +- .../basic/{ => panels/items}/Item.java | 34 +- .../items/buttons}/BindButton.java | 12 +- .../items/buttons}/BooleanButton.java | 49 +- .../{ => panels/items/buttons}/Button.java | 42 +- .../panels/items/buttons/ColorButton.java | 310 ++++++++ .../items/buttons}/DoubleSlider.java | 21 +- .../items/buttons}/EnumButton.java | 37 +- .../items/buttons}/IntSlider.java | 20 +- .../items/buttons}/ModuleButton.java | 118 +-- .../panels/items/buttons/StringButton.java | 131 ++++ .../features/gui/clickgui/csgo/Button.java | 45 -- ...tCsgoGuiScreen.java => CsgoGuiScreen.java} | 129 ++-- .../clickgui/csgo/properties/BindButton.java | 107 --- .../clickgui/csgo/properties/IContainer.java | 10 + .../csgo/properties/ModuleButton.java | 169 ----- .../{NavLink.java => properties/Panel.java} | 154 ++-- .../csgo/{ => properties/items}/Item.java | 2 +- .../properties/items/buttons/BindButton.java | 121 +++ .../{ => items/buttons}/BooleanButton.java | 50 +- .../csgo/properties/items/buttons/Button.java | 47 ++ .../properties/items/buttons/ColorButton.java | 308 ++++++++ .../items/buttons/ModuleButton.java | 238 ++++++ .../items/buttons/StringButton.java | 140 ++++ .../{ => items/buttons/enumB}/EnumButton.java | 41 +- .../buttons/enumB}/EnumValueButton.java | 2 +- .../buttons/enumB}/NormalButton.java | 47 +- .../buttons/slider}/DoubleSlider.java | 72 +- .../{ => items/buttons/slider}/IntSlider.java | 68 +- .../gui/clickgui/hud/HudEditorScreen.java | 48 +- .../gui/clickgui/hud/HudElementButton.java | 105 ++- .../gui/clickgui/particles/Particle.java | 16 +- .../features/gui/clickgui/particles/Snow.java | 11 +- .../features/gui/font/AbstractFont.java | 21 + .../templeclient/features/gui/font/CFont.java | 525 ++++++++++--- .../features/gui/font/FontUtils.java | 126 ++-- .../gui/font/MinecraftFontRenderer.java | 695 ------------------ .../features/gui/menu/CustomMainMenu.java | 4 +- .../features/gui/menu/alt/AltManager.java | 148 ++-- .../templeclient/features/module/Module.java | 72 +- .../module/modules/chat/ChatCrypt.java | 2 +- .../module/modules/chat/FancyChat.java | 15 +- .../module/modules/chat/GreenText.java | 2 +- .../features/module/modules/chat/Spammer.java | 2 +- .../module/modules/client/ClickGUI.java | 61 +- .../module/modules/client/Colors.java | 85 +++ .../features/module/modules/client/Font.java | 55 -- .../module/modules/client/FontSettings.java | 81 ++ .../features/module/modules/client/HUD.java | 32 +- .../module/modules/client/MiddleClick.java | 6 +- .../features/module/modules/client/Panic.java | 21 +- .../module/modules/client/hud/Armor.java | 16 +- .../module/modules/client/hud/Coords.java | 28 +- .../module/modules/client/hud/Durability.java | 30 + .../module/modules/client/hud/FPS.java | 17 +- .../module/modules/client/hud/Friends.java | 20 +- .../module/modules/client/hud/Inventory.java | 7 +- .../module/modules/client/hud/ModuleList.java | 39 +- .../modules/client/hud/Notifications.java | 12 +- .../module/modules/client/hud/Ping.java | 11 +- .../module/modules/client/hud/PlayerName.java | 9 +- .../module/modules/client/hud/PlayerView.java | 2 +- .../module/modules/client/hud/PotionHUD.java | 17 +- .../module/modules/client/hud/Server.java | 13 +- .../module/modules/client/hud/Speed.java | 14 +- .../module/modules/client/hud/TargetHUD.java | 30 +- .../module/modules/client/hud/Watermark.java | 18 +- .../hud/notification/NotificationInfo.java | 40 + .../hud/notification/NotificationType.java | 21 + .../notification/NotificationsRewrite.java | 71 ++ .../module/modules/combat/AimAssist.java | 36 +- .../module/modules/combat/AntiBots.java | 25 - .../features/module/modules/combat/Aura.java | 72 +- .../module/modules/combat/AutoArmor.java | 26 +- .../module/modules/combat/AutoCrystal.java | 332 +++++---- .../module/modules/combat/AutoDisconnect.java | 10 +- .../module/modules/combat/AutoGapple.java | 93 --- .../module/modules/combat/AutoTotem.java | 16 +- .../module/modules/combat/BowAimbot.java | 70 ++ .../module/modules/combat/BowSpam.java | 48 ++ .../module/modules/combat/HitBox.java | 52 -- .../module/modules/combat/Offhand.java | 100 +++ .../module/modules/combat/Surround.java | 29 +- .../combat/{Trigger.java => TriggerBot.java} | 11 +- .../module/modules/combat/Velocity.java | 101 ++- .../modules/{combat => misc}/AutoClicker.java | 13 +- .../module/modules/misc/AutoMount.java | 78 ++ .../module/modules/misc/AutoRespawn.java | 17 +- .../module/modules/misc/ChestStealer.java | 45 -- .../module/modules/misc/ExtraChest.java | 83 +++ .../module/modules/misc/FakeCreative.java | 24 - .../module/modules/misc/FakePlayer.java | 28 +- .../module/modules/misc/Gamemode.java | 55 ++ .../module/modules/misc/Log4jAlert.java | 6 +- .../module/modules/misc/Particles.java | 2 +- .../module/modules/movement/AutoWalk.java | 6 +- .../module/modules/movement/BoatFly.java | 22 - .../module/modules/movement/ElytraPlus.java | 138 ++-- .../module/modules/movement/FastFall.java | 23 + .../module/modules/movement/Flight.java | 87 ++- .../module/modules/movement/Glide.java | 19 - .../module/modules/movement/GuiWalk.java | 23 +- .../module/modules/movement/Jesus.java | 69 +- .../module/modules/movement/NoFall.java | 5 +- .../module/modules/movement/NoSlow.java | 70 ++ .../{YawLock.java => RotationLock.java} | 8 +- .../module/modules/movement/Speed.java | 46 -- .../module/modules/movement/Spider.java | 19 - .../module/modules/movement/Sprint.java | 14 +- .../module/modules/movement/Step.java | 30 + .../module/modules/movement/TunnelSpeed.java | 25 + .../module/modules/movement/speed/Speed.java | 14 + .../modules/movement/speed/sub/Bhop.java | 33 + .../modules/movement/speed/sub/Strafe.java | 115 +++ .../module/modules/player/AutoEat.java | 67 ++ .../features/module/modules/player/Blink.java | 13 +- .../FastXP.java => player/FastUse.java} | 8 +- .../features/module/modules/player/Reach.java | 2 +- .../module/modules/render/Ambience.java | 106 +++ .../module/modules/render/Aspect.java | 21 + .../module/modules/render/BlockOverlay.java | 97 --- .../module/modules/render/ChinaHat.java | 147 ++++ .../module/modules/render/Freecam.java | 26 +- .../module/modules/render/FullBright.java | 38 +- .../module/modules/render/Hitmarker.java | 14 +- .../module/modules/render/ItemESP.java | 65 -- .../module/modules/render/NameProtect.java | 5 +- .../module/modules/render/NameTags.java | 202 ++--- .../module/modules/render/NoRender.java | 110 ++- .../module/modules/render/PlayerESP.java | 91 --- .../module/modules/render/PopChams.java | 131 ++++ .../module/modules/render/Tracers.java | 17 +- .../features/module/modules/render/Trail.java | 175 +++++ .../module/modules/render/ViewModel.java | 13 +- .../module/modules/render/esp/ESP.java | 19 + .../module/modules/render/esp/sub/Block.java | 72 ++ .../module/modules/render/esp/sub/Hole.java | 139 ++++ .../module/modules/render/esp/sub/Item.java | 68 ++ .../module/modules/render/esp/sub/Player.java | 98 +++ .../module/modules/render/esp/sub/Shader.java | 189 +++++ .../{SpawnerESP.java => esp/sub/Spawner.java} | 10 +- .../{StorageESP.java => esp/sub/Storage.java} | 30 +- .../module/modules/render/esp/sub/Target.java | 184 +++++ .../modules/render/particle/Particle.java | 13 + .../particle/impl/ParticleTickHandler.java | 165 +++++ .../render/particle/sub/FireFlies.java | 128 ++++ .../render/particle/sub/HitParticle.java | 118 +++ .../module/modules/render/xray/XRay.java | 25 + .../module/modules/render/xray/sub/Ores.java | 56 ++ .../features/module/modules/world/Nuker.java | 9 +- .../module/modules/world/Scaffold.java | 343 ++++++--- .../templeclient/manager/CapeManager.java | 35 +- .../templeclient/manager/CommandManager.java | 5 +- .../templeclient/manager/HoleManager.java | 151 ++++ .../templeclient/manager/ModuleManager.java | 87 ++- .../templeclient/manager/SongManager.java | 2 +- .../templeclient/manager/ThreadManager.java | 12 + .../mixins/MixinEntityRenderer.java | 41 -- .../mixins/accessor/ICPacketUseEntity.java | 14 + .../mixins/accessor/IEntityRenderer.java | 12 + .../{ => accessor}/IMixinCPacketPlayer.java | 16 +- .../{ => accessor}/IMixinRenderManager.java | 2 +- .../accessor/IMixinSPacketEntityVelocity.java | 17 + .../IMixinSPacketExplosion.java | 2 +- .../templeclient/mixins/block/MixinBlock.java | 20 + .../mixins/{ => block}/MixinBlockLiquid.java | 12 +- .../block/MixinBlockRendererDispatcher.java | 70 ++ .../mixins/{ => entity}/MixinEntity.java | 8 +- .../{ => entity}/MixinEntityPlayer.java | 2 +- .../{ => entity}/MixinEntityPlayerSP.java | 12 +- .../mixins/{ => gui}/MixinGuiChat.java | 12 +- .../mixins/{ => gui}/MixinPotionOverlay.java | 4 +- .../{ => network}/MixinNetworkManager.java | 12 +- .../MixinAbstractClientPlayer.java | 9 +- .../mixins/render/MixinEntityRenderer.java | 142 ++++ .../{ => render}/MixinItemRenderer.java | 2 +- .../mixins/render/MixinLayerHeldItem.java | 30 + .../mixins/render/MixinRender.java | 34 + .../mixins/render/MixinRenderArmor.java | 20 + .../mixins/{ => world}/MixinWorldClient.java | 14 +- .../util/autocrystal/ACHelper.java | 125 ++-- .../util/autocrystal/ACSettings.java | 20 +- .../templeclient/util/autocrystal/ACUtil.java | 44 +- .../util/autocrystal/CrystalInfo.java | 14 +- .../util/autocrystal/CrystalUtil.java | 47 +- .../util/autocrystal/DamageUtil.java | 25 +- .../util/autocrystal/InventoryUtil.java | 18 +- .../util/autocrystal/PlayerInfo.java | 4 +- .../util/autocrystal/RotationUtil.java | 20 +- .../util/autocrystal/threads/ACCalculate.java | 27 +- .../util/autocrystal/threads/ACSubThread.java | 8 +- .../templeclient/util/color/ColorUtil.java | 142 ++++ .../templeclient/util/color/RainbowUtil.java | 17 +- .../templeclient/util/color/ShaderUtil.java | 114 +++ .../util/color/impl/BlackShader.java | 39 + .../util/color/impl/GradientShader.java | 66 ++ .../util/color/impl/RectBuilder.java | 140 ++++ .../util/color/impl/RoundedTexture.java | 38 + .../util/friend/FriendManager.java | 6 +- .../templeclient/util/keys/KeyUtil.java | 8 +- .../util/{system => math}/MathUtil.java | 47 +- .../templeclient/util/math/Quad.java | 56 ++ .../templeclient/util/math/Vec2d.java | 77 ++ .../templeclient/util/player/PlayerUtil.java | 20 +- .../templeclient/util/render/Easing.java | 50 ++ .../templeclient/util/render/RenderUtil.java | 623 +++++++++++++--- .../templeclient/util/render/StencilUtil.java | 62 ++ .../util/rotation/RotationUtil.java | 27 +- .../templeclient/util/setting/Setting.java | 10 +- .../util/setting/SettingHolder.java | 17 +- .../util/setting/SettingsManager.java | 28 +- .../util/setting/impl/BooleanSetting.java | 15 +- .../util/setting/impl/ColorSetting.java | 79 ++ .../util/setting/impl/DoubleSetting.java | 18 +- .../util/setting/impl/EnumSetting.java | 17 +- .../util/setting/impl/IntSetting.java | 17 +- .../util/setting/impl/StringSetting.java | 60 ++ .../util/world/BlockPosWithFacing.java | 14 + .../templeclient/util/world/BlockUtil.java | 202 +++++ .../{autocrystal => world}/EntityUtil.java | 18 +- .../assets/minecraft/{ => font}/FSEX300.ttf | Bin .../assets/minecraft/{ => font}/bold.ttf | Bin .../minecraft/{ => font}/calibri-bold.ttf | Bin .../assets/minecraft/{ => font}/smooth.ttf | Bin .../assets/minecraft/texts/splashes.txt | 2 +- .../assets/minecraft/textures/blank.png | Bin 0 -> 70 bytes .../minecraft/textures/esp/square-capture.png | Bin 0 -> 302101 bytes .../minecraft/textures/esp/square-dashes.png | Bin 0 -> 48169 bytes .../textures/esp/triangle-capture.png | Bin 0 -> 205701 bytes .../textures/esp/triangle-dashes.png | Bin 0 -> 185158 bytes .../assets/minecraft/textures/icons/chat.png | Bin 633 -> 0 bytes .../minecraft/textures/icons/client.png | Bin 725 -> 0 bytes .../minecraft/textures/icons/combat.png | Bin 773 -> 0 bytes .../assets/minecraft/textures/icons/logo.png | Bin 6744 -> 3351 bytes ...eaneous_selected.png => misc_selected.png} | Bin .../textures/icons/miscelleaneous.png | Bin 429 -> 0 bytes .../minecraft/textures/icons/movement.png | Bin 727 -> 0 bytes .../minecraft/textures/icons/player.png | Bin 541 -> 0 bytes .../minecraft/textures/icons/render.png | Bin 720 -> 0 bytes .../assets/minecraft/textures/icons/world.png | Bin 744 -> 0 bytes .../minecraft/textures/particles/circle.png | Bin 0 -> 10489 bytes .../minecraft/textures/particles/dollar.png | Bin 0 -> 23068 bytes .../minecraft/textures/particles/heart.png | Bin 0 -> 32724 bytes .../minecraft/textures/particles/text.png | Bin 0 -> 8112 bytes .../minecraft/textures/shaders/black.frag | 10 + .../minecraft/textures/shaders/gradient.frag | 25 + .../minecraft/textures/shaders/rect.frag | 32 + .../textures/shaders/roundedtex.frag | 15 + .../minecraft/textures/shaders/vertex.vsh | 6 + src/main/resources/mcmod.info | 30 +- src/main/resources/mixins.templeclient.json | 37 +- 276 files changed, 10220 insertions(+), 4018 deletions(-) create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/ArmorEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/FireEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/HeldItemEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/NamePlateEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPreEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPrePreEvent.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/command/commands/NameMcCommand.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/IContainer.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{ => panels}/Panel.java (85%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{ => panels/items}/Item.java (63%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{properties => panels/items/buttons}/BindButton.java (80%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{properties => panels/items/buttons}/BooleanButton.java (55%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{ => panels/items/buttons}/Button.java (66%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ColorButton.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{properties => panels/items/buttons}/DoubleSlider.java (82%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{properties => panels/items/buttons}/EnumButton.java (67%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{properties => panels/items/buttons}/IntSlider.java (82%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/{ => panels/items/buttons}/ModuleButton.java (64%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/StringButton.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Button.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/{ClientCsgoGuiScreen.java => CsgoGuiScreen.java} (52%) delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BindButton.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IContainer.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/ModuleButton.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/{NavLink.java => properties/Panel.java} (52%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/{ => properties/items}/Item.java (98%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BindButton.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons}/BooleanButton.java (56%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/Button.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ColorButton.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ModuleButton.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/StringButton.java rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons/enumB}/EnumButton.java (73%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons/enumB}/EnumValueButton.java (89%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons/enumB}/NormalButton.java (53%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons/slider}/DoubleSlider.java (58%) rename src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/{ => items/buttons/slider}/IntSlider.java (59%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/font/AbstractFont.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/gui/font/MinecraftFontRenderer.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Colors.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Font.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/FontSettings.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Durability.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationInfo.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationType.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationsRewrite.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AntiBots.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoGapple.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowAimbot.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowSpam.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/HitBox.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Offhand.java rename src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/{Trigger.java => TriggerBot.java} (86%) rename src/main/java/xyz/templecheats/templeclient/features/module/modules/{combat => misc}/AutoClicker.java (82%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoMount.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ChestStealer.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ExtraChest.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakeCreative.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Gamemode.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/BoatFly.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/FastFall.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Glide.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoSlow.java rename src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/{YawLock.java => RotationLock.java} (74%) delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Speed.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Spider.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Step.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/TunnelSpeed.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/Speed.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Bhop.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Strafe.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/player/AutoEat.java rename src/main/java/xyz/templecheats/templeclient/features/module/modules/{combat/FastXP.java => player/FastUse.java} (70%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Ambience.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Aspect.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/BlockOverlay.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ChinaHat.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ItemESP.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PlayerESP.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PopChams.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Trail.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/ESP.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Block.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Hole.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Item.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Player.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Shader.java rename src/main/java/xyz/templecheats/templeclient/features/module/modules/render/{SpawnerESP.java => esp/sub/Spawner.java} (73%) rename src/main/java/xyz/templecheats/templeclient/features/module/modules/render/{StorageESP.java => esp/sub/Storage.java} (59%) create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Target.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/Particle.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/impl/ParticleTickHandler.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/FireFlies.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/HitParticle.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/XRay.java create mode 100644 src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/sub/Ores.java create mode 100644 src/main/java/xyz/templecheats/templeclient/manager/HoleManager.java create mode 100644 src/main/java/xyz/templecheats/templeclient/manager/ThreadManager.java delete mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityRenderer.java create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/accessor/ICPacketUseEntity.java create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/accessor/IEntityRenderer.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => accessor}/IMixinCPacketPlayer.java (87%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => accessor}/IMixinRenderManager.java (87%) create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketEntityVelocity.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => accessor}/IMixinSPacketExplosion.java (88%) create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlock.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => block}/MixinBlockLiquid.java (76%) create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockRendererDispatcher.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => entity}/MixinEntity.java (80%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => entity}/MixinEntityPlayer.java (85%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => entity}/MixinEntityPlayerSP.java (90%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => gui}/MixinGuiChat.java (88%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => gui}/MixinPotionOverlay.java (92%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => network}/MixinNetworkManager.java (82%) rename src/main/java/xyz/templecheats/templeclient/mixins/{ => player}/MixinAbstractClientPlayer.java (79%) create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/render/MixinEntityRenderer.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => render}/MixinItemRenderer.java (97%) create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/render/MixinLayerHeldItem.java create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRender.java create mode 100644 src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRenderArmor.java rename src/main/java/xyz/templecheats/templeclient/mixins/{ => world}/MixinWorldClient.java (88%) create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/ColorUtil.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/ShaderUtil.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/impl/BlackShader.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/impl/GradientShader.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/impl/RectBuilder.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/color/impl/RoundedTexture.java rename src/main/java/xyz/templecheats/templeclient/util/{system => math}/MathUtil.java (80%) create mode 100644 src/main/java/xyz/templecheats/templeclient/util/math/Quad.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/math/Vec2d.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/render/Easing.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/render/StencilUtil.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/setting/impl/ColorSetting.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/setting/impl/StringSetting.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/world/BlockPosWithFacing.java create mode 100644 src/main/java/xyz/templecheats/templeclient/util/world/BlockUtil.java rename src/main/java/xyz/templecheats/templeclient/util/{autocrystal => world}/EntityUtil.java (66%) rename src/main/resources/assets/minecraft/{ => font}/FSEX300.ttf (100%) rename src/main/resources/assets/minecraft/{ => font}/bold.ttf (100%) rename src/main/resources/assets/minecraft/{ => font}/calibri-bold.ttf (100%) rename src/main/resources/assets/minecraft/{ => font}/smooth.ttf (100%) create mode 100644 src/main/resources/assets/minecraft/textures/blank.png create mode 100644 src/main/resources/assets/minecraft/textures/esp/square-capture.png create mode 100644 src/main/resources/assets/minecraft/textures/esp/square-dashes.png create mode 100644 src/main/resources/assets/minecraft/textures/esp/triangle-capture.png create mode 100644 src/main/resources/assets/minecraft/textures/esp/triangle-dashes.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/chat.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/client.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/combat.png rename src/main/resources/assets/minecraft/textures/icons/{miscelleaneous_selected.png => misc_selected.png} (100%) delete mode 100644 src/main/resources/assets/minecraft/textures/icons/miscelleaneous.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/movement.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/player.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/render.png delete mode 100644 src/main/resources/assets/minecraft/textures/icons/world.png create mode 100644 src/main/resources/assets/minecraft/textures/particles/circle.png create mode 100644 src/main/resources/assets/minecraft/textures/particles/dollar.png create mode 100644 src/main/resources/assets/minecraft/textures/particles/heart.png create mode 100644 src/main/resources/assets/minecraft/textures/particles/text.png create mode 100644 src/main/resources/assets/minecraft/textures/shaders/black.frag create mode 100644 src/main/resources/assets/minecraft/textures/shaders/gradient.frag create mode 100644 src/main/resources/assets/minecraft/textures/shaders/rect.frag create mode 100644 src/main/resources/assets/minecraft/textures/shaders/roundedtex.frag create mode 100644 src/main/resources/assets/minecraft/textures/shaders/vertex.vsh diff --git a/gradle.properties b/gradle.properties index eb05fb10..5556787e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ mod_id=templeclient mod_name=TempleClient mod_group=xyz.templecheats.templeclient -mod_version=1.8.5 +mod_version=1.8.8 mod_author=["PhilipPanda"] mod_description=a 1.12.2 Minecraft utility mod minecraft_version=1.12.2 @@ -11,4 +11,4 @@ mappings_version=20180814-1.12 mod_mixin_configs=mixins.${mod_id}.json mod_mixin_refmap=refmap.${mod_id}.json org.gradle.daemon=false -org.gradle.jvmargs=-Xmx3G \ No newline at end of file +org.gradle.jvmargs=-Xmx3G diff --git a/gradlew b/gradlew index cccdd3d5..aeb74cbb 100644 --- a/gradlew +++ b/gradlew @@ -1,78 +1,126 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,7 +129,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -89,84 +137,109 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/src/main/java/xyz/templecheats/templeclient/TempleClient.java b/src/main/java/xyz/templecheats/templeclient/TempleClient.java index 89c65bef..e662fabf 100644 --- a/src/main/java/xyz/templecheats/templeclient/TempleClient.java +++ b/src/main/java/xyz/templecheats/templeclient/TempleClient.java @@ -1,3 +1,8 @@ +/************************************************************************************************ + * Temple Client * + * (c) 2023-2024 Temple Client Development Team. All rights reserved. * + ************************************************************************************************/ + package xyz.templecheats.templeclient; import net.minecraft.client.Minecraft; @@ -16,10 +21,8 @@ import xyz.templecheats.templeclient.event.ForgeEventManager; import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.gui.menu.GuiEventsListener; -import xyz.templecheats.templeclient.manager.CapeManager; -import xyz.templecheats.templeclient.manager.CommandManager; -import xyz.templecheats.templeclient.manager.ModuleManager; -import xyz.templecheats.templeclient.manager.SongManager; +import xyz.templecheats.templeclient.features.gui.menu.alt.AltManager; +import xyz.templecheats.templeclient.manager.*; import xyz.templecheats.templeclient.util.friend.FriendManager; import xyz.templecheats.templeclient.util.keys.KeyUtil; import xyz.templecheats.templeclient.util.setting.SettingsManager; @@ -27,15 +30,13 @@ import java.lang.invoke.MethodHandles; import java.lang.reflect.Field; - @Mod(modid = TempleClient.MODID, name = TempleClient.NAME, version = TempleClient.VERSION) public class TempleClient { public static final String MODID = "templeclient"; public static final String NAME = "Temple Client"; - public static final String VERSION = "1.8.7"; + public static final String VERSION = "1.8.8"; public static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup(); public static String name = NAME + " " + VERSION; - public static AnnotatedEventManager eventBus; public static SettingsManager settingsManager; public static ModuleManager moduleManager; @@ -44,7 +45,10 @@ public class TempleClient { public static ConfigManager configManager; public static CapeManager capeManager; public static FriendManager friendManager; + public static AltManager altManager; public static SongManager SONG_MANAGER; + public static HoleManager holeManager = new HoleManager(); + public static ThreadManager threadManager; public static Logger logger; @EventHandler @@ -74,7 +78,10 @@ public void init(FMLInitializationEvent event) { friendManager = new FriendManager(); + altManager = new AltManager(); + SONG_MANAGER = new SongManager(); + threadManager = new ThreadManager(); MinecraftForge.EVENT_BUS.register(clientForgeEventManager); MinecraftForge.EVENT_BUS.register(commandManager); @@ -82,7 +89,7 @@ public void init(FMLInitializationEvent event) { MinecraftForge.EVENT_BUS.register(new KeyUtil()); MinecraftForge.EVENT_BUS.register(new GuiEventsListener()); - FontUtils.bootstrap(); + FontUtils.setupFonts(); configManager = new ConfigManager(); @@ -96,26 +103,24 @@ public void init(FMLInitializationEvent event) { @SubscribeEvent public void onChat(ClientChatEvent event) { - if(event.getMessage().startsWith(".")) { - if(TempleClient.commandManager.executeCommand(event.getMessage())) { + if (event.getMessage().startsWith(".")) + if (TempleClient.commandManager.executeCommand(event.getMessage())) event.setCanceled(true); - } - } } public static void setSession(Session s) { - Class mc = Minecraft.getMinecraft().getClass(); + Class < ? extends Minecraft > mc = Minecraft.getMinecraft().getClass(); try { Field session = null; - for(Field f : mc.getDeclaredFields()) { - if(f.getType().isInstance(s)) { + for (Field f: mc.getDeclaredFields()) { + if (f.getType().isInstance(s)) { session = f; } } - if(session == null) { + if (session == null) { throw new IllegalStateException("Session Null"); } @@ -125,7 +130,7 @@ public static void setSession(Session s) { name = "TempleClient 1.12.2 | User: " + Minecraft.getMinecraft().getSession().getUsername(); Display.setTitle(name); - } catch(Exception e) { + } catch (Exception e) { e.printStackTrace(); } } diff --git a/src/main/java/xyz/templecheats/templeclient/config/ConfigManager.java b/src/main/java/xyz/templecheats/templeclient/config/ConfigManager.java index f0947037..ec8efbd7 100644 --- a/src/main/java/xyz/templecheats/templeclient/config/ConfigManager.java +++ b/src/main/java/xyz/templecheats/templeclient/config/ConfigManager.java @@ -12,10 +12,7 @@ import xyz.templecheats.templeclient.util.friend.Friend; import xyz.templecheats.templeclient.util.setting.Setting; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; +import java.io.*; import java.util.ArrayList; import java.util.List; @@ -27,12 +24,15 @@ public class ConfigManager { private final File modulesDirectory; private final File hudElementsDirectory; private final File friendsDirectory; + private File altsDirectory; + private File altsFile; public ConfigManager() { this.mainDirectory = new File(System.getProperty("user.dir") + File.separator + "Temple Client"); this.modulesDirectory = new File(this.mainDirectory, "Modules"); this.hudElementsDirectory = new File(this.mainDirectory, "Hud Elements"); this.friendsDirectory = new File(this.mainDirectory, "Friends"); + this.altsDirectory = new File(this.mainDirectory, "Alts"); if (!this.modulesDirectory.exists()) { this.modulesDirectory.mkdirs(); @@ -45,6 +45,11 @@ public ConfigManager() { if (!this.friendsDirectory.exists()) { this.friendsDirectory.mkdirs(); } + + if (!this.altsDirectory.exists()) { + this.altsDirectory.mkdirs(); + } + this.altsFile = new File(this.altsDirectory, "alt_accounts.json"); } public void saveAll() { @@ -62,24 +67,24 @@ public void loadAll() { private void saveModules() { //iterate through each module to save its config - for (Module module : ModuleManager.getModules()) { + for (Module module: ModuleManager.getModules()) { //file that the config will be saved to final File moduleConfigFile = new File(this.modulesDirectory, module.getName() + ".json"); - //json object that will store properties of the module + //json object that will store panels of the module final JsonObject moduleObject = new JsonObject(); - //add properties + //add panels moduleObject.addProperty("toggled", module.isToggled()); moduleObject.addProperty("key", module.getKey()); //add settings - final List> settings = TempleClient.settingsManager.getSettingsByMod(module); + final List < Setting < ? >> settings = TempleClient.settingsManager.getSettingsByMod(module); if (!settings.isEmpty()) { final JsonObject settingsObject = new JsonObject(); - for (Setting setting : settings) { + for (Setting < ? > setting : settings) { setting.serialize(settingsObject); } @@ -100,7 +105,7 @@ private void saveModules() { private void loadModules() { - for (Module module : ModuleManager.getModules()) { + for (Module module: ModuleManager.getModules()) { //file that the config was saved to final File moduleConfigFile = new File(this.modulesDirectory, module.getName() + ".json"); @@ -118,14 +123,14 @@ private void loadModules() { //get json object from file final JsonObject moduleObject = GSON.fromJson(jsonReader, JsonObject.class); - //deserialize properties + //deserialize panels module.setToggled(moduleObject.get("toggled").getAsBoolean()); module.setKey(moduleObject.get("key").getAsInt()); //deserialize settings if (moduleObject.has("settings")) { final JsonObject settingsObject = moduleObject.get("settings").getAsJsonObject(); - for (Setting setting : TempleClient.settingsManager.getSettingsByMod(module)) { + for (Setting < ? > setting : TempleClient.settingsManager.getSettingsByMod(module)) { if (!settingsObject.has(setting.name)) continue; setting.deserialize(settingsObject); @@ -140,26 +145,26 @@ private void loadModules() { private void saveHud() { - for (HUD.HudElement element : HUD.INSTANCE.getHudElements()) { + for (HUD.HudElement element: HUD.INSTANCE.getHudElements()) { //file that the config will be saved to final File hudElementConfigFile = new File(this.hudElementsDirectory, element.getName() + ".json"); - //json object that will store properties of the module + //json object that will store panels of the module final JsonObject hudElementObject = new JsonObject(); - //add properties + //add panels hudElementObject.addProperty("enabled", element.isEnabled()); hudElementObject.addProperty("x", element.getX()); hudElementObject.addProperty("y", element.getY()); //add settings - final List> settings = TempleClient.settingsManager.getSettingsByMod(element); + final List < Setting < ? >> settings = TempleClient.settingsManager.getSettingsByMod(element); if (!settings.isEmpty()) { //json object just for settings final JsonObject settingsObject = new JsonObject(); - for (Setting setting : settings) { + for (Setting < ? > setting : settings) { setting.serialize(settingsObject); } @@ -179,7 +184,7 @@ private void saveHud() { } private void loadHud() { - for (HUD.HudElement element : HUD.INSTANCE.getHudElements()) { + for (HUD.HudElement element: HUD.INSTANCE.getHudElements()) { //file that the config was saved to final File hudElementConfigFile = new File(this.hudElementsDirectory, element.getName() + ".json"); @@ -197,7 +202,7 @@ private void loadHud() { //get json object from file final JsonObject hudElementObject = GSON.fromJson(jsonReader, JsonObject.class); - //deserialize properties + //deserialize panels element.setEnabled(hudElementObject.get("enabled").getAsBoolean()); element.setX(hudElementObject.get("x").getAsDouble()); element.setY(hudElementObject.get("y").getAsDouble()); @@ -205,7 +210,7 @@ private void loadHud() { //deserialize settings if (hudElementObject.has("settings")) { final JsonObject settingsObject = hudElementObject.get("settings").getAsJsonObject(); - for (Setting setting : TempleClient.settingsManager.getSettingsByMod(element)) { + for (Setting < ? > setting : TempleClient.settingsManager.getSettingsByMod(element)) { if (!settingsObject.has(setting.name)) continue; setting.deserialize(settingsObject); @@ -221,8 +226,8 @@ private void loadHud() { private void saveFriends() { final File friendsFile = new File(this.friendsDirectory, "Friends.json"); - final List friendNames = new ArrayList<>(); - for (Friend friend : TempleClient.friendManager.getFriends()) { + final List < String > friendNames = new ArrayList < > (); + for (Friend friend: TempleClient.friendManager.getFriends()) { friendNames.add(friend.getName()); } @@ -247,10 +252,9 @@ private void loadFriends() { final FileReader fileReader = new FileReader(friendsFile); final JsonReader jsonReader = GSON.newJsonReader(fileReader); - final List friendNames = GSON.fromJson(jsonReader, new TypeToken>() { - }.getType()); + final List < String > friendNames = GSON.fromJson(jsonReader, new TypeToken < List < String >> () {}.getType()); - for (String name : friendNames) { + for (String name: friendNames) { TempleClient.friendManager.addFriend(name); } } catch (Throwable t) { @@ -258,4 +262,21 @@ private void loadFriends() { t.printStackTrace(); } } + public List loadAlts() { + if (!altsFile.exists()) return new ArrayList<>(); + try (Reader reader = new FileReader(altsFile)) { + return GSON.fromJson(reader, new TypeToken>() {}.getType()); + } catch (IOException e) { + e.printStackTrace(); + } + return new ArrayList<>(); + } + + public void saveAlts(List alts) { + try (Writer writer = new FileWriter(altsFile)) { + GSON.toJson(alts, writer); + } catch (IOException e) { + e.printStackTrace(); + } + } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/event/EventCancellable.java b/src/main/java/xyz/templecheats/templeclient/event/EventCancellable.java index 1521db91..3a5817d1 100644 --- a/src/main/java/xyz/templecheats/templeclient/event/EventCancellable.java +++ b/src/main/java/xyz/templecheats/templeclient/event/EventCancellable.java @@ -3,8 +3,7 @@ public class EventCancellable extends EventStageable { private boolean canceled; - public EventCancellable() { - } + public EventCancellable() {} public EventCancellable(EventStage stage) { super(stage); diff --git a/src/main/java/xyz/templecheats/templeclient/event/EventStageable.java b/src/main/java/xyz/templecheats/templeclient/event/EventStageable.java index ce20e48a..7d73efaf 100644 --- a/src/main/java/xyz/templecheats/templeclient/event/EventStageable.java +++ b/src/main/java/xyz/templecheats/templeclient/event/EventStageable.java @@ -20,7 +20,8 @@ public void setStage(EventStage stage) { } public enum EventStage { - PRE, POST + PRE, + POST } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/event/ForgeEventManager.java b/src/main/java/xyz/templecheats/templeclient/event/ForgeEventManager.java index 4e6f09d1..f986dd7c 100644 --- a/src/main/java/xyz/templecheats/templeclient/event/ForgeEventManager.java +++ b/src/main/java/xyz/templecheats/templeclient/event/ForgeEventManager.java @@ -7,12 +7,16 @@ import net.minecraftforge.fml.common.gameevent.PlayerEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.event.events.render.Render3DEvent; +import xyz.templecheats.templeclient.event.events.render.Render3DPreEvent; +import xyz.templecheats.templeclient.event.events.render.Render3DPrePreEvent; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.manager.ModuleManager; public class ForgeEventManager { private boolean playerLoaded; - + public static long lastFrame, deltaTime; + public ForgeEventManager() { MinecraftForge.EVENT_BUS.register(this); playerLoaded = false; @@ -21,27 +25,39 @@ public ForgeEventManager() { public void onTickEvent(TickEvent.ClientTickEvent event) { TempleClient.getModuleManager().onPlayerTick(); } - + @SubscribeEvent public void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { //TempleClient.configManager.loadAll(); } - + @SubscribeEvent public void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) { TempleClient.configManager.saveAll(); } - + @SubscribeEvent public void onRenderWorldLast(RenderWorldLastEvent event) { - if(Minecraft.getMinecraft().player == null) { + if (Minecraft.getMinecraft().player == null) { return; } - - for(Module module : ModuleManager.getModules()) { - if(module.isToggled()) { + final Render3DPrePreEvent render3DPrePreEvent = new Render3DPrePreEvent(event.getPartialTicks()); + TempleClient.eventBus.dispatchEvent(render3DPrePreEvent); + + final Render3DPreEvent render3dPreEvent = new Render3DPreEvent(event.getPartialTicks()); + TempleClient.eventBus.dispatchEvent(render3dPreEvent); + + final Render3DEvent render3dEvent = new Render3DEvent(event.getPartialTicks()); + TempleClient.eventBus.dispatchEvent(render3dEvent); + + deltaTime = System.currentTimeMillis() - lastFrame; + lastFrame = System.currentTimeMillis(); + + for (Module module: ModuleManager.getModules()) { + if (module.isToggled()) { module.onRenderWorld(event.getPartialTicks()); } } } + } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/ArmorEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/ArmorEvent.java new file mode 100644 index 00000000..d812664e --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/ArmorEvent.java @@ -0,0 +1,6 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventCancellable; + +public class ArmorEvent extends EventCancellable { +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/FireEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/FireEvent.java new file mode 100644 index 00000000..59be8f1e --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/FireEvent.java @@ -0,0 +1,6 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventCancellable; + +public class FireEvent extends EventCancellable { +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/HeldItemEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/HeldItemEvent.java new file mode 100644 index 00000000..8841e37e --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/HeldItemEvent.java @@ -0,0 +1,6 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventCancellable; + +public class HeldItemEvent extends EventCancellable { +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/NamePlateEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/NamePlateEvent.java new file mode 100644 index 00000000..490dadd1 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/NamePlateEvent.java @@ -0,0 +1,12 @@ +package xyz.templecheats.templeclient.event.events.render; + +import net.minecraft.entity.Entity; +import xyz.templecheats.templeclient.event.EventCancellable; + +public class NamePlateEvent extends EventCancellable { + public final Entity entity; + + public NamePlateEvent(final Entity entity) { + this.entity = entity; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DEvent.java new file mode 100644 index 00000000..93e78f30 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DEvent.java @@ -0,0 +1,12 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventCancellable; +import xyz.templecheats.templeclient.event.EventStageable; + +public class Render3DEvent extends EventStageable { + public final float partialTicks; + + public Render3DEvent(final float partialTicks) { + this.partialTicks = partialTicks; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPreEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPreEvent.java new file mode 100644 index 00000000..2813f58a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPreEvent.java @@ -0,0 +1,11 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventStageable; + +public class Render3DPreEvent extends EventStageable { + public final float partialTicks; + + public Render3DPreEvent(final float partialTicks) { + this.partialTicks = partialTicks; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPrePreEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPrePreEvent.java new file mode 100644 index 00000000..5fe86afb --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/event/events/render/Render3DPrePreEvent.java @@ -0,0 +1,11 @@ +package xyz.templecheats.templeclient.event.events.render; + +import xyz.templecheats.templeclient.event.EventStageable; + +public class Render3DPrePreEvent extends EventStageable { //crazy naming ik. it's basically before the pre event. thus pre pre + public final float partialTicks; + + public Render3DPrePreEvent(final float partialTicks) { + this.partialTicks = partialTicks; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/world/EntityEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/world/EntityEvent.java index 401169cc..54423867 100644 --- a/src/main/java/xyz/templecheats/templeclient/event/events/world/EntityEvent.java +++ b/src/main/java/xyz/templecheats/templeclient/event/events/world/EntityEvent.java @@ -5,24 +5,24 @@ public class EntityEvent extends EventStageable { private final Entity entity; - + public EntityEvent(Entity entity) { this.entity = entity; } - + public Entity getEntity() { return entity; } - + public static class Add extends EntityEvent { public Add(Entity entity) { super(entity); } } - + public static class Delete extends EntityEvent { public Delete(Entity entity) { super(entity); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/event/events/world/LiquidCollisionEvent.java b/src/main/java/xyz/templecheats/templeclient/event/events/world/LiquidCollisionEvent.java index 54ea1a4f..a26236a4 100644 --- a/src/main/java/xyz/templecheats/templeclient/event/events/world/LiquidCollisionEvent.java +++ b/src/main/java/xyz/templecheats/templeclient/event/events/world/LiquidCollisionEvent.java @@ -8,20 +8,20 @@ public class LiquidCollisionEvent extends EventStageable { private AxisAlignedBB bb = BlockLiquid.NULL_AABB; private final BlockPos pos; - + public LiquidCollisionEvent(BlockPos pos) { this.pos = pos; } - + public AxisAlignedBB getBoundingBox() { return bb; } - + public void setBoundingBox(AxisAlignedBB bb) { this.bb = bb; } - + public BlockPos getBlockPos() { return pos; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/BindCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/BindCommand.java index 9c9b33c8..25230fb3 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/command/commands/BindCommand.java +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/BindCommand.java @@ -14,7 +14,6 @@ public class BindCommand extends Command { public String getName() { return ".bind"; } - @Override public void execute(String[] args) { if (args.length != 3) { @@ -43,8 +42,8 @@ public void execute(String[] args) { sendMessage("Bound " + moduleName + " to " + keyName + ".", false); } - private void sendMessage(String message, boolean isError) { - String templePrefix = isError ? TextFormatting.RED + "[Temple] " : TextFormatting.AQUA + "[Temple] "; + public static void sendMessage(String message, boolean isError) { + String templePrefix = isError ? TextFormatting.RED + "[TempleClient] " + TextFormatting.RESET : TextFormatting.AQUA + "[TempleClient] " + TextFormatting.RESET; String formattedMessage = isError ? TextFormatting.WHITE + message : TextFormatting.RESET + message; Minecraft.getMinecraft().player.sendMessage( new TextComponentString(templePrefix + formattedMessage) diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/CoordsCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/CoordsCommand.java index ed6bb568..6ac04c7a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/command/commands/CoordsCommand.java +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/CoordsCommand.java @@ -43,4 +43,4 @@ private void setClipboardString(String text) { e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/FriendCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/FriendCommand.java index fa380ce3..d5662483 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/command/commands/FriendCommand.java +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/FriendCommand.java @@ -41,7 +41,7 @@ public void execute(String[] args) { sendMessage("Removed " + name + " from friends list.", false); } else if (action.equalsIgnoreCase("list")) { StringBuilder friendsList = new StringBuilder("Friends: "); - for (Friend friend : TempleClient.friendManager.getFriends()) { + for (Friend friend: TempleClient.friendManager.getFriends()) { friendsList.append(friend.getName()).append(", "); } sendMessage(friendsList.toString(), false); diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/HelpCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/HelpCommand.java index 57433ba0..825ea55d 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/command/commands/HelpCommand.java +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/HelpCommand.java @@ -17,11 +17,12 @@ public void execute(String[] args) { Minecraft.getMinecraft().player.sendMessage(new TextComponentString(templePrefix + "Available Commands:")); - Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".bind - Binds a module to a key (ex: .bind freecam r)")); + Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".bind - Binds a module to a key")); Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".coords - Copies your coordinates to your clipboard")); Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".friend - Adds, removes & lists your friends")); Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".help - Shows this help message")); Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".ip - Copies current server ip to your clipboard")); Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".clickgui - Adjusts the scale of the ClickGUI.")); + Minecraft.getMinecraft().player.sendMessage(new TextComponentString(commandPrefix + ".namemc - Opens the NameMC profile of a player")); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/IpCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/IpCommand.java index 36b1fafa..2574238c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/command/commands/IpCommand.java +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/IpCommand.java @@ -47,4 +47,4 @@ private void setClipboardString(String text) { e.printStackTrace(); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/command/commands/NameMcCommand.java b/src/main/java/xyz/templecheats/templeclient/features/command/commands/NameMcCommand.java new file mode 100644 index 00000000..bf0996a9 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/command/commands/NameMcCommand.java @@ -0,0 +1,35 @@ +package xyz.templecheats.templeclient.features.command.commands; + +import java.awt.Desktop; +import java.net.URI; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextFormatting; +import xyz.templecheats.templeclient.features.command.Command; + +public class NameMcCommand extends Command { + @Override + public String getName() { + return ".namemc"; + } + + @Override + public void execute(String[] args) { + if (args.length < 2) { + Minecraft.getMinecraft().player.sendMessage(new TextComponentString(TextFormatting.RED + "[TempleClient] " + TextFormatting.RESET + "Name is required.")); + return; + } + + String username = args[1]; + String url = "https://namemc.com/profile/" + username + ".1"; + + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + try { + Desktop.getDesktop().browse(new URI(url)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClickGuiScreen.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClickGuiScreen.java index 4f2c8b89..69e66151 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClickGuiScreen.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClickGuiScreen.java @@ -1,5 +1,7 @@ package xyz.templecheats.templeclient.features.gui.clickgui.basic; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.ModuleButton; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.manager.ModuleManager; @@ -16,7 +18,7 @@ public void load() { @Override public void setupItems() { ModuleManager.getModules().forEach(module -> { - if(module.getCategory() == category) { + if(module.getCategory() == category && !module.submodule) { this.addButton(new ModuleButton(module)); } }); diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClientGuiScreen.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClientGuiScreen.java index 61871dab..42198a01 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClientGuiScreen.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ClientGuiScreen.java @@ -3,6 +3,8 @@ import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import org.lwjgl.input.Mouse; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; @@ -49,7 +51,7 @@ public void drawScreen(int unscaledMouseX, int unscaledMouseY, float partialTick // @Override // public void drawScreen(int unscaledMouseX, int unscaledMouseY, float partialTicks) { // this.drawDefaultBackground(); -// this.panels.forEach(panel -> panel.drawScreen(mouseX, mouseY, partialTicks)); +// this.panels.forEach(panels -> panels.drawScreen(mouseX, mouseY, partialTicks)); // } @Override diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/IContainer.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/IContainer.java new file mode 100644 index 00000000..a121166a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/IContainer.java @@ -0,0 +1,11 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels; + +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; + +import java.util.List; + +public interface IContainer { + List getItems(); + + void setItems(List items); +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Panel.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/Panel.java similarity index 85% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Panel.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/Panel.java index ec694b55..df96c9b2 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Panel.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/Panel.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; @@ -7,8 +7,12 @@ import net.minecraft.client.renderer.GlStateManager; import net.minecraft.init.SoundEvents; import net.minecraft.util.ResourceLocation; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClickGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.font.CFont; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; import xyz.templecheats.templeclient.util.render.RenderUtil; import java.io.IOException; @@ -16,18 +20,15 @@ import java.util.List; public abstract class Panel { + private final List items = new ArrayList<>(); private final Minecraft mc = Minecraft.getMinecraft(); private final String label; private int angle; - private int x; - private int y; - private int x2; - private int y2; - private int width; - private int height; + private int x, y; + private int dragX, dragY; + private final int width, height; private boolean open; public boolean drag; - private final List items = new ArrayList<>(); public Panel(String label, int x, int y, boolean open) { this.label = label; @@ -39,14 +40,14 @@ public Panel(String label, int x, int y, boolean open) { this.open = open; this.setupItems(); } - + public abstract void setupItems(); public void drawScreen(int mouseX, int mouseY, float partialTicks) { this.drag(mouseX, mouseY); float totalItemHeight = this.open ? this.getTotalItemHeight() - 2.0f : 0.0f; RenderUtil.drawRect(this.x, (float) this.y - 1.5f, this.x + this.width, this.y + this.height - 6, 0x77000000); - RenderUtil.drawGradientRect(this.x, (float) this.y - 1.5f, this.x + this.width, this.y + this.height - 6, ClickGUI.INSTANCE.getStartColor(), ClickGUI.INSTANCE.getEndColor()); + RenderUtil.drawGradientRect(this.x, (float) this.y - 1.5f, this.x + this.width, this.y + this.height - 6, ClickGUI.INSTANCE.getStartColor().getRGB(), ClickGUI.INSTANCE.getEndColor().getRGB()); if (ClickGUI.INSTANCE.particles.booleanValue()) { ClickGUI.INSTANCE.particleUtil.drawParticles(); @@ -55,9 +56,10 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { } if(this.open) { - RenderUtil.drawRect(this.x, (float) this.y + 12.5f, this.x + this.width, this.open ? (float) (this.y + this.height) + totalItemHeight : (float) (this.y + this.height - 1), 0x77000000); + RenderUtil.drawRect(this.x, (float) this.y + 12.5f, this.x + this.width, (float) (this.y + this.height) + totalItemHeight, 0x77000000); } - FontUtils.drawString(this.getLabel(), (float) this.x + 3.0f, (float) this.y + 1.5f, -1, false); + CFont font = FontSettings.INSTANCE.getFont().setSize(18); + font.drawString(this.getLabel(), (float) this.x + 3.0f, (float) this.y + 1.5f, -1, false, 1.0f); if(!open) { if(this.angle > 0) { @@ -86,15 +88,15 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { } } } - + private void drag(int mouseX, int mouseY) { if(!this.drag) { return; } - this.x = this.x2 + mouseX; - this.y = this.y2 + mouseY; + this.x = this.dragX + mouseX; + this.y = this.dragY + mouseY; } - + public void drawScreenPost(int mouseX, int mouseY) { if(this.open) { for(Item item : getItems()) { @@ -102,11 +104,11 @@ public void drawScreenPost(int mouseX, int mouseY) { } } } - + public void mouseClicked(int mouseX, int mouseY, int mouseButton) { if(mouseButton == 0 && this.isHovering(mouseX, mouseY)) { - this.x2 = this.x - mouseX; - this.y2 = this.y - mouseY; + this.dragX = this.x - mouseX; + this.dragY = this.y - mouseY; ClickGuiScreen.getInstance().getPanels().forEach(panel -> { if(panel.drag) { panel.drag = false; @@ -125,11 +127,11 @@ public void mouseClicked(int mouseX, int mouseY, int mouseButton) { } this.getItems().forEach(item -> item.mouseClicked(mouseX, mouseY, mouseButton)); } - + public void addButton(Button button) { this.items.add(button); } - + public void mouseReleased(int mouseX, int mouseY, int releaseButton) { if(releaseButton == 0) { this.drag = false; @@ -139,62 +141,62 @@ public void mouseReleased(int mouseX, int mouseY, int releaseButton) { } this.getItems().forEach(item -> item.mouseReleased(mouseX, mouseY, releaseButton)); } - + public void keyTyped(char typedChar, int keyCode) throws IOException { for(Item item : getItems()) { item.keyTyped(typedChar, keyCode); } } - + public final String getLabel() { return this.label; } - + public int getX() { return this.x; } - + public int getY() { return this.y; } - + public void setOpen(boolean open) { this.open = open; } - + public int getWidth() { return this.width; } - + public int getHeight() { return this.height; } - + public boolean getOpen() { return this.open; } - + public final List getItems() { return this.items; } - + private boolean isHovering(int mouseX, int mouseY) { return mouseX >= this.getX() && mouseX <= this.getX() + this.getWidth() && mouseY >= this.getY() && mouseY <= this.getY() + this.getHeight() - (this.open ? 2 : 0); } - + //added this method in, just to fix shit. It is from uz1 class in future public static float calculateRotation(float var0) { if((var0 %= 360.0F) >= 180.0F) { var0 -= 360.0F; } - + if(var0 < -180.0F) { var0 += 360.0F; } - + return var0; } - + private float getTotalItemHeight() { float height = 0.0f; for(Item item : getItems()) { @@ -202,11 +204,11 @@ private float getTotalItemHeight() { } return height; } - + public void setX(int dragX) { this.x = dragX; } - + public void setY(int dragY) { this.y = dragY; } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Item.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/Item.java similarity index 63% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Item.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/Item.java index cf0ae2dd..2f8307a9 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Item.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/Item.java @@ -1,16 +1,22 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items; import java.io.IOException; +import java.util.ArrayList; public class Item { private final String label; - protected float x; - protected float y; - protected int width; - protected int height; - + protected float x, y; + protected int width, height; + public final ArrayList items = new ArrayList<>(); + public Item(String label) { this.label = label; + } + + public Item(String label, int x, int y) { + this.label = label; + this.x = x; + this.y = y; } public void setLocation(float x, float y) { @@ -21,7 +27,7 @@ public void setLocation(float x, float y) { public void drawScreen(int mouseX, int mouseY, float partialTicks) {} public void drawScreenPost(int mouseX, int mouseY) {} - + public void mouseClicked(int mouseX, int mouseY, int mouseButton) {} public void mouseReleased(int mouseX, int mouseY, int releaseButton) {} @@ -39,6 +45,13 @@ public float getX() { public float getY() { return this.y; } + + public void setX(float x) { + this.x = x; + } + public void setY(float y) { + this.y = y; + } public int getWidth() { return this.width; @@ -55,5 +68,12 @@ public void setWidth(int width) { public void setHeight(int height) { this.height = height; } + + protected boolean isHovering(final int mouseX, final int mouseY) { + return mouseX >= this.getX() && + mouseX <= this.getX() + this.getWidth() && + mouseY >= this.getY() && + mouseY <= this.getY() + this.height; + } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BindButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BindButton.java similarity index 80% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BindButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BindButton.java index 7796901e..392a5559 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BindButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BindButton.java @@ -1,12 +1,9 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.text.TextFormatting; import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClickGuiScreen; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.util.render.RenderUtil; @@ -26,12 +23,7 @@ public BindButton(Module module) { public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !isHovering(mouseX, mouseY) ? 0x11555555 : 0x88555555); String s = listening ? "..." : Keyboard.getKeyName(module.getKey()); - - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x + 2.3, this.y + 4, 0); - GlStateManager.scale(0.8, 0.8, 0); - FontUtils.drawString(getLabel() + " " + TextFormatting.GRAY + s, 0, 0, 0xFFFFFFFF, false); - GlStateManager.popMatrix(); + font16.drawString(getLabel() + " " + TextFormatting.GRAY + s, this.x + 2.3, this.y + 4, 0xFFFFFFFF, false, 1.0f); } @Override diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BooleanButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BooleanButton.java similarity index 55% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BooleanButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BooleanButton.java index 715dfb88..90c9130a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/BooleanButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/BooleanButton.java @@ -1,13 +1,13 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; import net.minecraft.client.renderer.GlStateManager; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import java.awt.*; + public class BooleanButton extends Button { private final Button parentButton; private final BooleanSetting setting; @@ -18,26 +18,39 @@ public BooleanButton(BooleanSetting setting, Button parentButton) { this.parentButton = parentButton; width = 15; } - + + private int lightenColor(int color, float amount) { + int r = (color >> 16) & 0xFF; + int g = (color >> 8) & 0xFF; + int b = color & 0xFF; + float[] hsb = Color.RGBtoHSB(r, g, b, null); + + float newBrightness = Math.min(hsb[2] + amount, 1.0f); + return Color.HSBtoRGB(hsb[0], hsb[1], newBrightness) | (color & 0xFF000000); + } + + @Override public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { - if(this.getState()) { - RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, ClickGUI.INSTANCE.getStartColor()); - - if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, 0x22000000); - } + RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !this.isHovering(mouseX, mouseY) ? 0x11555555 : 0x88555555); + + int checkboxSize = 6; + int checkboxX = (int) (x + 2); + int checkboxY = (int) (y + (height / 2) - (checkboxSize / 2)); + + int topColor, bottomColor; + if (this.getState()) { + bottomColor = ClickGUI.INSTANCE.getStartColor().getRGB(); } else { - RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !this.isHovering(mouseX, mouseY) ? 0x11555555 : 0x88555555); + bottomColor = 0x11555555; } - - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x + 2.3, this.y + 4, 0); - GlStateManager.scale(0.8, 0.8, 0); - FontUtils.drawString(getLabel(), 0, 0, 0xFFFFFFFF, false); - GlStateManager.popMatrix(); + topColor = lightenColor(bottomColor, 0.1f); + + RenderUtil.drawGradientRect(checkboxX, checkboxY, checkboxX + checkboxSize, checkboxY + checkboxSize, topColor, bottomColor); + + font16.drawString(getLabel(), this.x + 2.3 + 8, this.y + 4, 0xFFFFFFFF, false, 1.0f); } - + @Override public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { super.mouseClicked(mouseX, mouseY, mouseButton); diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Button.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/Button.java similarity index 66% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Button.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/Button.java index 9fa15286..58c6da38 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/Button.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/Button.java @@ -1,20 +1,26 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.init.SoundEvents; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.font.CFont; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; import xyz.templecheats.templeclient.util.render.RenderUtil; public abstract class Button extends Item { - private boolean state; - + public boolean state; + public final CFont font18 = FontSettings.INSTANCE.getFont().setSize(18); + public final CFont font16 = FontSettings.INSTANCE.getFont().setSize(16); + public Button(String label) { super(label); this.height = 15; } - + @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { // The original exeter @@ -22,19 +28,18 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { // Future //RenderUtil.drawGradientRect(this.x, this.y, this.x + (float) this.width, this.y + (float) this.height, this.getState() ? (!this.isHovering(mouseX, mouseY) ? 0x77FB4242 : 0x55FB4242) : (!this.isHovering(mouseX, mouseY) ? 0x33555555 : 0x77AAAAAB), this.getState() ? (!this.isHovering(mouseX, mouseY) ? 0x77FB4242 : 0x55FB4242) : (!this.isHovering(mouseX, mouseY) ? 0x55555555 : 0x66AAAAAB)); - + if(this.getState()) { - //RenderUtil.drawGradientRect(x, y, x + width, y + height, !isHovering(mouseX, mouseY) ? 0x77fb4242 : 0x55fb4242, !isHovering(mouseX, mouseY) ? 0xAAfb4242 : 0x99fb4242); - RenderUtil.drawGradientRect(x, y, x + width, y + height, ClickGUI.INSTANCE.getStartColor(), ClickGUI.INSTANCE.getEndColor()); - + RenderUtil.drawGradientRect(x, y, x + getWidth(), y + height, ClickGUI.INSTANCE.getStartColor().getRGB(), ClickGUI.INSTANCE.getEndColor().getRGB()); + if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(x, y, x + width, y + height, 0x22000000); + RenderUtil.drawRect(x, y, x + getWidth(), y + height, 0x22000000); } } else { - RenderUtil.drawGradientRect(x, y, x + width, y + height, !isHovering(mouseX, mouseY) ? 0x33555555 : 0x88555555, !isHovering(mouseX, mouseY) ? 0x55555555 : 0x99555555); + RenderUtil.drawGradientRect(x, y, x + getWidth(), y + height, !isHovering(mouseX, mouseY) ? 0x33555555 : 0x88555555, !isHovering(mouseX, mouseY) ? 0x55555555 : 0x99555555); } - FontUtils.drawString(this.getLabel(), this.x + 2.0f, this.y + 4.0f, this.getState() ? -1 : -5592406, false); + font18.drawString(this.getLabel(), this.x + 2.0f, this.y + 4.0f, this.getState() ? -1 : -5592406, false, 1.0f); } @Override @@ -52,12 +57,7 @@ public void toggle() { public boolean getState() { return this.state; } - - @Override - public int getHeight() { - return 14; - } - + public abstract ClientGuiScreen getClientScreen(); protected boolean isHovering(int mouseX, int mouseY) { @@ -67,5 +67,11 @@ protected boolean isHovering(int mouseX, int mouseY) { } return (float) mouseX >= this.getX() && (float) mouseX <= this.getX() + (float) this.getWidth() && (float) mouseY >= this.getY() && (float) mouseY <= this.getY() + (float) this.height; } + public void setX(float x) { + this.x = x; + } + public void setY(float y) { + this.y = y; + } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ColorButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ColorButton.java new file mode 100644 index 00000000..0e6d5cbf --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ColorButton.java @@ -0,0 +1,310 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.SoundEvents; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.module.modules.client.hud.Notifications; +import xyz.templecheats.templeclient.util.color.ColorUtil; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.ColorSetting; + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +import static xyz.templecheats.templeclient.util.color.ColorUtil.*; +import static xyz.templecheats.templeclient.util.render.RenderUtil.*; + +public class ColorButton extends Item { + private boolean extended = false; + private Color finalColor; + private final Button parentButton; + private final ColorSetting setting; + private boolean draggingPickerBase; + private boolean draggingRGBSlider; + private boolean draggingAlphaSlider; + float[] color; + + public ColorButton(ColorSetting setting, Button parentButton) { + super(setting.name); + this.setting = setting; + this.parentButton = parentButton; + this.color = new float[]{0.0f, 0.0f, 0.0f}; + this.finalColor = setting.getColor(); + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { + RenderUtil.drawGradientRect(x, y, x + getWidth() + 1, y + height, !isHovering(mouseX, mouseY) ? 0x33555555 : 0x88555555, !isHovering(mouseX, mouseY) ? 0x55555555 : 0x99555555); + + RenderUtil.drawRect(x + getWidth() - 8, y + 4, x + getWidth() - 3, y + height - 5, setting.getColor().getRGB()); + RenderUtil.drawOutBorderedRect((int) x + getWidth() - 8, (int) y + 5, (int) x + getWidth() - 3, (int) y + height - 5, 1, Color.BLACK.getRGB()); + + if (extended) { + float pickerPosX = x; + float pickerPosY = y + 15; + + // Background + RenderUtil.drawRect(pickerPosX - 2, pickerPosY - 1, pickerPosX + getWidth() + 3, pickerPosY + 98, new Color(0x80151515, true).getRGB()); + updateColor(pickerPosX, pickerPosY, mouseX, mouseY); + drawColorPickerArea(pickerPosX, pickerPosY); + drawRGBSliders(pickerPosX, pickerPosY); + drawAlphaSlider(pickerPosX, pickerPosY); + drawBorders(pickerPosX, pickerPosY); + drawFuncButton(pickerPosX, pickerPosY, mouseX, mouseY); + } + + GlStateManager.pushMatrix(); + GlStateManager.translate(this.x + 2.3, this.y + 4, 0); + GlStateManager.scale(0.8, 0.8, 0); + parentButton.font18.drawString(this.setting.getName(), 0, 0, 0xFFFFFFFF, false, 1.0f); + GlStateManager.popMatrix(); + } + + private void updateColor(float pickerPosX, float pickerPosY, int mouseX, int mouseY) { + float position; + try { + color = new float[]{ + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[0], + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[1], + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[2] + }; + } + catch (Exception exception) { + Notifications.showNotification("Invalid color!"); + } + if (this.draggingRGBSlider) { + position = Math.min(Math.max(pickerPosX, mouseX), pickerPosX + getWidth()); + color[0] = (position - pickerPosX) / (float)getWidth(); + } else if (this.draggingAlphaSlider) { + position = ColorUtil.getAlphaFromPosition((int) (mouseX - pickerPosX), getWidth()); + setting.setAlpha((int)position); + } else if (this.draggingPickerBase) { + position = Math.min(Math.max(pickerPosX, mouseX), pickerPosX + getWidth()); + float restrictedY = Math.min(Math.max(pickerPosY, mouseY), pickerPosY + 54f); + color[1] = (position - pickerPosX) / (float)getWidth(); + color[2] = 1.0f - (restrictedY - pickerPosY) / 54f; + } + finalColor = getColor(new Color(Color.HSBtoRGB(color[0], color[1], color[2])), setting.getColor().getAlpha() / 255.f); + setting.setColor(finalColor); + } + + private void drawColorPickerArea(float pickerPosX, float pickerPosY) { + Color finalColor = Color.getHSBColor(color[0], 1.0f, 1.0f); + drawColorPickerRect(pickerPosX, pickerPosY, pickerPosX + getWidth(), pickerPosY + 57, finalColor); + + // Draw cursor + float[] handlePickerPos = ColorUtil.getPositionFromColor(setting.getColor(), getWidth() - 2, 54); + float cursorX = pickerPosX + handlePickerPos[0]; + float cursorY = pickerPosY + handlePickerPos[1]; + RenderUtil.drawRect(cursorX, cursorY, cursorX + 2, cursorY + 2, Color.WHITE.getRGB()); + } + + private void drawRGBSliders(float pickerPosX, float pickerPosY) { + for (int i = 0; i < getWidth() + 1; i++) { + Color step = Color.getHSBColor((float) i / getWidth(), 1.0f, 1.0f); + RenderUtil.drawRect(pickerPosX + i, pickerPosY + 68, pickerPosX + i + 1, pickerPosY + 58, step.getRGB()); + } + float handleRGBSliderPos = ColorUtil.getPositionFromColor(setting.getColor(), getWidth()); + RenderUtil.drawRect(pickerPosX + handleRGBSliderPos - 1, pickerPosY + 68, pickerPosX + handleRGBSliderPos + 1, pickerPosY + 58, 0xFFFFFFFF); + } + + private void drawAlphaSlider(float pickerPosX, float pickerPosY) { + boolean parallel = true; + int squareSize = 4; + int lastRectWidth = getWidth() % squareSize; + int width = getWidth() - lastRectWidth; + for (int i = -squareSize; i < width; i += squareSize) { + if (!parallel) { + RenderUtil.drawRect(pickerPosX + i, pickerPosY + 71, pickerPosX + i + squareSize, pickerPosY + 79, new Color(-1).getRGB()); + RenderUtil.drawRect(pickerPosX + i, pickerPosY + squareSize + 71, pickerPosX + i + squareSize, pickerPosY + 79, new Color(0x313131).getRGB()); + if (i < width - squareSize) { + int minX = (int) (pickerPosX + i + squareSize); + int maxX = (int) Math.min(pickerPosX + width, pickerPosX + i + squareSize * 2); + RenderUtil.drawRect(minX, pickerPosY + 71, maxX, pickerPosY + 79, new Color(0x313131).getRGB()); + RenderUtil.drawRect(minX, pickerPosY + 71 + squareSize, maxX, pickerPosY + 79, new Color(-1).getRGB()); + } + } + parallel = !parallel; + } + if (!parallel && lastRectWidth > 0) { + RenderUtil.drawRect(pickerPosX + width, pickerPosY + 71, pickerPosX + width + lastRectWidth, pickerPosY + 79, new Color(-1).getRGB()); + RenderUtil.drawRect(pickerPosX + width, pickerPosY + squareSize + 71, pickerPosX + width + lastRectWidth, pickerPosY + 79, new Color(0x313131).getRGB()); + } + + float handleAlphaSliderPos = getPositionFromAlpha(setting.getColor().getAlpha(), getWidth()); + RenderUtil.drawHorizontalGradientRect(pickerPosX, pickerPosY + 70, pickerPosX + getWidth(), pickerPosY + 79, setting.getColor().getTransparency(), setAlpha(setting.getColor(), 255).getRGB()); + RenderUtil.drawRect(pickerPosX + handleAlphaSliderPos - 1, pickerPosY + 70, pickerPosX + handleAlphaSliderPos + 1, pickerPosY + 79, 0xFFFFFFFF); + } + + private void drawBorders(float pickerPosX, float pickerPosY) { + // PickerBase border + RenderUtil.drawOutBorderedRect((int) pickerPosX, (int) pickerPosY + 1, (int) pickerPosX + getWidth(), (int) pickerPosY + 55, 1, Color.BLACK.getRGB()); + // RGB border + RenderUtil.drawOutBorderedRect((int) pickerPosX, (int) pickerPosY + 69, (int) pickerPosX + getWidth(), (int) pickerPosY + 58, 1, Color.BLACK.getRGB()); + // Alpha border + RenderUtil.drawOutBorderedRect((int) pickerPosX, (int) pickerPosY + 71, (int) pickerPosX + getWidth(), (int) pickerPosY + 79, 1, Color.BLACK.getRGB()); + } + + private void drawFuncButton(float pickerPosX, float pickerPosY, final int mouseX, final int mouseY) { + drawRect(pickerPosX + 1, pickerPosY + 82, (float) (pickerPosX + parentButton.font18.getStringWidth("Copy") + 4), (float) (pickerPosY + 84 + parentButton.font18.getFontHeight()), isCopyHover(mouseX, mouseY) ? new Color(50, 50, 50, 220).getRGB() : new Color(65, 65, 65, 250).getRGB()); + parentButton.font18.drawString("copy", pickerPosX + 2.3f, pickerPosY + 84, -1, true, 1.0f); + + drawRect(pickerPosX + getWidth() - 1, pickerPosY + 82, (float) (pickerPosX + getWidth() - parentButton.font18.getStringWidth("Paste") - 4), (float) (pickerPosY + 84 + parentButton.font18.getFontHeight()), isPasteHover(mouseX, mouseY) ? new Color(50, 50, 50, 220).getRGB() : new Color(65, 65, 65, 250).getRGB()); + parentButton.font18.drawString("paste", pickerPosX + getWidth() - 2.3f - parentButton.font18.getStringWidth("paste"), pickerPosY + 84, -1, true, 1.0f); + } + + private void drawColorPickerRect(float left, float top, float right, float bottom, Color color) { + drawHorizontalGradientRect(left, top, right, bottom, 0xFFFFFFFF, color.getRGB()); + drawGradientRect(left, top, right, bottom, 0, 0xFF000000); + } + + @Override + public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { + if (extended && mouseButton == 0) { + if (isPickerHover(mouseX, mouseY)) { + this.draggingPickerBase = true; + } else if (isRBGHover(mouseX, mouseY)) { + this.draggingRGBSlider = true; + } else if (isAlphaHover(mouseX, mouseY)) { + this.draggingAlphaSlider = true; + } + if (isCopyHover(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + handleCopyAction(); + } + if (isPasteHover(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + handlePasteAction(); + } + } + if (this.isHovering(mouseX, mouseY) && mouseButton == 0) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + this.toggle(); + } else { + super.mouseClicked(mouseX, mouseY, mouseButton); + } + } + + private void handleCopyAction() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0f)); + String hex = String.format("#%02x%02x%02x%02x", setting.getColor().getAlpha(), setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue()); + StringSelection selection = new StringSelection(hex); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + Notifications.showNotification("Copied the color to your clipboard."); + } + + private void handlePasteAction() { + try { + String clipboardContent = readClipboard(); + if (clipboardContent != null) { + if (clipboardContent.startsWith("#")) { + handleHexPaste(clipboardContent); + } else { + handleRGBPaste(clipboardContent); + } + Notifications.showNotification("Color Pasted: " + clipboardContent + "!"); + } else { + Notifications.showNotification("Invalid Color!"); + } + } catch (NumberFormatException e) { + Notifications.showNotification("Invalid color format! Use Hex (#FFFFFFFF) or RGB (255,255,255)"); + } + } + + private void handleHexPaste(String hex) { + int a = Integer.valueOf(hex.substring(1, 3), 16); + int r = Integer.valueOf(hex.substring(3, 5), 16); + int g = Integer.valueOf(hex.substring(5, 7), 16); + int b = Integer.valueOf(hex.substring(7, 9), 16); + + setting.setColor(new Color(r, g, b, a)); + } + + private void handleRGBPaste(String rgb) { + String[] color = rgb.split(","); + setting.setColor(new Color(Integer.parseInt(color[0]), Integer.parseInt(color[1]), Integer.parseInt(color[2]))); + } + + public boolean isCopyHover(final int mouseX, final int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX + 1 && + mouseX <= pickerPosX + parentButton.font18.getStringWidth("copy") + 4 && + mouseY >= pickerPosY + 82 && + mouseY <= pickerPosY + 84 + parentButton.font18.getFontHeight(); + } + + public boolean isPasteHover(int mouseX, int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX + getWidth() - 3 - parentButton.font18.getStringWidth("paste") && + mouseX <= (pickerPosX + getWidth() - parentButton.font18.getStringWidth("paste")) + parentButton.font18.getStringWidth("paste")&& + mouseY >= pickerPosY + 82 && + mouseY <= pickerPosY + 84 + parentButton.font18.getFontHeight(); + } + + private boolean isPickerHover(final int mouseX, final int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX && + mouseX <= pickerPosX + getWidth() && + mouseY >= pickerPosY && + mouseY <= pickerPosY + 54; + } + + private boolean isRBGHover(final int mouseX, final int mouseY) { + float sliderPosX = x; + float sliderPosY = y + 15; + return mouseX >= sliderPosX && + mouseX <= sliderPosX + getWidth() && + mouseY >= sliderPosY + 58 && + mouseY <= sliderPosY + 69; + } + + private boolean isAlphaHover(final int mouseX, final int mouseY) { + float sliderPosX = x; + float sliderPosY = y + 15; + return mouseX >= sliderPosX && + mouseX <= sliderPosX + getWidth() && + mouseY >= sliderPosY + 70 && + mouseY <= sliderPosY + 79; + } + + public static String readClipboard() { + try { + return (String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); + } + catch (UnsupportedFlavorException | IOException exception) { + return null; + } + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int state) { + if (state == 0) { + this.draggingPickerBase = false; + this.draggingRGBSlider = false; + this.draggingAlphaSlider = false; + } + } + + public void toggle() { + this.extended = !this.extended; + } + + public boolean getExtended() { + return this.extended; + } + + @Override + public int getWidth() { + return 82; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/DoubleSlider.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/DoubleSlider.java similarity index 82% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/DoubleSlider.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/DoubleSlider.java index 72694c4d..b66370df 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/DoubleSlider.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/DoubleSlider.java @@ -1,12 +1,9 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.TextFormatting; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Panel; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; @@ -30,17 +27,12 @@ public void drawScreen(final int mouseX, final int mouseY, final float partialTi double range = setting.max - setting.min; double percentBar = (value - setting.min) / range; - RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, ClickGUI.INSTANCE.getStartColor()); + RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, ClickGUI.INSTANCE.getStartColor().getRGB()); if(this.isHovering(mouseX, mouseY)) { RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, 0x22000000); } - - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x + 2.3, this.y + 4, 0); - GlStateManager.scale(0.8, 0.8, 0); - FontUtils.drawString(getLabel() + TextFormatting.GRAY + " " + Math.round(value * 100D) / 100D, 0, 0, 0xFFFFFFFF, false); - GlStateManager.popMatrix(); + parentButton.font16.drawString(getLabel() + TextFormatting.GRAY + " " + Math.round(value * 100D) / 100D, this.x + 2.3, this.y + 4, 0xFFFFFFFF, false, 1.0f); if(this.dragging) { double offset = (MathHelper.clamp((mouseX - x) / (this.width + 7.4f), 0, 1) * range); @@ -78,7 +70,8 @@ public int getHeight() { return 14; } - private boolean isHovering(final int mouseX, final int mouseY) { + @Override + protected boolean isHovering(final int mouseX, final int mouseY) { for(final Panel panel : this.parentButton.getClientScreen().getPanels()) { if(panel.drag) { return false; diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/EnumButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/EnumButton.java similarity index 67% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/EnumButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/EnumButton.java index b572a47d..1681f62b 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/EnumButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/EnumButton.java @@ -1,11 +1,8 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.text.TextFormatting; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; @@ -13,7 +10,7 @@ public class EnumButton> extends Button { private final Button parentButton; private final EnumSetting setting; private final T[] values; - + public EnumButton(EnumSetting setting, Button parentButton) { super(setting.name); this.setting = setting; @@ -21,18 +18,17 @@ public EnumButton(EnumSetting setting, Button parentButton) { this.values = setting.getValues(); width = 15; } - + @Override public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !isHovering(mouseX, mouseY) ? 0x11333333 : 0x88333333); - - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x + 2.3, this.y + 4, 0); - GlStateManager.scale(0.8, 0.8, 0); - FontUtils.drawString(getLabel() + TextFormatting.GRAY + " " + setting.value().toString(), 0, 0, 0xFFFFFFFF, false); - GlStateManager.popMatrix(); + + int textColor = ClickGUI.INSTANCE.getStartColor().getRGB(); + String displayText = getLabel() + TextFormatting.GRAY + " " + setting.value().toString(); + font16.drawString(displayText, this.x + 2.3, this.y + 4, textColor, false, 1.0f); } - + + @Override public void mouseClicked(int mouseX, int mouseY, int mouseButton) { super.mouseClicked(mouseX, mouseY, mouseButton); @@ -49,26 +45,19 @@ public void mouseClicked(int mouseX, int mouseY, int mouseButton) { if (count > values.length - 1) count = 0; else if (count < 0) count = values.length - 1; setting.setValue(values[count]); - - if(this.isHovering(mouseX, mouseY) && mouseButton == 0) { - if(this.getLabel().equals("Themes")) { - Minecraft.getMinecraft().displayGuiScreen(null); - Minecraft.getMinecraft().setIngameFocus(); - } - } } } - + @Override public int getHeight() { return 14; } - + @Override public boolean getState() { return false; } - + @Override public ClientGuiScreen getClientScreen() { return this.parentButton.getClientScreen(); diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/IntSlider.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/IntSlider.java similarity index 82% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/IntSlider.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/IntSlider.java index 87f4d063..98f6ea7b 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/properties/IntSlider.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/IntSlider.java @@ -1,12 +1,9 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.math.MathHelper; import net.minecraft.util.text.TextFormatting; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Panel; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.IntSetting; @@ -30,17 +27,13 @@ public void drawScreen(final int mouseX, final int mouseY, final float partialTi double range = setting.max - setting.min; double percentBar = (value - setting.min) / range; - RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, ClickGUI.INSTANCE.getStartColor()); + RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, ClickGUI.INSTANCE.getStartColor().getRGB()); if(this.isHovering(mouseX, mouseY)) { RenderUtil.drawRect(x, y, (float) (this.x + (percentBar * (this.width + 7.4f))), y + height, 0x22000000); } - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x + 2.3, this.y + 4, 0); - GlStateManager.scale(0.8, 0.8, 0); - FontUtils.drawString(getLabel() + TextFormatting.GRAY + " " + value, 0, 0, 0xFFFFFFFF, false); - GlStateManager.popMatrix(); + parentButton.font16.drawString(getLabel() + TextFormatting.GRAY + " " + value, this.x + 2.3, this.y + 4, 0xFFFFFFFF, false, 1.0f); if(this.dragging) { int offset = (int) (MathHelper.clamp((mouseX - x) / (this.width + 7.4f), 0, 1) * range); @@ -78,7 +71,8 @@ public int getHeight() { return 14; } - private boolean isHovering(final int mouseX, final int mouseY) { + @Override + protected boolean isHovering(final int mouseX, final int mouseY) { for(final Panel panel : this.parentButton.getClientScreen().getPanels()) { if(panel.drag) { return false; diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ModuleButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ModuleButton.java similarity index 64% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ModuleButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ModuleButton.java index 4c9445dc..3e25a805 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/ModuleButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/ModuleButton.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.basic; +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; @@ -7,8 +7,10 @@ import net.minecraft.init.SoundEvents; import net.minecraft.util.ResourceLocation; import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.properties.BindButton; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClickGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.IContainer; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.util.render.RenderUtil; @@ -18,49 +20,47 @@ import java.util.ArrayList; import java.util.List; -import static xyz.templecheats.templeclient.features.gui.clickgui.basic.Panel.calculateRotation; +import static xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel.calculateRotation; -public class ModuleButton extends Button { +public class ModuleButton extends Button implements IContainer { private final Module module; - private final List items = new ArrayList<>(); - private boolean subOpen; + private List items = new ArrayList<>(); + private boolean open; private long timeHovering; - - private int startScrollIdx; - private int endScrollIdx; private int progress; - private int scrollBarHeight; - private int subScrollCtrHeight; - private int wrapNum; - public ModuleButton(Module module) { super(module.getName()); this.module = module; - progress = 0; - this.startScrollIdx = 0; - this.endScrollIdx = 0; - this.wrapNum = 11; - this.scrollBarHeight = 220; - this.subScrollCtrHeight = 220; + this.progress = 0; final List> settings = TempleClient.settingsManager.getSettingsByMod(module); + if(!module.parent) { + this.items.add(new BindButton(module)); + } + if(!module.submodules.isEmpty()) { + for(Module submodule : module.submodules) { + items.add(new ModuleButton(submodule)); + } + } for (Setting s : settings) { this.items.add(s.createBasicButton(this)); } - this.items.add(new BindButton(module)); } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { super.drawScreen(mouseX, mouseY, partialTicks); if(!this.items.isEmpty()) { - if(ClickGUI.INSTANCE.gears.booleanValue()) { + if (module.submodule) { + font18.drawString(!this.open ? "+" : "-", this.x - 1.0f + (float) getWidth() - 8.0f, this.y + 4.0f, -1, false, 1.0f); + } + if(ClickGUI.INSTANCE.gears.booleanValue() && !module.submodule) { GlStateManager.pushMatrix(); GlStateManager.enableBlend(); Minecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation("textures/icons/gear.png")); GlStateManager.translate(getX() + getWidth() - 6.7F, getY() + 7.7F - 0.3F, 0.0F); - if(this.subOpen) { + if(this.open) { ++progress; GlStateManager.rotate(calculateRotation((float) this.progress), 0.0F, 0.0F, 1.0F); } @@ -69,34 +69,41 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { GlStateManager.popMatrix(); } - if(this.subOpen) { + if(this.open) { float height = 1.0f; - for(Item item : items) { + for(Item item : getItems()) { item.setLocation(this.x + 1.0f, this.y + (height += 15.0f)); item.setHeight(15); item.setWidth(this.width - 9); item.drawScreen(mouseX, mouseY, partialTicks); + float offset = item.getHeight() - 14; + if (item instanceof ColorButton && ((ColorButton) item).getExtended()) { + height += 98; + } + if (item instanceof IContainer && module.parent) { + height += offset; + } } } } } - + @Override public void drawScreenPost(int mouseX, int mouseY) { if(this.isHovering(mouseX, mouseY)) { if(this.timeHovering == 0) { this.timeHovering = System.currentTimeMillis(); } - + if(System.currentTimeMillis() - this.timeHovering > 500) { final String description = module.getDescription(); final float startX = mouseX + 7; final float startY = mouseY + 7; - final float width = (float) FontUtils.getStringWidth(description); - final float height = (float) FontUtils.getFontHeight(); - + final float width = (float) font18.getStringWidth(description); + final float height = (float) font18.getFontHeight(); + RenderUtil.drawRect(startX - 1, startY - 1, startX + width, startY + height, 0x88000000); - FontUtils.drawString(description, startX, startY, -1, false); + font18.drawString(description, startX, startY, -1, false, 1.0f); } } else { this.timeHovering = 0; @@ -108,62 +115,81 @@ public void mouseClicked(int mouseX, int mouseY, int mouseButton) { super.mouseClicked(mouseX, mouseY, mouseButton); if(!this.items.isEmpty()) { if(mouseButton == 1 && this.isHovering(mouseX, mouseY)) { - this.subOpen = !this.subOpen; + open = !open; Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); } - if(this.subOpen) { - for(Item item : items) { + if(this.open) { + for(Item item : getItems()) { item.mouseClicked(mouseX, mouseY, mouseButton); } } } } - + @Override public void mouseReleased(int mouseX, int mouseY, int releaseButton) { super.mouseReleased(mouseX, mouseY, releaseButton); - if(!items.isEmpty() && subOpen) { - for(Item item : items) { + if(!items.isEmpty() && open) { + for(Item item : getItems()) { item.mouseReleased(mouseX, mouseY, releaseButton); } } } - + @Override public void keyTyped(char typedChar, int keyCode) throws IOException { super.keyTyped(typedChar, keyCode); - if(!items.isEmpty() && subOpen) { - for(Item item : items) { + if(!items.isEmpty() && open) { + for(Item item : getItems()) { item.keyTyped(typedChar, keyCode); } } } - + @Override public int getHeight() { - if(this.subOpen) { + if(this.open) { int height = 14; - for(Item item : items) { + for(Item item : getItems()) { height += item.getHeight() + 1; + + if (item instanceof ColorButton && ((ColorButton) item).getExtended()) { + height += 98; + } } return height + 2; } return 14; } - + + @Override + public int getWidth() { + return module.submodule ? 82 : 84; + } + @Override public void toggle() { module.toggle(); } - + @Override public boolean getState() { return module.isEnabled(); } - + @Override public ClientGuiScreen getClientScreen() { return ClickGuiScreen.getInstance(); } + + @Override + public List getItems() { + return items; + } + + @Override + public void setItems(List items) { + this.items = items; + } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/StringButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/StringButton.java new file mode 100644 index 00000000..62272388 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/basic/panels/items/buttons/StringButton.java @@ -0,0 +1,131 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ChatAllowedCharacters; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.StringSetting; +import xyz.templecheats.templeclient.util.time.TimerUtil; + +public class StringButton extends Item { + private final Button parentButton; + private final StringSetting setting; + private boolean typing; + private CurrentString currentString = new CurrentString(""); + private final TimerUtil idleTimer = new TimerUtil(); + private boolean idling; + + public StringButton(String label, Button parentButton, StringSetting setting) { + super(label); + this.parentButton = parentButton; + this.setting = setting; + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { + RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !isHovering(mouseX, mouseY) ? 0x11555555 : 0x88555555); + + GlStateManager.pushMatrix(); + if(this.typing) { + parentButton.font16.drawString(this.currentString.getString() + typingIcon(), this.x + 2.3f, this.y + 4, -1, false, 1f); + } else { + parentButton.font16.drawString(this.setting.getName() + ": " + this.setting.value(), this.x + 2.3f, this.y + 4, -1,false, 1f); + } + GlStateManager.popMatrix(); + } + + @Override + public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { + if(this.isHovering(mouseX, mouseY) && mouseButton == 0) { + toggle(); + return; + } + super.mouseClicked(mouseX, mouseY, mouseButton); + } + + @Override + public void keyTyped(char typedChar, int keyCode) { + if (typing) { + switch (keyCode) { + case 1: { + return; + } + case 28: { + enterString(); + } + case 14: { + setString(StringButton.removeLastChar(currentString.getString())); + } + } + if (ChatAllowedCharacters.isAllowedCharacter(typedChar)) { + setString(currentString.getString() + typedChar); + } + } + } + + private void enterString() { + if (this.currentString.getString().isEmpty()) { + this.setting.setValue(this.setting.getStringValue()); + } else { + this.setting.setValue(this.currentString.getString()); + } + this.setString(""); + toggle(); + } + + public void setString(String newString) { + this.currentString = new CurrentString(newString); + } + + public static String removeLastChar ( String str ) { + String output = ""; + if ( str != null && !str.isEmpty()) { + output = str.substring ( 0 , str.length ( ) - 1 ); + } + return output; + } + + public void toggle() { + typing = !typing; + } + + public boolean getState() { + return !typing; + } + + @Override + protected boolean isHovering(final int mouseX, final int mouseY) { + for(final Panel panel : this.parentButton.getClientScreen().getPanels()) { + if(panel.drag) { + return false; + } + } + return mouseX >= this.getX() && mouseX <= this.getX() + this.getWidth() && mouseY >= this.getY() && mouseY <= this.getY() + this.height; + } + + public String typingIcon() { + if (idleTimer.passedMs(500L)) { + idling = !idling; + idleTimer.resetNT(); + } + if (idling) { + return "_"; + } + return ""; + } + + public static class CurrentString { + private final String string; + + public + CurrentString(String string) { + this.string = string; + } + + public + String getString() { + return this.string; + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Button.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Button.java deleted file mode 100644 index 0a2b776a..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Button.java +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.init.SoundEvents; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; -import xyz.templecheats.templeclient.util.render.RenderUtil; - -public abstract class Button extends Item { - private boolean state; - - public Button(String label) { - super(label); - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - } - - @Override - public void mouseClicked(int mouseX, int mouseY, int mouseButton) { - if(mouseButton == 0 && this.isHovering(mouseX, mouseY)) { - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - } - } - - public void toggle() { - this.state = !this.state; - } - - public boolean getState() { - return this.state; - } - - @Override - public int getHeight() { - return this.height; - } - - public abstract ClientCsgoGuiScreen getClientScreen(); - - protected boolean isHovering(int mouseX, int mouseY) { - return (float) this.getX() <= mouseX && (float) mouseX <= this.getX() + (float) this.getWidth() && this.getY() <= (float) mouseY && (float) mouseY <= this.getY() + (float) this.height; - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/ClientCsgoGuiScreen.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/CsgoGuiScreen.java similarity index 52% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/ClientCsgoGuiScreen.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/CsgoGuiScreen.java index 73bc0321..04e3a49c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/ClientCsgoGuiScreen.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/CsgoGuiScreen.java @@ -1,49 +1,59 @@ package xyz.templecheats.templeclient.features.gui.clickgui.csgo; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ResourceLocation; import org.lwjgl.input.Mouse; import org.lwjgl.opengl.GL11; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.ModuleButton; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.ModuleButton; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.font.CFont; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; import xyz.templecheats.templeclient.manager.ModuleManager; -import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.color.impl.RoundedTexture; +import xyz.templecheats.templeclient.util.math.Vec2d; +import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Comparator; -public class ClientCsgoGuiScreen extends GuiScreen { - public static ModuleButton openedModule = null; - private final ArrayList navs = new ArrayList<>(); - private static ClientCsgoGuiScreen instance; +import static xyz.templecheats.templeclient.util.render.RenderUtil.drawHead; +import static xyz.templecheats.templeclient.util.render.StencilUtil.*; - public boolean drag; - public int x; - public int y; +public class CsgoGuiScreen extends GuiScreen { + private static final ResourceLocation LOGO = new ResourceLocation("textures/icons/logo.png"); + + private final ArrayList navs = new ArrayList<>(); + private static CsgoGuiScreen instance; + + public boolean drag; - public int oldX; - public int oldY; + public int x, y; + public int oldX, oldY; public int oldAbsY; - public int width; - public int height; + public int width, height; public int minHeight; - public int absY; - public ClientCsgoGuiScreen() { - this.x = 200; + public CsgoGuiScreen() { + this.x = 250; this.y = 70; this.absY = this.y; - this.width = 492; - this.height = 400; - this.minHeight = 400; + this.width = 528; + this.height = 380; + this.minHeight = 380; this.load(); } @@ -55,11 +65,11 @@ public void load() { int y = this.y + 30; for(final Module.Category category : Module.Category.values()) { - this.getNavs().add(new NavLink(category.name(), this.x+25, y+=25, false) { + this.getNavs().add(new Panel(category.name(), this.x + 40, y += 25, false) { @Override public void setupItems() { ModuleManager.getModules().forEach(module -> { - if(module.getCategory() == category) { + if(module.getCategory() == category && !module.parent) { this.addButton(new ModuleButton(module)); } }); @@ -77,27 +87,21 @@ public void drawScreen(int unscaledMouseX, int unscaledMouseY, float partialTick this.drag(mouseX, mouseY); GlStateManager.pushMatrix(); - GlStateManager.translate(0.0F, 0.0F, 1); // Translate along z-axis by depth - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); GlStateManager.scale(ClickGUI.INSTANCE.scale.doubleValue(), ClickGUI.INSTANCE.scale.doubleValue(), 1); final int scroll = Mouse.getDWheel(); if (scroll > 0) { - if(this.y < this.absY) { - // Scroll up - this.y += 10; + if(y < this.absY) { + y += 10; } } else if (scroll < 0) { - if(this.y+this.height > this.absY+this.minHeight) { - // Scroll down - this.y -= 10; + if(y+this.height > this.absY+this.minHeight) { + y -= 10; } } - // board - RenderUtil.drawRect(this.x+48, this.y, this.x+this.width, this.y+this.height, 0xFF131313); - if(this.y > this.absY) { this.y = this.absY; } @@ -105,31 +109,48 @@ public void drawScreen(int unscaledMouseX, int unscaledMouseY, float partialTick this.y = this.absY+this.minHeight - this.height; } - // board around 3px 0xFF333331 - RenderUtil.drawOutBorderedRect(this.x, this.y, this.x+this.width, this.y+this.height, 4, 0xFF333331); - // board around end + new RectBuilder(new Vec2d(x, absY), new Vec2d(x + 118, absY + minHeight)) + .outlineColor(new Color(0xFF121210)).width(1.0).color(new Color(0xFF0C0C0C)).radius(5.0).draw(); + new RectBuilder(new Vec2d(x + 109, absY), new Vec2d(x + width, absY + minHeight)) + .color(new Color(0xFF131313)).outlineColor(new Color(0xFF282826)).width(1.5).radius(6.0).draw(); + new RectBuilder(new Vec2d(x + 109, absY), new Vec2d(x + width / 2, absY + minHeight)) + .colorH(new Color(0xFF131313), new Color(0x0131313, true)).outlineColorH(new Color(0xFF282826), new Color(0x0131313, true)).width(1.5).draw(); + + // kys + GlStateManager.pushMatrix(); + initStencilToWrite(); + new RoundedTexture().drawRoundTextured(x + 6, absY + minHeight - 35, 25f, 25f, 6 , 1.0f); + readStencilBuffer(1); + drawHead(mc.player, new Vec2d(x + 6, absY + minHeight - 35), new Vec2d(x + 31, absY + minHeight - 10)); + uninitStencilBuffer(); + GlStateManager.popMatrix(); - // board around 1px 0xFF282826 - RenderUtil.drawOutBorderedRect(this.x, this.y, this.x+this.width, this.y+this.height, 1, 0xFF282826); - // board around end + CFont cFont = FontSettings.INSTANCE.getFont().setSize(16); + cFont.drawString(mc.player.getName(), x + 38, absY + minHeight - 32, -1, false, 1f); + cFont.drawString("UID: " + mc.player.getEntityId(), x + 38, absY + minHeight - 22, Color.DARK_GRAY, false, 1f); - // vertical split border start - RenderUtil.drawRect(this.x, this.absY, this.x+48, this.absY+this.minHeight, 0xFF0C0C0C); - RenderUtil.drawRect(this.x+48, this.absY, this.x+48+1, this.absY+this.minHeight, 0xFF282826); - RenderUtil.drawInBorderedRect(this.x, this.y, this.x+48, this.absY+this.minHeight, 1, 0xFF121210); + GlStateManager.pushMatrix(); + Minecraft.getMinecraft().getTextureManager().bindTexture(LOGO); + GlStateManager.color(1, 1, 1, 1); + Gui.drawScaledCustomSizeModalRect(x + 38, absY + 10, 0, 0, 32, 32, 32, 32, 32, 32); + GlStateManager.popMatrix(); - for (int i=0, y = this.absY + 8; i nav.drawScreenPost(mouseX, mouseY)); - - // Draw the rainbow - RenderUtil.drawHorizontalGradientRect(this.x, this.y, this.x+this.width/2, this.y+2, 0xFF4D7186, 0xFF6A4367); - RenderUtil.drawHorizontalGradientRect(this.x+this.width/2, this.y, this.x+this.width, this.y+2, 0xFF6A4367, 0xFF747A3A); - GlStateManager.popMatrix(); } @@ -164,7 +185,7 @@ public void mouseReleased(int unscaledMouseX, int unscaledMouseY, int releaseBut @Override protected void keyTyped(char typedChar, int keyCode) { try { - for(NavLink nav : navs) { + for(Panel nav : navs) { nav.keyTyped(typedChar, keyCode); } super.keyTyped(typedChar, keyCode); @@ -178,7 +199,7 @@ public boolean doesGuiPauseGame() { return false; } - public ArrayList getNavs() { + public ArrayList getNavs() { return this.navs; } @@ -195,7 +216,7 @@ private boolean isHovering(int mouseX, int mouseY) { return this.x+40 <= mouseX && mouseX <= this.x+this.width && this.y <= mouseY && mouseY <= this.y+this.height; } - public static ClientCsgoGuiScreen getInstance() { - return instance == null ? (instance = new ClientCsgoGuiScreen()) : instance; + public static CsgoGuiScreen getInstance() { + return instance == null ? (instance = new CsgoGuiScreen()) : instance; } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BindButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BindButton.java deleted file mode 100644 index c201efd6..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BindButton.java +++ /dev/null @@ -1,107 +0,0 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; - -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.text.TextFormatting; -import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; - -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.render.RenderUtil; -import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; - -import java.io.IOException; - -public class BindButton extends Button { - private final Module module; - private boolean listening; - - public BindButton(Module module) { - super("Keybind"); - this.module = module; - this.height = 10; - } - - @Override - public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+3, this.y, 0); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function - - if(this.getState()) { // if selected - RenderUtil.drawRect(0, 4, 6, 10, ClickGUI.INSTANCE.getStartColor()); - - } else { // if not selected - RenderUtil.drawRect(0, 4, 6, 10, 0x88555555); - } - - if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(0, 4, 6, 10, 0x22000000); - } - RenderUtil.drawGradientRect(0, 4, 6, 10, 0x33555555, 0xAA333333); - - GlStateManager.scale(0.6, 0.6, 1); - FontUtils.drawString("Enable", 10/0.6, 8, 0xFFD2D2D2, false); - String s; - if (listening) { - s = " . . . "; // Set s to some default string if listening is true - } else { - String keyName = Keyboard.getKeyName(module.getKey()); - s = (module.getKey() != Keyboard.KEY_NONE) ? keyName : "-"; // If keyName is not null, use it. Otherwise, set s to "[-]" - } - FontUtils.drawString(TextFormatting.DARK_GRAY + "["+ s +"]", 35/0.6, 8, 0xFFFFFFFF, false); - GlStateManager.disableDepth(); // Disable depth testing after drawing - GlStateManager.popMatrix(); - } - - @Override - public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { - super.mouseClicked(mouseX, mouseY, mouseButton); - if (mouseButton == 0 && this.x <= mouseX && mouseX <= this.x + 30 && this.y <= mouseY && mouseY <= this.y+10) { - this.toggle(); - } - - if (mouseButton == 0) { - if (this.x+35 <= mouseX && mouseX <= this.x + this.getWidth() && this.y <= mouseY && mouseY <= this.y+10) { - listening = true; - } else { - listening = false; - } - } - } - - @Override - public void keyTyped(char typedChar, int keyCode) throws IOException { - if(listening) { - if(keyCode != Keyboard.KEY_ESCAPE && keyCode != Keyboard.KEY_DELETE && keyCode != Keyboard.KEY_BACK) { - module.setKey(keyCode); - } else { - module.setKey(Keyboard.KEY_NONE); - } - listening = false; - } - } - - @Override - public int getHeight() { - return this.height; - } - - @Override - public void toggle() { - module.toggle(); - } - - @Override - public boolean getState() { - return module.isEnabled(); - } - - @Override - public ClientCsgoGuiScreen getClientScreen() { - return ClientCsgoGuiScreen.getInstance(); - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IContainer.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IContainer.java new file mode 100644 index 00000000..d4926392 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IContainer.java @@ -0,0 +1,10 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; + +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; + +import java.util.List; + +public interface IContainer { + List getItems(); + void setItems(List items); +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/ModuleButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/ModuleButton.java deleted file mode 100644 index 54b3ee02..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/ModuleButton.java +++ /dev/null @@ -1,169 +0,0 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.audio.PositionedSoundRecord; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.init.SoundEvents; -import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.render.RenderUtil; -import xyz.templecheats.templeclient.util.setting.Setting; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import org.lwjgl.opengl.GL11; - -public class ModuleButton extends Button { - private final Module module; - private final List items = new ArrayList<>(); - - private long timeHovering; - - public ModuleButton(Module module) { - super(module.getName()); - this.module = module; - - this.items.add(new BindButton(module)); - - final List> settings = TempleClient.settingsManager.getSettingsByMod(module); - for (Setting s : settings) { - this.items.add(s.createCsgoButton(this)); - } - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - super.drawScreen(mouseX, mouseY, partialTicks); - if(!this.items.isEmpty()) { - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x, this.y, 0); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function - if (items.size() > 1) { - // start draw around - RenderUtil.drawRect(0, 0, 0+5, 0+1, 0xFF282826); - RenderUtil.drawRect(5+(int)FontUtils.getStringWidth(this.getLabel())*0.8f+0, 0, 0+this.width, 0+1, 0xFF282826); - RenderUtil.drawRect(0, 0, 0+1, 0+this.height, 0xFF282826); - RenderUtil.drawRect(0+this.width, 0, 0+this.width+1, 0+this.height, 0xFF282826); - RenderUtil.drawRect(0, 0+this.height, 0+this.width, 0+this.height+1, 0xFF282826); - // end draw around - } - - GlStateManager.scale(0.8, 0.8, 1); - FontUtils.drawString(this.getLabel(), 5/0.8, (float)(-2/0.8), 0xFFFFFFFF, false); - GlStateManager.disableDepth(); // Disable depth testing after drawing - GlStateManager.popMatrix(); - - int minH=5; - for(int i=0, index=0; i 500) { - final String description = module.getDescription(); - final float startX = mouseX + 7; - final float startY = mouseY + 7; - final float width = (float) FontUtils.getStringWidth(description); - final float height = (float) FontUtils.getFontHeight(); - - RenderUtil.drawRect(startX - 1, startY - 1, startX + width, startY + height, 0x88000000); - FontUtils.drawString(description, startX, startY, -1, false); - } - } else { - this.timeHovering = 0; - } - } - - @Override - public void mouseClicked(int mouseX, int mouseY, int mouseButton) { - super.mouseClicked(mouseX, mouseY, mouseButton); - if(!this.items.isEmpty()) { - if(mouseButton == 1 && this.isHovering(mouseX, mouseY)) { - Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - } - - for(Item item : items) { - System.out.println(item.getLabel()+", "+item.getHeight()); - item.mouseClicked(mouseX, mouseY, mouseButton); - } - } - } - - @Override - public void mouseReleased(int mouseX, int mouseY, int releaseButton) { - super.mouseReleased(mouseX, mouseY, releaseButton); - if(!items.isEmpty()) { - for(Item item : items) { - item.mouseReleased(mouseX, mouseY, releaseButton); - } - } - } - - @Override - public void keyTyped(char typedChar, int keyCode) throws IOException { - super.keyTyped(typedChar, keyCode); - if(!items.isEmpty()) { - for(Item item : items) { - item.keyTyped(typedChar, keyCode); - } - } - } - - @Override - public int getHeight() { - return this.height; - } - - @Override - public void toggle() { - module.toggle(); - } - - @Override - public boolean getState() { - return module.isEnabled(); - } - - @Override - public ClientCsgoGuiScreen getClientScreen() { - return ClientCsgoGuiScreen.getInstance(); - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/NavLink.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/Panel.java similarity index 52% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/NavLink.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/Panel.java index 9a97e3e9..2743a722 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/NavLink.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/Panel.java @@ -1,79 +1,92 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.SoundEvents; import net.minecraft.util.ResourceLocation; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; -import xyz.templecheats.templeclient.util.render.RenderUtil; - +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.font.CFont; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; +import xyz.templecheats.templeclient.util.color.RainbowUtil; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; + +import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.List; -public abstract class NavLink { +public abstract class Panel { private final Minecraft mc = Minecraft.getMinecraft(); - private final String label; - private int angle; - private int x; - private int y; - private int x2; - private int y2; - private int width; - private int height; - public boolean open; - public boolean drag; - public int color = 0xFF747474; - private final List items = new ArrayList<>(); + private final String label; + private int x, y; + private final int width, height; + public boolean open, drag; + private final RainbowUtil rainbowUtil = new RainbowUtil(); + public int[] color; - public NavLink(String label, int x, int y, boolean open) { + public Panel(String label, int x, int y, boolean open) { this.label = label; this.x = x; this.y = y; - this.angle = 180; - this.width = 48; - this.height = 48; + this.width = 100; + this.height = 25; this.open = open; this.setupItems(); - this.color = 0xFF131313; + this.color = new int[]{Color.WHITE.getRGB(), Color.WHITE.getRGB()}; } public abstract void setupItems(); public void drawScreen(int mouseX, int mouseY, float partialTicks) { - // float totalItemHeight = this.open ? this.getTotalItemHeight() - 2.0f : 0.0f; - RenderUtil.drawRect(this.x, (float) this.y, this.x + this.width, this.y + this.height, this.color); - // RenderUtil.drawGradientRect(this.x, (float) this.y - 1.5f, this.x + this.width, this.y + this.height - 6, 0x77FB4242, 0x77FB4242);//0x77FB4242, 0x77FB4242); - - // Minecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation("textures/"+this.label+".png")); - // Gui.drawModalRectWithCustomSizedTexture(this.x, this.y, 0, 0, 25, 25, 25, 25); - - // FontUtils.drawString(this.getLabel(), (float) this.x + 3.0f, (float) this.y + 1.5f/* - 4.0f*/, -1, false); //15592941 if(open) { - this.color = 0xFF131313; - - RenderUtil.drawRect(this.x, this.y+1, this.x+this.width, this.y, 0xFF282826); - RenderUtil.drawRect(this.x, this.y+this.height, this.x+this.width, this.y+this.height-1, 0xFF282826); - - RenderUtil.drawRect(this.x + this.width, (float) this.y, this.x + this.width+1, this.y + this.height, this.color); + color[0] = ClickGUI.INSTANCE.getStartColor().getRGB(); + color[1] = ClickGUI.INSTANCE.getEndColor().getRGB(); } else { - this.color = 0xFF0C0C0C; + this.color[0] = 0xFF0C0C0C; + this.color[1] = 0xFF0C0C0C; } + int step = (int) (mc.player.ticksExisted + mc.getRenderPartialTicks()); + int color0 = rainbowUtil.rainbowProgress(5, step, color[0], color[1]); + int color1 = rainbowUtil.rainbowProgress(5, step / 10, color[0], color[1]); + + new RectBuilder(new Vec2d(x + 10, y), new Vec2d(x + width - 5, y + height)) + .outlineColorH(new Color(0x1F1F1F), new Color(35, 35, 35)) + .width(0.5) + .colorH(new Color(color0), new Color(color1)) + .radius(2.5) + .draw(); GlStateManager.pushMatrix(); - GlStateManager.color(1, 1, 1, 1); - mc.getTextureManager().bindTexture(this.open ? new ResourceLocation("textures/icons/"+this.label+"_selected.png") : new ResourceLocation("textures/icons/"+this.label+".png")); - Gui.drawScaledCustomSizeModalRect(this.x + 13, this.y + 13, 0.0F, 0.0F, 22, 22, 22, 22, 22.0F, 22.0F); + if (this.open) { + GlStateManager.color(1, 1, 1, 1); + } else { + GlStateManager.color(0.3f, 0.3f, 0.3f, 1f); + } + mc.getTextureManager().bindTexture(new ResourceLocation("textures/icons/"+this.label+"_selected.png")); + Gui.drawScaledCustomSizeModalRect(this.x + 15, this.y + 6, 0.0F, 0.0F, 12, 12, 12, 12, 12.0F, 12.0F); GlStateManager.popMatrix(); + final CFont font22 = FontSettings.INSTANCE.getFont().setSize(22); + font22.drawString(this.label, (float) (x + 33), (float) (y + 7), this.open ? -1 : new Color(76, 76, 76).getRGB(), true, 1.0F); + if(this.open) { - // float y = ClientCsgoGuiScreen.getInstance().y + 40; + // sort the item A B C + for (int i = 0; i < items.size() - 1; i++) { + for (int j = i + 1; j < items.size(); j++) { + String labelI = items.get(i).getLabel(); + String labelJ = items.get(j).getLabel(); + + char firstCharI = labelI.charAt(0); + char firstCharJ = labelJ.charAt(0); - // sort the item from long to short - for (int i = 0; i < items.size()-1; i++) { - for (int j = i+1; j < items.size(); j++) { - if (items.get(i).getHeight() < items.get(j).getHeight()) { + if (firstCharI > firstCharJ) { Item temp = items.get(i); items.set(i, items.get(j)); items.set(j, temp); @@ -82,21 +95,20 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { } int[] heights = {0, 0, 0}; - int left = 16; + int left; int bottomIndex = 0; - // arrange the item for(Item item : getItems()) { if (item.getHeight() == 10 + 5 + 2) { int minH = 354; - item.setLocation(this.x + 48 + (57 * (bottomIndex % 7)) + 16, minH + ClientCsgoGuiScreen.getInstance().y + 22 * (bottomIndex/7)); + item.setLocation(this.x + 105 + (57 * (bottomIndex % 7)) + 16, minH + CsgoGuiScreen.getInstance().y + 22 * ((float) bottomIndex / 7)); item.drawScreen(mouseX, mouseY, partialTicks); bottomIndex++; } else { int minH = heights[0]; int minIndex = 0; - for (int i=1; i<3; i++) { + for (int i=1; i<2; i++) { if (minH > heights[i]) { minIndex = i; minH = heights[i]; @@ -107,9 +119,10 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { if (minIndex == 0) { left = 16; } - - item.setLocation(this.x + 48 + (117 * minIndex) + left, minH + ClientCsgoGuiScreen.getInstance().y + 22); + + item.setLocation(this.x + 105 + (176 * minIndex) + left, minH + CsgoGuiScreen.getInstance().y + 22); item.drawScreen(mouseX, mouseY, partialTicks); + heights[minIndex] += item.getHeight() + 10; } } @@ -125,10 +138,10 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { max += 20; - if (max < ClientCsgoGuiScreen.getInstance().minHeight) { - max = ClientCsgoGuiScreen.getInstance().minHeight; + if (max < CsgoGuiScreen.getInstance().minHeight) { + max = CsgoGuiScreen.getInstance().minHeight; } - ClientCsgoGuiScreen.getInstance().height = max; + CsgoGuiScreen.getInstance().height = max; } } @@ -143,19 +156,13 @@ public void drawScreenPost(int mouseX, int mouseY) { public void mouseClicked(int mouseX, int mouseY, int mouseButton) { if (mouseButton == 0 && this.isHovering(mouseX, mouseY)) { // close all panels - ClientCsgoGuiScreen.getInstance().getNavs().forEach(panel -> panel.open = false); + CsgoGuiScreen.getInstance().getNavs().forEach(panel -> panel.open = false); - ClientCsgoGuiScreen.getInstance().y = ClientCsgoGuiScreen.getInstance().absY; + CsgoGuiScreen.getInstance().y = CsgoGuiScreen.getInstance().absY; this.open = true; - // mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); return; } - - // if(mouseButton == 1 && this.isHovering(mouseX, mouseY)) { - // this.open = !this.open; - // // mc.getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); - // return; - // } if(!this.open) { return; } @@ -219,26 +226,5 @@ public final List getItems() { private boolean isHovering(int mouseX, int mouseY) { return mouseX >= this.getX() && mouseX <= this.getX() + this.getWidth() && mouseY >= this.getY() && mouseY <= this.getY() + this.getHeight() - (this.open ? 2 : 0); } - - //added this method in, just to fix shit. It is from uz1 class in future - public static float calculateRotation(float var0) { - if((var0 %= 360.0F) >= 180.0F) { - var0 -= 360.0F; - } - - if(var0 < -180.0F) { - var0 += 360.0F; - } - - return var0; - } - - private float getTotalItemHeight() { - float height = 0.0f; - for(Item item : getItems()) { - height += (float) item.getHeight() + 1.5f; - } - return height; - } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Item.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/Item.java similarity index 98% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Item.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/Item.java index 971543aa..a5dc3fd4 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/Item.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/Item.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items; import java.io.IOException; diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BindButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BindButton.java new file mode 100644 index 00000000..c402d811 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BindButton.java @@ -0,0 +1,121 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.text.TextFormatting; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; + +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; + +import java.awt.*; +import java.io.IOException; + +import static xyz.templecheats.templeclient.util.math.MathUtil.lerp; + +public class BindButton extends Button { + private final Module module; + private boolean listening; + + public BindButton(Module module) { + super("Keybind"); + this.module = module; + this.height = 10; + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { + GlStateManager.pushMatrix(); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); + + drawCheckBox(new Vec2d(x + getWidth() * 1.91 + 3, y - ((font14.getStringWidth(module.getDescription()) > 196 - 36) ? 6 : 1.3))); + + String str; + if (listening) { + str = "..."; + } else { + String keyName = Keyboard.getKeyName(module.getKey()); + str = (module.getKey() != Keyboard.KEY_NONE) ? keyName : "NONE"; + } + double textWidth = font14.getStringWidth(str); + + double boxWidth = lerp(25F, (float) (textWidth + 8), 1.0F); + + new RectBuilder(new Vec2d(x + (5 / 0.8) + font20.getStringWidth(module.getName()) + 2, y + font14.getFontHeight() - ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 19 : 15f)), new Vec2d(this.x + (5 / 0.8) + font20.getStringWidth(module.getName()) + boxWidth, y + 10 + font14.getFontHeight() - ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 18 : 14f))) + .outlineColor(new Color(55, 55, 55)) + .width(0.8) + .color(new Color(35, 35, 35)) + .radius(1.2) + .draw(); + + font14.drawString(str, (float) ((x + 5 / 0.8) + font20.getStringWidth(module.getName()) + 5), y + font14.getFontHeight() - ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 16 : 12f), module.isEnabled() ? Color.WHITE : new Color(155, 155, 155), false, 1.0f); + GlStateManager.disableDepth(); + GlStateManager.popMatrix(); + } + + private void drawCheckBox(Vec2d pos) { + double radius = 2.5; + + Vec2d p1 = pos.minus(radius * 2.5, radius).minus(2.5, 1.5); + Vec2d p2 = pos.plus(radius * 2.5, radius).plus(2.5, 1.5); + + new RectBuilder(p1, p2) + .outlineColor(this.getState() ? ClickGUI.INSTANCE.getStartColor() : new Color(99, 104, 107)) + .width(0.8) + .color(new Color(35, 35, 35)) + .radius(15.0) + .draw(); + Vec2d cp = pos.minus(radius * 1.5, 0.0).plus(radius * 3.0 - (!getState() ? 8 : 0), 0.0); + + Color color = this.getState() ? ClickGUI.INSTANCE.getStartColor() : Color.WHITE; + new RectBuilder(cp.minus(radius + 0.2), cp.plus(radius + 0.2)).color(color).radius(radius + 0.2).draw(); + } + + @Override + public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { + super.mouseClicked(mouseX, mouseY, mouseButton); + if (mouseButton == 0 + && this.x + getWidth() * 1.88 <= mouseX + && mouseX <= this.x + getWidth() * 1.9 + 11 + && this.y - ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 13 : 10) <= mouseY + && mouseY <= this.y + ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 13 : 10) + ) { + this.toggle(); + } + if (mouseButton == 0) { + listening = this.x + (5 / 0.8) + font20.getStringWidth(module.getName()) + 5 <= mouseX && mouseX <= this.x + (5 / 0.8) + font20.getStringWidth(module.getName()) + 25 && this.y + font14.getFontHeight() - ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 21 : 18) <= mouseY && mouseY <= this.y + ((font14.getStringWidth(module.getDescription()) > 188 - 32) ? 13 : 10) + font14.getFontHeight() - 12f; + } + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + if(listening) { + if(keyCode != Keyboard.KEY_ESCAPE && keyCode != Keyboard.KEY_DELETE && keyCode != Keyboard.KEY_BACK) { + module.setKey(keyCode); + } else { + module.setKey(Keyboard.KEY_NONE); + } + listening = false; + } + } + + @Override + public void toggle() { + module.toggle(); + } + + @Override + public boolean getState() { + return module.isEnabled(); + } + + @Override + public CsgoGuiScreen getClientScreen() { + return CsgoGuiScreen.getInstance(); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BooleanButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BooleanButton.java similarity index 56% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BooleanButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BooleanButton.java index 190d251a..2f80a01a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/BooleanButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/BooleanButton.java @@ -1,15 +1,17 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; import org.lwjgl.opengl.GL11; import net.minecraft.client.renderer.GlStateManager; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import java.awt.*; + public class BooleanButton extends Button { private final Button parentButton; private final BooleanSetting setting; @@ -24,26 +26,21 @@ public BooleanButton(BooleanSetting setting, Button parentButton) { @Override public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+3, this.y, 0); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function - - if(this.getState()) { // if selected - RenderUtil.drawRect(0, 4, 6, 10, ClickGUI.INSTANCE.getStartColor()); - - } else { // if not selected - RenderUtil.drawRect(0, 4, 6, 10, 0x88555555); - } - - RenderUtil.drawGradientRect(0, 4, 6, 10, 0x33555555, 0xAA333333); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); + new RectBuilder(new Vec2d(x + 5, y + 5), new Vec2d(x + 13, y + 13)) + .outlineColor(parentButton.color[0]) + .width(0.9) + .color(new Color(45, 45, 45)) + .radius(1.0) + .draw(); + new RectBuilder(new Vec2d(x + 6.5, y + 6.5), new Vec2d(x + 11.5, y + 11.5)) + .color(this.getState() ? parentButton.color[0] : new Color(45, 45, 45, 0)) + .radius(0.5) + .draw(); - if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(0, 4, 6, 10, 0x22000000); - } - - GlStateManager.scale(0.6, 0.6, 1); - FontUtils.drawString(getLabel(), 10/0.6, 8, 0xFFD2D2D2, false); - GlStateManager.disableDepth(); // Disable depth testing after drawing + font16.drawString(getLabel(), (int) x + 3 + (10 / 0.6), y + 6, new Color(208, 208, 208).getRGB(), false, 1.0f); + GlStateManager.disableDepth(); GlStateManager.popMatrix(); } @@ -54,11 +51,6 @@ public void mouseClicked(final int mouseX, final int mouseY, final int mouseButt } super.mouseClicked(mouseX, mouseY, mouseButton); } - - @Override - public int getHeight() { - return this.height; - } @Override public void toggle() { @@ -71,7 +63,7 @@ public boolean getState() { } @Override - public ClientCsgoGuiScreen getClientScreen() { + public CsgoGuiScreen getClientScreen() { return this.parentButton.getClientScreen(); } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/Button.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/Button.java new file mode 100644 index 00000000..70448648 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/Button.java @@ -0,0 +1,47 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.init.SoundEvents; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.font.CFont; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; + +import java.awt.*; + +public abstract class Button extends Item { + private boolean state; + public final CFont font12 = FontSettings.INSTANCE.getFont().setSize(12); + public final CFont font14 = FontSettings.INSTANCE.getFont().setSize(14); + public final CFont font16 = FontSettings.INSTANCE.getFont().setSize(16); + public final CFont font18 = FontSettings.INSTANCE.getFont().setSize(18); + public final CFont font20 = FontSettings.INSTANCE.getFont().setSize(20); + public Color[] color; + public Button(String label) { + super(label); + this.color = new Color[]{ClickGUI.INSTANCE.getStartColor(), ClickGUI.INSTANCE.getEndColor()}; + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) { + if(mouseButton == 0 && this.isHovering(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + } + } + + public void toggle() { + this.state = !this.state; + } + + public boolean getState() { + return this.state; + } + + public abstract CsgoGuiScreen getClientScreen(); + + protected boolean isHovering(int mouseX, int mouseY) { + return this.getX() <= mouseX && (float) mouseX <= this.getX() + (float) this.getWidth() && this.getY() <= (float) mouseY && (float) mouseY <= this.getY() + (float) this.height; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ColorButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ColorButton.java new file mode 100644 index 00000000..4010a0be --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ColorButton.java @@ -0,0 +1,308 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.SoundEvents; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.module.modules.client.hud.Notifications; +import xyz.templecheats.templeclient.util.color.ColorUtil; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.color.impl.RoundedTexture; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.render.StencilUtil; +import xyz.templecheats.templeclient.util.setting.impl.ColorSetting; + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; + +import static xyz.templecheats.templeclient.util.color.ColorUtil.*; +import static xyz.templecheats.templeclient.util.render.RenderUtil.*; + +public class ColorButton extends Item { + private boolean extended = false; + private Color finalColor; + private final Button parentButton; + private final ColorSetting setting; + private boolean draggingPickerBase; + private boolean draggingRGBSlider; + private boolean draggingAlphaSlider; + float[] color; + + public ColorButton(ColorSetting setting, Button parentButton) { + super(setting.name); + this.parentButton = parentButton; + this.setting = setting; + this.height = getExtended() ? 108 : 15; + this.color = new float[]{0.0f, 0.0f, 0.0f}; + this.finalColor = setting.getColor(); + } + + @Override + public int getHeight() { + return getExtended() ? 108 : 15; + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { + new RectBuilder(new Vec2d(x + getWidth() - 16, y + 5), new Vec2d(x + getWidth() - 3, y + height - 4)) + .outlineColor(Color.WHITE).width(0.8).color(setting.getColor()).radius(2.0).draw(); + if (extended) { + float pickerPosX = x; + float pickerPosY = y + 16; + + // Background + new RectBuilder(new Vec2d(pickerPosX - 2, pickerPosY - 2), new Vec2d(pickerPosX + getWidth() + 3, pickerPosY + 95)) + .outlineColor(new Color(35, 35, 35)).width(0.8).color(new Color(0x80151515)).radius(3.0).draw(); + updateColor(pickerPosX, pickerPosY, mouseX, mouseY); + drawColorPickerArea(pickerPosX, pickerPosY); + drawRGBSliders(pickerPosX, pickerPosY); + drawAlphaSlider(pickerPosX, pickerPosY); + drawFuncButton(pickerPosX, pickerPosY, mouseX, mouseY); + } + GlStateManager.pushMatrix(); + parentButton.font14.drawString(this.setting.getName(), x + 2.3, y + 5, 0xFFFFFFFF, false, 1.0f); + GlStateManager.popMatrix(); + } + + private void updateColor(float pickerPosX, float pickerPosY, int mouseX, int mouseY) { + float position; + try { + color = new float[]{ + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[0], + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[1], + Color.RGBtoHSB(setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue(), null)[2] + }; + } + catch (Exception exception) { + Notifications.showNotification("Invalid color!"); + } + if (this.draggingRGBSlider) { + position = Math.min(Math.max(pickerPosX, mouseX), pickerPosX + getWidth()); + color[0] = (position - pickerPosX) / (float)getWidth(); + } else if (this.draggingAlphaSlider) { + position = ColorUtil.getAlphaFromPosition((int) (mouseX - pickerPosX), getWidth()); + setting.setAlpha((int)position); + } else if (this.draggingPickerBase) { + position = Math.min(Math.max(pickerPosX, mouseX), pickerPosX + getWidth()); + float restrictedY = Math.min(Math.max(pickerPosY, mouseY), pickerPosY + 54f); + color[1] = (position - pickerPosX) / (float)getWidth(); + color[2] = 1.0f - (restrictedY - pickerPosY) / 54f; + } + finalColor = getColor(new Color(Color.HSBtoRGB(color[0], color[1], color[2])), setting.getColor().getAlpha() / 255.f); + setting.setColor(finalColor); + } + + private void drawColorPickerArea(float pickerPosX, float pickerPosY) { + Color finalColor = Color.getHSBColor(color[0], 1.0f, 1.0f); + drawColorPickerRect(pickerPosX, pickerPosY, pickerPosX + getWidth(), pickerPosY + 57, finalColor); + + // Draw cursor + float[] handlePickerPos = ColorUtil.getPositionFromColor(setting.getColor(), getWidth() - 2, 54); + float cursorX = pickerPosX + handlePickerPos[0]; + float cursorY = pickerPosY + handlePickerPos[1]; + RenderUtil.drawRect(cursorX, cursorY, cursorX + 2, cursorY + 2, Color.WHITE.getRGB()); + } + + private void drawRGBSliders(float pickerPosX, float pickerPosY) { + GlStateManager.pushMatrix(); + StencilUtil.initStencilToWrite(); + new RoundedTexture().drawRoundTextured(pickerPosX, pickerPosY + 60, getWidth() - 1, 59, 1.5f, 1f); + StencilUtil.readStencilBuffer(1); + for (int i = 0; i < getWidth() - 1; i++) { + Color step = Color.getHSBColor((float) i / getWidth(), 1.0f, 1.0f); + RenderUtil.drawRect(pickerPosX + i, pickerPosY + 68, pickerPosX + i + 1, pickerPosY + 58, step.getRGB()); + } + new RectBuilder(new Vec2d(pickerPosX, pickerPosY + 68), new Vec2d(pickerPosX + getWidth(), pickerPosY + 59)).outlineColor(Color.black).width(0.7).color(new Color(0, 0, 0, 0)).draw(); + StencilUtil.uninitStencilBuffer(); + GlStateManager.popMatrix(); + float handleRGBSliderPos = ColorUtil.getPositionFromColor(setting.getColor(), getWidth()); + RenderUtil.drawRect(pickerPosX + handleRGBSliderPos - 1, pickerPosY + 68, pickerPosX + handleRGBSliderPos + 1, pickerPosY + 59, 0xFFFFFFFF); + } + + private void drawAlphaSlider(float pickerPosX, float pickerPosY) { + float handleAlphaSliderPos = getPositionFromAlpha(setting.getColor().getAlpha(), getWidth()); + new RectBuilder(new Vec2d(pickerPosX, pickerPosY + 70), new Vec2d(pickerPosX + getWidth(), pickerPosY + 79)) + .color(new Color(55, 55, 55)).radius(1.5).draw(); + new RectBuilder(new Vec2d(pickerPosX, pickerPosY + 70), new Vec2d(pickerPosX + getWidth(), pickerPosY + 79)) + .outlineColor(Color.black).width(0.7) + .colorH(new Color(0, 0, 0, 0), setAlpha(setting.getColor(), 255)).radius(1.5).draw(); + RenderUtil.drawRect(pickerPosX + handleAlphaSliderPos - 1, pickerPosY + 70, pickerPosX + handleAlphaSliderPos + 1, pickerPosY + 79, 0xFFFFFFFF); + } + + private void drawFuncButton(float pickerPosX, float pickerPosY, final int mouseX, final int mouseY) { + // Copy + new RectBuilder(new Vec2d(pickerPosX + 1, pickerPosY + 82), new Vec2d(pickerPosX + parentButton.font14.getStringWidth("Copy") + 4, pickerPosY + 85 + parentButton.font14.getFontHeight())) + .color(isCopyHover(mouseX, mouseY) ? new Color(50, 50, 50, 220) : new Color(65, 65, 65, 250)) + .radius(1.0).draw(); + parentButton.font14.drawString("copy", pickerPosX + 2.3f, pickerPosY + 84, -1, true, 1.0f); + + // Paste + new RectBuilder(new Vec2d(pickerPosX + getWidth() - 1, pickerPosY + 82), new Vec2d(pickerPosX + getWidth() - parentButton.font14.getStringWidth("Paste") - 4, pickerPosY + 85 + parentButton.font14.getFontHeight())) + .color(isPasteHover(mouseX, mouseY) ? new Color(50, 50, 50, 220) : new Color(65, 65, 65, 250)) + .radius(1.0).draw(); + parentButton.font14.drawString("paste", pickerPosX + getWidth() - 2.3f - parentButton.font14.getStringWidth("paste"), pickerPosY + 84, -1, true, 1.0f); + } + + private void drawColorPickerRect(float left, float top, float right, float bottom, Color color) { + new RectBuilder(new Vec2d(left, top), new Vec2d(right, bottom)).outlineColor(Color.BLACK).width(0.8).colorH(Color.WHITE, color).radius(1.5).draw(); + new RectBuilder(new Vec2d(left, top), new Vec2d(right, bottom)).outlineColor(Color.BLACK).width(0.8).colorV(new Color(0,0,0,0), Color.BLACK).radius(1.5).draw(); + } + + @Override + public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { + if (extended && mouseButton == 0) { + if (isPickerHover(mouseX, mouseY)) { + this.draggingPickerBase = true; + } else if (isRBGHover(mouseX, mouseY)) { + this.draggingRGBSlider = true; + } else if (isAlphaHover(mouseX, mouseY)) { + this.draggingAlphaSlider = true; + } + if (isCopyHover(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + handleCopyAction(); + } + if (isPasteHover(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + handlePasteAction(); + } + } + if (this.isHovering(mouseX, mouseY) && mouseButton == 0) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + this.toggle(); + } else { + super.mouseClicked(mouseX, mouseY, mouseButton); + } + } + + private void handleCopyAction() { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0f)); + String hex = String.format("#%02x%02x%02x%02x", setting.getColor().getAlpha(), setting.getColor().getRed(), setting.getColor().getGreen(), setting.getColor().getBlue()); + StringSelection selection = new StringSelection(hex); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(selection, selection); + Notifications.showNotification("Copied the color to your clipboard."); + } + + private void handlePasteAction() { + try { + String clipboardContent = readClipboard(); + if (clipboardContent != null) { + if (clipboardContent.startsWith("#")) { + handleHexPaste(clipboardContent); + } else { + handleRGBPaste(clipboardContent); + } + Notifications.showNotification("Color Pasted: " + clipboardContent + "!"); + } else { + Notifications.showNotification("Invalid Color!"); + } + } catch (NumberFormatException e) { + Notifications.showNotification("Invalid color format! Use Hex (#FFFFFFFF) or RGB (255,255,255)"); + } + } + + private void handleHexPaste(String hex) { + int a = Integer.valueOf(hex.substring(1, 3), 16); + int r = Integer.valueOf(hex.substring(3, 5), 16); + int g = Integer.valueOf(hex.substring(5, 7), 16); + int b = Integer.valueOf(hex.substring(7, 9), 16); + + setting.setColor(new Color(r, g, b, a)); + } + + private void handleRGBPaste(String rgb) { + String[] color = rgb.split(","); + if (color.length >= 3) { + setting.setColor(new Color(Integer.parseInt(color[0]), Integer.parseInt(color[1]), Integer.parseInt(color[2]))); + } else { + Notifications.showNotification("Invalid RGB format!"); + } + } + + public boolean isCopyHover(final int mouseX, final int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX + 1 && + mouseX <= pickerPosX + parentButton.font14.getStringWidth("copy") + 4 && + mouseY >= pickerPosY + 82 && + mouseY <= pickerPosY + 84 + parentButton.font14.getFontHeight(); + } + + public boolean isPasteHover(int mouseX, int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX + getWidth() - 3 - parentButton.font14.getStringWidth("paste") && + mouseX <= (pickerPosX + getWidth() - parentButton.font14.getStringWidth("paste")) + parentButton.font14.getStringWidth("paste")&& + mouseY >= pickerPosY + 82 && + mouseY <= pickerPosY + 84 + parentButton.font14.getFontHeight(); + } + + private boolean isPickerHover(final int mouseX, final int mouseY) { + float pickerPosX = x; + float pickerPosY = y + 15; + return mouseX >= pickerPosX && + mouseX <= pickerPosX + getWidth() && + mouseY >= pickerPosY && + mouseY <= pickerPosY + 54; + } + + private boolean isRBGHover(final int mouseX, final int mouseY) { + float sliderPosX = x; + float sliderPosY = y + 15; + return mouseX >= sliderPosX && + mouseX <= sliderPosX + getWidth() && + mouseY >= sliderPosY + 58 && + mouseY <= sliderPosY + 69; + } + + private boolean isAlphaHover(final int mouseX, final int mouseY) { + float sliderPosX = x; + float sliderPosY = y + 15; + return mouseX >= sliderPosX && + mouseX <= sliderPosX + getWidth() && + mouseY >= sliderPosY + 70 && + mouseY <= sliderPosY + 79; + } + + private boolean isHovering(final int mouseX, final int mouseY) { + return mouseX >= this.getX() && mouseX <= this.getX() + this.getWidth() && mouseY >= this.getY() && mouseY <= this.getY() + this.height; + } + + public static String readClipboard() { + try { + return (String)Toolkit.getDefaultToolkit().getSystemClipboard().getData(DataFlavor.stringFlavor); + } + catch (UnsupportedFlavorException | IOException exception) { + return null; + } + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int state) { + if (state == 0) { + this.draggingPickerBase = false; + this.draggingRGBSlider = false; + this.draggingAlphaSlider = false; + } + } + + public void toggle() { + this.extended = !this.extended; + } + + public boolean getExtended() { + return this.extended; + } + + @Override + public int getWidth() { + return 86; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ModuleButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ModuleButton.java new file mode 100644 index 00000000..e4baf61e --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/ModuleButton.java @@ -0,0 +1,238 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.SoundEvents; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.IContainer; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.font.CFont; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.util.setting.Setting; + +import java.awt.*; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.lwjgl.opengl.GL11; + +public class ModuleButton extends Button implements IContainer { + private final Module module; + private List items = new ArrayList<>(); + int color0, color1, color2, color3; + int offsetY; + public ModuleButton(Module module) { + super(module.getName()); + this.module = module; + + if(!module.parent) { + this.items.add(new BindButton(module)); + } + final List> settings = TempleClient.settingsManager.getSettingsByMod(module); + for (Setting s : settings) { + this.items.add(s.createCsgoButton(this)); + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + if (!this.items.isEmpty()) { + GlStateManager.pushMatrix(); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); + Color color = new Color(0x101010); + + String description = module.getDescription(); + int maxLineWidth = getWidth() - 36; + List lines = new ArrayList<>(); + offsetY = (font14.getStringWidth(description) > maxLineWidth) ? 12 : 8; + + new RectBuilder(new Vec2d(x, y), new Vec2d(x + getWidth(), y + height)) + .outlineColor( + this.getState() ? new Color(color3) : new Color(40, 40, 40), + this.getState() ? new Color(color2) : new Color(25, 25, 25), + this.getState() ? new Color(color0) : new Color(25, 25, 25), + this.getState() ? new Color(color1) : new Color(40, 40, 40) + ).width(0.9).color(color).radius(2.0).draw(); + if (getItems().size() > 1) { + new RectBuilder(new Vec2d(x + 3, y + font20.getFontHeight() + 15 + ((font14.getStringWidth(description) > maxLineWidth) ? 7 : 0)), new Vec2d(x + getWidth() - 3, y + height - 3)) + .color(new Color(25, 25, 25)).radius(3.0).draw(); + } + font20.drawString(this.getLabel(), (float) (x + 5 / 0.8), (float) (y + font20.getFontHeight() - 6.5), module.isEnabled() ? Color.WHITE : new Color(99, 104, 107), false, 1.0f); + + while (font14.getStringWidth(description) > maxLineWidth) { + int endIndex = findLastSpaceIndex(description, maxLineWidth, font14); + if (endIndex == -1) { + endIndex = font14.trimStringToWidth(description, maxLineWidth).length(); + } + String line = description.substring(0, endIndex); + lines.add(line); + description = description.substring(endIndex).trim(); + } + if (!description.isEmpty()) { + lines.add(description); + } + + int yOffset = 0; + for (String line : lines) { + font14.drawString(line, x + 5 / 0.8f, y + font14.getFontHeight() + 9 + yOffset, new Color(99, 104, 107).getRGB(), false, 1.0f); + yOffset += (int) (font14.getFontHeight() + 1); + } + + GlStateManager.disableDepth(); + GlStateManager.popMatrix(); + + int height = 4; + for (int i = 0, index = 0; i < getItems().size(); ) { + if (index == 1) { + if (items.get(i - 1).getHeight() != items.get(i).getHeight()) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + } + + items.get(i).setLocation(this.x + (float) this.getWidth() / 2 * index + 3, this.y + height + (offsetY - 1)); + items.get(i).setWidth((this.getWidth() / 2) - 12); + items.get(i).drawScreen(mouseX, mouseY, partialTicks); + + index += 1; + + if (index == 2) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + + i++; + + if (i == items.size() && index == 1) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + color0 = ClickGUI.INSTANCE.getClientColor(i); + color1 = ClickGUI.INSTANCE.getClientColor(i + 1); + color0 = ClickGUI.INSTANCE.getClientColor(i + 5); + color1 = ClickGUI.INSTANCE.getClientColor(i + 20); + } + this.setHeight(height + offsetY + 1); + } + } + + private int findLastSpaceIndex(String text, int maxWidth, CFont fontRenderer) { + int index = -1; + int currentWidth = 0; + + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + float charWidth = fontRenderer.getCharWidthFloat(c); + + if (currentWidth + charWidth > maxWidth) { + return index; + } + + if (c == ' ') { + index = i; + } + + currentWidth += (int) charWidth; + } + + return index; + } + + /*@Override + public int getHeight() { + int height = 4; + + for (int i = 0, index = 0; i < getItems().size(); ) { + if (index == 1) { + if (items.get(i - 1).getHeight() != items.get(i).getHeight()) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + } + index += 1; + + if (index == 2) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + i++; + + if (i == items.size() && index == 1) { + index = 0; + height += items.get(i - 1).getHeight() + 4; + } + } + return height + offsetY + 1; + }*/ + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) { + super.mouseClicked(mouseX, mouseY, mouseButton); + if(!this.items.isEmpty()) { + if(mouseButton == 1 && this.isHovering(mouseX, mouseY)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); + } + for(Item item : getItems()) { + System.out.println(item.getLabel()+", "+item.getHeight()); + item.mouseClicked(mouseX, mouseY, mouseButton); + } + } + } + + @Override + public void mouseReleased(int mouseX, int mouseY, int releaseButton) { + super.mouseReleased(mouseX, mouseY, releaseButton); + if(!items.isEmpty()) { + for(Item item : getItems()) { + item.mouseReleased(mouseX, mouseY, releaseButton); + } + } + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + super.keyTyped(typedChar, keyCode); + if(!items.isEmpty()) { + for(Item item : getItems()) { + item.keyTyped(typedChar, keyCode); + } + } + } + + @Override + public int getWidth() { + return 196; + } + + @Override + public void toggle() { + module.toggle(); + } + + @Override + public boolean getState() { + return module.isEnabled(); + } + + @Override + public CsgoGuiScreen getClientScreen() { + return CsgoGuiScreen.getInstance(); + } + + @Override + public List getItems() { + return items; + } + + @Override + public void setItems(List items) { + this.items = items; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/StringButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/StringButton.java new file mode 100644 index 00000000..136d55aa --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/StringButton.java @@ -0,0 +1,140 @@ +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.util.ChatAllowedCharacters; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.color.impl.RoundedTexture; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.StringSetting; +import xyz.templecheats.templeclient.util.time.TimerUtil; + +import java.awt.*; + +import static xyz.templecheats.templeclient.util.render.RenderUtil.drawHead; +import static xyz.templecheats.templeclient.util.render.StencilUtil.*; + +public class StringButton extends Item { + private final Button parentButton; + private final StringSetting setting; + private boolean typing; + private CurrentString currentString = new StringButton.CurrentString(""); + private final TimerUtil idleTimer = new TimerUtil(); + private boolean idling; + + public StringButton(String label, Button parentButton, StringSetting setting) { + super(label); + this.parentButton = parentButton; + this.setting = setting; + this.height = 21; + } + + @Override + public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { + new RectBuilder(new Vec2d(x + 1, y + 6), new Vec2d(x + width + 7.5, y + height)) + .outlineColor(new Color(0x494949)).width(0.8) + .color(!isHovering(mouseX, mouseY) ? new Color(0x262626) : new Color(0x2A2A2A)) + .radius(2.0).draw(); + new RectBuilder(new Vec2d(x + 2, y + 5), new Vec2d(x + parentButton.font12.getStringWidth(this.setting.getName()) + 2, y + 8)) + .color(new Color(25, 25, 25)) + .radius(2.0).draw(); + + GlStateManager.pushMatrix(); + parentButton.font12.drawString(this.setting.getName(), this.x + 2.3, this.y + 3, -1, false, 1f); + if(this.typing) { + parentButton.font14.drawString(this.currentString.getString() + typingIcon(), this.x + 5f, this.y + 10, -1, false, 1f); + } else { + parentButton.font14.drawString(this.setting.value(), this.x + 5f, this.y + 10, -1,false, 1f); + } + GlStateManager.popMatrix(); + } + + @Override + public void mouseClicked(final int mouseX, final int mouseY, final int mouseButton) { + if(this.isHovering(mouseX, mouseY) && mouseButton == 0) { + toggle(); + return; + } + super.mouseClicked(mouseX, mouseY, mouseButton); + } + + protected boolean isHovering(int mouseX, int mouseY) { + return this.getX() <= mouseX && (float) mouseX <= this.getX() + (float) this.getWidth() && this.getY() <= (float) mouseY && (float) mouseY <= this.getY() + (float) this.height; + } + + @Override + public void keyTyped(char typedChar, int keyCode) { + if (typing) { + switch (keyCode) { + case 1: { + return; + } + case 28: { + enterString(); + } + case 14: { + setString(removeLastChar(currentString.getString())); + } + } + if ( ChatAllowedCharacters.isAllowedCharacter(typedChar)) { + setString(currentString.getString() + typedChar); + } + } + } + + private void enterString() { + if (this.currentString.getString().isEmpty()) { + this.setting.setValue(this.setting.getStringValue()); + } else { + this.setting.setValue(this.currentString.getString()); + } + this.setString(""); + toggle(); + } + + public void setString(String newString) { + this.currentString = new CurrentString(newString); + } + + public static String removeLastChar ( String str ) { + String output = ""; + if ( str != null && !str.isEmpty()) { + output = str.substring ( 0 , str.length ( ) - 1 ); + } + return output; + } + + public void toggle() { + typing = !typing; + } + + public boolean getState() { + return !typing; + } + + public String typingIcon() { + if (idleTimer.passedMs(500L)) { + idling = !idling; + idleTimer.resetNT(); + } + if (idling) { + return "_"; + } + return ""; + } + + public static class CurrentString { + private final String string; + + public + CurrentString(String string) { + this.string = string; + } + + public + String getString() { + return this.string; + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumButton.java similarity index 73% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumButton.java index 83f0f21c..251f7766 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumButton.java @@ -1,21 +1,22 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.enumB; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Gui; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; -import xyz.templecheats.templeclient.util.render.RenderUtil; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import java.awt.*; import java.util.ArrayList; import java.util.List; -public class EnumButton> extends Button { - private final Button parentButton; +public class EnumButton> extends xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button { + private final xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parentButton; private final EnumSetting setting; private final List> items = new ArrayList<>(); private boolean subOpen; @@ -36,19 +37,14 @@ public EnumButton(EnumSetting setting, Button parentButton) { @Override public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { if(!this.items.isEmpty()) { - // RenderUtil.drawRect(x, y, x + width + 7.4F, y + height, !isHovering(mouseX, mouseY) ? 0x11333333 : 0x88333333); - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+2, this.y, 0); - - RenderUtil.drawRect(0, 8, width-4, 20, !this.isHovering(mouseX, mouseY) ? 0xFF2A2927 : 0x88888888); - RenderUtil.drawGradientRect(0, 8, width-4, 20, 0x33555555, 0xAA333333); - - GlStateManager.scale(0.6, 0.6, 0); - FontUtils.drawString(getLabel(), 2/0.6, 0, 0xFFD2D2D2, false); - FontUtils.drawString(setting.value().toString(), 5/0.6, (float)(12/0.6), 0xFFD2D2D2, false); + new RectBuilder(new Vec2d(x + getWidth() / 1.836, y + 6), new Vec2d(x + getWidth() - 8, y + 21)) + .color(!this.isHovering(mouseX, mouseY) ? new Color(0xFF2A2927) : new Color(0x363636)) + .radius(2.0).draw(); + font16.drawString(getLabel(), x + 3 + 2 / 0.6, y + 10, 0xFFD2D2D2, false, 1.0f); + font16.drawString(setting.value().toString(), x + getWidth() / 1.8, y + 10, 0xFFD2D2D2, false, 1.0f); mc.getTextureManager().bindTexture(new ResourceLocation("textures/icons/down.png")); - Gui.drawScaledCustomSizeModalRect(width+15, 20, 0.0F, 0.0F, 8, 8, 8, 8, 8, 8); + Gui.drawScaledCustomSizeModalRect((int) (x + getWidth() - 23), (int) (y + 8), 0.0F, 0.0F, 7, 8, 7, 8, 7, 8); GlStateManager.popMatrix(); if (this.subOpen) { @@ -89,6 +85,11 @@ public void mouseReleased(int mouseX, int mouseY, int mouseButton) { super.mouseReleased(mouseX, mouseY, mouseButton); } + @Override + public int getWidth() { + return 188; + } + @Override public int getHeight() { return this.height; @@ -100,7 +101,7 @@ public boolean getState() { } @Override - public ClientCsgoGuiScreen getClientScreen() { + public CsgoGuiScreen getClientScreen() { return this.parentButton.getClientScreen(); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumValueButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumValueButton.java similarity index 89% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumValueButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumValueButton.java index d2556903..b5ac11ed 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/EnumValueButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/EnumValueButton.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.enumB; public class EnumValueButton> extends NormalButton { public final T value; diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/NormalButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/NormalButton.java similarity index 53% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/NormalButton.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/NormalButton.java index da1d412a..13a48b84 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/NormalButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/enumB/NormalButton.java @@ -1,14 +1,17 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.enumB; import org.lwjgl.opengl.GL11; import net.minecraft.client.renderer.GlStateManager; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; import xyz.templecheats.templeclient.util.render.RenderUtil; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import java.awt.*; + public class NormalButton extends Button { public NormalButton(String label) { super(label); @@ -18,25 +21,21 @@ public NormalButton(String label) { @Override public void drawScreen(final int mouseX, final int mouseY, final float partialTicks) { GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+2, this.y, 5); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function - RenderUtil.drawRect(0, 0, width-4, 12, 0xFF2A2927); - GlStateManager.scale(0.6, 0.6, 1); - FontUtils.drawString(getLabel(), 5/0.6, (float)(4/0.6), !isHovering(mouseX, mouseY) ? 0xFFFFFFFF : ClickGUI.INSTANCE.getStartColor(), false); - GlStateManager.disableDepth(); // Disable depth testing after drawing + GlStateManager.translate(0, 0, 5); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); + RenderUtil.drawRect(x + getWidth() / 1.836f, y, x + getWidth() - 8, y + 12, 0xFF2A2927); + new RectBuilder(new Vec2d(x + getWidth() / 1.836, y), new Vec2d(x + getWidth() - 10, y + 12)) + .outlineColor(new Color(0x262626)) + .width(0.5) + .color(new Color(0xFF2A2927)) + .radius(2.0) + .draw(); + font12.drawString(getLabel(), x + (getWidth() / 1.8), y + (4/0.6) - 1.5, !isHovering(mouseX, mouseY) ? 0xFFFFFFFF : ClickGUI.INSTANCE.getStartColor().getRGB(), false, 1.0f); + GlStateManager.disableDepth(); GlStateManager.popMatrix(); } - // @Override - // public String mouseClicked(int mouseX, int mouseY, int mouseButton) { - // if(mouseButton == 0 && this.isHovering(mouseX, mouseY)) { - // return getLabel(); - // } - - // return "Arial"; - // } - @Override public String otherEvent(int mouseX, int mouseY, int mouseButton) { if(mouseButton == 0 && this.isHovering(mouseX, mouseY)) { @@ -46,8 +45,8 @@ public String otherEvent(int mouseX, int mouseY, int mouseButton) { } @Override - public int getHeight() { - return this.height; + public int getWidth() { + return 188; } protected boolean isHovering(int mouseX, int mouseY) { @@ -55,7 +54,7 @@ protected boolean isHovering(int mouseX, int mouseY) { } @Override - public ClientCsgoGuiScreen getClientScreen() { - return ClientCsgoGuiScreen.getInstance(); + public CsgoGuiScreen getClientScreen() { + return CsgoGuiScreen.getInstance(); } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/DoubleSlider.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/DoubleSlider.java similarity index 58% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/DoubleSlider.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/DoubleSlider.java index 92692b4f..f8095ab6 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/DoubleSlider.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/DoubleSlider.java @@ -1,19 +1,24 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.slider; import org.lwjgl.opengl.GL11; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.math.MathHelper; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.NavLink; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import java.awt.*; + +import static xyz.templecheats.templeclient.util.Globals.mc; + public class DoubleSlider extends Item { - private final Button parentButton; + private final xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parentButton; private final DoubleSetting setting; private boolean dragging; private double value; @@ -31,47 +36,33 @@ public void drawScreen(final int mouseX, final int mouseY, final float partialTi double range = setting.max - setting.min; double percentBar = (value - setting.min) / range; - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+3, this.y, 0); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function + int color0 = ClickGUI.INSTANCE.getClientColor((int) range); + int color1 = ClickGUI.INSTANCE.getClientColor((int) range + 1); - RenderUtil.drawRect(0, 8, (float) ((percentBar * (this.width-4))), 13, ClickGUI.INSTANCE.getStartColor()); - RenderUtil.drawRect(0, 8, (float) (this.width-4), 13, 0x88555555); + GlStateManager.pushMatrix(); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(0, 8, (float) ((percentBar * (this.width-4))), 13, 0x22000000); + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + 3 + width, y + 14)).color(new Color(0x22000000)).radius(1.0).draw(); } + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + 3 + width, y + 14)).colorH(new Color(0x33555555), new Color(0xAA333333)).radius(1.0).draw(); + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + percentBar * (this.width), y + 14)).colorH(new Color(color0), new Color(color1)).radius(1.0).draw(); - RenderUtil.drawGradientRect(0, 8, (float) (this.width-4), 13, 0x33555555, 0xAA333333); - - GlStateManager.scale(0.6, 0.6, 1); - FontUtils.drawString(getLabel(), 0, 0, 0xFFD2D2D2, false); - - for (int i = -1, cidx=0; i <= 1; i++) { - for (int j = -1; j <= 1; j++) { - FontUtils.csgoBoldNormal.drawString( - Double.toString(Math.round(value * 100D) / 100D), - (int)(percentBar * (this.width-4))/0.9 + i, - 19+j, - 0xFF131313+cidx - ); + double circleX = x + percentBar * (this.width); + new RectBuilder(new Vec2d(circleX - 2, y + 10.8), new Vec2d(circleX + 2, y + 14.8)).color(new Color(color1)).radius(4.0).draw(); - cidx++; - } - } + parentButton.font14.drawString(getLabel(), x + 3, y + 4, 0xFFD2D2D2, false, 1.0f); + parentButton.font12.drawString(Double.toString(Math.round(value * 100D) / 100D), x + width - (parentButton.font12.getStringWidth(Double.toString(Math.round(value * 100D) / 100D)) / 2) - 8, y + 5, Color.WHITE, false, 1.0f); - FontUtils.csgoBoldNormal.drawString( - Double.toString(Math.round(value * 100D) / 100D), - (int)(percentBar * (this.width-4))/0.9, - 19, - 0xFFFFFFFF - ); - GlStateManager.disableDepth(); // Disable depth testing after drawing + GlStateManager.disableDepth(); GlStateManager.popMatrix(); + dragging(mouseX, range); + } + private void dragging(final int mouseX, double range) { if(this.dragging) { - double offset = (MathHelper.clamp((mouseX - x) / (this.width-4), 0, 1) * range); + double offset = (MathHelper.clamp((mouseX - x) / (this.width), 0, 1) * range); this.value = setting.min + offset; if(!(this.setting.parent instanceof ClickGUI) || !this.setting.name.equals("Scale")) { @@ -101,13 +92,8 @@ public void mouseReleased(int mouseX, int mouseY, int state) { super.mouseReleased(mouseX, mouseY, state); } - @Override - public int getHeight() { - return this.height; - } - private boolean isHovering(final int mouseX, final int mouseY) { - for(final NavLink nav : this.parentButton.getClientScreen().getNavs()) { + for(final Panel nav : this.parentButton.getClientScreen().getNavs()) { if(nav.drag) { return false; } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IntSlider.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/IntSlider.java similarity index 59% rename from src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IntSlider.java rename to src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/IntSlider.java index 1af75f3f..5b61c600 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/IntSlider.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/csgo/properties/items/buttons/slider/IntSlider.java @@ -1,18 +1,20 @@ -package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties; +package xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.slider; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.math.MathHelper; import org.lwjgl.opengl.GL11; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.NavLink; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; -import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; import xyz.templecheats.templeclient.util.setting.impl.IntSetting; +import java.awt.*; + public class IntSlider extends Item { - private final Button parentButton; + private final xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parentButton; private final IntSetting setting; private boolean dragging; private int value; @@ -30,47 +32,30 @@ public void drawScreen(final int mouseX, final int mouseY, final float partialTi double range = setting.max - setting.min; double percentBar = (value - setting.min) / range; - GlStateManager.pushMatrix(); - GlStateManager.translate(this.x+3, this.y, 0); - GlStateManager.enableDepth(); // Enable depth testing - GlStateManager.depthFunc(GL11.GL_LEQUAL); // Configure depth function + int color0 = ClickGUI.INSTANCE.getClientColor((int) range); + int color1 = ClickGUI.INSTANCE.getClientColor((int) range + 1); - RenderUtil.drawRect(0, 8, (float) ((percentBar * (this.width-4))), 13, ClickGUI.INSTANCE.getStartColor()); - RenderUtil.drawRect(0, 8, (float) (this.width-4), 13, 0x88555555); + GlStateManager.pushMatrix(); + GlStateManager.enableDepth(); + GlStateManager.depthFunc(GL11.GL_LEQUAL); if(this.isHovering(mouseX, mouseY)) { - RenderUtil.drawRect(0, 8, (float) ((percentBar * (this.width-4))), 13, 0x22000000); + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + 3 + width, y + 14)).color(new Color(0x22000000)).radius(1.0).draw(); } + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + 3 + width, y + 14)).colorH(new Color(0x33555555), new Color(0xAA333333)).radius(1.0).draw(); + new RectBuilder(new Vec2d(x + 3, y + 12), new Vec2d(x + percentBar * (this.width), y + 14)).colorH(new Color(color0), new Color(color1)).radius(1.0).draw(); - RenderUtil.drawGradientRect(0, 8, (float) (this.width-4), 13, 0x33555555, 0xAA333333); - - GlStateManager.scale(0.6, 0.6, 1); - FontUtils.drawString(getLabel(), 0, 0, 0xFFD2D2D2, false); - - for (int i = -1, cidx=0; i <= 1; i++) { - for (int j = -1; j <= 1; j++) { - FontUtils.csgoBoldNormal.drawString( - Integer.toString(value), - (int)(percentBar * (this.width-4))/0.9 + i, - 19+j, - 0xFF131313+cidx - ); + double circleX = x + percentBar * (this.width); + new RectBuilder(new Vec2d(circleX - 2, y + 10.8), new Vec2d(circleX + 2, y + 14.8)).color(new Color(color1)).radius(4.0).draw(); - cidx++; - } - } + parentButton.font14.drawString(getLabel(), x + 3, y + 4, 0xFFD2D2D2, false, 1.0f); + parentButton.font12.drawString(Integer.toString(value), x + width - (parentButton.font12.getStringWidth(Integer.toString(value)) / 2) - 8, y + 5, Color.WHITE, false, 1.0f); - FontUtils.csgoBoldNormal.drawString( - Integer.toString(value), - (int)(percentBar * (this.width-4))/0.9, - 19, - 0xFFFFFFFF - ); - GlStateManager.disableDepth(); // Disable depth testing after drawing + GlStateManager.disableDepth(); GlStateManager.popMatrix(); if(this.dragging) { - int offset = (int) (MathHelper.clamp((mouseX - x) / (this.width-4), 0, 1) * range); + int offset = (int) (MathHelper.clamp((mouseX - x) / (this.width), 0, 1) * range); value = setting.min + offset; setting.setIntValue(setting.min + offset); @@ -101,13 +86,8 @@ public void mouseReleased(int mouseX, int mouseY, int state) { super.mouseReleased(mouseX, mouseY, state); } - @Override - public int getHeight() { - return this.height; - } - private boolean isHovering(final int mouseX, final int mouseY) { - for(final NavLink nav : this.parentButton.getClientScreen().getNavs()) { + for(final Panel nav : this.parentButton.getClientScreen().getNavs()) { if(nav.drag) { return false; } diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudEditorScreen.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudEditorScreen.java index 876c310d..fca8b010 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudEditorScreen.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudEditorScreen.java @@ -1,7 +1,13 @@ package xyz.templecheats.templeclient.features.gui.clickgui.hud; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; import xyz.templecheats.templeclient.features.module.modules.client.HUD; public class HudEditorScreen extends ClientGuiScreen { @@ -14,7 +20,7 @@ public void load() { this.getPanels().add(new Panel("Hud Editor", 200, 100, true) { @Override public void setupItems() { - for(HUD.HudElement element : HUD.INSTANCE.getHudElements()) { + for (HUD.HudElement element: HUD.INSTANCE.getHudElements()) { this.addButton(new HudElementButton(element)); } } @@ -23,6 +29,42 @@ public void setupItems() { super.load(); } + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + int screenWidth = sr.getScaledWidth(); + int screenHeight = sr.getScaledHeight(); + + int centerX = screenWidth / 2; + int centerY = screenHeight / 2; + + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + drawLine(centerX, 0, centerX, screenHeight, 1.0F); + + drawLine(0, centerY, screenWidth, centerY, 1.0F); + } + + private void drawLine(int x1, int y1, int x2, int y2, float thickness) { + GlStateManager.glLineWidth(thickness); + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.begin(1, DefaultVertexFormats.POSITION); + bufferbuilder.pos(x1, y1, 0.0D).endVertex(); + bufferbuilder.pos(x2, y2, 0.0D).endVertex(); + tessellator.draw(); + + GlStateManager.enableAlpha(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + } + public static HudEditorScreen getInstance() { return instance == null ? (instance = new HudEditorScreen()) : instance; } @@ -30,4 +72,4 @@ public static HudEditorScreen getInstance() { protected double getScale() { return HUD.INSTANCE.hudScale.doubleValue(); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudElementButton.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudElementButton.java index d0e39152..bc40a208 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudElementButton.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/hud/HudElementButton.java @@ -2,15 +2,19 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.Gui; import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; import net.minecraft.init.SoundEvents; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.MathHelper; import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClientGuiScreen; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Panel; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.Panel; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.ColorButton; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.Setting; @@ -20,36 +24,63 @@ import java.util.List; public class HudElementButton extends Button { + /* + * Variables + */ private final HUD.HudElement element; - private final List items = new ArrayList<>(); + private final List < Item > items = new ArrayList < > (); private boolean subOpen; private long timeHovering; - private double dragX; private double dragY; + private int progress; public HudElementButton(HUD.HudElement element) { super(element.getName()); this.element = element; - final List> settings = TempleClient.settingsManager.getSettingsByMod(element); for (Setting s : settings) { this.items.add(s.createBasicButton(this)); } + + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + int screenWidth = sr.getScaledWidth(); + int screenHeight = sr.getScaledHeight(); + if (this.element.getX() == 0 && this.element.getY() == 0) { + this.element.setX((double) screenWidth / 2); + this.element.setY((double) screenHeight / 2); + } } @Override public void drawScreen(int mouseX, int mouseY, float partialTicks) { super.drawScreen(mouseX, mouseY, partialTicks); - if(!this.items.isEmpty()) { - FontUtils.drawString(!this.subOpen ? "+" : "-", this.x - 1.0f + (float) this.width - 8.0f, this.y + 4.0f, -1, false); - if(this.subOpen) { + if (!this.items.isEmpty()) { + if (ClickGUI.INSTANCE.gears.booleanValue()) { + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + Minecraft.getMinecraft().getTextureManager().bindTexture(new ResourceLocation("textures/icons/gear.png")); + GlStateManager.translate(this.x + this.width - 6.7F, this.y + 7.7F - 0.3F, 0); + if (this.subOpen) { + ++this.progress; + GlStateManager.rotate(Panel.calculateRotation((float) this.progress), 0.0F, 0.0F, 1.0F); + } + Gui.drawScaledCustomSizeModalRect(-5, -5, 0, 0, 10, 10, 10, 10, 10.0F, 10.0F); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + + if (this.subOpen) { float height = 1.0f; - for(Item item : items) { + for (Item item: items) { item.setLocation(this.x + 1.0f, this.y + (height += 15.0f)); item.setHeight(15); item.setWidth(this.width - 9); item.drawScreen(mouseX, mouseY, partialTicks); + + if (item instanceof ColorButton && ((ColorButton) item).getExtended()) { + height += 98; + } } } } @@ -61,7 +92,7 @@ private void drag(int mouseX, int mouseY) { final double x = this.element.isDragging() ? this.dragX + mouseX : this.element.getX(); final double y = this.element.isDragging() ? this.dragY + mouseY : this.element.getY(); - if(HUD.INSTANCE.clamping.booleanValue()) { + if (HUD.INSTANCE.clamping.booleanValue()) { final ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); final double screenWidth = sr.getScaledWidth() / HUD.INSTANCE.hudScale.doubleValue(); final double screenHeight = sr.getScaledHeight() / HUD.INSTANCE.hudScale.doubleValue(); @@ -76,20 +107,20 @@ private void drag(int mouseX, int mouseY) { @Override public void drawScreenPost(int mouseX, int mouseY) { - if(this.isHovering(mouseX, mouseY)) { - if(this.timeHovering == 0) { + if (this.isHovering(mouseX, mouseY)) { + if (this.timeHovering == 0) { this.timeHovering = System.currentTimeMillis(); } - if(System.currentTimeMillis() - this.timeHovering > 500) { + if (System.currentTimeMillis() - this.timeHovering > 500) { final String description = element.getDescription(); final float startX = mouseX + 7; final float startY = mouseY + 7; - final float width = (float) FontUtils.getStringWidth(description); - final float height = (float) FontUtils.getFontHeight(); + final float width = (float) font18.getStringWidth(description); + final float height = (float) font18.getFontHeight(); RenderUtil.drawRect(startX - 1, startY - 1, startX + width, startY + height, 0x88000000); - FontUtils.drawString(description, startX, startY, -1, false); + font18.drawString(description, startX, startY, -1, false, 1.0f); } } else { this.timeHovering = 0; @@ -99,19 +130,19 @@ public void drawScreenPost(int mouseX, int mouseY) { @Override public void mouseClicked(int mouseX, int mouseY, int mouseButton) { super.mouseClicked(mouseX, mouseY, mouseButton); - if(!this.items.isEmpty()) { - if(mouseButton == 1 && this.isHovering(mouseX, mouseY)) { + if (!this.items.isEmpty()) { + if (mouseButton == 1 && this.isHovering(mouseX, mouseY)) { this.subOpen = !this.subOpen; Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(SoundEvents.UI_BUTTON_CLICK, 1.0F)); } - if(this.subOpen) { - for(Item item : items) { + if (this.subOpen) { + for (Item item: items) { item.mouseClicked(mouseX, mouseY, mouseButton); } } } - if(mouseButton == 0 && this.isHoveringOnElement(mouseX, mouseY)) { + if (mouseButton == 0 && this.isHoveringOnElement(mouseX, mouseY)) { this.dragX = this.element.getX() - mouseX; this.dragY = this.element.getY() - mouseY; this.element.setDragging(true); @@ -121,13 +152,13 @@ public void mouseClicked(int mouseX, int mouseY, int mouseButton) { @Override public void mouseReleased(int mouseX, int mouseY, int releaseButton) { super.mouseReleased(mouseX, mouseY, releaseButton); - if(!items.isEmpty() && subOpen) { - for(Item item : items) { + if (!items.isEmpty() && subOpen) { + for (Item item: items) { item.mouseReleased(mouseX, mouseY, releaseButton); } } - if(releaseButton == 0) { + if (releaseButton == 0) { this.element.setDragging(false); } } @@ -135,8 +166,8 @@ public void mouseReleased(int mouseX, int mouseY, int releaseButton) { @Override public void keyTyped(char typedChar, int keyCode) throws IOException { super.keyTyped(typedChar, keyCode); - if(!items.isEmpty() && subOpen) { - for(Item item : items) { + if (!items.isEmpty() && subOpen) { + for (Item item: items) { item.keyTyped(typedChar, keyCode); } } @@ -144,10 +175,14 @@ public void keyTyped(char typedChar, int keyCode) throws IOException { @Override public int getHeight() { - if(this.subOpen) { + if (this.subOpen) { int height = 14; - for(Item item : items) { + for (Item item: items) { height += item.getHeight() + 1; + + if (item instanceof ColorButton && ((ColorButton) item).getExtended()) { + height += 98; + } } return height + 2; } @@ -170,14 +205,14 @@ public ClientGuiScreen getClientScreen() { } private boolean isHoveringOnElement(int mouseX, int mouseY) { - for(Panel panel : this.getClientScreen().getPanels()) { - if(!panel.drag) continue; + for (Panel panel: this.getClientScreen().getPanels()) { + if (!panel.drag) continue; return false; } - for(HUD.HudElement element : HUD.INSTANCE.getHudElements()) { - if(!element.isDragging()) continue; + for (HUD.HudElement element: HUD.INSTANCE.getHudElements()) { + if (!element.isDragging()) continue; return false; } return mouseX >= this.element.getX() && mouseX <= this.element.getX() + this.element.getWidth() && mouseY >= this.element.getY() && mouseY <= this.element.getY() + this.element.getHeight(); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Particle.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Particle.java index e4f3e6e8..5e3742df 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Particle.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Particle.java @@ -12,7 +12,7 @@ public class Particle { private final Vector2f pos; private static final Random random = new Random(); - private float size; + private final float size; private final Vector2f velocity; public Particle(Vector2f velocity, float x, float y, float size) { @@ -56,26 +56,26 @@ public void setup(int delta, float speed) { this.pos.setX(0.0f); } if (this.pos.getX() < 0.0f) { - this.pos.setX((float)Display.getWidth()); + this.pos.setX((float) Display.getWidth()); } if (this.pos.getY() > Display.getHeight()) { this.pos.setY(0.0f); } if (this.pos.getY() < 0.0f) { - this.pos.setY((float)Display.getHeight()); + this.pos.setY((float) Display.getHeight()); } } public static class Util { - private final List particles; + private final List < Particle > particles; - public Util(int in) { - particles = new ArrayList<>(); + public Util(int in ) { + particles = new ArrayList < > (); addParticle(in); } - public void addParticle(int in) { + public void addParticle(int in ) { for (int i = 0; i < in; ++i) particles.add(getParticle()); } @@ -94,7 +94,7 @@ public void drawParticles() { glColor4f(1.0f, 1.0f, 1.0f, 1.0f); - for (Particle particle : particles) { + for (Particle particle: particles) { particle.setup(2, 0.1f); glPointSize(particle.size); glBegin(GL_POINTS); diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Snow.java b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Snow.java index d33021cf..be652fce 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Snow.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/clickgui/particles/Snow.java @@ -37,17 +37,16 @@ public void setY(int y) { } public void drawSnow(ScaledResolution res) { - Gui.drawRect(getX(), getY(), getX()+ size, getY()+ size, 0x99C9C5C5); + Gui.drawRect(getX(), getY(), getX() + size, getY() + size, 0x99C9C5C5); setY(getY() + speed); if (getY() > res.getScaledHeight() + 10 || getY() < -10) { - setY(-10); - Random random = new Random(); - - speed = random.nextInt(10) + 1; - size = random.nextInt(4) + 1; + setY(-10); + setX(random.nextInt(res.getScaledWidth())); + speed = random.nextInt(3) + 1; + size = random.nextInt(2) + 1; } } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/font/AbstractFont.java b/src/main/java/xyz/templecheats/templeclient/features/gui/font/AbstractFont.java new file mode 100644 index 00000000..81f174f5 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/font/AbstractFont.java @@ -0,0 +1,21 @@ +package xyz.templecheats.templeclient.features.gui.font; + +import java.awt.*; + +public interface AbstractFont { + float getStringWidth(String text); + float getFontHeight(); + + void drawStringWithShadow(String text, float x, float y, int color, float scale); + void drawStringWithShadow(String text, float x, float y, Color color, float scale); + + void drawString(String text, float x, float y, Color color, boolean shadow, float scale); + void drawString(String text, float x, float y, int color, boolean shadow, float scale); + + void drawCenteredString(String text, float x, float y, Color color, boolean shadow, float scale); + + String trimStringToWidth(String text, int width); + + String trimStringToWidth(String text, int width, boolean reverse); + +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/font/CFont.java b/src/main/java/xyz/templecheats/templeclient/features/gui/font/CFont.java index d7709165..0c5a527c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/font/CFont.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/font/CFont.java @@ -1,147 +1,468 @@ -/** - * This FontRenderer was made by a user, and was modified. - */ - package xyz.templecheats.templeclient.features.gui.font; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.texture.DynamicTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import org.apache.commons.lang3.tuple.MutablePair; import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; import java.awt.*; import java.awt.geom.Rectangle2D; import java.awt.image.BufferedImage; -public class CFont { - float imgSize = 512; - CharData[] charData = new CharData[256]; - Font font; - boolean antiAlias, fractionalMetrics; - int fontHeight = -1, charOffset = 0; - DynamicTexture tex; +import static org.lwjgl.opengl.GL11.*; + +public class CFont implements AbstractFont { + private static final Tessellator tessellator = Tessellator.getInstance(); + private static final BufferBuilder buffer = tessellator.getBuffer(); + private static int[] colorCode; + private static final String colorcodeIdentifiers = "0123456789abcdefklmnor"; + private final FontData regular = new FontData(Font.PLAIN), italic = new FontData(Font.ITALIC); + private final Font font; + private int fontHeight; + private CFont boldFont; + private static final float kerning = 8.3f; - public CFont(Font font, boolean antiAlias, boolean fractionalMetrics) { + public CFont(Font font) { + generateColorCodes(); this.font = font; - this.antiAlias = antiAlias; - this.fractionalMetrics = fractionalMetrics; - this.tex = this.setupTexture(font, antiAlias, fractionalMetrics, this.charData); + setupTexture(regular); + setupTexture(italic); + } + + public boolean hasBold() { + return this.boldFont != null; } - protected DynamicTexture setupTexture(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) { - BufferedImage img = this.generateFontImage(font, antiAlias, fractionalMetrics, chars); + private void setupTexture(FontData fontData) { + BufferedImage image = new BufferedImage(1, 1, BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = (Graphics2D) image.getGraphics(); + + Font currentFont = fontData.textType == 0 ? font : font.deriveFont(fontData.textType); + graphics.setFont(currentFont); + handleSprites(fontData, currentFont, graphics); + } - try { - return new DynamicTexture(img); - } catch (Exception e) { - e.printStackTrace(); - return null; + @Override + public void drawStringWithShadow(String text, float x, float y, int color, float scale) { + drawString(text, x, y, color, true, scale); + } + + @Override + public void drawStringWithShadow(String text, float x, float y, Color color, float scale) { + drawStringWithShadow(text, x, y, color.getRGB(), scale); + } + + @Override + public void drawString(String text, float x, float y, int color, boolean shadow, float scale) { + if (FontSettings.INSTANCE.isEnabled()) { + if (shadow) drawString(text, x + 0.5f, y + 0.5f, color, true, scale, false); + drawString(text, x, y, color, false, scale, false); + } else { + Minecraft.getMinecraft().fontRenderer.drawString(text, x, y, color, shadow); } } - protected BufferedImage generateFontImage(Font font, boolean antiAlias, boolean fractionalMetrics, CharData[] chars) { - int imgSize = (int) this.imgSize; - BufferedImage bufferedImage = new BufferedImage(imgSize, imgSize, 2); - Graphics2D graphics = (Graphics2D) bufferedImage.getGraphics(); - graphics.setFont(font); - graphics.setColor(new Color(255, 255, 255, 0)); - graphics.fillRect(0, 0, imgSize, imgSize); - graphics.setColor(Color.WHITE); - graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, fractionalMetrics ? RenderingHints.VALUE_FRACTIONALMETRICS_ON : RenderingHints.VALUE_FRACTIONALMETRICS_OFF); - graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, antiAlias ? RenderingHints.VALUE_TEXT_ANTIALIAS_ON : RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); - graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, antiAlias ? RenderingHints.VALUE_ANTIALIAS_ON : RenderingHints.VALUE_ANTIALIAS_OFF); - FontMetrics fontMetrics = graphics.getFontMetrics(); - int charHeight = 0; - int positionX = 0; - int positionY = 1; - int index = 0; + public void drawString(String text, double x, double y, int color, boolean shadow, float scale) { + drawString(text, (float) x, (float) y, color, shadow, scale); + } + + @Override + public void drawString(String text, float x, float y, Color color, boolean shadow, float scale) { + drawString(text, x, y, color.getRGB(), shadow, scale); + } + + @Override + public void drawCenteredString(String text, float x, float y, Color color, boolean shadow, float scale) { + drawString(text, x - (getStringWidth(text) / 2), y, color.getRGB(), shadow, scale); + } + + @Override + public String trimStringToWidth(String text, int width) { + return this.trimStringToWidth(text, width, false); + } - while (index < chars.length) { - char c = (char) index; - CharData charData = new CharData(); - Rectangle2D dimensions = fontMetrics.getStringBounds(String.valueOf(c), graphics); - charData.width = dimensions.getBounds().width + 8; - charData.height = dimensions.getBounds().height; - - if (positionX + charData.width >= imgSize) { - positionX = 0; - positionY += charHeight; - charHeight = 0; + @Override + public String trimStringToWidth(String text, int width, boolean reverse) { + if (text == null) return ""; + StringBuilder buffer = new StringBuilder(); + float lineWidth = 0.0F; + int offset = reverse ? text.length() - 1 : 0; + int increment = reverse ? -1 : 1; + boolean var8 = false; + boolean var9 = false; + + + for (int index = offset; index >= 0 && index < text.length() && lineWidth < (float) width; index += increment) { + char character = text.charAt(index); + float charWidth = this.getCharWidthFloat(character); + + if (var8) { + var8 = false; + + if (character != 108 && character != 76) { + if (character == 114 || character == 82) { + var9 = false; + } + } else { + var9 = true; + } + } else if (charWidth < 0) { + var8 = true; + } else { + lineWidth += charWidth; + + if (var9) { + ++lineWidth; + } } - if (charData.height > charHeight) { - charHeight = charData.height; + if (lineWidth > (float) width) { + break; } - charData.storedX = positionX; - charData.storedY = positionY; + if (reverse) { + buffer.insert(0, character); + } else { + buffer.append(character); + } + } + + return buffer.toString(); + } + + public float getCharWidthFloat(char c) { + if (c == 167) { + return -1; + } else if (c == 32) { + return 2; + } else { + int var2 = ("\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000").indexOf(c); - if (charData.height > this.fontHeight) { - this.fontHeight = charData.height; + if (c > 0 && var2 != -1) { + return ((regular.chars[var2].width / 2.f) - 4.f); + } else if (c < regular.chars.length && ((regular.chars[c].width / 2.f) - 4.f) != 0) { + int var3 = ((int) ((regular.chars[c].width / 2.f) - 4.f)) >>> 4; + int var4 = ((int) ((regular.chars[c].width / 2.f) - 4.f)) & 15; + var3 &= 15; + ++var4; + return (float) ((var4 - var3) / 2 + 1); + } else { + return 0; } + } + } + + public float drawString(String text, float x, float y, int color, boolean shadow, float scale, boolean smooth) { + if (text == null) { + return 0; + } + if (color == 0x20FFFFFF) { + color = 0xFFFFFF; + } + if ((color & 0xFC000000) == 0) { + color |= 0xFF000000; + } + if (shadow) { + color = (color & 0xFCFCFC) >> 2 | color & 0xFF000000; + } + float alpha = (float) (color >> 24 & 255) / 255f; - chars[index] = charData; - graphics.drawString(String.valueOf(c), positionX + 2, positionY + fontMetrics.getAscent()); - positionX += charData.width; - ++index; + GlStateManager.pushMatrix(); + GlStateManager.scale(0.5, 0.5, 0.5); + GlStateManager.translate(0.0, FontSettings.INSTANCE.getOffset(), 0.0); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.resetColor(); + GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); + GlStateManager.enableTexture2D(); + GlStateManager.bindTexture(this.regular.texture.getGlTextureId()); + if (smooth) { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); + } else { + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); + GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); } - return bufferedImage; + float returnVal = drawCustomChars(text, x, y, color, shadow); + + GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE); + GlStateManager.popMatrix(); + GlStateManager.resetColor(); + GlStateManager.bindTexture(0); + + return returnVal; } - public void drawChar(CharData[] chars, char c, float x, float y) throws ArrayIndexOutOfBoundsException { - try { - this.drawQuad(x, y, chars[c].width, chars[c].height, chars[c].storedX, chars[c].storedY, chars[c].width, chars[c].height); - } catch (Exception e) { - e.printStackTrace(); + private float drawCustomChars(String text, double x, double y, int color, boolean shadow) { + x = (x - 1) * 2; + y = (y - 3) * 2; + FontData currentData = this.regular; + float alpha = (float) (color >> 24 & 255) / 255f; + boolean bold = false, + italic = false, + strikethrough = false, + underline = false; + + for (int index = 0; index < text.length(); index++) { + char character = text.charAt(index); + if (character == '\u00a7') { + int colorIndex = 21; + + try { + colorIndex = colorcodeIdentifiers.indexOf(text.charAt(index + 1)); + } catch (Exception e) { + e.printStackTrace(); + } + + if (colorIndex < 16) { + bold = false; + italic = false; + underline = false; + strikethrough = false; + GlStateManager.bindTexture(this.regular.texture.getGlTextureId()); + currentData = this.regular; + + if (colorIndex < 0) { + colorIndex = 15; + } + if (shadow) { + colorIndex += 16; + } + int colorcode = colorCode[colorIndex]; + GlStateManager.color((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha); + } else { + switch (colorIndex) { + case 17: + if (hasBold()) { + bold = true; + if (italic) { + GlStateManager.bindTexture(this.boldFont.italic.texture.getGlTextureId()); + currentData = this.boldFont.italic; + } else { + GlStateManager.bindTexture(this.boldFont.regular.texture.getGlTextureId()); + currentData = this.boldFont.regular; + } + } + break; + case 18: + strikethrough = true; + break; + case 19: + underline = true; + break; + case 20: + italic = true; + if (bold && hasBold()) { + GlStateManager.bindTexture(this.boldFont.italic.texture.getGlTextureId()); + currentData = this.boldFont.italic; + } else { + GlStateManager.bindTexture(this.italic.texture.getGlTextureId()); + currentData = this.italic; + } + break; + default: + bold = false; + italic = false; + underline = false; + strikethrough = false; + GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); + GlStateManager.bindTexture(this.regular.texture.getGlTextureId()); + currentData = this.regular; + break; + } + } + ++index; + } else if (character < currentData.chars.length) { + CharData charData = currentData.chars[character]; + drawQuad((float) x, (float) y, charData.width, charData.height, charData.storedX, charData.storedY, currentData.imageSize.getLeft(), currentData.imageSize.getRight()); + + if (strikethrough) { + this.drawLine(x, y + (double) (charData.height / 2), x + (double) charData.width - 8, y + (double) (charData.height / 2)); + } + if (underline) { + this.drawLine(x + 2.5f, y + (double) charData.height - 1, x + charData.width - 6, y + (double) charData.height - 1); + } + x += Math.round((currentData.chars[character].width - kerning + FontSettings.INSTANCE.getGapSize()) * 2) / 2.0; + } + } + return (float) (x / 2); + } + + protected void drawQuad(float x2, float y2, float width, float height, float srcX, float srcY, float imgWidth, float imgHeight) { + float renderSRCX = srcX / imgWidth; + float renderSRCY = srcY / imgHeight; + float renderSRCWidth = width / imgWidth; + float renderSRCHeight = height / imgHeight; + + buffer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_TEX); + buffer.pos(x2 + width, y2, 0).tex(renderSRCX + renderSRCWidth, renderSRCY).endVertex(); + buffer.pos(x2, y2, 0).tex(renderSRCX, renderSRCY).endVertex(); + buffer.pos(x2, y2 + height, 0).tex(renderSRCX, renderSRCY + renderSRCHeight).endVertex(); + buffer.pos(x2, y2 + height, 0).tex(renderSRCX, renderSRCY + renderSRCHeight).endVertex(); + buffer.pos(x2 + width, y2 + height, 0).tex(renderSRCX + renderSRCWidth, renderSRCY + renderSRCHeight).endVertex(); + buffer.pos(x2 + width, y2, 0).tex(renderSRCX + renderSRCWidth, renderSRCY).endVertex(); + + tessellator.draw(); + } + + private void drawLine(double x2, double y2, double x1, double y1) { + buffer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + buffer.pos(x2, y2, 0).endVertex(); + buffer.pos(x1, y1, 0).endVertex(); + tessellator.draw(); + } + + @Override + public float getStringWidth(String text) { + if (FontSettings.INSTANCE.isEnabled()) { + return (float) getStringWidth(text, kerning); + } else { + return Minecraft.getMinecraft().fontRenderer.getStringWidth(text); } } - protected void drawQuad(float x2, float y2, float width, float height, float srcX, float srcY, float srcWidth, float srcHeight) { - float renderSRCX = srcX / this.imgSize; - float renderSRCY = srcY / this.imgSize; - float renderSRCWidth = srcWidth / this.imgSize; - float renderSRCHeight = srcHeight / this.imgSize; - GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); - GL11.glVertex2d(x2 + width, y2); - GL11.glTexCoord2f(renderSRCX, renderSRCY); - GL11.glVertex2d(x2, y2); - GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); - GL11.glVertex2d(x2, y2 + height); - GL11.glTexCoord2f(renderSRCX, renderSRCY + renderSRCHeight); - GL11.glVertex2d(x2, y2 + height); - GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY + renderSRCHeight); - GL11.glVertex2d(x2 + width, y2 + height); - GL11.glTexCoord2f(renderSRCX + renderSRCWidth, renderSRCY); - GL11.glVertex2d(x2 + width, y2); - } - - public void setAntiAlias(boolean antiAlias) { - if (this.antiAlias != antiAlias) { - this.antiAlias = antiAlias; - this.tex = this.setupTexture(this.font, antiAlias, this.fractionalMetrics, this.charData); + public double getStringWidth(String text, float kerning) { + if (text == null) { + return 0; + } + float width = 0; + CharData[] currentData = regular.chars; + for (int index = 0; index < text.length(); index++) { + char character = text.charAt(index); + + if (character == '\u00a7') { + int colorIndex = colorcodeIdentifiers.indexOf(text.charAt(index + 1)); + switch (colorIndex) { + case 17: + if (hasBold()) { + currentData = this.boldFont.regular.chars; + } + break; + case 20: + currentData = this.regular.chars; + break; + default: + currentData = regular.chars; + break; + } + ++index; + } else if (character < currentData.length) { + width += currentData[character].width - kerning + FontSettings.INSTANCE.getGapSize(); + } } + + return width / 2; } - public boolean isFractionalMetrics() { - return this.fractionalMetrics; + @Override + public float getFontHeight() { + return (float) (this.fontHeight - 8) / 2; } - public void setFractionalMetrics(boolean fractionalMetrics) { - if (this.fractionalMetrics != fractionalMetrics) { - this.fractionalMetrics = fractionalMetrics; - this.tex = this.setupTexture(this.font, this.antiAlias, fractionalMetrics, this.charData); + void generateColorCodes() { + if (colorCode == null) { + colorCode = new int[32]; + for (int index = 0; index < 32; ++index) { + final int noClue = (index >> 3 & 0x1) * 85; + int red = (index >> 2 & 0x1) * 170 + noClue; + int green = (index >> 1 & 0x1) * 170 + noClue; + int blue = (index & 0x1) * 170 + noClue; + if (index == 6) { + red += 85; + } + if (index >= 16) { + red /= 4; + green /= 4; + blue /= 4; + } + colorCode[index] = (red & 255) << 16 | (green & 255) << 8 | blue & 255; + } } } - public void setFont(Font font) { - this.font = font; - this.tex = this.setupTexture(font, this.antiAlias, this.fractionalMetrics, this.charData); + private void handleSprites(FontData fontData, Font currentFont, Graphics2D graphics2D) { + handleSprites(fontData, currentFont, graphics2D, false); } - protected static class CharData { - public int width, height, - storedX, storedY; + private void handleSprites(FontData fontData, Font currentFont, Graphics2D graphics2D, boolean drawString) { + int charHeight = 0; + int positionX = 0; + int positionY = 1; + int index = 0; + FontMetrics fontMetrics = graphics2D.getFontMetrics(); + + if (drawString) { + BufferedImage image = new BufferedImage(fontData.imageSize.getLeft(), fontData.imageSize.getRight(), BufferedImage.TYPE_INT_ARGB); + Graphics2D graphics = (Graphics2D) image.getGraphics(); + + graphics.setFont(currentFont); + graphics.setColor(new Color(255, 255, 255, 0)); + graphics.fillRect(0, 0, fontData.imageSize.getLeft(), fontData.imageSize.getRight()); + graphics.setColor(Color.WHITE); + graphics.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON); + graphics.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON); + graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + + for (CharData data : fontData.chars) { + char c = (char) index; + graphics.drawString(String.valueOf(c), data.storedX + 2, data.storedY + fontMetrics.getAscent()); + index++; + } + + fontData.texture = new DynamicTexture(image); + } else { + while (index < fontData.chars.length) { + char c = (char) index; + CharData charData = new CharData(); + Rectangle2D dimensions = fontMetrics.getStringBounds(String.valueOf(c), graphics2D); + charData.width = dimensions.getBounds().width + kerning; + charData.height = dimensions.getBounds().height; + + if (positionX + charData.width >= fontData.imageSize.getLeft()) { + positionX = 0; + positionY += charHeight; + charHeight = 0; + } - protected CharData() { + if (charData.height > charHeight) { + charHeight = charData.height; + } + + charData.storedX = positionX; + charData.storedY = positionY; + + if (charData.height > this.fontHeight) { + this.fontHeight = charData.height; + } + + fontData.chars[index] = charData; + positionX += (int) charData.width; + fontData.imageSize.setRight(positionY + fontMetrics.getAscent()); + ++index; + } + handleSprites(fontData, currentFont, graphics2D, true); + } + } + + private static class FontData { + private final CharData[] chars = new CharData[256]; + private final int textType; + private DynamicTexture texture; + private final MutablePair imageSize = MutablePair.of(512, 0); + + public FontData(int textType) { + this.textType = textType; } } -} \ No newline at end of file + + private static class CharData { + private float width; + private int height, storedX, storedY; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/font/FontUtils.java b/src/main/java/xyz/templecheats/templeclient/features/gui/font/FontUtils.java index 4e8d4b41..3c3d7d30 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/font/FontUtils.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/font/FontUtils.java @@ -1,96 +1,68 @@ package xyz.templecheats.templeclient.features.gui.font; import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.GlStateManager; import net.minecraft.util.ResourceLocation; import java.awt.*; import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; public class FontUtils { - public static MinecraftFontRenderer normal; - public static MinecraftFontRenderer csgoNormal; - public static MinecraftFontRenderer csgoBoldNormal; + private static final HashMap> customFontMap = new HashMap<>(); - private static Font smoothFont; - private static Font boldFont; - private static Font csgoFont; - private static Font csgoBoldFont; + static { + setupFonts(); + } - static { - bootstrap(); - } + public static void setupFonts() { + for (Fonts font : Fonts.values()) { + font.reloadFonts(); + HashMap fontSizes = new HashMap<>(); + for (int size : font.sizes) { + fontSizes.put(size, new CFont(font.fromSize(size))); + } + customFontMap.put(font, fontSizes); + } + } - public static void bootstrap() { - smoothFont = loadFont("smooth.ttf", 23); - boldFont = loadFont("bold.ttf", 25); - csgoFont = loadFont("FSEX300.ttf", 20); - csgoBoldFont = loadFont("calibri-bold.ttf", 20); + public enum Fonts { + DEFAULT("smooth", 12, 14, 16, 18, 20, 22, 24, 26, 28, 32, 40, 80), + DEFAULT_BOLD("bold", 12, 14, 16, 18, 20, 22, 24, 26, 28, 32, 40, 80), + CSGO("FSEX300", 12, 14, 16, 18, 20, 22, 24, 26, 28, 32, 40, 80), + CSGO_BOLD("calibri-bold", 12, 14, 16, 18, 20, 22, 24, 26, 28, 32, 40, 80); - normal = new MinecraftFontRenderer(boldFont, true, true); - csgoNormal = new MinecraftFontRenderer(csgoFont, true, true); - csgoBoldNormal = new MinecraftFontRenderer(csgoBoldFont, true, true); - } + private final ResourceLocation location; + private Font font; + private final int[] sizes; - private static Font loadFont(String location, int size) { - Font font = null; - try(InputStream is = Minecraft.getMinecraft().getResourceManager().getResource(new ResourceLocation(location)).getInputStream()) { - font = Font.createFont(Font.TRUETYPE_FONT, is).deriveFont(Font.PLAIN, size); - } catch(Exception e) { - e.printStackTrace(); - font = new Font("default", Font.PLAIN, size); - } - return font; - } + Fonts(String fontName, int... sizes) { + this.location = new ResourceLocation("minecraft", "font/" + fontName + ".ttf"); + this.sizes = sizes; + } - public static void setSmoothFont() { - normal = new MinecraftFontRenderer(smoothFont, true, true); - } - public static void setBoldFont() { - normal = new MinecraftFontRenderer(boldFont, true, true); - } + public void reloadFonts() { + font = loadFont(location); + } - public static void drawString(String text, double x, double y, int color, boolean shadow) { - drawString(text, x, y, color, shadow, xyz.templecheats.templeclient.features.module.modules.client.Font.INSTANCE.isEnabled()); - } + public Font fromSize(int size) { + return font.deriveFont(Font.PLAIN, size); + } - public static void drawString(String text, double x, double y, int color, boolean shadow, boolean customFont) { - if(customFont) { - GlStateManager.pushMatrix(); - GlStateManager.translate(x, y, 0); - GlStateManager.scale(0.8, 0.8, 0); - if(shadow) { - FontUtils.normal.drawStringWithShadow(text, 0, 0, color); - } else { - FontUtils.normal.drawString(text, 0, 0, color); - } - GlStateManager.popMatrix(); - } else { - Minecraft.getMinecraft().fontRenderer.drawString(text, (float) x, (float) y, color, shadow); - } - } + public CFont setSize(int size) { + return customFontMap.get(this).computeIfAbsent(size, k -> null); + } + } - public static double getStringWidth(String text) { - return getStringWidth(text, xyz.templecheats.templeclient.features.module.modules.client.Font.INSTANCE.isEnabled()); - } + private static Font loadFont(ResourceLocation location) { + try { + InputStream inputStream = Minecraft.getMinecraft().getResourceManager().getResource(location).getInputStream(); + return Font.createFont(Font.TRUETYPE_FONT, inputStream); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Error loading font."); + return new Font("SansSerif", Font.PLAIN, 64); + } + } +} - public static double getStringWidth(String text, boolean customFont) { - if(customFont) { - return FontUtils.normal.getStringWidth(text) * 0.8; - } else { - return Minecraft.getMinecraft().fontRenderer.getStringWidth(text); - } - } - - public static double getFontHeight() { - return getFontHeight(xyz.templecheats.templeclient.features.module.modules.client.Font.INSTANCE.isEnabled()); - } - - public static double getFontHeight(boolean customFont) { - if(customFont) { - return FontUtils.normal.getHeight() * 0.8; - } else { - return 9; - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/font/MinecraftFontRenderer.java b/src/main/java/xyz/templecheats/templeclient/features/gui/font/MinecraftFontRenderer.java deleted file mode 100644 index cd6ee262..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/font/MinecraftFontRenderer.java +++ /dev/null @@ -1,695 +0,0 @@ -package xyz.templecheats.templeclient.features.gui.font; - -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.texture.DynamicTexture; -import org.lwjgl.opengl.GL11; - -import java.awt.*; -import java.util.ArrayList; -import java.util.List; - -public class MinecraftFontRenderer extends CFont { - CharData[] boldChars = new CharData[256], - italicChars = new CharData[256], - boldItalicChars = new CharData[256]; - int[] colorCode = new int[32]; - String colorcodeIdentifiers = "0123456789abcdefklmnor"; - DynamicTexture texBold, texItalic, texItalicBold; - - public MinecraftFontRenderer(Font font, boolean antiAlias, boolean fractionalMetrics) { - super(font, antiAlias, fractionalMetrics); - this.setupMinecraftColorcodes(); - this.setupBoldItalicIDs(); - } - - public int drawStringWithShadow(String text, double x2, float y2, int color) { - - float shadowWidth = this.drawString(text, x2 + 0.9f, (double) y2 + 0.5f, color, true, 8.3f); - - return (int) Math.max(shadowWidth, this.drawString(text, x2, y2, color, false, 8.3f)); - } - - public int drawString(String text, double x2, float y2, int color) { - return (int) this.drawString(text, x2, y2, color, false, 8.3f); - } - - public int drawPassword(String text, double x2, float y2, int color) { - return (int) this.drawString(text.replaceAll(".", "."), x2, y2, color, false, 8f); - } - - public int drawNoBSString(String text, double x2, float y2, int color) { - return (int) this.drawNoBSString(text, x2, y2, color, false); - } - - public int drawSmoothString(String text, double x2, float y2, int color) { - return (int) this.drawSmoothString(text, x2, y2, color, false); - } - - public double getPasswordWidth(String text) { - return this.getStringWidth(text.replaceAll(".", "."), 8); - } - - public float drawCenteredString(String text, float x2, float y2, int color) { - return this.drawString(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color); - } - - public float drawNoBSCenteredString(String text, float x2, float y2, int color) { - return this.drawNoBSString(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color); - } - - public float drawCenteredStringWithShadow(String text, float x2, float y2, int color) { - return this.drawStringWithShadow(text, x2 - (float) (this.getStringWidth(text) / 2), y2, color); - } - - public float drawString(String text, double x, double y, int color, boolean shadow, float kerning) { - x -= 1.0; - - if (text == null) { - return 0; - } - - if (color == 0x20FFFFFF) { - color = 0xFFFFFF; - } - - if ((color & 0xFC000000) == 0) { - color |= 0xFF000000; - } - - if (shadow) { - color = (color & 0xFCFCFC) >> 2 | color & 0xFF000000; - } - - CharData[] currentData = this.charData; - float alpha = (float) (color >> 24 & 255) / 255f; - boolean randomCase = false, - bold = false, - italic = false, - strikethrough = false, - underline = false, - render = true; - x *= 2; - y = (y - 3) * 2; - GL11.glPushMatrix(); - GlStateManager.scale(0.5, 0.5, 0.5); - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.enableTexture2D(); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId()); - - for (int index = 0; index < text.length(); index++) { - char character = text.charAt(index); - - if (character == '\u00a7') { - int colorIndex = 21; - - try { - colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1)); - } catch (Exception e) { - e.printStackTrace(); - } - - if (colorIndex < 16) { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - - if (colorIndex < 0) { - colorIndex = 15; - } - - if (shadow) { - colorIndex += 16; - } - - int colorcode = this.colorCode[colorIndex]; - GlStateManager.color((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha); - } else if (colorIndex == 16) { - randomCase = true; - } else if (colorIndex == 17) { - bold = true; - - if (italic) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texBold.getGlTextureId()); - currentData = this.boldChars; - } - } else if (colorIndex == 18) { - strikethrough = true; - } else if (colorIndex == 19) { - underline = true; - } else if (colorIndex == 20) { - italic = true; - - if (bold) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texItalic.getGlTextureId()); - currentData = this.italicChars; - } - } else { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - } - - ++index; - } else if (character < currentData.length) { - GL11.glBegin(GL11.GL_TRIANGLES); - this.drawChar(currentData, character, (float) x, (float) y); - GL11.glEnd(); - - if (strikethrough) { - this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1); - } - - if (underline) { - this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1); - } - - x += currentData[character].width - kerning + this.charOffset; - } - } - - GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE); - GL11.glPopMatrix(); - GL11.glColor4f(1, 1, 1, 1); - return (float) x / 2f; - } - - public float drawSmoothString(String text, double x, double y, int color, boolean shadow) { - x -= 1; - - if (text == null) { - return 0; - } - - CharData[] currentData = this.charData; - float alpha = (float) (color >> 24 & 255) / 255f; - boolean randomCase = false, - bold = false, - italic = false, - strikethrough = false, - underline = false, - render = true; - x *= 2; - y = (y - 3) * 2; - GL11.glPushMatrix(); - GlStateManager.scale(0.5, 0.5, 0.5); - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.enableTexture2D(); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId()); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR); - - for (int index = 0; index < text.length(); index++) { - char character = text.charAt(index); - - if (character == '\u00a7') { - int colorIndex = 21; - - try { - colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1)); - } catch (Exception e) { - e.printStackTrace(); - } - - if (colorIndex < 16) { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - - if (colorIndex < 0) { - colorIndex = 15; - } - - if (shadow) { - colorIndex += 16; - } - - int colorcode = this.colorCode[colorIndex]; - GlStateManager.color((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha); - } else if (colorIndex == 16) { - randomCase = true; - } else if (colorIndex == 17) { - bold = true; - - if (italic) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texBold.getGlTextureId()); - currentData = this.boldChars; - } - } else if (colorIndex == 18) { - strikethrough = true; - } else if (colorIndex == 19) { - underline = true; - } else if (colorIndex == 20) { - italic = true; - - if (bold) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texItalic.getGlTextureId()); - currentData = this.italicChars; - } - } else { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - } - - ++index; - } else if (character < currentData.length) { - GL11.glBegin(GL11.GL_TRIANGLES); - this.drawChar(currentData, character, (float) x, (float) y); - GL11.glEnd(); - - if (strikethrough) { - this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1); - } - - if (underline) { - this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1); - } - - x += currentData[character].width - 8.3f + this.charOffset; - } - } - - GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE); - GL11.glPopMatrix(); - GL11.glColor4f(1, 1, 1, 1); - return (float) x / 2f; - } - - public float drawNoBSString(String text, double x, double y, int color, boolean shadow) { - x -= 1; - - if (text == null) { - return 0; - } - - CharData[] currentData = this.charData; - float alpha = (float) (color >> 24 & 0xFF) / 255f; - boolean randomCase = false, - bold = false, - italic = false, - strikethrough = false, - underline = false, - render = true; - x *= 2; - y = (y - 3) * 2; - GL11.glPushMatrix(); - GlStateManager.scale(0.5, 0.5, 0.5); - GlStateManager.enableBlend(); - GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.enableTexture2D(); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - GL11.glBindTexture(GL11.GL_TEXTURE_2D, this.tex.getGlTextureId()); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST); - GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST); - - for (int index = 0; index < text.length(); index++) { - char character = text.charAt(index); - - if (character == '\u00a7') { - int colorIndex = 21; - - try { - colorIndex = "0123456789abcdefklmnor".indexOf(text.charAt(index + 1)); - } catch (Exception e) { - e.printStackTrace(); - } - - if (colorIndex < 16) { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - - if (colorIndex < 0) { - colorIndex = 15; - } - - if (shadow) { - colorIndex += 16; - } - - int colorcode = this.colorCode[colorIndex]; - GlStateManager.color((float) (colorcode >> 16 & 255) / 255f, (float) (colorcode >> 8 & 255) / 255f, (float) (colorcode & 255) / 255f, alpha); - } else if (colorIndex == 16) { - randomCase = true; - } else if (colorIndex == 17) { - bold = true; - - if (italic) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texBold.getGlTextureId()); - currentData = this.boldChars; - } - } else if (colorIndex == 18) { - strikethrough = true; - } else if (colorIndex == 19) { - underline = true; - } else if (colorIndex == 20) { - italic = true; - - if (bold) { - GlStateManager.bindTexture(this.texItalicBold.getGlTextureId()); - currentData = this.boldItalicChars; - } else { - GlStateManager.bindTexture(this.texItalic.getGlTextureId()); - currentData = this.italicChars; - } - } else { - bold = false; - italic = false; - randomCase = false; - underline = false; - strikethrough = false; - GlStateManager.color((float) (color >> 16 & 255) / 255f, (float) (color >> 8 & 255) / 255f, (float) (color & 255) / 255f, alpha); - GlStateManager.bindTexture(this.tex.getGlTextureId()); - currentData = this.charData; - } - - ++index; - } else if (character < currentData.length) { - GL11.glBegin(GL11.GL_TRIANGLES); - this.drawChar(currentData, character, (float) x, (float) y); - GL11.glEnd(); - - if (strikethrough) { - this.drawLine(x, y + (double) (currentData[character].height / 2), x + (double) currentData[character].width - 8, y + (double) (currentData[character].height / 2), 1); - } - - if (underline) { - this.drawLine(x, y + (double) currentData[character].height - 2, x + (double) currentData[character].width - 8, y + (double) currentData[character].height - 2, 1); - } - - x += currentData[character].width - 8.3f + this.charOffset; - } - } - - GL11.glHint(GL11.GL_POLYGON_SMOOTH_HINT, GL11.GL_DONT_CARE); - GL11.glPopMatrix(); - GL11.glColor4f(1, 1, 1, 1); - return (float) x / 2f; - } - - public double getStringWidth(String text) { - if (text == null) { - return 0; - } - - float width = 0; - CharData[] currentData = charData; - boolean bold = false, italic = false; - - for (int index = 0; index < text.length(); index++) { - char character = text.charAt(index); - - if (character == '\u00a7') { - int colorIndex = "0123456789abcdefklmnor".indexOf(character); - - bold = false; - italic = false; - - ++index; - } else if (character < currentData.length) { - width += currentData[character].width - 8.3f + charOffset; - } - } - - return width / 2; - } - - public double getStringWidth(String text, float kerning) { - if (text == null) { - return 0; - } - - float width = 0; - CharData[] currentData = charData; - boolean bold = false, italic = false; - - for (int index = 0; index < text.length(); index++) { - char c = text.charAt(index); - - if (c == '\u00a7') { - int colorIndex = "0123456789abcdefklmnor".indexOf(c); - - bold = false; - italic = false; - - ++index; - } else if (c < currentData.length) { - width += currentData[c].width - kerning + charOffset; - } - } - - return width / 2; - } - - public int getHeight() { - return (this.fontHeight - 8) / 2; - } - - @Override - public void setFont(Font font) { - super.setFont(font); - this.setupBoldItalicIDs(); - } - - @Override - public void setAntiAlias(boolean antiAlias) { - super.setAntiAlias(antiAlias); - this.setupBoldItalicIDs(); - } - - @Override - public void setFractionalMetrics(boolean fractionalMetrics) { - super.setFractionalMetrics(fractionalMetrics); - this.setupBoldItalicIDs(); - } - - private void setupBoldItalicIDs() { - this.texBold = this.setupTexture(this.font.deriveFont(Font.BOLD), this.antiAlias, this.fractionalMetrics, this.boldChars); - this.texItalic = this.setupTexture(this.font.deriveFont(Font.ITALIC), this.antiAlias, this.fractionalMetrics, this.italicChars); - this.texItalicBold = this.setupTexture(this.font.deriveFont(Font.BOLD | Font.ITALIC), this.antiAlias, this.fractionalMetrics, this.boldItalicChars); - } - - private void drawLine(double x2, double y2, double x1, double y1, float width) { - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glLineWidth(width); - GL11.glBegin(GL11.GL_LINES); - GL11.glVertex2d(x2, y2); - GL11.glVertex2d(x1, y1); - GL11.glEnd(); - GL11.glEnable(GL11.GL_TEXTURE_2D); - } - - public List wrapWords(String text, double width) { - ArrayList finalWords = new ArrayList<>(); - - if (getStringWidth(text) > width) { - String[] words = text.split(" "); - StringBuilder currentWord = new StringBuilder(); - char lastColorCode = 65535; - - for (String word : words) { - for (int innerIndex = 0; innerIndex < word.toCharArray().length; innerIndex++) { - char c = word.toCharArray()[innerIndex]; - - if (c == '\u00a7' && innerIndex < word.toCharArray().length - 1) { - lastColorCode = word.toCharArray()[innerIndex + 1]; - } - } - - if (getStringWidth(currentWord + word + " ") < width) { - currentWord.append(word).append(" "); - } else { - finalWords.add(currentWord.toString()); - currentWord = new StringBuilder("\u00a7" + lastColorCode + word + " "); - } - } - - if (currentWord.length() > 0) { - if (getStringWidth(currentWord.toString()) < width) { - finalWords.add("\u00a7" + lastColorCode + currentWord + " "); - currentWord = new StringBuilder(); - } else { - finalWords.addAll(formatString(currentWord.toString(), width)); - } - } - } else { - finalWords.add(text); - } - - return finalWords; - } - - public List formatString(String string, double width) { - ArrayList finalWords = new ArrayList<>(); - StringBuilder currentWord = new StringBuilder(); - char lastColorCode = 65535; - char[] chars = string.toCharArray(); - - for (int index = 0; index < chars.length; index++) { - char c = chars[index]; - - if (c == '\u00a7' && index < chars.length - 1) { - lastColorCode = chars[index + 1]; - } - - if (getStringWidth(currentWord.toString() + c) < width) { - currentWord.append(c); - } else { - finalWords.add(currentWord.toString()); - currentWord = new StringBuilder("\u00a7" + lastColorCode + c); - } - } - - if (currentWord.length() > 0) { - finalWords.add(currentWord.toString()); - } - - return finalWords; - } - - private void setupMinecraftColorcodes() { - int index = 0; - - while (index < 32) { - int noClue = (index >> 3 & 1) * 85; - int red = (index >> 2 & 1) * 170 + noClue; - int green = (index >> 1 & 1) * 170 + noClue; - int blue = (index & 1) * 170 + noClue; - - if (index == 6) { - red += 85; - } - - if (index >= 16) { - red /= 4; - green /= 4; - blue /= 4; - } - - this.colorCode[index] = (red & 255) << 16 | (green & 255) << 8 | blue & 255; - ++index; - } - } - - public String trimStringToWidth(String text, int width) { - return this.trimStringToWidth(text, width, false); - } - - public String trimStringToWidthPassword(String text, int width, boolean custom) { - text = text.replaceAll(".", "."); - return this.trimStringToWidth(text, width, custom); - } - - private float getCharWidthFloat(char c) { - if (c == 167) { - return -1; - } else if (c == 32) { - return 2; - } else { - int var2 = "\u00c0\u00c1\u00c2\u00c8\u00ca\u00cb\u00cd\u00d3\u00d4\u00d5\u00da\u00df\u00e3\u00f5\u011f\u0130\u0131\u0152\u0153\u015e\u015f\u0174\u0175\u017e\u0207\u0000\u0000\u0000\u0000\u0000\u0000\u0000 !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\u0000\u00c7\u00fc\u00e9\u00e2\u00e4\u00e0\u00e5\u00e7\u00ea\u00eb\u00e8\u00ef\u00ee\u00ec\u00c4\u00c5\u00c9\u00e6\u00c6\u00f4\u00f6\u00f2\u00fb\u00f9\u00ff\u00d6\u00dc\u00f8\u00a3\u00d8\u00d7\u0192\u00e1\u00ed\u00f3\u00fa\u00f1\u00d1\u00aa\u00ba\u00bf\u00ae\u00ac\u00bd\u00bc\u00a1\u00ab\u00bb\u2591\u2592\u2593\u2502\u2524\u2561\u2562\u2556\u2555\u2563\u2551\u2557\u255d\u255c\u255b\u2510\u2514\u2534\u252c\u251c\u2500\u253c\u255e\u255f\u255a\u2554\u2569\u2566\u2560\u2550\u256c\u2567\u2568\u2564\u2565\u2559\u2558\u2552\u2553\u256b\u256a\u2518\u250c\u2588\u2584\u258c\u2590\u2580\u03b1\u03b2\u0393\u03c0\u03a3\u03c3\u03bc\u03c4\u03a6\u0398\u03a9\u03b4\u221e\u2205\u2208\u2229\u2261\u00b1\u2265\u2264\u2320\u2321\u00f7\u2248\u00b0\u2219\u00b7\u221a\u207f\u00b2\u25a0\u0000" - .indexOf(c); - - if (c > 0 && var2 != -1) { - return ((charData[var2].width / 2.f) - 4.f); - } else if (((charData[c].width / 2.f) - 4.f) != 0) { - int var3 = ((int) ((charData[c].width / 2.f) - 4.f)) >>> 4; - int var4 = ((int) ((charData[c].width / 2.f) - 4.f)) & 15; - var3 &= 15; - ++var4; - return (float) ((var4 - var3) / 2 + 1); - } else { - return 0; - } - } - } - - public String trimStringToWidth(String text, int width, boolean custom) { - StringBuilder buffer = new StringBuilder(); - float lineWidth = 0.0F; - int offset = custom ? text.length() - 1 : 0; - int increment = custom ? -1 : 1; - boolean var8 = false; - boolean var9 = false; - - for (int index = offset; index >= 0 && index < text.length() && lineWidth < (float) width; index += increment) { - char character = text.charAt(index); - float charWidth = this.getCharWidthFloat(character); - - if (var8) { - var8 = false; - - if (character != 108 && character != 76) { - if (character == 114 || character == 82) { - var9 = false; - } - } else { - var9 = true; - } - } else if (charWidth < 0) { - var8 = true; - } else { - lineWidth += charWidth; - - if (var9) { - ++lineWidth; - } - } - - if (lineWidth > (float) width) { - break; - } - - if (custom) { - buffer.insert(0, character); - } else { - buffer.append(character); - } - } - - return buffer.toString(); - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/menu/CustomMainMenu.java b/src/main/java/xyz/templecheats/templeclient/features/gui/menu/CustomMainMenu.java index c05ba94f..2d87be9a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/menu/CustomMainMenu.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/menu/CustomMainMenu.java @@ -40,7 +40,7 @@ public void drawScreen(int mouseX, int mouseY, float partialTicks) { String username = session.getUsername(); drawString(this.fontRenderer, "Logged in as: " + username, 0, 0, new Color(0xFFFFFF).getRGB()); - drawString(this.fontRenderer, "Made by PhilipPanda", 0, 10, new Color(0xFFADD8E6).getRGB()); + drawString(this.fontRenderer, "Made by PhilipPanda", 0, 10, new Color(0xFFADD8E6).getRGB()); Minecraft.getMinecraft().getTextureManager().bindTexture(IMAGE_LOCATION); int imageWidth = 30; @@ -82,4 +82,4 @@ protected void actionPerformed(GuiButton button) throws IOException { } super.actionPerformed(button); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/gui/menu/alt/AltManager.java b/src/main/java/xyz/templecheats/templeclient/features/gui/menu/alt/AltManager.java index 528d5721..3e8c47a0 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/gui/menu/alt/AltManager.java +++ b/src/main/java/xyz/templecheats/templeclient/features/gui/menu/alt/AltManager.java @@ -7,114 +7,104 @@ import net.minecraft.client.gui.GuiButton; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.gui.GuiTextField; -import net.minecraft.util.ResourceLocation; import net.minecraft.util.Session; import org.lwjgl.input.Keyboard; -import org.lwjgl.opengl.GL11; import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.menu.CustomMainMenu; -import java.awt.*; import java.io.IOException; +import java.lang.reflect.Field; import java.net.Proxy; +import java.util.ArrayList; +import java.util.List; public class AltManager extends GuiScreen { - GuiTextField inputField; - private final int buttonWidth = 100; - private final int buttonHeight = 20; - private final int fieldWidth = 200; - private final ResourceLocation background = new ResourceLocation("textures/gui/background.jpg"); + private GuiTextField inputField; + private GuiButton addButton, deleteButton, loginButton; + private List alts = new ArrayList<>(); + private int selectedAltIndex = -1; @Override public void initGui() { - int centerY = this.height / 2; - int centerX = this.width / 2; - this.buttonList.clear(); - - inputField = new GuiTextField(1, fontRenderer, centerX - fieldWidth / 2, centerY, fieldWidth, 20); - inputField.setText("Username"); - - this.buttonList.add(new GuiButton(1, centerX - buttonWidth / 2, centerY + 32, buttonWidth, buttonHeight, "Login") { - @Override - public void drawButton(Minecraft mc, int mouseX, int mouseY, float partialTicks) { - super.drawButton(mc, mouseX, mouseY, partialTicks); - drawCenteredString(mc.fontRenderer, this.displayString, this.x + this.width / 2, this.y + (this.height - 8) / 2, Color.WHITE.getRGB()); - } - }); + int centerX = this.width / 2; + int centerY = this.height / 4; + this.inputField = new GuiTextField(10, this.fontRenderer, centerX - 100, 25, 200, 20); + this.addButton = new GuiButton(0, centerX - 100, 50, 98, 20, "Add Account"); + this.deleteButton = new GuiButton(1, centerX + 2, 50, 98, 20, "Delete Account"); + this.loginButton = new GuiButton(2, centerX - 49, 75, 98, 20, "Login"); + this.buttonList.add(this.addButton); + this.buttonList.add(this.deleteButton); + this.buttonList.add(this.loginButton); + this.deleteButton.enabled = false; + this.loginButton.enabled = false; + this.alts = TempleClient.configManager.loadAlts(); + Keyboard.enableRepeatEvents(true); } - public static void changeName(String name) { + @Override + protected void actionPerformed(GuiButton button) throws IOException { + if (button.id == 0 && !this.inputField.getText().isEmpty()) { + alts.add(this.inputField.getText()); + TempleClient.configManager.saveAlts(alts); + this.inputField.setText(""); + } else if (button.id == 1 && selectedAltIndex >= 0) { + alts.remove(selectedAltIndex); + TempleClient.configManager.saveAlts(alts); + selectedAltIndex = -1; + this.deleteButton.enabled = false; + this.loginButton.enabled = false; + } else if (button.id == 2 && selectedAltIndex >= 0) { + String username = alts.get(selectedAltIndex); + changeName(username); + } + } + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + super.keyTyped(typedChar, keyCode); + this.inputField.textboxKeyTyped(typedChar, keyCode); + } + private void changeName(String name) { YggdrasilAuthenticationService service = new YggdrasilAuthenticationService(Proxy.NO_PROXY, ""); - YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication)service.createUserAuthentication(Agent.MINECRAFT); + YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) service.createUserAuthentication(Agent.MINECRAFT); auth.logOut(); - Session session = new Session(name, name, "0", "legacy"); - try { - TempleClient.setSession(session); + Field sessionField = Minecraft.class.getDeclaredField("session"); + sessionField.setAccessible(true); + sessionField.set(Minecraft.getMinecraft(), session); } catch (Exception e) { e.printStackTrace(); } } @Override - protected void actionPerformed(GuiButton button) throws IOException { - if (button.id == 1) { - changeName(inputField.getText()); - } - } - - @Override - public void updateScreen() { - inputField.updateCursorCounter(); - } - - @Override - protected void keyTyped(char typedChar, int keyCode) throws IOException { - switch (keyCode) { - case Keyboard.KEY_ESCAPE: - mc.displayGuiScreen(new CustomMainMenu()); - break; - default: - inputField.textboxKeyTyped(typedChar, keyCode); + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.drawDefaultBackground(); + super.drawScreen(mouseX, mouseY, partialTicks); + this.inputField.drawTextBox(); + int startY = 100; + for (int i = 0; i < alts.size(); i++) { + int posY = startY + (i * 20); + if (i == selectedAltIndex) { + drawCenteredString(fontRenderer, alts.get(i) + " [Selected]", this.width / 2, posY, 0xFFFF00); + } else { + drawCenteredString(fontRenderer, alts.get(i), this.width / 2, posY, 0xFFFFFF); + } } } @Override protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { - inputField.mouseClicked(mouseX, mouseY, mouseButton); super.mouseClicked(mouseX, mouseY, mouseButton); - } - - @Override - public void drawScreen(int mouseX, int mouseY, float partialTicks) { - GL11.glColor4f(1, 1, 1, 1); - Minecraft.getMinecraft().getTextureManager().bindTexture(background); - drawScaledCustomSizeModalRect(0, 0, 0, 0, this.width, this.height, this.width, this.height, this.width, this.height); - - for (Object aButtonList : this.buttonList) { - ((GuiButton) aButtonList).drawButton(this.mc, mouseX, mouseY, partialTicks); + this.inputField.mouseClicked(mouseX, mouseY, mouseButton); + int startY = 100; + for (int i = 0; i < alts.size(); i++) { + int posY = startY + (i * 20); + if (mouseY >= posY - 10 && mouseY <= posY + 10 && mouseX >= this.width / 2 - 100 && mouseX <= this.width / 2 + 100) { + selectedAltIndex = i; + this.deleteButton.enabled = true; + this.loginButton.enabled = true; + } } - - inputField.drawTextBox(); - String usernameText = "Your Username: " + mc.getSession().getUsername(); - int textWidth = mc.fontRenderer.getStringWidth(usernameText); - mc.fontRenderer.drawStringWithShadow(usernameText, (this.width - textWidth) / 2.0f, this.height / 2.0f - 20, Color.yellow.getRGB()); - } - - private void drawGradientBackground() { - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glShadeModel(GL11.GL_SMOOTH); - GL11.glBegin(GL11.GL_QUADS); - GL11.glColor3f(0.4f, 0.4f, 0.4f); - GL11.glVertex2f(0, 0); - GL11.glVertex2f(this.width, 0); - GL11.glColor3f(0.2f, 0.2f, 0.2f); - GL11.glVertex2f(this.width, this.height); - GL11.glVertex2f(0, this.height); - GL11.glEnd(); - GL11.glShadeModel(GL11.GL_FLAT); - GL11.glEnable(GL11.GL_TEXTURE_2D); } -} \ No newline at end of file +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/Module.java b/src/main/java/xyz/templecheats/templeclient/features/module/Module.java index bbb8520b..6fbd02d6 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/Module.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/Module.java @@ -4,14 +4,27 @@ import net.minecraftforge.common.MinecraftForge; import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.features.module.modules.client.hud.Notifications; +import xyz.templecheats.templeclient.features.module.modules.client.hud.notification.NotificationType; +import xyz.templecheats.templeclient.features.module.modules.client.hud.notification.NotificationsRewrite; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; import xyz.templecheats.templeclient.util.setting.SettingHolder; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; + public class Module extends SettingHolder { + /* + * Variables + */ + public static final Minecraft mc = Minecraft.getMinecraft(); + public ArrayList submodules = new ArrayList<>(); private final String description; - public final Category category; - public boolean toggled; + public Category category; public int KeyCode; - public static final Minecraft mc = Minecraft.getMinecraft(); + public boolean enableByDefault; + public boolean toggled; + public boolean submodule = false; + public boolean parent = false; private boolean queueEnable; public Module(String name, String description, int keyCode, Category c) { @@ -21,6 +34,33 @@ public Module(String name, String description, int keyCode, Category c) { this.category = c; } + public Module(String name, String description, Category c, boolean parent) { + super(name); + this.description = description; + this.category = c; + this.parent = parent; + } + + public Module(String name, String description, int keyCode, Category c, boolean submodule) { + super(name); + this.description = description; + this.KeyCode = keyCode; + this.category = c; + this.submodule = submodule; + + for (Class clazz : modules()) { + try { + Module sub = clazz.getConstructor().newInstance(); + + sub.category = category; + submodules.add(sub); + } catch (InstantiationException | IllegalAccessException | InvocationTargetException | + NoSuchMethodException e) { + TempleClient.logger.error("Cant create new instance of submodule of " + name + " module!", e, e.getCause()); + } + } + } + public String getDescription() { return this.description; } @@ -33,13 +73,13 @@ public int getKey() { return KeyCode; } public final void onUpdateInternal() { - if(mc.player != null) { - if(this.queueEnable) { + if (mc.player != null) { + if (this.queueEnable) { this.queueEnable = false; this.onEnable(); } - if(this.isToggled()) { + if (this.isToggled()) { this.onUpdate(); } } @@ -54,7 +94,9 @@ public void onUpdateConstant() {} public void onRenderWorld(float partialTicks) {} public void onEnable() {} - public void onDisable() {} + public void onDisable() { + GradientShader.finish(); + } public String getHudInfo() { return ""; @@ -62,12 +104,15 @@ public String getHudInfo() { public void enable() { this.toggled = true; - MinecraftForge.EVENT_BUS.register(this); + if (this.isEnabled() && !this.enableByDefault) { + MinecraftForge.EVENT_BUS.register(this); + } TempleClient.eventBus.addEventListener(this); - if(mc.player != null) { + if (mc.player != null) { this.onEnable(); Notifications.showNotification(this.getName() + " has been enabled"); + NotificationsRewrite.addMessage(this.getName(), " has been enable", NotificationType.INFO); } else { this.queueEnable = true; } @@ -78,9 +123,10 @@ public void disable() { MinecraftForge.EVENT_BUS.unregister(this); TempleClient.eventBus.removeEventListener(this); - if(mc.player != null) { + if (mc.player != null) { this.onDisable(); Notifications.showNotification(this.getName() + " has been disabled"); + NotificationsRewrite.addMessage(this.getName(), " has been disabled", NotificationType.INFO); } } @@ -89,9 +135,9 @@ public void toggle() { } public void setToggled(boolean toggled) { - if(toggled == this.toggled) return; + if (toggled == this.toggled) return; - if(toggled) { + if (toggled) { this.enable(); } else { this.disable(); @@ -113,7 +159,7 @@ public Category getCategory() { public enum Category { Chat, Combat, - Miscelleaneous, + Misc, Movement, Player, Render, diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/ChatCrypt.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/ChatCrypt.java index 2208c672..9dac3965 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/ChatCrypt.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/ChatCrypt.java @@ -32,7 +32,7 @@ public class ChatCrypt extends Module { } } public ChatCrypt() { - super("ChatCrypt", "Encrypts your chat messages so only temple client users can see.", 0, Module.Category.Chat); + super("ChatCrypt", "Encrypt and Decrypt chat messages that users with Decrypt online can see", 0, Module.Category.Chat); } public static String encrypt(String value) { diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/FancyChat.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/FancyChat.java index c587f1e5..e1f0a095 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/FancyChat.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/FancyChat.java @@ -16,25 +16,30 @@ public class FancyChat extends Module { private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Uwu); public FancyChat() { - super("FancyChat", "Translates chat to different languages", 0, Category.Chat); + super("FancyChat", "Makes your text look gamer", 0, Category.Chat); registerSettings(mode); } @SubscribeEvent public void onChat(ClientChatEvent event) { + String message = event.getMessage(); + if (message.startsWith("/") || message.startsWith(".")) { + return; + } + switch (mode.value()) { case Uwu: - event.setMessage(translateToUwu(event.getMessage())); + event.setMessage(translateToUwu(message)); break; case MorseCode: - event.setMessage(translateToMorse(event.getMessage())); + event.setMessage(translateToMorse(message)); break; case Reverse: - event.setMessage(translateToReverse(event.getMessage())); + event.setMessage(translateToReverse(message)); break; case Byte: - event.setMessage(translateToByte(event.getMessage())); + event.setMessage(translateToByte(message)); break; } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/GreenText.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/GreenText.java index 29a6a5ae..a9f609db 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/GreenText.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/GreenText.java @@ -7,7 +7,7 @@ public class GreenText extends Module { public GreenText() { - super("GreenText", "Places > behind your message", 0, Category.Chat); + super("GreenText", "Puts '>' in front of your messages", 0, Category.Chat); } @SubscribeEvent diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/Spammer.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/Spammer.java index d5d250c2..2029501b 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/Spammer.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/chat/Spammer.java @@ -9,7 +9,7 @@ public class Spammer extends Module { private int timer = 0; public Spammer() { - super("Spammer", "Spams a message in chat", 0, Category.Chat); + super("Spammer", "Spams chat", 0, Category.Chat); this.registerSettings(delay); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/ClickGUI.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/ClickGUI.java index e5a5c872..7017ba9b 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/ClickGUI.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/ClickGUI.java @@ -4,13 +4,12 @@ import org.lwjgl.opengl.Display; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.util.color.RainbowUtil; -import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; -import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; -import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; +import xyz.templecheats.templeclient.util.setting.impl.*; import xyz.templecheats.templeclient.features.gui.clickgui.particles.Particle; import xyz.templecheats.templeclient.features.gui.clickgui.particles.Snow; +import java.awt.*; + public class ClickGUI extends Module { /** * Instance @@ -18,26 +17,20 @@ public class ClickGUI extends Module { public static ClickGUI INSTANCE; public final Particle.Util particleUtil = new Particle.Util(100); public final Snow snow = new Snow(0, 0, 1, 1); - private RainbowUtil rainbowUtil = new RainbowUtil(); + private final RainbowUtil rainbowUtil = new RainbowUtil(); /** * Settings */ - public final DoubleSetting scale = new DoubleSetting("Scale", this, 0.5, 2, 0.8); - public final IntSetting scrollSpeed = new IntSetting("Scroll Speed", this, 0, 100, 10); - private final BooleanSetting rainbow = new BooleanSetting("Rainbow", this, false); - public final BooleanSetting particles = new BooleanSetting("Particles", this, false); - public final BooleanSetting scaledResolution = new BooleanSetting("Scaled Resolution", this, false); - public final EnumSetting theme = new EnumSetting<>("Theme", this, Theme.Default); public final BooleanSetting gears = new BooleanSetting("Gears", this, true); - private final IntSetting startRed = new IntSetting("Start Red", this, 255, 0, 0); - private final IntSetting startGreen = new IntSetting("Start Green", this, 0, 255, 123); - private final IntSetting startBlue = new IntSetting("Start Blue", this, 0, 255, 230); - private final IntSetting startAlpha = new IntSetting("Start Alpha", this, 0, 255, 255); - private final IntSetting endRed = new IntSetting("End Red", this, 0, 255, 74); - private final IntSetting endGreen = new IntSetting("End Green", this, 0, 255, 216); - private final IntSetting endBlue = new IntSetting("End Blue", this, 0, 255, 230); - private final IntSetting endAlpha = new IntSetting("End Alpha", this, 0, 255, 255); + public final BooleanSetting particles = new BooleanSetting("Particles", this, false); + private final BooleanSetting rainbow = new BooleanSetting("Rainbow", this, false); + private final BooleanSetting scaledResolution = new BooleanSetting("Scaled Resolution", this, false); + private final ColorSetting startColor = new ColorSetting("Start Color", this, Color.CYAN); + private final ColorSetting endColor = new ColorSetting("End Color", this, Color.CYAN); + public final IntSetting scrollSpeed = new IntSetting("Scroll Speed", this, 0, 100, 10); + public final DoubleSetting scale = new DoubleSetting("Scale", this, 0.5, 2, 0.8); + public final EnumSetting < Theme > theme = new EnumSetting < > ("Theme", this, Theme.Default); /** * Variables @@ -45,16 +38,18 @@ public class ClickGUI extends Module { private int rainbowColor; public ClickGUI() { - super("ClickGUI", "Customize your ClickGUI", Keyboard.KEY_RSHIFT, Category.Client); + super("ClickGUI", "Screen to configure modules", Keyboard.KEY_RSHIFT, Category.Client); INSTANCE = this; - this.registerSettings(rainbow, particles, gears, scaledResolution, scrollSpeed, scale, startRed, endRed, startGreen, endGreen, startBlue, endBlue, startAlpha, endAlpha, theme); + this.registerSettings(gears, particles, rainbow, scaledResolution, + endColor, startColor, scrollSpeed, + scale, + theme); } - @Override public void onUpdateConstant() { - if(this.rainbow.booleanValue()) { + if (this.rainbow.booleanValue()) { rainbowUtil.updateRainbow(); rainbowColor = rainbowUtil.getRainbowColor(); } @@ -65,20 +60,24 @@ public void onUpdateConstant() { } } - public int getStartColor() { - if(this.rainbow.booleanValue()) { - return startAlpha.intValue() << 24 | (rainbowColor >> 16 & 0xFF) << 16 | (rainbowColor >> 8 & 0xFF) << 8 | (rainbowColor & 0xFF); + public int getClientColor(int offset) { + return rainbowUtil.rainbowProgress(5, offset * 200, getStartColor().getRGB(), getEndColor().getRGB()); + } + + public Color getStartColor() { + if (this.rainbow.booleanValue()) { + return new Color(rainbowColor); } - return startAlpha.intValue() << 24 | startRed.intValue() << 16 | startGreen.intValue() << 8 | startBlue.intValue(); + return startColor.getColor(); } - public int getEndColor() { - if(this.rainbow.booleanValue()) { - return endAlpha.intValue() << 24 | (rainbowColor >> 16 & 0xFF) << 16 | (rainbowColor >> 8 & 0xFF) << 8 | (rainbowColor & 0xFF); + public Color getEndColor() { + if (this.rainbow.booleanValue()) { + return new Color(rainbowColor); } - return endAlpha.intValue() << 24 | endRed.intValue() << 16 | endGreen.intValue() << 8 | endBlue.intValue(); + return endColor.getColor(); } public enum Theme { diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Colors.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Colors.java new file mode 100644 index 00000000..35a756bd --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Colors.java @@ -0,0 +1,85 @@ +package xyz.templecheats.templeclient.features.module.modules.client; + +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.combat.AutoCrystal; +import xyz.templecheats.templeclient.features.module.modules.render.esp.sub.Block; +import xyz.templecheats.templeclient.features.module.modules.render.PopChams; +import xyz.templecheats.templeclient.features.module.modules.render.esp.sub.Shader; +import xyz.templecheats.templeclient.util.color.RainbowUtil; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.ColorSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import java.awt.*; + +public class Colors extends Module { + public static Colors INSTANCE; + private final RainbowUtil rainbowUtil = new RainbowUtil(); + + public Colors() { + super("Colors", "Configure various color settings", Keyboard.KEY_NONE, Category.Client); + INSTANCE = this; + setToggled(true); + this.registerSettings(step, speed, staticColor, friendColor, gradientColor1, gradientColor2, fogColor, lightMapColor); + } + /* + * Settings + */ + public final DoubleSetting step = new DoubleSetting("Step", this, 0.1, 5, 0.5); + public final DoubleSetting speed = new DoubleSetting("Speed", this, 0, 5, 1); + public final ColorSetting staticColor = new ColorSetting("Static", this, Color.CYAN); + public final ColorSetting friendColor = new ColorSetting("Friend", this, Color.GREEN); + public final ColorSetting gradientColor1 = new ColorSetting("Gradient 1", this, Color.BLUE); + public final ColorSetting gradientColor2 = new ColorSetting("Gradient 2", this, Color.CYAN); + public final ColorSetting fogColor = new ColorSetting("Fog", this, Color.RED); + public final ColorSetting lightMapColor = new ColorSetting("LightMap", this, Color.RED); + public final EnumSetting theme = new EnumSetting<>("Mode", this, Mode.Gradient); + + public Color getColor() { + return this.staticColor.getColor(); + } + + public Color getColorAlpha() { + Color color = this.staticColor.getColor(); + return new Color(color.getRed(), color.getGreen(), color.getBlue(), 200); + } + + public Color getColor(double offset) { + return new Color(rainbowUtil.rainbowProgress(5, (int) (offset * 200), getGradient()[0].getRGB(), getGradient()[1].getRGB())); + } + + public Color[] getGradient() { + return new Color[]{ + this.gradientColor1.getColor(), + this.gradientColor2.getColor(), + }; + } + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + doBindBlank(); + } + public void doBindBlank() { //fix items turning white + if (!(Block.rendering && Shader.rendering && PopChams.rendering && AutoCrystal.rendering)) { + RenderUtil.bindBlank(); + } + } + + public Color getFogColor() { + return this.fogColor.getColor(); + } + + public Color getLightMapColor() { + return this.lightMapColor.getColor(); + } + public Color getFriendColor() { + return this.friendColor.getColor(); + } + public enum Mode{ + Gradient, + Normal + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Font.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Font.java deleted file mode 100644 index a0a72a97..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Font.java +++ /dev/null @@ -1,55 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.client; - -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; - -public class Font extends Module { - /** - * Instance - */ - public static Font INSTANCE; - - /** - * Settings - */ - private final EnumSetting mode = new EnumSetting<>("Font", this, FontValue.Smooth); - - /** - * Variables - */ - private FontValue lastMode = null; - - public Font() { - super("Font", "Changes the ClickGUI font", Keyboard.KEY_NONE, Category.Client); - INSTANCE = this; - - this.registerSettings(mode); - } - - @Override - public void onEnable() { - //FontUtils.setCustomFont(); - } - - @Override - public void onUpdateConstant() { - if (mode.value() != lastMode) { - switch (mode.value()) { - case Smooth: - FontUtils.setSmoothFont(); - break; - case Bold: - FontUtils.setBoldFont(); - break; - } - lastMode = mode.value(); - } - } - - private enum FontValue { - Smooth, - Bold, - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/FontSettings.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/FontSettings.java new file mode 100644 index 00000000..0070dd8a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/FontSettings.java @@ -0,0 +1,81 @@ +package xyz.templecheats.templeclient.features.module.modules.client; + +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.*; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class FontSettings extends Module { + /** + * Instance + */ + public static FontSettings INSTANCE; + + /** + * Settings + */ + private final EnumSetting mode = new EnumSetting < > ("Font", this, FontUtils.Fonts.DEFAULT); + public final DoubleSetting shadowShift = new DoubleSetting("Shadow Shift", this, 1.0, 10.0, 4.5); + private final DoubleSetting gapSize = new DoubleSetting("Gap", this, -10.0, 10.0, 1.65); + private final DoubleSetting lineOffset = new DoubleSetting("Vertical Offset", this, -10.0, 10.0, 3.59); + private final DoubleSetting lodBiasSetting = new DoubleSetting("Smoothing", this , -10.0, 10.0, -1.0); + /* + * Variables + */ + private boolean reloadFont = false; + public FontSettings() { + super("Font", "Change TempleClient's font settings", Keyboard.KEY_NONE, Category.Client); + INSTANCE = this; + + this.registerSettings(gapSize, lineOffset, mode); + } + + public FontUtils.Fonts getFont() { + return mode.value(); + } + + public float getOffset() { + return this.isEnabled() ? lineOffset.floatValue() * 1.3f - 4.5f : 0; + } + + public float getGapSize() { + return this.isEnabled() ? gapSize.floatValue() * 0.5f - 0.8f : 0; + } + + public static float getSize() { + return 0.12f; + } + + public float getGap() { + return gapSize.floatValue() * 0.5f - 0.8f; + } + + public float getLineSpace() { + return (float) (getSize() * (0.8 * 0.05f + 0.77f)); + } + + public float getLodBias() { + return lodBiasSetting.floatValue() * 0.25f - 0.5f; + } + + public float getBaselineOffset() { + return lineOffset.floatValue() * 2.0f - 4.5f; + } + + @Override + public void onEnable() { + reloadFont = true; + } + + @Override + public void onUpdate() { + if (reloadFont) { + FontUtils.setupFonts(); + reloadFont = false; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/HUD.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/HUD.java index 58f478d2..31c39c18 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/HUD.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/HUD.java @@ -8,8 +8,10 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.gui.clickgui.hud.HudEditorScreen; +import xyz.templecheats.templeclient.features.gui.font.CFont; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.features.module.modules.client.hud.*; +import xyz.templecheats.templeclient.features.module.modules.client.hud.notification.NotificationsRewrite; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.SettingHolder; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; @@ -33,22 +35,24 @@ public class HUD extends Module { /** * Variables */ - private final List hudElements = new ArrayList<>(); + private final List < HudElement > hudElements = new ArrayList < > (); public HUD() { - super("HUD", "Shows HUD Variants in your HUD", Keyboard.KEY_GRAVE, Category.Client); + super("HUD", "In-Game Heads up Display", Keyboard.KEY_GRAVE, Category.Client); INSTANCE = this; - this.registerSettings(hudScale, clamping); + this.registerSettings(clamping, hudScale); this.setToggled(true); this.hudElements.add(new Armor()); this.hudElements.add(new Coords()); + this.hudElements.add(new Durability()); this.hudElements.add(new FPS()); this.hudElements.add(new Friends()); this.hudElements.add(new Inventory()); this.hudElements.add(new ModuleList()); + this.hudElements.add(new NotificationsRewrite()); this.hudElements.add(new Notifications()); this.hudElements.add(new Ping()); this.hudElements.add(new PlayerView()); @@ -62,27 +66,28 @@ public HUD() { @SubscribeEvent public void onRender(RenderGameOverlayEvent.Post event) { - if(event.getType() != RenderGameOverlayEvent.ElementType.TEXT || Panic.isPanic) { + if (event.getType() != RenderGameOverlayEvent.ElementType.TEXT || Panic.isPanic) { return; } GlStateManager.pushMatrix(); GlStateManager.scale(this.hudScale.doubleValue(), this.hudScale.doubleValue(), 0); this.hudElements.forEach(element -> { - if(!element.isEnabled()) { + if (!element.isEnabled()) { return; } - if(mc.currentScreen instanceof HudEditorScreen && element.getWidth() > -1 && element.getHeight() > -1) { - RenderUtil.drawRect((float) element.getX(), (float) element.getY(), (float) (element.getX() + element.getWidth()), (float) (element.getY() + element.getHeight()), element.isDragging() ? 0x802D2D2D : 0x80000000); + if (mc.currentScreen instanceof HudEditorScreen && element.getWidth() > -1 && element.getHeight() > -1) { + RenderUtil.drawRect((float) element.getX(), (float) element.getY(), (float)(element.getX() + element.getWidth()), (float)(element.getY() + element.getHeight()), element.isDragging() ? 0x802D2D2D : 0x80000000); } final ScaledResolution sr = new ScaledResolution(mc); final double screenWidth = sr.getScaledWidth() / this.hudScale.doubleValue(); final double screenHeight = sr.getScaledHeight() / this.hudScale.doubleValue(); - if(this.clamping.booleanValue()) { - element.setX(MathHelper.clamp(element.getX(), 0, screenWidth - element.getWidth())); + if (this.clamping.booleanValue()) { + // TODO load this shit from coordinates config + element.setX(MathHelper.clamp(element.getX(), 0, screenWidth - element.getWidth())); // person coding this is retarded af element.setY(MathHelper.clamp(element.getY(), 0, screenHeight - element.getHeight())); } @@ -93,13 +98,14 @@ public void onRender(RenderGameOverlayEvent.Post event) { GlStateManager.popMatrix(); } - public List getHudElements() { + public List < HudElement > getHudElements() { return this.hudElements; } public static abstract class HudElement extends SettingHolder { protected static final Minecraft mc = Minecraft.getMinecraft(); private final String description; + public final CFont font = FontSettings.INSTANCE.getFont().setSize(18); private double x = 100, y = 100, width = -1, height = -1; private boolean enabled, dragging, leftOfCenter, topOfCenter; @@ -108,7 +114,7 @@ public HudElement(String name, String description) { this.description = description; } - protected abstract void renderElement(ScaledResolution sr); + public abstract void renderElement(ScaledResolution sr); public String getDescription() { return this.description; @@ -135,7 +141,7 @@ public double getWidth() { } public void setWidth(double width) { - if(!this.leftOfCenter && width != this.width && width >= 0 && this.width >= 0) { + if (!this.leftOfCenter && width != this.width && width >= 0 && this.width >= 0) { final double screenWidth = new ScaledResolution(mc).getScaledWidth() / ClickGUI.INSTANCE.scale.doubleValue(); final double newWidth = Math.max(width, 0); @@ -152,7 +158,7 @@ public double getHeight() { } public void setHeight(double height) { - if(!this.topOfCenter && height != this.height && height >= 0 && this.height >= 0) { + if (!this.topOfCenter && height != this.height && height >= 0 && this.height >= 0) { final double screenHeight = new ScaledResolution(mc).getScaledHeight() / ClickGUI.INSTANCE.scale.doubleValue(); final double newHeight = Math.max(height, 0); diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/MiddleClick.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/MiddleClick.java index 30e83ba2..5ae8fdc8 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/MiddleClick.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/MiddleClick.java @@ -11,11 +11,13 @@ import xyz.templecheats.templeclient.util.friend.Friend; public class MiddleClick extends Module { - + /* + * Variables + */ private boolean isButtonPressed = false; public MiddleClick() { - super("MiddleClick", "Adds a player to your friend list when you middle click them", Keyboard.KEY_NONE, Category.Client); + super("MiddleClick", "Actions for middle clicking", Keyboard.KEY_NONE, Category.Client); } @Override diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Panic.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Panic.java index 41bb3e4f..30c4d369 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Panic.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/Panic.java @@ -7,29 +7,32 @@ import xyz.templecheats.templeclient.manager.ModuleManager; public class Panic extends Module { + /* + * Variables + */ public static boolean isPanic = false; - + public Panic() { - super("Panic", "Disables everything so you wont get caught ;)", Keyboard.KEY_NONE, Category.Client); + super("Panic", "Turn off all modules", Keyboard.KEY_NONE, Category.Client); } - + @Override public void onEnable() { isPanic = true; - + Display.setTitle("Minecraft 1.12.2"); - - for(Module m : ModuleManager.getModules()) { - if(m != this) { + + for (Module m: ModuleManager.getModules()) { + if (m != this) { m.setToggled(false); } } } - + @Override public void onDisable() { isPanic = false; - + Display.setTitle("TempleClient 1.12.2 | User: " + Minecraft.getMinecraft().getSession().getUsername()); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Armor.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Armor.java index 1a6d2e88..99a9e5b1 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Armor.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Armor.java @@ -9,7 +9,10 @@ import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; public class Armor extends HUD.HudElement { - private final EnumSetting displayMode = new EnumSetting<>("Display", this, DisplayMode.Horizontal); + /* + * Settings + */ + private final EnumSetting < DisplayMode > displayMode = new EnumSetting < > ("Display", this, DisplayMode.Horizontal); public Armor() { super("Armor", "Shows your Armor in the HUD"); @@ -18,7 +21,7 @@ public Armor() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { if (displayMode.value() == DisplayMode.Vertical) { this.setWidth(16); this.setHeight(84); @@ -33,13 +36,13 @@ protected void renderElement(ScaledResolution sr) { int startX = (int) this.getX(); int startY = (int) this.getY(); - for(ItemStack stack : Lists.reverse(mc.player.inventory.armorInventory)) { - if(!stack.isEmpty()) { + for (ItemStack stack: Lists.reverse(mc.player.inventory.armorInventory)) { + if (!stack.isEmpty()) { mc.getRenderItem().renderItemAndEffectIntoGUI(stack, startX, startY); mc.getRenderItem().renderItemOverlays(mc.fontRenderer, stack, startX, startY); } - if(displayMode.value() == DisplayMode.Vertical) { + if (displayMode.value() == DisplayMode.Vertical) { startY += 21; } else { startX += 21; @@ -47,10 +50,11 @@ protected void renderElement(ScaledResolution sr) { } RenderHelper.disableStandardItemLighting(); + GlStateManager.popMatrix(); } private enum DisplayMode { Vertical, Horizontal } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Coords.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Coords.java index 5e2daabe..3dd2548a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Coords.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Coords.java @@ -2,12 +2,14 @@ import net.minecraft.client.gui.ScaledResolution; import net.minecraft.util.text.TextFormatting; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; public class Coords extends HUD.HudElement { + /* + * Settings + */ private final BooleanSetting dimensionCoords = new BooleanSetting("Dimension Coords", this, false); public Coords() { @@ -16,7 +18,7 @@ public Coords() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { float[] playerPos = { Math.round(mc.player.posX * 100D) / 100F, Math.round(mc.player.posY * 100D) / 100F, @@ -25,12 +27,12 @@ protected void renderElement(ScaledResolution sr) { String coordsString = TextFormatting.GRAY + "XYZ: " + TextFormatting.RESET + playerPos[0] + ", " + playerPos[1] + ", " + playerPos[2]; - FontUtils.drawString(coordsString, this.getX(), this.getY() + FontUtils.getFontHeight() + 2, ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(coordsString, this.getX(), this.getY() + font.getFontHeight() + 2, ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); - double width = FontUtils.getStringWidth(coordsString); + double width = font.getStringWidth(coordsString); - if(dimensionCoords.booleanValue()) { - if(mc.player.dimension == 0) { + if (dimensionCoords.booleanValue()) { + if (mc.player.dimension == 0) { float[] netherPos = { Math.round(mc.player.posX * 12.5D) / 100F, playerPos[1], @@ -39,10 +41,10 @@ protected void renderElement(ScaledResolution sr) { String netherCoordsString = TextFormatting.GRAY + "Nether: " + TextFormatting.RESET + netherPos[0] + ", " + netherPos[1] + ", " + netherPos[2]; - width = Math.max(width, FontUtils.getStringWidth(netherCoordsString)); + width = Math.max(width, font.getStringWidth(netherCoordsString)); - FontUtils.drawString(netherCoordsString, this.getX(), this.getY(), 0xFFFFFF, true); - } else if(mc.player.dimension == -1) { + font.drawString(netherCoordsString, this.getX(), this.getY(), 0xFFFFFF, true, 1.0f); + } else if (mc.player.dimension == -1) { float[] overworldPos = { playerPos[0] * 8, playerPos[1], @@ -51,13 +53,13 @@ protected void renderElement(ScaledResolution sr) { String overworldCoordsString = TextFormatting.GRAY + "Overworld: " + TextFormatting.RESET + overworldPos[0] + ", " + overworldPos[1] + ", " + overworldPos[2]; - width = Math.max(width, FontUtils.getStringWidth(overworldCoordsString)); + width = Math.max(width, font.getStringWidth(overworldCoordsString)); - FontUtils.drawString(overworldCoordsString, this.getX(), this.getY(), 0xFFFFFF, true); + font.drawString(overworldCoordsString, this.getX(), this.getY(), 0xFFFFFF, true, 1.0f); } } this.setWidth(width); - this.setHeight((FontUtils.getFontHeight() * 2) + 2); + this.setHeight((font.getFontHeight() * 2) + 2); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Durability.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Durability.java new file mode 100644 index 00000000..b36e09e2 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Durability.java @@ -0,0 +1,30 @@ +package xyz.templecheats.templeclient.features.module.modules.client.hud; + +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; +import xyz.templecheats.templeclient.features.module.modules.client.HUD; + +public class Durability extends HUD.HudElement { + public Durability() { + super("Durability", "Shows the durability of the item you're holding in the HUD"); + } + + @Override + public void renderElement(ScaledResolution sr) { + ItemStack heldItem = mc.player.getHeldItemMainhand(); + if (!heldItem.isEmpty() && heldItem.isItemStackDamageable()) { + String itemName = heldItem.getDisplayName(); + int durability = heldItem.getMaxDamage() - heldItem.getItemDamage(); + + String durabilityText = itemName + durability; + + this.setWidth(font.getStringWidth(durabilityText)); + this.setHeight(font.getFontHeight()); + + font.drawString(itemName, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + font.drawString(String.valueOf(durability), this.getX() + font.getStringWidth(itemName + " "), this.getY(), 0xFFFFFF, true, 1.0f); + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/FPS.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/FPS.java index 616eef47..b62fb6bb 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/FPS.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/FPS.java @@ -2,7 +2,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -10,16 +9,16 @@ public class FPS extends HUD.HudElement { public FPS() { super("FPS", "Shows FPS in the HUD"); } - + @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { final String fpsText = "FPS "; final int fpsValue = Minecraft.getDebugFPS(); - - this.setWidth(FontUtils.getStringWidth(fpsText + fpsValue)); - this.setHeight(FontUtils.getFontHeight()); - - FontUtils.drawString(fpsText, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); - FontUtils.drawString(String.valueOf(fpsValue), this.getX() + FontUtils.getStringWidth(fpsText), this.getY(), 0xFFFFFF, true); + + this.setWidth(font.getStringWidth(fpsText + fpsValue)); + this.setHeight(font.getFontHeight()); + + font.drawString(fpsText, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + font.drawString(String.valueOf(fpsValue), this.getX() + font.getStringWidth(fpsText), this.getY(), 0xFFFFFF, true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Friends.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Friends.java index fb6b8920..49dccb6e 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Friends.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Friends.java @@ -2,7 +2,6 @@ import net.minecraft.client.gui.ScaledResolution; import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; import xyz.templecheats.templeclient.util.friend.Friend; @@ -11,6 +10,9 @@ import java.util.List; public class Friends extends HUD.HudElement { + /* + * Settings + */ private final BooleanSetting leftOfCenter = new BooleanSetting("LeftOfCenter", this, true); public Friends() { @@ -18,34 +20,34 @@ public Friends() { } @Override - protected void renderElement(ScaledResolution sr) { - List friends = TempleClient.friendManager.getFriends(); + public void renderElement(ScaledResolution sr) { + List < Friend > friends = TempleClient.friendManager.getFriends(); friends.sort((Friend friend1, Friend friend2) -> { String name1 = friend1.getName(); String name2 = friend2.getName(); - return Double.compare(FontUtils.getStringWidth(this.isTopOfCenter() ? name2 : name1), FontUtils.getStringWidth(this.isTopOfCenter() ? name1 : name2)); + return Double.compare(font.getStringWidth(this.isTopOfCenter() ? name2 : name1), font.getStringWidth(this.isTopOfCenter() ? name1 : name2)); }); double y = 0; double maxWidth = 0; double totalHeight = 0; - for (Friend friend : friends) { + for (Friend friend: friends) { String name = friend.getName(); - double width = FontUtils.getStringWidth(name) + 10; - double height = FontUtils.getFontHeight() + 2; + double width = font.getStringWidth(name) + 10; + double height = font.getFontHeight() + 2; maxWidth = Math.max(maxWidth, width); totalHeight += height; - FontUtils.drawString(name, this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - FontUtils.getStringWidth(name) : 0), this.getY() + y, ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(name, this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - font.getStringWidth(name) : 0), this.getY() + y, ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); y += height; } - this.setWidth(!friends.isEmpty() ? FontUtils.getStringWidth(this.isTopOfCenter() ? friends.get(0).getName() : friends.get(friends.size() - 1).getName()) : 0); + this.setWidth(!friends.isEmpty() ? font.getStringWidth(this.isTopOfCenter() ? friends.get(0).getName() : friends.get(friends.size() - 1).getName()) : 0); this.setHeight(totalHeight); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Inventory.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Inventory.java index 63dc51d9..2153bcd7 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Inventory.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Inventory.java @@ -12,7 +12,7 @@ public Inventory() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { this.setWidth(162); this.setHeight(54); @@ -22,9 +22,9 @@ protected void renderElement(ScaledResolution sr) { int startX = (int) this.getX(); int startY = (int) this.getY(); - for(int i = 9; i < 36; i++) { + for (int i = 9; i < 36; i++) { final ItemStack itemStack = mc.player.inventory.mainInventory.get(i); - if(!itemStack.isEmpty()) { + if (!itemStack.isEmpty()) { final int x = startX + (i % 9) * 18; final int y = startY + ((i - 9) / 9) * 18; @@ -34,5 +34,6 @@ protected void renderElement(ScaledResolution sr) { } RenderHelper.disableStandardItemLighting(); + GlStateManager.popMatrix(); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/ModuleList.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/ModuleList.java index 6ddf7feb..f3d9aad3 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/ModuleList.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/ModuleList.java @@ -2,7 +2,6 @@ import com.mojang.realmsclient.gui.ChatFormatting; import net.minecraft.client.gui.ScaledResolution; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -16,45 +15,45 @@ public class ModuleList extends HUD.HudElement { * Settings */ private final BooleanSetting metadata = new BooleanSetting("Metadata", this, true); - + public ModuleList() { super("ModuleList", "Shows active module in the HUD"); this.registerSettings(metadata); - + this.setEnabled(true); this.setX(2); - this.setY(FontUtils.getFontHeight() + 4); + this.setY(font.getFontHeight() + 4); } - + @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { final ArrayList mods = ModuleManager.getActiveModules(); - - mods.removeIf(mod -> mod.getCategory() == Module.Category.Client); - + + mods.removeIf(mod -> mod.getCategory() == Module.Category.Client || mod.submodule); + mods.sort((Module mod1, Module mod2) -> { final String text1 = this.getModText(mod1); final String text2 = this.getModText(mod2); - return Double.compare(FontUtils.getStringWidth(this.isTopOfCenter() ? text2 : text1), FontUtils.getStringWidth(this.isTopOfCenter() ? text1 : text2)); + return Double.compare(font.getStringWidth(this.isTopOfCenter() ? text2 : text1), font.getStringWidth(this.isTopOfCenter() ? text1 : text2)); }); - + double y = 0; - for(Module mod : mods) { + for (Module mod: mods) { final String text = this.getModText(mod); - FontUtils.drawString(text, this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - FontUtils.getStringWidth(text) : 0), this.getY() + y, ClickGUI.INSTANCE.getStartColor(), true); - - y += FontUtils.getFontHeight() + 2D; + font.drawString(text, this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - font.getStringWidth(text) : 0), this.getY() + y, ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + + y += font.getFontHeight() + 2D; } - - this.setWidth(!mods.isEmpty() ? FontUtils.getStringWidth(this.getModText(this.isTopOfCenter() ? mods.get(0) : mods.get(mods.size() - 1))) : 0); + + this.setWidth(!mods.isEmpty() ? font.getStringWidth(this.getModText(this.isTopOfCenter() ? mods.get(0) : mods.get(mods.size() - 1))) : 0); this.setHeight(y); } - + private String getModText(Module module) { - if(module.getHudInfo().isEmpty() || !this.metadata.booleanValue()) { + if (module.getHudInfo().isEmpty() || !this.metadata.booleanValue()) { return module.getName(); } - + return String.format("%s %s[%s%s%s]", module.getName(), ChatFormatting.DARK_GRAY, ChatFormatting.GRAY, module.getHudInfo(), ChatFormatting.DARK_GRAY); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Notifications.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Notifications.java index 9033ce90..8629b06f 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Notifications.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Notifications.java @@ -1,11 +1,13 @@ package xyz.templecheats.templeclient.features.module.modules.client.hud; import net.minecraft.client.gui.ScaledResolution; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; public class Notifications extends HUD.HudElement { + /* + * Variables + */ private static String notificationText = ""; private static long notificationTime; private float notificationFade; @@ -15,7 +17,7 @@ public Notifications() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { updateFade(); if (notificationFade > 0) { drawNotification(sr); @@ -40,9 +42,9 @@ private void updateFade() { private void drawNotification(ScaledResolution sr) { final String notification = notificationText; - this.setWidth(FontUtils.getStringWidth(notification)); - this.setHeight(FontUtils.getFontHeight()); + this.setWidth(font.getStringWidth(notification)); + this.setHeight(font.getFontHeight()); - FontUtils.drawString(notification, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(notification, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Ping.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Ping.java index 3f2e5e91..5c0304c0 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Ping.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Ping.java @@ -3,7 +3,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; import net.minecraft.client.network.NetworkPlayerInfo; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -13,15 +12,15 @@ public Ping() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { final String pingText = "Ping "; NetworkPlayerInfo playerInfo = Minecraft.getMinecraft().getConnection().getPlayerInfo(Minecraft.getMinecraft().player.getUniqueID()); final int pingValue = playerInfo == null ? 0 : playerInfo.getResponseTime(); - this.setWidth(FontUtils.getStringWidth(pingText + pingValue)); - this.setHeight(FontUtils.getFontHeight()); + this.setWidth(font.getStringWidth(pingText + pingValue)); + this.setHeight(font.getFontHeight()); - FontUtils.drawString(pingText, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); - FontUtils.drawString(String.valueOf(pingValue), this.getX() + FontUtils.getStringWidth(pingText), this.getY(), 0xFFFFFF, true); + font.drawString(pingText, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + font.drawString(String.valueOf(pingValue), this.getX() + font.getStringWidth(pingText), this.getY(), 0xFFFFFF, true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerName.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerName.java index ef337c7b..fc2abf6d 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerName.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerName.java @@ -2,7 +2,6 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -15,13 +14,13 @@ public PlayerName() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { final String playerName = Minecraft.getMinecraft().player.getName(); final String text = "Welcome " + playerName; - this.setWidth(FontUtils.getStringWidth(text)); - this.setHeight(FontUtils.getFontHeight()); + this.setWidth(font.getStringWidth(text)); + this.setHeight(font.getFontHeight()); - FontUtils.drawString(text, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(text, (float) this.getX(), (float) this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerView.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerView.java index 242b2cd7..6b354fe2 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerView.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PlayerView.java @@ -12,7 +12,7 @@ public PlayerView() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { this.setWidth(40); this.setHeight(70); diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PotionHUD.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PotionHUD.java index 914e6893..13ab739a 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PotionHUD.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/PotionHUD.java @@ -6,7 +6,6 @@ import net.minecraft.client.resources.I18n; import net.minecraft.potion.Potion; import net.minecraft.potion.PotionEffect; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -22,34 +21,34 @@ public PotionHUD() { } @Override - protected void renderElement(ScaledResolution sr) { - List effects = new ArrayList<>(Minecraft.getMinecraft().player.getActivePotionEffects()); + public void renderElement(ScaledResolution sr) { + List < PotionEffect > effects = new ArrayList < > (Minecraft.getMinecraft().player.getActivePotionEffects()); effects.sort((PotionEffect effect1, PotionEffect effect2) -> { String combinedText1 = getEffectText(effect1); String combinedText2 = getEffectText(effect2); - return Double.compare(FontUtils.getStringWidth(this.isTopOfCenter() ? combinedText2 : combinedText1), FontUtils.getStringWidth(this.isTopOfCenter() ? combinedText1 : combinedText2)); + return Double.compare(font.getStringWidth(this.isTopOfCenter() ? combinedText2 : combinedText1), font.getStringWidth(this.isTopOfCenter() ? combinedText1 : combinedText2)); }); double y = 0; double maxWidth = 0; double totalHeight = 0; - for (PotionEffect effect : effects) { + for (PotionEffect effect: effects) { String combinedText = getEffectText(effect); - double width = FontUtils.getStringWidth(combinedText) + 10; - double height = FontUtils.getFontHeight() + 2; + double width = font.getStringWidth(combinedText) + 10; + double height = font.getFontHeight() + 2; maxWidth = Math.max(maxWidth, width); totalHeight += height; - FontUtils.drawString(combinedText, this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - FontUtils.getStringWidth(combinedText) : 0), this.getY() + y, ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(combinedText, (float) (this.getX() + (!this.isLeftOfCenter() ? this.getWidth() - font.getStringWidth(combinedText) : 0)), (float) (this.getY() + y), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); y += height; } - this.setWidth(!effects.isEmpty() ? FontUtils.getStringWidth(getEffectText(this.isTopOfCenter() ? effects.get(0) : effects.get(effects.size() - 1))) : 0); + this.setWidth(!effects.isEmpty() ? font.getStringWidth(getEffectText(this.isTopOfCenter() ? effects.get(0) : effects.get(effects.size() - 1))) : 0); this.setHeight(totalHeight); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Server.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Server.java index 50535b53..c126b9a4 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Server.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Server.java @@ -2,10 +2,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.gui.ScaledResolution; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; +import java.util.Objects; + public class Server extends HUD.HudElement { public Server() { super("Server", "Shows the server name in the HUD"); @@ -15,12 +16,12 @@ public Server() { } @Override - protected void renderElement(ScaledResolution sr) { - final String serverName = Minecraft.getMinecraft().isSingleplayer() ? "singleplayer" : Minecraft.getMinecraft().getCurrentServerData().serverIP; + public void renderElement(ScaledResolution sr) { + final String serverName = Minecraft.getMinecraft().isSingleplayer() ? "singleplayer" : Objects.requireNonNull(Minecraft.getMinecraft().getCurrentServerData()).serverIP; - this.setWidth(FontUtils.getStringWidth(serverName)); - this.setHeight(FontUtils.getFontHeight()); + this.setWidth(font.getStringWidth(serverName)); + this.setHeight(font.getFontHeight()); - FontUtils.drawString(serverName, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); + font.drawString(serverName, (float) this.getX(), (float) this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Speed.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Speed.java index cc960a51..95ebe976 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Speed.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Speed.java @@ -4,11 +4,13 @@ import net.minecraft.client.gui.ScaledResolution; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.math.Vec3d; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; public class Speed extends HUD.HudElement { + /* + * Variables + */ private Vec3d lastPos = Vec3d.ZERO; public Speed() { @@ -16,7 +18,7 @@ public Speed() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { EntityPlayer player = Minecraft.getMinecraft().player; if (player == null) return; @@ -25,10 +27,10 @@ protected void renderElement(ScaledResolution sr) { double speedValue = (currentPos.distanceTo(lastTickPos)) * 20; final String speedText = "Speed "; - this.setWidth(FontUtils.getStringWidth(speedText + String.format("%.2f", speedValue)) + 10); - this.setHeight(FontUtils.getFontHeight()); + this.setWidth(font.getStringWidth(speedText + String.format("%.2f", speedValue)) + 10); + this.setHeight(font.getFontHeight()); - FontUtils.drawString(speedText, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); - FontUtils.drawString(String.format("%.2f", speedValue), this.getX() + FontUtils.getStringWidth(speedText), this.getY(), 0xFFFFFF, true); + font.drawString(speedText, (float) this.getX(), (float) this.getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + font.drawString(String.format("%.2f", speedValue), (float) (this.getX() + font.getStringWidth(speedText)), (float) this.getY(), 0xFFFFFF, true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/TargetHUD.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/TargetHUD.java index efe20390..8498fc96 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/TargetHUD.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/TargetHUD.java @@ -7,7 +7,6 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import org.lwjgl.opengl.GL11; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -20,7 +19,7 @@ public TargetHUD() { } @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { boolean show = false; double healthBarWidth = 0; String enemyNickname = ""; @@ -29,7 +28,7 @@ protected void renderElement(ScaledResolution sr) { EntityPlayer entity = null; RayTraceResult objectMouseOver = mc.objectMouseOver; - if(objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY && objectMouseOver.entityHit instanceof EntityPlayer) { + if (objectMouseOver != null && objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY && objectMouseOver.entityHit instanceof EntityPlayer) { entity = (EntityPlayer) objectMouseOver.entityHit; enemyNickname = entity.getName(); enemyHP = entity.getHealth(); @@ -40,9 +39,9 @@ protected void renderElement(ScaledResolution sr) { this.setWidth(140); this.setHeight(40); - if(show && mc.world != null && mc.player != null) { - final float x = (float) (this.getX() + this.getWidth() + 1); - final float y = (float) (this.getY() + this.getHeight() - 30); + if (show && mc.world != null && mc.player != null) { + final float x = (float)(this.getX() + this.getWidth() + 1); + final float y = (float)(this.getY() + this.getHeight() - 30); final float health = Math.round(enemyHP); double hpPercentage = health / 20; @@ -52,20 +51,19 @@ protected void renderElement(ScaledResolution sr) { final String healthStr = String.valueOf(Math.round(enemyHP)); - Gui.drawRect((int) (x - 140.5), (int) (y - 9.5), (int) (x - 0.5), (int) (y + 30.5f), new Color(31, 31, 31, 255).getRGB()); - Gui.drawRect((int) (x - 99.0f), (int) (y + 6.0f), (int) (x - 2.0f), (int) (y + 15.0f), new Color(40, 40, 40, 255).getRGB()); - Gui.drawRect((int) (x - 99.0f), (int) (y + 6.0f), (int) (x - 99.0f + healthBarWidth), (int) (y + 15.0f), ClickGUI.INSTANCE.getStartColor()); + Gui.drawRect((int)(x - 140.5), (int)(y - 9.5), (int)(x - 0.5), (int)(y + 30.5f), new Color(31, 31, 31, 255).getRGB()); + Gui.drawRect((int)(x - 99.0f), (int)(y + 6.0f), (int)(x - 2.0f), (int)(y + 15.0f), new Color(40, 40, 40, 255).getRGB()); + Gui.drawRect((int)(x - 99.0f), (int)(y + 6.0f), (int)(x - 99.0f + healthBarWidth), (int)(y + 15.0f), ClickGUI.INSTANCE.getStartColor().getRGB()); - Gui.drawRect((int) (x - 99.0f), (int) (y + 6.0f), (int) (x - 99.0f + hpWidth), (int) (y + 15.0f), ClickGUI.INSTANCE.getStartColor()); + Gui.drawRect((int)(x - 99.0f), (int)(y + 6.0f), (int)(x - 99.0f + hpWidth), (int)(y + 15.0f), ClickGUI.INSTANCE.getStartColor().getRGB()); - FontUtils.drawString(healthStr, x - 138.0f + 46.0f - mc.fontRenderer.getStringWidth(healthStr) / 2.0f, y + 19.5f, -1, true); - FontUtils.drawString("\u2764", x - 138.0f + 46.0f + mc.fontRenderer.getStringWidth(healthStr), y + 19.5f, ClickGUI.INSTANCE.getStartColor(), true); - FontUtils.drawString(entity.getName(), x - 97, y - 5.0f, -1, true); + font.drawString(healthStr, x - 138.0f + 46.0f - mc.fontRenderer.getStringWidth(healthStr) / 2.0f, y + 19.5f, -1, true, 1.0f); + font.drawString("\u2764", x - 138.0f + 46.0f + mc.fontRenderer.getStringWidth(healthStr), y + 19.5f, ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); + font.drawString(entity.getName(), x - 97, y - 5.0f, -1, true, 1.0f); try { - this.drawHead(Objects.requireNonNull(mc.getConnection()).getPlayerInfo(entity.getUniqueID()).getLocationSkin(), (int) (x - 139), (int) (y - 8)); - } catch(Exception ignored) { - } + this.drawHead(Objects.requireNonNull(mc.getConnection()).getPlayerInfo(entity.getUniqueID()).getLocationSkin(), (int)(x - 139), (int)(y - 8)); + } catch (Exception ignored) {} } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Watermark.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Watermark.java index 7d219634..15a755cf 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Watermark.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/Watermark.java @@ -2,26 +2,26 @@ import net.minecraft.client.gui.ScaledResolution; import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; public class Watermark extends HUD.HudElement { public Watermark() { super("Watermark", "Shows watermark in the HUD"); - + this.setEnabled(true); this.setX(2); this.setY(2); } - + + @Override - protected void renderElement(ScaledResolution sr) { + public void renderElement(ScaledResolution sr) { final String text = "templecheats.xyz v" + TempleClient.VERSION; - - this.setWidth(FontUtils.getStringWidth(text)); - this.setHeight(FontUtils.getFontHeight()); - - FontUtils.drawString(text, this.getX(), this.getY(), ClickGUI.INSTANCE.getStartColor(), true); + + this.setWidth(font.getStringWidth(text)); + this.setHeight(font.getFontHeight()); + + font.drawString(text, getX(), getY(), ClickGUI.INSTANCE.getStartColor().getRGB(), true, 1.0f); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationInfo.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationInfo.java new file mode 100644 index 00000000..2c24a948 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationInfo.java @@ -0,0 +1,40 @@ +package xyz.templecheats.templeclient.features.module.modules.client.hud.notification; + +import static net.minecraft.util.math.MathHelper.clamp; +import static xyz.templecheats.templeclient.features.module.modules.client.hud.notification.NotificationsRewrite.*; + +public class NotificationInfo { + String text; + String description; + NotificationType type; + long spawnTime; + + private final long KEEPTIME = (long) (INSTANCE.keepTime.doubleValue() * 1000L); + private final long SHOWTIME = (long) (INSTANCE.showTime.doubleValue() * 100L); + private final long HIDETIME = (long) (INSTANCE.hideTime.doubleValue() * 100L); + + public NotificationInfo(String text, String description, NotificationType type) { + this.text = text; + this.description = description; + this.type = type; + this.spawnTime = System.currentTimeMillis(); + } + + private long timeExisted() { + return System.currentTimeMillis() - spawnTime; + } + + double getProgress() { + double p = 0.0; + + if (timeExisted() <= SHOWTIME) p = (timeExisted() / (double) SHOWTIME); + if (timeExisted() > SHOWTIME) p = 1.0; + if (timeExisted() > SHOWTIME + KEEPTIME) p = 1.0 - ((timeExisted() - SHOWTIME - KEEPTIME) / (double) HIDETIME); + + return INSTANCE.easing.value().inc(clamp(p, 0.0, 1.0)); + } + + boolean shouldRemove() { + return timeExisted() > SHOWTIME + KEEPTIME + HIDETIME + 100L; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationType.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationType.java new file mode 100644 index 00000000..a2a7d4f8 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationType.java @@ -0,0 +1,21 @@ +package xyz.templecheats.templeclient.features.module.modules.client.hud.notification; + +public enum NotificationType { + SUCCESS("Success"), + INFO("Info"), + ERROR("Error"), + DEBUG("Debug"); + + public final String typeName; + + NotificationType(String typeName) { + this.typeName = typeName; + } + + public String getTypeName() { + return typeName; + } +} + + + diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationsRewrite.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationsRewrite.java new file mode 100644 index 00000000..36c9ea32 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/client/hud/notification/NotificationsRewrite.java @@ -0,0 +1,71 @@ +package xyz.templecheats.templeclient.features.module.modules.client.hud.notification; + +import net.minecraft.client.gui.ScaledResolution; +import xyz.templecheats.templeclient.features.module.modules.client.HUD; +import xyz.templecheats.templeclient.util.color.impl.RectBuilder; +import xyz.templecheats.templeclient.util.math.Vec2d; +import xyz.templecheats.templeclient.util.render.Easing; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class NotificationsRewrite extends HUD.HudElement { + public static NotificationsRewrite INSTANCE; + /* + * Settings + */ + public final EnumSetting easing = new EnumSetting <>("Easing", this, Easing.IN_CUBIC); + public final DoubleSetting keepTime = new DoubleSetting("KeepTime", this, 1, 5, 2); + public final DoubleSetting showTime = new DoubleSetting("ShowTime", this, 1, 5, 3); + public final DoubleSetting hideTime = new DoubleSetting("HieTime", this, 1, 5, 5); + /* + * Variables + */ + private static final List notificationList = new ArrayList<>(); + private double initialX; + + public NotificationsRewrite() { + super("Notifications2", "Shows notifications on the screen"); + INSTANCE = this; + registerSettings(easing, keepTime, showTime, hideTime); + } + + public static void addMessage(String text, String description, NotificationType type) { + notificationList.add(new NotificationInfo(text, description, type)); + } + + @Override + public void renderElement(ScaledResolution sr) { + double y = getY(); + + notificationList.removeIf(NotificationInfo::shouldRemove); + while (notificationList.size() > 5) { + notificationList.remove(0); + } + if (!notificationList.isEmpty()) { + initialX = getX(); + } + for (NotificationInfo notification : notificationList) { + draw(new Vec2d(initialX, y), notification.text, notification.description); + + y -= notification.getProgress() * (getHeight() + 10.0); + + this.setWidth(font.getStringWidth(notification.text + notification.description)); + this.setHeight(25); + + } + } + + private void draw(Vec2d pos, String text, String description) { + float textWidth = font.getStringWidth(text + description); + new RectBuilder(new Vec2d(pos.x, pos.y), new Vec2d(pos.x + textWidth, pos.y + getHeight())) + .color(new Color(255, 255, 255, 150)) + .radius(2.0) + .draw(); + + font.drawString(text + description, (float) pos.x, (float) (pos.y + getHeight() / 2.5), new Color(0, 0, 0, 255), false, 1.0f); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AimAssist.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AimAssist.java index 6862c366..4a57bce1 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AimAssist.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AimAssist.java @@ -8,15 +8,28 @@ import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; import java.util.Comparator; public class AimAssist extends Module { + /* + * Settings + */ + private final BooleanSetting visibility = new BooleanSetting("Visible-Only", this, true); + private final DoubleSetting smoothing = new DoubleSetting("Smoothing-Factor", this, 1.0f, 50.0f, 5.0f); + + /* + * Variables + */ private EntityLivingBase renderTarget; public AimAssist() { - super("AimAssist","Locks on target", Keyboard.KEY_NONE, Category.Combat); + super("AimAssist", "Locks on target", Keyboard.KEY_NONE, Category.Combat); + registerSettings(smoothing, visibility); } + @SubscribeEvent public void onUpdate(RenderWorldLastEvent e) { double range = 5; @@ -29,9 +42,13 @@ public void onUpdate(RenderWorldLastEvent e) { this.renderTarget = target; - if (target != null && mc.player.canEntityBeSeen(target)) { - mc.player.rotationYaw = rotations(target)[0]; - mc.player.rotationPitch = rotations(target)[1]; + if (target != null) { + if (!mc.player.canEntityBeSeen(target) && visibility.booleanValue()) return; + float[] targetRotations = rotations(target); + float targetYaw = targetRotations[0]; + float targetPitch = targetRotations[1]; + mc.player.rotationYaw += (targetYaw - mc.player.rotationYaw) / smoothing.floatValue(); + mc.player.rotationPitch += (targetPitch - mc.player.rotationPitch) / smoothing.floatValue(); } } @@ -42,14 +59,17 @@ public float[] rotations(EntityPlayer entity) { double u = MathHelper.sqrt(x * x + z * z); - float u2 = (float) (MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); - float u3 = (float) (-MathHelper.atan2(y, u) * (180D / Math.PI)); + float u2 = (float)(MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); + float u3 = (float)(-MathHelper.atan2(y, u) * (180D / Math.PI)); - return new float[]{u2, u3}; + return new float[] { + u2, + u3 + }; } @Override public String getHudInfo() { - if(this.renderTarget != null) { + if (this.renderTarget != null) { return this.renderTarget.getName(); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AntiBots.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AntiBots.java deleted file mode 100644 index 0501bcb8..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AntiBots.java +++ /dev/null @@ -1,25 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.combat; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; - -public class AntiBots extends Module { - public AntiBots() { - super("AntiBots","Tries to prevent bans", Keyboard.KEY_NONE, Category.Combat); - } - - @SubscribeEvent - public void onUpdate(RenderWorldLastEvent e) { - try { - for (EntityPlayer entityPlayer : mc.world.playerEntities) { - if (entityPlayer.isInvisible() && entityPlayer != mc.player) { - mc.world.removeEntity(entityPlayer); - } - } - } catch (Exception ex) { - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Aura.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Aura.java index 3d703a02..9872d9bf 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Aura.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Aura.java @@ -4,23 +4,36 @@ import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemSword; import net.minecraft.util.EnumHand; +import net.minecraft.util.math.Vec3d; import org.lwjgl.input.Keyboard; import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.event.events.player.MotionEvent; +import xyz.templecheats.templeclient.event.events.render.Render3DPrePreEvent; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.rotation.RotationUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; import xyz.templecheats.templeclient.util.setting.impl.IntSetting; +import java.awt.*; import java.util.Comparator; +import static org.lwjgl.opengl.GL11.*; + public class Aura extends Module { - private final BooleanSetting ignoreWalls = new BooleanSetting("Ignore Walls", this, true); + /* + * Settings + */ + private final BooleanSetting ignoreWalls = new BooleanSetting("Raytrace", this, true); + private final BooleanSetting requireWeapon = new BooleanSetting("Sword-Only", this, true); private final BooleanSetting rotate = new BooleanSetting("Rotate", this, true); + private final BooleanSetting renderRange = new BooleanSetting("Render Range", this, true); private final BooleanSetting onlyCritical = new BooleanSetting("Only Critical", this, false); private final BooleanSetting disableOnDeath = new BooleanSetting("Disable On Death", this, false); private final BooleanSetting players = new BooleanSetting("Players", this, true); @@ -28,14 +41,19 @@ public class Aura extends Module { private final BooleanSetting mobs = new BooleanSetting("Mobs", this, false); private final IntSetting waitTick = new IntSetting("Wait Tick", this, 0, 20, 0); private final DoubleSetting range = new DoubleSetting("Range", this, 0.1d, 6d, 4.5d); - private final EnumSetting waitMode = new EnumSetting<>("Wait Mode", this, WaitMode.Dynamic); + private final DoubleSetting renderSpeed = new DoubleSetting("Render Speed", this, 0.1, 5, 2.5); + private final EnumSetting waitMode = new EnumSetting<>("Mode", this, WaitMode.Dynamic); + + /* + * Variables + */ private int waitCounter; - private EntityLivingBase target, renderTarget; + private EntityLivingBase target, renderTarget = null; public Aura() { - super("Aura","Automatically aims and attacks enemies", Keyboard.KEY_NONE, Category.Combat); + super("Aura","Automatically attack entities nearby", Keyboard.KEY_NONE, Category.Combat); - registerSettings(ignoreWalls, rotate, onlyCritical, disableOnDeath, players, animals, mobs, waitTick, range, waitMode); + registerSettings(ignoreWalls, onlyCritical, requireWeapon, disableOnDeath, players, mobs, animals, waitTick, range, renderRange, renderSpeed, waitMode); } @Override @@ -52,6 +70,7 @@ public void onMotion(MotionEvent event) { } switch (event.getStage()) { + case PRE: if (waitMode.value() == WaitMode.Dynamic) { if (mc.player.getCooledAttackStrength(0) < 1) { @@ -65,7 +84,7 @@ public void onMotion(MotionEvent event) { waitCounter = 0; } } - + if (requireWeapon.booleanValue() && !hasSwordMainHand()) return; this.target = mc.world.loadedEntityList.stream() .filter(entity -> entity instanceof EntityLivingBase && !entity.equals(mc.player) && (!(entity instanceof EntityOtherPlayerMP) || !((EntityOtherPlayerMP) entity).getGameProfile().equals(mc.player.getGameProfile()))) .map(entity -> (EntityLivingBase) entity) @@ -105,6 +124,9 @@ public void onMotion(MotionEvent event) { } } + private boolean hasSwordMainHand() { + return mc.player.getHeldItemMainhand().getItem() instanceof ItemSword; + } @Override public String getHudInfo() { if(this.renderTarget != null) { @@ -113,6 +135,44 @@ public String getHudInfo() { return ""; } + private float i = 0.0f; + @Listener + public void onRender3DPre(Render3DPrePreEvent event) { + if (renderTarget != null && renderRange.booleanValue() && hasSwordMainHand()) { + final Vec3d vec = RenderUtil.interpolateEntity(renderTarget); + final Color color = Colors.INSTANCE.getGradient()[0]; + final Color color2 = Colors.INSTANCE.getGradient()[1]; + final Color top = new Color(color2.getRed(), color2.getGreen(), color2.getBlue(), 0); + final float sin = ((float) Math.sin(i / (100.0f / renderSpeed.doubleValue())) / 2.0f); + final float sin2 = ((float) Math.sin(i / 25.0f + renderSpeed.floatValue() / 2.0f)); + i++; + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_DEPTH_TEST); + glShadeModel(GL_SMOOTH); + glDisable(GL_CULL_FACE); + glBegin(GL_QUAD_STRIP); + for (int i = 0; i <= 360; i++) { + final double x = ((Math.cos(i * Math.PI / 180F) * range.doubleValue()) + vec.x); + final double y = (vec.y + (renderTarget.height / 2.0f)); + final double z = ((Math.sin(i * Math.PI / 180F) * range.doubleValue()) + vec.z); + RenderUtil.glColor(color); + glVertex3d(x, y + (sin2 * renderTarget.height), z); + RenderUtil.glColor(top); + glVertex3d(x, y + (sin * renderTarget.height), z); + } + + glEnd(); + glEnable(GL_CULL_FACE); + glShadeModel(GL_FLAT); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glPopMatrix(); + } + } private enum WaitMode { Dynamic, diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoArmor.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoArmor.java index 31be267a..45e3fce1 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoArmor.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoArmor.java @@ -13,20 +13,26 @@ import java.util.Arrays; public class AutoArmor extends Module { + /* + * Settings + */ private final BooleanSetting pickupIfFull = new BooleanSetting("Pickup If Full", this, false); - private final BooleanSetting replace = new BooleanSetting("Replace Empty", this, false); private final BooleanSetting preserve = new BooleanSetting("Preserve Damaged", this, false); + private final BooleanSetting replace = new BooleanSetting("Replace Empty", this, false); private final IntSetting preserveDmg = new IntSetting("Damage %", this, 0, 100, 5); private final IntSetting delay = new IntSetting("Delay", this, 0, 20, 10); + /* + * Variables + */ private int[] bestArmorDamage; private int[] bestArmorSlots; private int timer; public AutoArmor() { - super("AutoArmor","Automatically equips armor", Keyboard.KEY_NONE, Category.Combat); + super("AutoArmor", "Automatically equips your best armor", Keyboard.KEY_NONE, Category.Combat); - registerSettings(pickupIfFull, replace, preserve, preserveDmg, delay); + registerSettings(pickupIfFull, preserve, replace, preserveDmg, delay); } @Override @@ -66,19 +72,17 @@ private void searchSlots() { for (int i = 0; i < this.bestArmorSlots.length; ++i) { final ItemStack itemStack = AutoArmor.mc.player.inventory.armorItemInSlot(i); if (itemStack.getItem() instanceof ItemArmor) { - final ItemArmor armor = (ItemArmor)itemStack.getItem(); + final ItemArmor armor = (ItemArmor) itemStack.getItem(); if (this.preserve.booleanValue()) { - final float dmg = (itemStack.getMaxDamage() - (float)itemStack.getItemDamage()) / itemStack.getMaxDamage(); + final float dmg = (itemStack.getMaxDamage() - (float) itemStack.getItemDamage()) / itemStack.getMaxDamage(); final int percent = (int)(dmg * 100.0f); if (percent > this.preserveDmg.intValue()) { this.bestArmorDamage[i] = armor.damageReduceAmount; } - } - else { + } else { this.bestArmorDamage[i] = armor.damageReduceAmount; } - } - else if (itemStack.isEmpty() && !this.replace.booleanValue()) { + } else if (itemStack.isEmpty() && !this.replace.booleanValue()) { this.bestArmorDamage[i] = Integer.MAX_VALUE; } } @@ -86,7 +90,7 @@ else if (itemStack.isEmpty() && !this.replace.booleanValue()) { final ItemStack itemStack = AutoArmor.mc.player.inventory.getStackInSlot(i); if (itemStack.getCount() <= 1) { if (itemStack.getItem() instanceof ItemArmor) { - final ItemArmor armor = (ItemArmor)itemStack.getItem(); + final ItemArmor armor = (ItemArmor) itemStack.getItem(); final int armorType = armor.armorType.ordinal() - 2; if (this.bestArmorDamage[armorType] < armor.damageReduceAmount) { this.bestArmorDamage[armorType] = armor.damageReduceAmount; @@ -96,4 +100,4 @@ else if (itemStack.isEmpty() && !this.replace.booleanValue()) { } } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoCrystal.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoCrystal.java index 975da55a..4a2980cc 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoCrystal.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoCrystal.java @@ -1,9 +1,10 @@ -/** +/* * This AutoCrystal was made by GameSense, and was modified. */ - package xyz.templecheats.templeclient.features.module.modules.combat; +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; +import it.unimi.dsi.fastutil.objects.ObjectSet; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityEnderCrystal; import net.minecraft.init.Items; @@ -15,7 +16,9 @@ import net.minecraft.network.Packet; import net.minecraft.network.play.client.CPacketAnimation; import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock; +import net.minecraft.network.play.client.CPacketUseEntity; import net.minecraft.network.play.server.SPacketSoundEffect; +import net.minecraft.network.play.server.SPacketSpawnObject; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.SoundCategory; @@ -27,11 +30,13 @@ import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.mixins.accessor.ICPacketUseEntity; import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.event.events.network.PacketEvent; import xyz.templecheats.templeclient.event.events.player.MotionEvent; import xyz.templecheats.templeclient.event.events.world.EntityEvent; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; import xyz.templecheats.templeclient.util.autocrystal.*; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; @@ -42,56 +47,69 @@ import java.util.*; +import static net.minecraft.network.play.client.CPacketUseEntity.Action.ATTACK; + public class AutoCrystal extends Module { - /** + /* * Settings */ - private final EnumSetting server = new EnumSetting<>("Server", this, Server.OneTwelve); - private final EnumSetting crystalPriority = new EnumSetting<>("Prioritise", this, Priority.Damage); - private final BooleanSetting instant = new BooleanSetting("Instant", this, false); - private final IntSetting attackSpeed = new IntSetting("Attack Speed", this, 0, 20, 20); - private final DoubleSetting range = new DoubleSetting("Range", this, 0.0, 6.0, 4.5); - private final DoubleSetting wallRange = new DoubleSetting("Wall Range", this, 0.0, 6.0, 3.5); - private final DoubleSetting enemyRange = new DoubleSetting("Enemy Range", this, 0.0, 16.0, 6.0); private final BooleanSetting antiWeakness = new BooleanSetting("Anti Weakness", this, true); private final BooleanSetting autoSwitch = new BooleanSetting("Auto Switch", this, true); + private final BooleanSetting fill = new BooleanSetting("Box Fill", this, true); + private final BooleanSetting inhibit = new BooleanSetting("Inhibit", this, true); + private final BooleanSetting predict = new BooleanSetting("Predict", this, false); + + private final BooleanSetting instant = new BooleanSetting("Instant", this, false); + + private final BooleanSetting setDead = new BooleanSetting("Set Dead", this, false); + private final BooleanSetting noGapSwitch = new BooleanSetting("No Gap Switch", this, false); - private final DoubleSetting minDmg = new DoubleSetting("Min Damage", this, 0.0, 36.0, 5.0); - private final DoubleSetting maxSelfDmg = new DoubleSetting("Max Self Dmg", this, 1.0, 36.0, 10.0); - private final IntSetting facePlaceValue = new IntSetting("FacePlace HP", this, 0, 36, 8); - private final IntSetting armourFacePlace = new IntSetting("Armour Durability %", this, 0, 100, 20); - private final DoubleSetting minFacePlaceDmg = new DoubleSetting("Min FacePlace Damage", this, 0.0, 10.0, 2.0); - private final BooleanSetting rotate = new BooleanSetting("Rotate", this, true); + private final BooleanSetting outline = new BooleanSetting("Box Outline", this, true); private final BooleanSetting raytrace = new BooleanSetting("Raytrace", this, false); + private final BooleanSetting rotate = new BooleanSetting("Rotate", this, true); private final BooleanSetting wait = new BooleanSetting("Force Wait", this, true); - private final IntSetting timeout = new IntSetting("Timeout", this, 1, 50, 10); + private final DoubleSetting enemyRange = new DoubleSetting("Enemy Range", this, 0.0, 16.0, 6.0); + private final DoubleSetting maxSelfDmg = new DoubleSetting("Max Self Dmg", this, 1.0, 36.0, 10.0); + private final DoubleSetting minDmg = new DoubleSetting("Min Dmg", this, 0.0, 36.0, 5.0); + private final DoubleSetting minFacePlaceDmg = new DoubleSetting("Min FacePlace Dmg", this, 0.0, 10.0, 2.0); + private final DoubleSetting defaultOpacityVal = new DoubleSetting("DefaultOpacity", this, 0.0, 1, 0.5); + private final DoubleSetting opacity = new DoubleSetting("Opacity", this, 0.0, 1, 0.5); + + private final DoubleSetting range = new DoubleSetting("Range", this, 0.0, 6.0, 4.5); + private final DoubleSetting wallRange = new DoubleSetting("Wall Range", this, 0.0, 6.0, 3.5); + private final IntSetting armourFacePlace = new IntSetting("Armour Dura %", this, 0, 100, 20); + private final IntSetting attackSpeed = new IntSetting("Attack Speed", this, 0, 20, 20); + private final IntSetting facePlaceValue = new IntSetting("FacePlace HP", this, 0, 36, 8); private final IntSetting maxTargets = new IntSetting("Max Targets", this, 1, 5, 2); - private final BooleanSetting fill = new BooleanSetting("Box Fill", this, true); - private final BooleanSetting outline = new BooleanSetting("Box Outline", this, true); - private final IntSetting red = new IntSetting("Box Red", this, 0, 255, 255); - private final IntSetting green = new IntSetting("Box Green", this, 0, 255, 0); - private final IntSetting blue = new IntSetting("Box Blue", this, 0, 255, 0); - - /** + private final IntSetting timeout = new IntSetting("Timeout", this, 1, 50, 10); + private final EnumSetting < Priority > crystalPriority = new EnumSetting < > ("Prioritise", this, Priority.Damage); + private final EnumSetting < Server > server = new EnumSetting < > ("Server", this, Server.OneTwelve); + public static boolean rendering; + /* * Variables */ private final TimerUtil timer = new TimerUtil(); - private List targets = new ArrayList<>(); + private List < CrystalInfo.PlaceInfo > targets = new ArrayList <> (); + private final ArrayList attackedCrystals = new ArrayList<>(); + private final ObjectSet placedPos = new ObjectOpenHashSet<>(); private boolean switchCooldown, isAttacking, rotating, finished; private Vec3d lastHitVec = Vec3d.ZERO; private BlockPos render; - private EntityEnderCrystal curCrystal, lastCrystal; - private BlockPos curPos, lastPos; - + private BlockPos curPos, lastPos, lastRenderPos; + boolean offhand = false; + + public AutoCrystal() { - super("AutoCrystal", "Automatically places / breaks crystals near enemies and detonates them", Keyboard.KEY_NONE, Category.Combat); - this.registerSettings(instant, antiWeakness, autoSwitch, noGapSwitch, rotate, raytrace, wait, fill, outline, attackSpeed, range, wallRange, enemyRange, minDmg, maxSelfDmg, facePlaceValue, armourFacePlace, minFacePlaceDmg, timeout, maxTargets, red, green, blue, server, crystalPriority); + super("AutoCrystal", "Automatically places and explodes end crystals for crystal pvp", Keyboard.KEY_NONE, Category.Combat); + this.registerSettings(antiWeakness, autoSwitch, instant, noGapSwitch, raytrace, rotate, setDead, wait, + attackSpeed, armourFacePlace, facePlaceValue, maxTargets, timeout, + enemyRange, inhibit, predict, defaultOpacityVal, maxSelfDmg, minDmg, minFacePlaceDmg, range, wallRange, fill, outline, opacity, crystalPriority, server); } @SubscribeEvent public void onClientTick(TickEvent.ClientTickEvent event) { - if(mc.player == null || mc.world == null || mc.player.isDead) { + if (mc.player == null || mc.world == null || mc.player.isDead) { return; } @@ -102,18 +120,18 @@ public void onClientTick(TickEvent.ClientTickEvent event) { double enemyDistance = enemyRange.doubleValue() + range.doubleValue(); ACHelper.INSTANCE.recalculateValues(settings, player, armourPercent, enemyDistance); - if(event.phase == TickEvent.Phase.START) { + if (event.phase == TickEvent.Phase.START) { collectTargetFinder(); } else { - if(finished) { + if (finished) { startTargetFinder(); finished = false; } } targets.removeIf(placeInfo -> placeInfo.target.entity.isDead || placeInfo.target.entity.getHealth() == 0 || TempleClient.friendManager.isFriend(placeInfo.target.entity.getName())); - if(!breakCrystal(settings)) { - if(!placeCrystal(settings)) { + if (!breakCrystal(settings)) { + if (!placeCrystal(settings)) { rotating = false; isAttacking = false; render = null; @@ -123,9 +141,9 @@ public void onClientTick(TickEvent.ClientTickEvent event) { @Listener public void onMotion(MotionEvent event) { - switch(event.getStage()) { + switch (event.getStage()) { case PRE: - if(this.rotating) { + if (this.rotating) { final Vec2f rotation = RotationUtil.getRotationTo(lastHitVec); event.setYaw(rotation.x); event.setPitch(rotation.y); @@ -136,24 +154,28 @@ public void onMotion(MotionEvent event) { } } - @Listener public void onEntityAdd(EntityEvent.Add event) { - if(this.instant.booleanValue() && this.lastPos != null && this.curCrystal == null && event.getEntity() instanceof EntityEnderCrystal) { + if (this.instant.booleanValue() && this.lastPos != null && this.curCrystal == null && event.getEntity() instanceof EntityEnderCrystal) { final EntityEnderCrystal crystal = (EntityEnderCrystal) event.getEntity(); - - if(crystal != null && crystal.getPosition().down().equals(this.lastPos)) { + + if (crystal != null && crystal.getPosition().down().equals(this.lastPos)) { final float selfDamage = DamageUtil.calculateDamageThreaded(crystal, new PlayerInfo(mc.player, false)); - - if(selfDamage > this.maxSelfDmg.doubleValue()) { + + if (selfDamage > this.maxSelfDmg.doubleValue()) { return; } - - if(selfDamage >= mc.player.getHealth() + mc.player.getAbsorptionAmount()) { + + if (selfDamage >= mc.player.getHealth() + mc.player.getAbsorptionAmount()) { return; } - + if (inhibit.booleanValue() && attackedCrystals.contains(crystal.getEntityId())) return; + this.breakCrystalInternal(this.curCrystal = crystal, false); + if (setDead.booleanValue()) { + mc.world.removeEntity(crystal); + crystal.setDead(); + } this.lastPos = null; } } @@ -162,23 +184,23 @@ public void onEntityAdd(EntityEvent.Add event) { @Listener public void onEntityDelete(EntityEvent.Delete event) { - if(this.instant.booleanValue() && this.lastCrystal != null && this.curPos == null && event.getEntity() instanceof EntityEnderCrystal) { + if (this.instant.booleanValue() && this.lastCrystal != null && this.curPos == null && event.getEntity() instanceof EntityEnderCrystal) { final EntityEnderCrystal crystal = (EntityEnderCrystal) event.getEntity(); - - if(crystal.equals(this.lastCrystal)) { + + if (crystal.equals(this.lastCrystal)) { final BlockPos pos = crystal.getPosition().down(); - - if(CrystalUtil.canPlaceCrystal(pos, this.server.value(), true)) { + + if (CrystalUtil.canPlaceCrystal(pos, this.server.value(), true)) { final float selfDamage = DamageUtil.calculateDamageThreaded(pos, new PlayerInfo(mc.player, false)); - - if(selfDamage > this.maxSelfDmg.doubleValue()) { + + if (selfDamage > this.maxSelfDmg.doubleValue()) { return; } - - if(selfDamage >= mc.player.getHealth() + mc.player.getAbsorptionAmount()) { + + if (selfDamage >= mc.player.getHealth() + mc.player.getAbsorptionAmount()) { return; } - + this.placeCrystalInternal(this.curPos = pos); this.lastCrystal = null; } @@ -186,16 +208,37 @@ public void onEntityDelete(EntityEvent.Delete event) { } } - @Listener public void onPacketRecieve(PacketEvent.Receive event) { Packet packet = event.getPacket(); - if(packet instanceof SPacketSoundEffect) { + if (event.getPacket() instanceof SPacketSpawnObject && predict.booleanValue()) { + final SPacketSpawnObject spawnPacket = (SPacketSpawnObject) event.getPacket(); + if (spawnPacket.getType() != 51) { + return; + } + if (inhibit.booleanValue() && attackedCrystals.contains(spawnPacket.getEntityID())) return; + final BlockPos pos = new BlockPos(spawnPacket.getX(), spawnPacket.getY() - 1, spawnPacket.getZ()); + if (placedPos.remove(pos)) { + final ICPacketUseEntity packetUseEntity = (ICPacketUseEntity) new CPacketUseEntity(); + packetUseEntity.setEntityId(spawnPacket.getEntityID()); + packetUseEntity.setAction(ATTACK); + mc.getConnection().sendPacket((Packet) packetUseEntity); + mc.getConnection().sendPacket(new CPacketAnimation(EnumHand.MAIN_HAND)); + if (lastPos != null && lastPos.equals(pos)) { + mc.getConnection().sendPacket(new CPacketPlayerTryUseItemOnBlock(lastPos, EnumFacing.UP, offhand ? EnumHand.OFF_HAND : EnumHand.MAIN_HAND, 0.5F, 1.0F, 0.5F)); + } + } + mc.player.swingArm(EnumHand.OFF_HAND); + if (setDead.booleanValue()) { + mc.world.removeEntityFromWorld(spawnPacket.getEntityID()); + } + } + if (packet instanceof SPacketSoundEffect) { final SPacketSoundEffect packetSoundEffect = (SPacketSoundEffect) packet; - if(packetSoundEffect.getCategory() == SoundCategory.BLOCKS && packetSoundEffect.getSound() == SoundEvents.ENTITY_GENERIC_EXPLODE) { - for(Entity entity : new ArrayList<>(mc.world.loadedEntityList)) { - if(entity instanceof EntityEnderCrystal) { - if(entity.getDistanceSq(packetSoundEffect.getX(), packetSoundEffect.getY(), packetSoundEffect.getZ()) <= 36.0f) { + if (packetSoundEffect.getCategory() == SoundCategory.BLOCKS && packetSoundEffect.getSound() == SoundEvents.ENTITY_GENERIC_EXPLODE) { + for (Entity entity : new ArrayList<>(mc.world.loadedEntityList)) { + if (entity instanceof EntityEnderCrystal) { + if (entity.getDistanceSq(packetSoundEffect.getX(), packetSoundEffect.getY(), packetSoundEffect.getZ()) <= 36.0f) { entity.setDead(); } } @@ -203,51 +246,78 @@ public void onPacketRecieve(PacketEvent.Receive event) { } } } - + + @Override public void onRenderWorld(float partialTicks) { - if(this.render != null) { - RenderUtil.blockESP(this.render, this.fill.booleanValue(), this.outline.booleanValue(), true, red.intValue() / 255F, green.intValue() / 255F, blue.intValue() / 255F); + if (render != null) { + opacity.setDoubleValue(defaultOpacityVal.doubleValue()); + rendering = false; + GradientShader.setup(opacity.floatValue()); + rendering = true; + if (fill.booleanValue()) + RenderUtil.boxShader(render); + if (outline.booleanValue()) + RenderUtil.outlineShader(render); + RenderUtil.outlineShader(render); + RenderUtil.outlineShader(render); + + GradientShader.finish(); + lastRenderPos = render; + rendering = false; + } else { + if (opacity.doubleValue() > 0) { + opacity.setDoubleValue(opacity.doubleValue() - 0.01f); + GradientShader.setup(opacity.floatValue()); + if (fill.booleanValue()) + RenderUtil.boxShader(lastRenderPos); + if (outline.booleanValue()) + RenderUtil.outlineShader(lastRenderPos); + RenderUtil.outlineShader(lastRenderPos); + RenderUtil.outlineShader(lastRenderPos); + GradientShader.finish(); + } } } - + @Override public void onEnable() { ACHelper.INSTANCE.onEnable(); } - + @Override public void onDisable() { ACHelper.INSTANCE.onDisable(); - + render = null; rotating = false; targets.clear(); + attackedCrystals.clear(); } - + public boolean breakCrystal(ACSettings settings) { if (!targets.isEmpty()) { - List currentTargets; + List < CrystalInfo.PlaceInfo > currentTargets; if (targets.size() < maxTargets.intValue()) { - currentTargets = new ArrayList<>(targets); + currentTargets = new ArrayList < > (targets); } else { currentTargets = targets.subList(0, maxTargets.intValue()); } - List crystals = ACHelper.INSTANCE.getTargetableCrystals(); - - TreeSet possibleCrystals = new TreeSet<>(crystalPriority.value().breakComparator); - - for(CrystalInfo.PlaceInfo currentTarget : currentTargets) { + List < EntityEnderCrystal > crystals = ACHelper.INSTANCE.getTargetableCrystals(); + + TreeSet < CrystalInfo.BreakInfo > possibleCrystals = new TreeSet < > (crystalPriority.value().breakComparator); + + for (CrystalInfo.PlaceInfo currentTarget: currentTargets) { CrystalInfo.BreakInfo breakInfo = ACUtil.calculateBestBreakable(settings, new PlayerInfo(currentTarget.target.entity, currentTarget.target.lowArmour), crystals); - if(breakInfo != null) { + if (breakInfo != null) { possibleCrystals.add(breakInfo); } } - if(!possibleCrystals.isEmpty()) { + if (!possibleCrystals.isEmpty()) { this.curCrystal = possibleCrystals.last().crystal; - - if(this.breakCrystalInternal(this.curCrystal, true)) { + + if (this.breakCrystalInternal(this.curCrystal, true)) { this.lastCrystal = this.curCrystal; return true; } @@ -257,90 +327,100 @@ public boolean breakCrystal(ACSettings settings) { } private boolean breakCrystalInternal(EntityEnderCrystal crystal, boolean checkDelay) { - if(mc.player.canEntityBeSeen(crystal) || mc.player.getDistance(crystal) < wallRange.doubleValue()) { - if(antiWeakness.booleanValue() && mc.player.isPotionActive(MobEffects.WEAKNESS) && (!mc.player.isPotionActive(MobEffects.STRENGTH) || mc.player.getActivePotionEffect(MobEffects.STRENGTH) - .getAmplifier() < 2)) { - if(!isAttacking) { + if (mc.player.canEntityBeSeen(crystal) || mc.player.getDistance(crystal) < wallRange.doubleValue()) { + if (antiWeakness.booleanValue() && mc.player.isPotionActive(MobEffects.WEAKNESS) && (!mc.player.isPotionActive(MobEffects.STRENGTH) || mc.player.getActivePotionEffect(MobEffects.STRENGTH) + .getAmplifier() < 2)) { + if (!isAttacking) { isAttacking = true; } // search for sword and tools in hotbar int newSlot = InventoryUtil.findFirstItemSlot(ItemSword.class, 0, 8); - if(newSlot == -1) { + if (newSlot == -1) { InventoryUtil.findFirstItemSlot(ItemTool.class, 0, 8); } // check if any swords or tools were found - if(newSlot != -1) { + if (newSlot != -1) { mc.player.inventory.currentItem = newSlot; switchCooldown = true; } } - if(!checkDelay || timer.getTimePassed() / 50L >= 20 - attackSpeed.intValue()) { + if (!checkDelay || timer.getTimePassed() / 50L >= 20 - attackSpeed.intValue()) { timer.reset(); rotating = rotate.booleanValue(); lastHitVec = crystal.getPositionVector(); - - mc.playerController.attackEntity(mc.player, crystal); - mc.player.swingArm(EnumHand.MAIN_HAND); + if (!inhibit.booleanValue() || inhibit.booleanValue() && attackedCrystals.contains(crystal.getEntityId())) { + mc.playerController.attackEntity(mc.player, crystal); + if (setDead.booleanValue()) mc.world.removeEntityFromWorld(crystal.getEntityId()); + } + attackedCrystals.add(crystal.getEntityId()); + if (setDead.booleanValue() && !inhibit.booleanValue()) { + mc.world.removeEntity(crystal); + crystal.setDead(); + } + if (mc.player.getHeldItemOffhand().getItem() == Items.END_CRYSTAL) + mc.player.swingArm(EnumHand.OFF_HAND); + else + mc.player.swingArm(EnumHand.MAIN_HAND); } return true; } - return false; } - + private boolean placeCrystal(ACSettings settings) { - List currentTargets; - if(targets.size() < maxTargets.intValue()) { - currentTargets = new ArrayList<>(targets); + List < CrystalInfo.PlaceInfo > currentTargets; + if (targets.size() < maxTargets.intValue()) { + currentTargets = new ArrayList < > (targets); } else { currentTargets = targets.subList(0, maxTargets.intValue()); } - List placements = ACHelper.INSTANCE.getPossiblePlacements(); - - TreeSet possiblePlacements = new TreeSet<>(crystalPriority.value().placeComparator); - - for(CrystalInfo.PlaceInfo currentTarget : currentTargets) { + List < BlockPos > placements = ACHelper.INSTANCE.getPossiblePlacements(); + + TreeSet < CrystalInfo.PlaceInfo > possiblePlacements = new TreeSet < > (crystalPriority.value().placeComparator); + + for (CrystalInfo.PlaceInfo currentTarget: currentTargets) { CrystalInfo.PlaceInfo placeInfo = ACUtil.calculateBestPlacement(settings, new PlayerInfo(currentTarget.target.entity, currentTarget.target.lowArmour), placements); - if(placeInfo != null) { + if (placeInfo != null) { + placedPos.add(placeInfo.pos); possiblePlacements.add(placeInfo); } } - if(possiblePlacements.isEmpty()) { + if (possiblePlacements.isEmpty()) { return false; } - + this.curPos = possiblePlacements.last().pos; - - if(this.placeCrystalInternal(this.curPos)) { + + if (this.placeCrystalInternal(this.curPos)) { this.lastPos = this.curPos; return true; } - + return false; } private boolean placeCrystalInternal(BlockPos pos) { // check to see if we are holding crystals or not int crystalSlot = mc.player.getHeldItemMainhand().getItem() == Items.END_CRYSTAL ? mc.player.inventory.currentItem : -1; - if(crystalSlot == -1) { + if (crystalSlot == -1) { crystalSlot = InventoryUtil.findFirstItemSlot(ItemEndCrystal.class, 0, 8); } - boolean offhand = false; - if(mc.player.getHeldItemOffhand().getItem() == Items.END_CRYSTAL) { + offhand = false; + if (mc.player.getHeldItemOffhand().getItem() == Items.END_CRYSTAL) { offhand = true; - } else if(crystalSlot == -1) { + } else if (crystalSlot == -1) { return false; } - + placedPos.add(pos); this.render = pos; // autoSwitch stuff - if(!offhand && mc.player.inventory.currentItem != crystalSlot) { - if(this.autoSwitch.booleanValue()) { - if(!noGapSwitch.booleanValue() || !(mc.player.getHeldItemMainhand().getItem() == Items.GOLDEN_APPLE)) { + if (!offhand && mc.player.inventory.currentItem != crystalSlot) { + if (this.autoSwitch.booleanValue()) { + if (!noGapSwitch.booleanValue() || !(mc.player.getHeldItemMainhand().getItem() == Items.GOLDEN_APPLE)) { mc.player.inventory.currentItem = crystalSlot; rotating = false; this.switchCooldown = true; @@ -349,16 +429,16 @@ private boolean placeCrystalInternal(BlockPos pos) { return false; } - if(this.switchCooldown) { + if (this.switchCooldown) { this.switchCooldown = false; return false; } EnumFacing validFace = mc.player.posY + mc.player.getEyeHeight() > pos.getY() + 0.5 || !mc.world.isAirBlock(pos.down()) ? EnumFacing.UP : EnumFacing.DOWN; - if(raytrace.booleanValue()) { + if (raytrace.booleanValue()) { RayTraceResult result = mc.world.rayTraceBlocks(new Vec3d(mc.player.posX, mc.player.posY + (double) mc.player.getEyeHeight(), mc.player.posZ), new Vec3d((double) pos.getX() + 0.5, (double) pos.getY() - 0.5, (double) pos.getZ() + 0.5)); - if(result == null || result.sideHit == null) { + if (result == null || result.sideHit == null) { render = null; return false; } else { @@ -374,17 +454,17 @@ private boolean placeCrystalInternal(BlockPos pos) { return true; } - + private void startTargetFinder() { long timeoutTime = System.currentTimeMillis() + timeout.intValue(); ACHelper.INSTANCE.startCalculations(timeoutTime); } - + private void collectTargetFinder() { - List output = ACHelper.INSTANCE.getOutput(wait.booleanValue()); - if(output != null) { + List < CrystalInfo.PlaceInfo > output = ACHelper.INSTANCE.getOutput(wait.booleanValue()); + if (output != null) { finished = true; - if(!output.isEmpty()) { + if (!output.isEmpty()) { targets = output; } } else { @@ -397,10 +477,10 @@ public enum Priority { Closest(Comparator.comparingDouble(o -> -mc.player.getDistanceSq(o.target.entity)), Comparator.comparingDouble(o -> -mc.player.getDistanceSq(o.target.entity))), Health(Comparator.comparingDouble(o -> o.damage), Comparator.comparingDouble(o -> o.damage)); - public final Comparator placeComparator; - public final Comparator breakComparator; + public final Comparator < CrystalInfo.PlaceInfo > placeComparator; + public final Comparator < CrystalInfo.BreakInfo > breakComparator; - Priority(Comparator placeComparator, Comparator breakComparator) { + Priority(Comparator < CrystalInfo.PlaceInfo > placeComparator, Comparator < CrystalInfo.BreakInfo > breakComparator) { this.placeComparator = placeComparator; this.breakComparator = breakComparator; } @@ -422,4 +502,4 @@ public String toString() { return this.name; } } -} \ No newline at end of file +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoDisconnect.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoDisconnect.java index e0f93b82..b0e36b3d 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoDisconnect.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoDisconnect.java @@ -9,12 +9,18 @@ import xyz.templecheats.templeclient.util.setting.impl.IntSetting; public class AutoDisconnect extends Module { + /* + * Settings + */ private final IntSetting healthThreshold = new IntSetting("Health", this, 1, 20, 10); + /* + * Variables + */ private boolean shouldDisconnect = false; public AutoDisconnect() { - super("AutoDisconnect","Automatically disconnects when health is low enough", Keyboard.KEY_NONE, Category.Combat); + super("AutoDisconnect", "Automatically logs you out when you have low health", Keyboard.KEY_NONE, Category.Combat); registerSettings(healthThreshold); } @@ -34,4 +40,4 @@ public void onClientConnectedToServer(FMLNetworkEvent.ClientConnectedToServerEve this.toggled = false; } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoGapple.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoGapple.java deleted file mode 100644 index 54b53178..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoGapple.java +++ /dev/null @@ -1,93 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.combat; - -import net.minecraft.client.Minecraft; -import net.minecraft.client.settings.KeyBinding; -import net.minecraft.init.Items; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumHand; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; - -public class AutoGapple extends Module { - private final IntSetting healthThreshold = new IntSetting("Health", this, 1, 20, 10); - private boolean isEatingGapple = false; - private int originalSlot = -1; - - public AutoGapple() { - super("AutoGapple", "Automatically swaps & eats a (notch) apple when health is below the set threshold or not fully recovered", Keyboard.KEY_NONE, Category.Combat); - TempleClient.settingsManager.rSetting(healthThreshold); - } - - @Override - public void onUpdate() { - if (!isEatingGapple && (Minecraft.getMinecraft().player.getHealth() <= this.healthThreshold.intValue() || (isEatingGapple && Minecraft.getMinecraft().player.getHealth() < Minecraft.getMinecraft().player.getMaxHealth()))) { - final int gappleSlot = this.getGappleSlot(); - - if (gappleSlot == -999) { - return; - } - - if (gappleSlot != -1) { - if (this.originalSlot == -1) { - this.originalSlot = Minecraft.getMinecraft().player.inventory.currentItem; - } - Minecraft.getMinecraft().player.inventory.currentItem = gappleSlot; - } - - KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindUseItem.getKeyCode(), true); - isEatingGapple = true; - } else if (Minecraft.getMinecraft().player.getHealth() >= Minecraft.getMinecraft().player.getMaxHealth() && isEatingGapple) { - stopEating(); - } - } - - private void stopEating() { - KeyBinding.setKeyBindState(Minecraft.getMinecraft().gameSettings.keyBindUseItem.getKeyCode(), false); - if (this.originalSlot != -1) { - Minecraft.getMinecraft().player.inventory.currentItem = this.originalSlot; - this.originalSlot = -1; - } - isEatingGapple = false; - } - - @Override - public void onEnable() { - isEatingGapple = false; - originalSlot = -1; - } - - @Override - public void onDisable() { - stopEating(); - } - - private int getGappleSlot() { - final ItemStack mainHand = mc.player.getHeldItem(EnumHand.MAIN_HAND); - if(!mainHand.isEmpty() && mainHand.getItem() == Items.GOLDEN_APPLE) { - return mc.player.inventory.currentItem; - } - - final ItemStack offHand = mc.player.getHeldItem(EnumHand.OFF_HAND); - if(!offHand.isEmpty() && offHand.getItem() == Items.GOLDEN_APPLE) { - return -1; - } - - int slot = -999; - - for(int i = 0; i < 9; i++) { - final ItemStack stack = mc.player.inventory.getStackInSlot(i); - - if(stack.getItem() == Items.GOLDEN_APPLE) { - slot = i; - - if(stack.getMetadata() > 0) { - return slot; - } - } - } - - return slot; - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoTotem.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoTotem.java index 1645b259..2a73b258 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoTotem.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoTotem.java @@ -5,11 +5,18 @@ import net.minecraft.item.ItemStack; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.manager.ModuleManager; import xyz.templecheats.templeclient.util.setting.impl.IntSetting; public class AutoTotem extends Module { + /* + * Settings + */ private final IntSetting healthThreshold = new IntSetting("Health", this, 1, 20, 10); + /* + * Variables + */ private int delay = 0; private int totems; private int totemsOffHand; @@ -17,7 +24,7 @@ public class AutoTotem extends Module { private ItemStack originalOffhandItem = ItemStack.EMPTY; public AutoTotem() { - super("AutoTotem","Automatically places a totem in your offhand", Keyboard.KEY_NONE, Category.Combat); + super("AutoTotem", "Automatically places a totem in your offhand", Keyboard.KEY_NONE, Category.Combat); registerSettings(healthThreshold); } @@ -73,5 +80,10 @@ private void switchBackToOriginal() { public void onEnable() { totemSwitchDelay = 0; originalOffhandItem = ItemStack.EMPTY; + super.onEnable(); + Offhand offhand = (Offhand) ModuleManager.getModuleByName("Offhand"); + if (offhand.isEnabled()) { + offhand.disable(); + } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowAimbot.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowAimbot.java new file mode 100644 index 00000000..9680fd85 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowAimbot.java @@ -0,0 +1,70 @@ +package xyz.templecheats.templeclient.features.module.modules.combat; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.passive.IAnimals; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import java.util.Comparator; + +public class BowAimbot extends Module { + /* + * Settings + */ + private final BooleanSetting players = new BooleanSetting("Players", this, true); + private final BooleanSetting mobs = new BooleanSetting("Mobs", this, false); + private final BooleanSetting animals = new BooleanSetting("Animals", this, false); + private final DoubleSetting range = new DoubleSetting("Range", this, 1, 25, 10); + private final IntSetting extrapolation = new IntSetting("Extrapolation", this, 0, 10, 1); + + public BowAimbot() { + super("BowAimbot", "Automatically aims your bow at entities", Keyboard.KEY_NONE, Category.Combat); + registerSettings(players, mobs, animals, range, extrapolation); + } + + @Override + public void onUpdate() { + Entity target = mc.world.loadedEntityList.stream() + .filter(entity -> entity instanceof EntityLivingBase) + .filter(entity -> (entity instanceof EntityPlayer && players.booleanValue()) || + (entity.isCreatureType(EnumCreatureType.MONSTER, false) && mobs.booleanValue()) || + (entity instanceof IAnimals && animals.booleanValue() && !entity.isCreatureType(EnumCreatureType.MONSTER, false))) + .filter(entity -> entity != mc.player && !TempleClient.friendManager.isFriend(entity.getName())) + .filter(entity -> mc.player.getDistance(entity) <= range.doubleValue()) + .min(Comparator.comparing(entity -> entity.getDistance(mc.player))) + .orElse(null); + + if (target != null) { + aimAtTarget((EntityLivingBase) target); + } + } + + private void aimAtTarget(EntityLivingBase target) { + if (mc.player.getHeldItemMainhand().getItem() instanceof net.minecraft.item.ItemBow || mc.player.getHeldItemOffhand().getItem() instanceof net.minecraft.item.ItemBow) { + double speedX = target.posX - target.lastTickPosX; + double speedY = target.posY - target.lastTickPosY; + double speedZ = target.posZ - target.lastTickPosZ; + + double accelerationX = speedX - (target.lastTickPosX - target.prevPosX); + double accelerationY = speedY - (target.lastTickPosY - target.prevPosY); + double accelerationZ = speedZ - (target.lastTickPosZ - target.prevPosZ); + + double posX = target.posX + speedX + 0.5 * accelerationX; + double posZ = target.posZ + speedZ + 0.5 * accelerationZ; + + double diffX = posX - mc.player.posX; + double diffZ = posZ - mc.player.posZ; + + mc.player.rotationYaw = (float) (Math.atan2(diffZ, diffX) * 180.0 / Math.PI) - 90.0F; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowSpam.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowSpam.java new file mode 100644 index 00000000..dd203907 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/BowSpam.java @@ -0,0 +1,48 @@ +package xyz.templecheats.templeclient.features.module.modules.combat; + +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.CPacketPlayerDigging; +import net.minecraft.network.play.client.CPacketPlayerTryUseItem; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public class BowSpam extends Module { + /* + * Settings + */ + private final IntSetting ticks = new IntSetting("Ticks", this, 1, 10, 5); + + /* + * Variables + */ + private int tickCounter = 0; + + public BowSpam() { + super("BowSpam", "Spam arrows", Keyboard.KEY_NONE, Category.Combat); + this.registerSettings(ticks); + } + + @SubscribeEvent + public void onClientTick(TickEvent.ClientTickEvent event) { + if (mc.player == null || mc.world == null) { + return; + } + + ItemStack itemInHand = mc.player.getHeldItemMainhand(); + if (itemInHand.getItem() == Items.BOW && mc.player.isHandActive()) { + if (tickCounter >= ticks.intValue()) { + mc.player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.RELEASE_USE_ITEM, BlockPos.ORIGIN, mc.player.getHorizontalFacing())); + mc.player.stopActiveHand(); + mc.player.connection.sendPacket(new CPacketPlayerTryUseItem(mc.player.getActiveHand())); + tickCounter = 0; + } else { + tickCounter++; + } + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/HitBox.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/HitBox.java deleted file mode 100644 index 72a1da33..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/HitBox.java +++ /dev/null @@ -1,52 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.combat; - -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; - -public class HitBox extends Module { - private final DoubleSetting size = new DoubleSetting("Size", this, 0.1, 1, 1); - - public HitBox() { - super("Hitbox","Increases entities hitbox", Keyboard.KEY_NONE, Category.Combat); - - registerSettings(size); - } - - @SubscribeEvent - public void onUpdate(RenderWorldLastEvent e) { - if (this.toggled) { - float size = this.size.floatValue(); - - for (EntityPlayer player : mc.world.playerEntities) { - if (player != null && player != mc.player) { - player.setEntityBoundingBox(new AxisAlignedBB( - player.posX - size, - player.getEntityBoundingBox().minY, - player.posZ - size, - player.posX + size, - player.getEntityBoundingBox().maxY, - player.posZ + size - )); - } - } - } else { - for (EntityPlayer player : mc.world.playerEntities) { - if (player != null && player != mc.player) { - player.setEntityBoundingBox(new AxisAlignedBB( - player.posX - 0.3F, - player.getEntityBoundingBox().minY, - player.posZ - 0.3F, - player.posX + 0.3F, - player.getEntityBoundingBox().maxY, - player.posZ + 0.3F - )); - } - } - } - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Offhand.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Offhand.java new file mode 100644 index 00000000..28977c06 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Offhand.java @@ -0,0 +1,100 @@ +package xyz.templecheats.templeclient.features.module.modules.combat; + +import net.minecraft.init.Items; +import net.minecraft.inventory.ClickType; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.CPacketPlayer; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.manager.ModuleManager; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; + +import java.util.Arrays; + +public class Offhand extends Module { + /* + * Settings + */ + private final DoubleSetting health = new DoubleSetting("Health", this, 0.0d, 36.0d, 14.0d); + private final DoubleSetting defaultHealthVal = new DoubleSetting("DHV", this, 0.0f, 36.0f, 14.0f); + + public Offhand() { + super("Offhand", "Puts items in you're offhand", Keyboard.KEY_NONE, Category.Combat); + registerSettings(health, defaultHealthVal); + } + + @Override + public void onUpdate() { + final int slot = slot(); + if (slot != -1) { + swapItem(slot); + } + if (mc.player.getHeldItemOffhand().isEmpty()) { + inventorySlot(Items.END_CRYSTAL); + } + } + private int slot() { + if (mc.currentScreen != null) { + return -1; + } + final int totem = inventorySlot(Items.TOTEM_OF_UNDYING); + if (totem == -1) { + health.setDoubleValue(0.1f); + } else { + health.setDoubleValue(defaultHealthVal.doubleValue()); + } + if (mc.player.getHealth() + mc.player.getAbsorptionAmount() <= health.doubleValue()) { + return totem; + } + if (mc.player.getHeldItemMainhand().getItem().equals(Items.DIAMOND_SWORD)) { + if (mc.gameSettings.keyBindUseItem.isKeyDown()) { + return inventorySlot(Items.GOLDEN_APPLE); + } + + } + final int crystal = inventorySlot(Items.END_CRYSTAL); + if (crystal != -1) { + return inventorySlot(Items.END_CRYSTAL); + } + return totem; + } + + private void swapItem(final int i) { + final Item item = mc.player.inventory.getStackInSlot(i).getItem(); + if (!mc.player.getHeldItemOffhand().getItem().equals(item)) { + int slot = i < 9 ? i + 36 : i; + swap(new int[]{slot, 45, slot}); + mc.playerController.updateController(); + } + } + + private void swap(final int[] slots) { + if (mc.getConnection() != null) { + Arrays.stream(slots).forEach(i -> mc.playerController.windowClick(0, i, 0, ClickType.PICKUP, mc.player)); + mc.getConnection().sendPacket(new CPacketPlayer()); + } + } + + public int inventorySlot(final Item item) { + int itemSlot = -1; + for (int i = 45; i > 0; --i) { + final ItemStack stack = mc.player.inventory.getStackInSlot(i); + if (stack.getItem().equals(item)) { + itemSlot = i; + break; + } + } + return itemSlot; + } + + @Override + public void onEnable() { + super.onEnable(); + AutoTotem autoTotem = (AutoTotem) ModuleManager.getModuleByName("AutoTotem"); + if (autoTotem.isEnabled()) { + autoTotem.disable(); + } + } +} + diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Surround.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Surround.java index 65538ab7..c7fb223c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Surround.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Surround.java @@ -18,8 +18,14 @@ import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; import xyz.templecheats.templeclient.util.time.TimerUtil; - public class Surround extends Module { + /** + * Setings + */ + private final BooleanSetting disableOnJump = new BooleanSetting("Disable On Jump", this, false); + private final BooleanSetting strictDir = new BooleanSetting("Strict Dir", this, false); + private final DoubleSetting placeDelay = new DoubleSetting("Place Delay", this, 0d, 150d, 10d); + /** * Variables */ @@ -27,21 +33,18 @@ public class Surround extends Module { private EnumFacing placeFace; private TimerUtil timer = new TimerUtil(); - /** - * Setings - */ - private final BooleanSetting strictDir = new BooleanSetting("Strict Dir", this, false); - private final DoubleSetting placeDelay = new DoubleSetting("Place Delay", this, 0d, 150d, 10d); - public Surround() { - super("Surround", "Surrounds you with blocks", Keyboard.KEY_NONE, Category.Combat); + super("Surround", "Automatically surrounds your feet with obsidian", Keyboard.KEY_NONE, Category.Combat); - registerSettings(strictDir, placeDelay); + registerSettings(disableOnJump, strictDir, placeDelay); } - @Listener public void onMotion(MotionEvent event) { + if (disableOnJump.booleanValue() && mc.player.motionY > 0) { + this.disable(); + return; + } final EnumHand placeHand; int newSlot = -1; int oldSlot = mc.player.inventory.currentItem; @@ -71,7 +74,7 @@ public void onMotion(MotionEvent event) { case PRE: final BlockPos playerPos = new BlockPos(mc.player.posX, mc.player.posY, mc.player.posZ); - for (EnumFacing direction : EnumFacing.values()) { + for (EnumFacing direction: EnumFacing.values()) { if (direction == EnumFacing.UP || direction == EnumFacing.DOWN) { continue; } @@ -82,7 +85,7 @@ public void onMotion(MotionEvent event) { continue; } - for (EnumFacing supportDir : EnumFacing.values()) { + for (EnumFacing supportDir: EnumFacing.values()) { final BlockPos supportPos = targetPos.offset(supportDir); if (this.isSupportBlock(supportPos, supportDir.getOpposite())) { @@ -92,7 +95,7 @@ public void onMotion(MotionEvent event) { } if (this.canPlaceBlock(supportPos)) { - for (EnumFacing extendDir : EnumFacing.values()) { + for (EnumFacing extendDir: EnumFacing.values()) { final BlockPos extendPos = supportPos.offset(extendDir); if (this.isSupportBlock(extendPos, extendDir.getOpposite())) { diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Trigger.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/TriggerBot.java similarity index 86% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Trigger.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/TriggerBot.java index 801eaa77..75b51e84 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Trigger.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/TriggerBot.java @@ -11,12 +11,15 @@ import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.features.module.Module; -public class Trigger extends Module { +public class TriggerBot extends Module { + /* + * Variables + */ private Entity entity; private EntityLivingBase renderTarget; - public Trigger() { - super("Trigger","Automatically hits target when aimed at", Keyboard.KEY_NONE, Category.Combat); + public TriggerBot() { + super("TriggerBot", "Automatically attack entities that are on your crosshair", Keyboard.KEY_NONE, Category.Combat); } @SubscribeEvent @@ -42,7 +45,7 @@ public void onPlayerTick(TickEvent.PlayerTickEvent e) { } @Override public String getHudInfo() { - if(this.renderTarget != null) { + if (this.renderTarget != null) { return this.renderTarget.getName(); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Velocity.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Velocity.java index 768f6506..e6ba8d6c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Velocity.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/Velocity.java @@ -1,29 +1,108 @@ package xyz.templecheats.templeclient.features.module.modules.combat; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.projectile.EntityFishHook; +import net.minecraft.network.play.client.CPacketEntityAction; +import net.minecraft.network.play.client.CPacketPlayer; import net.minecraft.network.play.server.SPacketEntityVelocity; import net.minecraft.network.play.server.SPacketExplosion; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; import xyz.templecheats.templeclient.event.events.network.PacketEvent; import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.mixins.IMixinSPacketExplosion; +import xyz.templecheats.templeclient.mixins.accessor.IMixinSPacketEntityVelocity; +import xyz.templecheats.templeclient.mixins.accessor.IMixinSPacketExplosion; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public final class Velocity extends Module { + /* + * Settings + */ + private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.CancelPacket); + private final IntSetting horizontalVelocity = new IntSetting("Horizontal", this, 1, 100, 100); + private final IntSetting verticalVelocity = new IntSetting("Vertical", this, 1, 100, 100); + private final BooleanSetting explosions = new BooleanSetting("Explosions", this, true); + private boolean cancelVelocity = false; + + /* + * Variables + */ + + public final Minecraft mc = Minecraft.getMinecraft(); -public class Velocity extends Module { public Velocity() { - super("Velocity","Reduces knockback", Keyboard.KEY_NONE, Category.Combat); + super("Velocity", "Reduces knockback velocity", Keyboard.KEY_NONE, Category.Combat); + registerSettings(explosions, horizontalVelocity, verticalVelocity, mode); } - @Listener - public void onPacketRecieve(PacketEvent.Receive event) { - if(event.getPacket() instanceof SPacketEntityVelocity && ((SPacketEntityVelocity) event.getPacket()).getEntityID() == mc.player.getEntityId()) { - event.setCanceled(true); + public void onPacketReceive(PacketEvent.Receive event) { + if (mc.player == null) return; + if (mode.value() == Mode.CancelPacket) { + if (event.getPacket() instanceof SPacketEntityVelocity && ((SPacketEntityVelocity) event.getPacket()).getEntityID() == this.mc.player.getEntityId() || event.getPacket() instanceof SPacketExplosion || event.getPacket() instanceof EntityFishHook) { + event.setCanceled(true); + } + } else { + if (event.getPacket() instanceof SPacketEntityVelocity) { + SPacketEntityVelocity velocityPacket = (SPacketEntityVelocity) event.getPacket(); + if (velocityPacket.getEntityID() == mc.player.getEntityId()) { + switch (mode.value()) { + case Normal: + if (this.horizontalVelocity.intValue() == 0 && this.verticalVelocity.intValue() == 0) { + event.setCanceled(true); + } else { + ((IMixinSPacketEntityVelocity) velocityPacket).setMotionX(velocityPacket.getMotionX() / 100 * this.horizontalVelocity.intValue()); + ((IMixinSPacketEntityVelocity) velocityPacket).setMotionZ(velocityPacket.getMotionZ() / 100 * this.horizontalVelocity.intValue()); + ((IMixinSPacketEntityVelocity) velocityPacket).setMotionY(velocityPacket.getMotionY() / 100 * this.verticalVelocity.intValue()); + } + break; + case Grim: + event.setCanceled(true); + cancelVelocity = true; + break; + } + } + } else if (event.getPacket() instanceof SPacketExplosion && this.explosions.booleanValue()) { + SPacketExplosion explosionPacket = (SPacketExplosion) event.getPacket(); + switch (mode.value()) { + case Normal: + if (this.horizontalVelocity.intValue() == 0 && this.verticalVelocity.intValue() == 0) { + ((IMixinSPacketExplosion) explosionPacket).setMotionX(0); + ((IMixinSPacketExplosion) explosionPacket).setMotionY(0); + ((IMixinSPacketExplosion) explosionPacket).setMotionZ(0); + } else { + ((IMixinSPacketExplosion) explosionPacket).setMotionX(explosionPacket.getMotionX() / 100 * this.horizontalVelocity.intValue()); + ((IMixinSPacketExplosion) explosionPacket).setMotionY(explosionPacket.getMotionY() / 100 * this.verticalVelocity.intValue()); + ((IMixinSPacketExplosion) explosionPacket).setMotionZ(explosionPacket.getMotionZ() / 100 * this.horizontalVelocity.intValue()); + } + break; + case Grim: + event.setCanceled(true); + cancelVelocity = true; + break; + } + } } + } - if(event.getPacket() instanceof SPacketExplosion) { - ((IMixinSPacketExplosion) event.getPacket()).setMotionX(0); - ((IMixinSPacketExplosion) event.getPacket()).setMotionY(0); - ((IMixinSPacketExplosion) event.getPacket()).setMotionZ(0); + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.START && cancelVelocity && mode.value() == Mode.Grim) { + cancelVelocity = false; + float yaw = mc.player.rotationYaw; + float pitch = mc.player.rotationPitch; + mc.player.connection.sendPacket(new CPacketPlayer.PositionRotation(mc.player.posX, mc.player.getEntityBoundingBox().minY, mc.player.posZ, yaw, pitch, mc.player.onGround)); + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SPRINTING)); } } + + public enum Mode { + Normal, + CancelPacket, + Grim + } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoClicker.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoClicker.java similarity index 82% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoClicker.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoClicker.java index 83313a4f..fda24b13 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/AutoClicker.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoClicker.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.module.modules.combat; +package xyz.templecheats.templeclient.features.module.modules.misc; import net.minecraft.client.settings.KeyBinding; import org.lwjgl.input.Keyboard; @@ -10,16 +10,21 @@ import java.util.function.IntSupplier; public class AutoClicker extends Module { + /* + * Settings + */ private final IntSetting cps = new IntSetting("CPS", this, 1, 100, 10); - private final EnumSetting clickType = new EnumSetting<>("Click Type", this, ClickType.LeftClick); + private final EnumSetting < ClickType > clickType = new EnumSetting < > ("Click Type", this, ClickType.LeftClick); + /* + * Variables + */ private long lastClick; private long hold; - private double holdLength; public AutoClicker() { - super("AutoClicker","Automatically clicks the mouse while mouse is held down", Keyboard.KEY_NONE, Category.Combat); + super("AutoClicker", "Automatically clicks while mouse is held down", Keyboard.KEY_NONE, Category.Misc); registerSettings(cps, clickType); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoMount.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoMount.java new file mode 100644 index 00000000..163e23e4 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoMount.java @@ -0,0 +1,78 @@ +package xyz.templecheats.templeclient.features.module.modules.misc; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.passive.*; +import net.minecraft.entity.item.EntityBoat; +import net.minecraft.entity.item.EntityMinecart; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import java.util.List; + +public class AutoMount extends Module { + /* + * Settings + */ + private final BooleanSetting horses = new BooleanSetting("Horses", this, true); + private final BooleanSetting donkeys = new BooleanSetting("Donkeys", this, true); + private final BooleanSetting llamas = new BooleanSetting("Llamas", this, true); + private final BooleanSetting boats = new BooleanSetting("Boats", this, true); + private final BooleanSetting minecarts = new BooleanSetting("Minecarts", this, true); + private final BooleanSetting pigs = new BooleanSetting("Pigs", this, true); + private final IntSetting range = new IntSetting("Range", this, 1, 6, 3); + private final IntSetting delay = new IntSetting("Delay", this, 1, 10, 5); + + /* + * Variables + */ + private int ticks = 0; + + public AutoMount() { + super("AutoMount", "Automatically mounts entities", Keyboard.KEY_NONE, Category.Misc); + this.registerSettings(horses, donkeys, llamas, boats, minecarts, pigs, range, delay); + } + @SubscribeEvent + public void onTick(TickEvent.ClientTickEvent event) { + if (event.phase == TickEvent.Phase.START) { + if (mc.player == null || mc.world == null) { + return; + } + + if (mc.player.isRiding()) { + return; + } + + ticks++; + + if (ticks < delay.intValue()) { + return; + } + + ticks = 0; + + List < Entity > entities = mc.world.getEntitiesWithinAABBExcludingEntity(mc.player, mc.player.getEntityBoundingBox().grow(range.intValue())); + for (Entity entity: entities) { + if ((entity instanceof EntityHorse && horses.booleanValue()) || + (entity instanceof EntityDonkey && donkeys.booleanValue()) || + (entity instanceof EntityLlama && llamas.booleanValue()) || + (entity instanceof EntityBoat && boats.booleanValue()) || + (entity instanceof EntityMinecart && minecarts.booleanValue()) || + (entity instanceof EntityPig && pigs.booleanValue())) { + mc.player.startRiding(entity); + break; + } + } + } + } + + @Override + public void onDisable() { + if (mc.player != null && mc.player.isRiding()) { + mc.player.dismountRidingEntity(); + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoRespawn.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoRespawn.java index eb8b65cb..a2cd3ad2 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoRespawn.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/AutoRespawn.java @@ -3,13 +3,20 @@ import net.minecraft.client.Minecraft; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.StringSetting; public class AutoRespawn extends Module { - + /* + * Variables + */ private long deathTime = 0; + private final BooleanSetting autoKit = new BooleanSetting("AutoKit", this, false); + private final StringSetting command = new StringSetting("Command", this, "/kit temple"); public AutoRespawn() { - super("AutoRespawn","Automatically respawn after death", Keyboard.KEY_NONE, Category.Miscelleaneous); + super("AutoRespawn", "Automatically respawn when you die", Keyboard.KEY_NONE, Category.Misc); + registerSettings(autoKit, command); } @Override @@ -20,6 +27,10 @@ public void onUpdate() { if (System.currentTimeMillis() - deathTime > 100) { Minecraft.getMinecraft().player.respawnPlayer(); + if (autoKit.booleanValue() && deathTime++ >= 20) { + if (!command.getStringValue().startsWith("/")) return; + Minecraft.getMinecraft().player.sendChatMessage(command.getStringValue()); + } deathTime = 0; } } else { @@ -27,4 +38,4 @@ public void onUpdate() { } } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ChestStealer.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ChestStealer.java deleted file mode 100644 index 8359945e..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ChestStealer.java +++ /dev/null @@ -1,45 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.misc; - -import net.minecraft.client.Minecraft; -import net.minecraft.inventory.ClickType; -import net.minecraft.inventory.Container; -import net.minecraft.inventory.Slot; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; - -public class ChestStealer extends Module { - private int counter = 0; - private static final int THRESHOLD = 10; - private static final long DELAY = 1000; - public ChestStealer() { - super("ChestStealer", "Steals everything from any container", Keyboard.KEY_NONE, Category.Miscelleaneous); - } - - @Override - public void onUpdate() { - if (mc.player.openContainer == null) { - return; - } - - Container container = mc.player.openContainer; - for (int i = 0; i < container.inventorySlots.size(); i++) { - Slot slot = container.getSlot(i); - - if (slot.inventory == mc.player.inventory) { - continue; - } - - if (slot.getHasStack()) { - int finalI = i; - new Thread(() -> { - try { - Thread.sleep(DELAY); - Minecraft.getMinecraft().playerController.windowClick(container.windowId, finalI, 0, ClickType.QUICK_MOVE, mc.player); - } catch (InterruptedException e) { - e.printStackTrace(); - } - }).start(); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ExtraChest.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ExtraChest.java new file mode 100644 index 00000000..ba937e44 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/ExtraChest.java @@ -0,0 +1,83 @@ +package xyz.templecheats.templeclient.features.module.modules.misc; + +import net.minecraft.client.Minecraft; +import net.minecraft.inventory.ClickType; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public class ExtraChest extends Module { + /* + * Settings + */ + private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Steal); + private final IntSetting dropDelay = new IntSetting("Drop Delay", this, 1, 10, 1); + private final IntSetting stealDelay = new IntSetting("Steal Delay", this, 1, 10, 1); + + public ExtraChest() { + super("ExtraChest", "Automatically steal/fill items from containers", Keyboard.KEY_NONE, Category.Misc); + registerSettings(dropDelay, stealDelay, mode); + } + + @Override + public void onUpdate() { + if (mc.player.openContainer == null) { + return; + } + + Container container = mc.player.openContainer; + switch (mode.value()) { + case Steal: + case Drop: + for (int i = 0; i < container.inventorySlots.size(); i++) { + Slot slot = container.getSlot(i); + + if (slot.inventory == mc.player.inventory) { + continue; + } + + if (slot.getHasStack()) { + performAction(container, i, mode.value()); + } + } + break; + } + } + + private void performAction(Container container, int slotId, Mode mode) { + new Thread(() -> { + try { + Thread.sleep(getDelay()); + switch (mode) { + case Steal: + Minecraft.getMinecraft().playerController.windowClick(container.windowId, slotId, 0, ClickType.QUICK_MOVE, mc.player); + break; + case Drop: + Minecraft.getMinecraft().playerController.windowClick(container.windowId, slotId, 1, ClickType.THROW, mc.player); + break; + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + }).start(); + } + + private long getDelay() { + switch (mode.value()) { + case Steal: + return stealDelay.intValue() * 100; + case Drop: + return dropDelay.intValue() * 100; + default: + return 1; + } + } + + private enum Mode { + Steal, + Drop + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakeCreative.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakeCreative.java deleted file mode 100644 index 87dbbeef..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakeCreative.java +++ /dev/null @@ -1,24 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.misc; - -import net.minecraft.world.GameType; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.features.module.modules.client.Panic; - -public class FakeCreative extends Module { - public FakeCreative() { - super("FakeCreative","Client sided creative", Keyboard.KEY_NONE, Category.Miscelleaneous); - } - - @Override - public void onEnable() { - mc.playerController.setGameType(GameType.CREATIVE); - } - - @Override - public void onDisable() { - if (!Panic.isPanic) { - mc.playerController.setGameType(GameType.SURVIVAL); - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakePlayer.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakePlayer.java index 9bb3f9d4..514ed3cb 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakePlayer.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/FakePlayer.java @@ -4,31 +4,42 @@ import net.minecraft.client.entity.EntityOtherPlayerMP; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.features.module.modules.client.Panic; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.StringSetting; import java.util.Random; public class FakePlayer extends Module { - private static final Random random = new Random(); + /* + * Setting + */ + private final StringSetting name = new StringSetting("Name", this, "Temple-Client"); private final BooleanSetting moveButton = new BooleanSetting("Move", this, false); + + /* + * Variables + */ + private static final Random random = new Random(); private AttackableFakePlayer fakePlayer; private BlockPos respawnLocation; public FakePlayer() { - super("FakePlayer","Spawns in a fake player", Keyboard.KEY_NONE, Category.Miscelleaneous); + super("FakePlayer", "Spawns in a fake player", Keyboard.KEY_NONE, Category.Misc); - this.registerSettings(moveButton); + this.registerSettings(name, moveButton); } @Override public void onEnable() { - if(mc.player == null) { + if (mc.player == null) { return; } - GameProfile profile = new GameProfile(mc.player.getUniqueID(), "temple-client bot"); + GameProfile profile = new GameProfile(mc.player.getUniqueID(), name.getStringValue()); fakePlayer = new AttackableFakePlayer(mc.world, profile); fakePlayer.setEntityId(-1882); fakePlayer.copyLocationAndAnglesFrom(mc.player); @@ -37,9 +48,14 @@ public void onEnable() { mc.world.addEntityToWorld(fakePlayer.getEntityId(), fakePlayer); } + @SubscribeEvent + public void onPlayerLogout(PlayerEvent.PlayerLoggedOutEvent event) { + this.disable(); + } + @Override public void onDisable() { - if(fakePlayer == null) { + if (fakePlayer == null) { return; } if (!Panic.isPanic) { diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Gamemode.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Gamemode.java new file mode 100644 index 00000000..f89208c8 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Gamemode.java @@ -0,0 +1,55 @@ +package xyz.templecheats.templeclient.features.module.modules.misc; + +import net.minecraft.world.GameType; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import static xyz.templecheats.templeclient.features.module.modules.misc.Gamemode.ClientGameType.*; + +public class Gamemode extends Module { + /* + * Settings + */ + private final EnumSetting gameType = new EnumSetting<>("Gamemode", this, CREATIVE); + public Gamemode() { + super("Gamemode", "Change your gamemode client-side", Keyboard.KEY_NONE, Category.Misc); + this.registerSettings(gameType); + } + + @Override + public void onUpdate() { + switch (gameType.value()) { + case SURVIVAL: + mc.playerController.setGameType(GameType.SURVIVAL); + break; + case CREATIVE: + mc.playerController.setGameType(GameType.CREATIVE); + break; + case ADVENTURE: + mc.playerController.setGameType(GameType.ADVENTURE); + break; + case SPECTATOR: + mc.playerController.setGameType(GameType.SPECTATOR); + break; + } + } + + public enum ClientGameType { + SURVIVAL("Survival"), + CREATIVE("Creative"), + ADVENTURE("Adventure"), + SPECTATOR("Spectator"); + + private final String name; + + ClientGameType(String name) { + this.name = name; + } + + @Override + public String toString() { + return this.name; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Log4jAlert.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Log4jAlert.java index a5edb5a2..989953e6 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Log4jAlert.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Log4jAlert.java @@ -9,11 +9,13 @@ import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; public class Log4jAlert extends Module { - + /* + * Settings + */ private final BooleanSetting DisconnectOnReceive = new BooleanSetting("Disconnect", this, false); public Log4jAlert() { - super("Log4jAlert", "Alerts you when someone sends a log4j exploit in chat", Keyboard.KEY_NONE, Category.Miscelleaneous); + super("Log4jAlert", "Alerts you when someone sends a log4j exploit in chat", Keyboard.KEY_NONE, Category.Misc); this.registerSettings(DisconnectOnReceive); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Particles.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Particles.java index c940aab5..7e1a50d2 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Particles.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/misc/Particles.java @@ -7,7 +7,7 @@ public class Particles extends Module { public Particles() { - super("Particles","Increases particle volume", Keyboard.KEY_NONE, Category.Miscelleaneous); + super("Particles", "Customizes particle volume and texture", Keyboard.KEY_NONE, Category.Misc); } @SubscribeEvent diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/AutoWalk.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/AutoWalk.java index 17535bf6..d99fd335 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/AutoWalk.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/AutoWalk.java @@ -8,7 +8,7 @@ public class AutoWalk extends Module { public AutoWalk() { - super("AutoWalk","Automatically walks towards the direction your aiming at", Keyboard.KEY_NONE, Category.Movement); + super("AutoWalk", "Automatically walks", Keyboard.KEY_NONE, Category.Movement); } @Override @@ -29,7 +29,7 @@ public void onUpdate() { KeyBinding.setKeyBindState(mc.gameSettings.keyBindForward.getKeyCode(), true); if (isInWater()) { - KeyBinding.setKeyBindState(mc.gameSettings.keyBindJump.getKeyCode(), true); // Swim upwards + KeyBinding.setKeyBindState(mc.gameSettings.keyBindJump.getKeyCode(), true); } else { KeyBinding.setKeyBindState(mc.gameSettings.keyBindJump.getKeyCode(), false); } @@ -40,4 +40,4 @@ private boolean isInWater() { BlockPos playerPos = new BlockPos(mc.player.posX, mc.player.posY, mc.player.posZ); return mc.world.getBlockState(playerPos).getMaterial() == Material.WATER; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/BoatFly.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/BoatFly.java deleted file mode 100644 index e23173b3..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/BoatFly.java +++ /dev/null @@ -1,22 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.movement; - -import net.minecraft.entity.item.EntityBoat; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; - -public class BoatFly extends Module { - public BoatFly() { - super("BoatFly", "Allows flying in a boat", Keyboard.KEY_NONE, Category.Movement); - } - - @SubscribeEvent - public void onPlayerTick(TickEvent.PlayerTickEvent e) { - if (mc.player == null || mc.world == null) return; - if (mc.player.getRidingEntity() instanceof EntityBoat) { - EntityBoat boat = (EntityBoat) mc.player.getRidingEntity(); - boat.motionY = mc.gameSettings.keyBindJump.isKeyDown() ? 1 : 0; - } - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/ElytraPlus.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/ElytraPlus.java index a7ea8ce8..6fe56f57 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/ElytraPlus.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/ElytraPlus.java @@ -1,73 +1,113 @@ package xyz.templecheats.templeclient.features.module.modules.movement; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.event.events.player.MoveEvent; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.math.MathUtil; -public class ElytraPlus extends Module { - private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Boost); - private final DoubleSetting speed = new DoubleSetting("Control Speed", this, 0, 5, 1); - private boolean moving; +public final class ElytraPlus extends Module { + /* + * Settings + */ + public final EnumSetting < Mode > mode = new EnumSetting < > ("Mode", this, Mode.Look); + public final DoubleSetting speed = new DoubleSetting("Speed", this, 1.0f, 5.0f, 0.1f); + public final DoubleSetting speedX = new DoubleSetting("SpeedX", this, 1.0f, 5.0f, 0.1f); + public final DoubleSetting speedYUp = new DoubleSetting("SpeedYUp", this, 1.0f, 5.0f, 0.1f); + public final DoubleSetting speedYDown = new DoubleSetting("SpeedYDown", this, 1.0f, 5.0f, 0.1f); + public final DoubleSetting speedZ = new DoubleSetting("SpeedZ", this, 1.0f, 5.0f, 0.1f); + public final BooleanSetting noKick = new BooleanSetting("NoKick", this, false); public ElytraPlus() { - super("Elytra+","Allows you to fly with elytras", Keyboard.KEY_NONE, Category.Movement); + super("ElytraPlus", "Allows for better elytra control", Keyboard.KEY_NONE, Category.Movement); + this.registerSettings(noKick, speed, speedX, speedYUp, speedYDown, speedZ, mode); + } - registerSettings(speed, mode); + @Override + public void onEnable() { + super.onEnable(); } - @SubscribeEvent - public void onPlayerTick(TickEvent.PlayerTickEvent event) { - if (mc.player == null || !mc.player.isElytraFlying()) return; + @Override + public void onDisable() { + super.onDisable(); - float yaw = mc.player.rotationYaw; - float pitch = mc.player.rotationPitch; - double boostSpeed = 0.02; - double controlSpeed = speed.doubleValue(); - double controlUpSpeed = speed.doubleValue(); - double controlDownSpeed = -speed.doubleValue(); - double controlMoveSpeed = speed.doubleValue(); + if (Minecraft.getMinecraft().player != null) { + Minecraft.getMinecraft().player.capabilities.isFlying = false; + } + } + @Listener + public void move(MoveEvent event) { + Minecraft mc = Minecraft.getMinecraft(); - if (mode.value() == Mode.Boost) { - if (mc.gameSettings.keyBindForward.isKeyDown()) { - mc.player.motionX -= Math.sin(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * boostSpeed; - mc.player.motionZ += Math.cos(Math.toRadians(yaw)) * Math.cos(Math.toRadians(pitch)) * boostSpeed; - mc.player.motionY += Math.sin(Math.toRadians(pitch)) * boostSpeed; - } - if (mc.gameSettings.keyBindJump.isKeyDown()) mc.player.motionY += boostSpeed; - if (mc.gameSettings.keyBindSneak.isKeyDown()) mc.player.motionY -= boostSpeed; - } else if (mode.value() == Mode.Control) { - double verticalMotion = 0.0; - double horizontalMotionX = 0.0; - double horizontalMotionZ = 0.0; + if (mc.player.isElytraFlying()) { + final double[] directionSpeed = MathUtil.directionSpeed(this.speed.doubleValue()); - if (mc.gameSettings.keyBindForward.isKeyDown()) { - horizontalMotionX -= Math.sin(Math.toRadians(yaw)) * controlMoveSpeed; - horizontalMotionZ += Math.cos(Math.toRadians(yaw)) * controlMoveSpeed; - } - if (mc.gameSettings.keyBindBack.isKeyDown()) { - horizontalMotionX += Math.sin(Math.toRadians(yaw)) * controlMoveSpeed; - horizontalMotionZ -= Math.cos(Math.toRadians(yaw)) * controlMoveSpeed; - } - if (mc.gameSettings.keyBindLeft.isKeyDown()) { - horizontalMotionX -= Math.sin(Math.toRadians(yaw - 90)) * controlMoveSpeed; - horizontalMotionZ += Math.cos(Math.toRadians(yaw - 90)) * controlMoveSpeed; - } - if (mc.gameSettings.keyBindRight.isKeyDown()) { - horizontalMotionX -= Math.sin(Math.toRadians(yaw + 90)) * controlMoveSpeed; - horizontalMotionZ += Math.cos(Math.toRadians(yaw + 90)) * controlMoveSpeed; + if (this.mode.value() == Mode.Control) { + mc.player.motionY = 0; + mc.player.motionX = 0; + mc.player.motionZ = 0; + + if (mc.player.movementInput.jump) { + mc.player.motionY = (this.speed.doubleValue() / 2) * this.speedYUp.doubleValue(); + } else if (mc.player.movementInput.sneak) { + mc.player.motionY = -(this.speed.doubleValue() / 2) * this.speedYDown.doubleValue(); + } + if (mc.player.movementInput.moveStrafe != 0 || mc.player.movementInput.moveForward != 0) { + mc.player.motionX = directionSpeed[0] * this.speedX.doubleValue(); + mc.player.motionZ = directionSpeed[1] * this.speedZ.doubleValue(); + } + + event.setX(mc.player.motionX); + event.setY(mc.player.motionY); + event.setZ(mc.player.motionZ); + } else if (this.mode.value() == Mode.Look) { + mc.player.motionX = 0; + mc.player.motionY = 0; + mc.player.motionZ = 0; + if (mc.gameSettings.keyBindForward.isKeyDown() || mc.gameSettings.keyBindBack.isKeyDown()) { + mc.player.motionY = (this.speed.doubleValue() * (-1 * (Math.sin(MathUtil.degToRad(mc.player.rotationPitch))))) * mc.player.movementInput.moveForward; + } + if (mc.player.movementInput.jump) { + mc.player.motionY = (this.speed.doubleValue() / 2) * this.speedYUp.doubleValue(); + } else if (mc.player.movementInput.sneak) { + mc.player.motionY = -(this.speed.doubleValue() / 2) * this.speedYDown.doubleValue(); + } + if (mc.player.movementInput.moveStrafe != 0 && mc.player.movementInput.moveForward == 0) { + mc.player.motionX = directionSpeed[0] * this.speedX.doubleValue(); + mc.player.motionZ = directionSpeed[1] * this.speedZ.doubleValue(); + } else if (mc.player.movementInput.moveStrafe != 0 || mc.player.movementInput.moveForward != 0) { + mc.player.motionX = directionSpeed[0] * (Math.cos(Math.abs(MathUtil.degToRad(mc.player.rotationPitch)))) * this.speedX.doubleValue(); + mc.player.motionZ = directionSpeed[1] * (Math.cos(Math.abs(MathUtil.degToRad(mc.player.rotationPitch)))) * this.speedZ.doubleValue(); + } + event.setX(mc.player.motionX); + event.setY(mc.player.motionY); + event.setZ(mc.player.motionZ); } - if (mc.gameSettings.keyBindJump.isKeyDown()) verticalMotion += controlUpSpeed; - if (mc.gameSettings.keyBindSneak.isKeyDown()) verticalMotion += controlDownSpeed; + } + } - mc.player.setVelocity(horizontalMotionX, verticalMotion, horizontalMotionZ); + private void freezePlayer(EntityPlayer player) { + player.motionX = 0; + player.motionY = 0; + player.motionZ = 0; + } + + private void runNoKick(EntityPlayer player) { + if (this.noKick.booleanValue() && !player.isElytraFlying()) { + if (player.ticksExisted % 4 == 0) { + player.motionY = -0.04f; + } } } private enum Mode { - Boost, + Look, Control } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/FastFall.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/FastFall.java new file mode 100644 index 00000000..44ad6b71 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/FastFall.java @@ -0,0 +1,23 @@ +package xyz.templecheats.templeclient.features.module.modules.movement; + +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public class FastFall extends Module { + public final IntSetting fallSpeed = new IntSetting("Fall Speed", this, 1, 50, 2); + + public FastFall() { + super("FastFall", "allows you to go down blocks fast", Keyboard.KEY_NONE, Category.Movement); + registerSettings(fallSpeed); + } + @Override + public void onUpdate() { + if (mc.player.isElytraFlying() || mc.player.isOnLadder() || mc.player.capabilities.isFlying || mc.player.motionY > 0.0 || mc.gameSettings.keyBindJump.isKeyDown()) { + return; + } + if (mc.player.onGround) { + mc.player.motionY = -fallSpeed.intValue(); + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Flight.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Flight.java index f8a1b3df..3ee8e782 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Flight.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Flight.java @@ -1,38 +1,101 @@ package xyz.templecheats.templeclient.features.module.modules.movement; +import net.minecraft.client.Minecraft; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; public class Flight extends Module { + /* + * Settings + */ + private final EnumSetting mode = new EnumSetting<>("Mode", this, FlightMode.Creative); + private final BooleanSetting antiKick = new BooleanSetting("Anti Kick", this, false); + private final IntSetting speedSetting = new IntSetting("Speed", this, 1, 20, 5); + + /* + * Variables + */ + private int tickCounter = 0; + public Flight() { - super("Flight","Allows flying (really?)", Keyboard.KEY_NONE, Category.Movement); + super("Flight", "Fly like a bird", Keyboard.KEY_NONE, Category.Movement); + registerSettings(antiKick, speedSetting, mode); } @Override public void onEnable() { - mc.player.capabilities.isFlying = true; - mc.player.capabilities.allowFlying = true; + if (mode.value() == FlightMode.Creative) { + mc.player.capabilities.allowFlying = true; + mc.player.capabilities.isFlying = true; + } } @Override public void onDisable() { mc.player.capabilities.isFlying = false; mc.player.capabilities.allowFlying = false; + mc.player.capabilities.setFlySpeed(0.05f); + tickCounter = 0; } @SubscribeEvent - public void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { - if (event.player == mc.player) { - onEnable(); + public void onPlayerTick(TickEvent.PlayerTickEvent event) { + if (event.player != mc.player) { + return; } - } - @SubscribeEvent - public void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) { - if (event.player == mc.player) { - onDisable(); + if (mode.value() == FlightMode.Normal) { + mc.player.capabilities.isFlying = false; + float speed = speedSetting.intValue() * 0.05f; + if (mc.gameSettings.keyBindJump.isKeyDown()) { + mc.player.motionY = speed; + } else if (mc.gameSettings.keyBindSneak.isKeyDown()) { + mc.player.motionY = -speed; + } else if (!antiKick.booleanValue() || (antiKick.booleanValue() && tickCounter % 60 != 0)) { + mc.player.motionY = 0; + } + + double forward = mc.player.movementInput.moveForward; + double strafe = mc.player.movementInput.moveStrafe; + float yaw = mc.player.rotationYaw; + + if (forward != 0 || strafe != 0) { + if (forward != 0) { + if (strafe > 0) { + yaw += (forward > 0 ? -45 : 45); + } else if (strafe < 0) { + yaw += (forward > 0 ? 45 : -45); + } + strafe = 0; + forward = forward > 0 ? 1 : -1; + } + + double sin = Math.sin(Math.toRadians(yaw + 90)); + double cos = Math.cos(Math.toRadians(yaw + 90)); + mc.player.motionX = forward * speed * cos + strafe * speed * sin; + mc.player.motionZ = forward * speed * sin - strafe * speed * cos; + } else { + mc.player.motionX = 0; + mc.player.motionZ = 0; + } + } + + if (antiKick.booleanValue()) { + if (tickCounter >= 60) { + mc.player.motionY -= 0.5; + tickCounter = 0; + } + tickCounter++; } } + + private enum FlightMode { + Normal, + Creative + } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Glide.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Glide.java deleted file mode 100644 index 44b56b66..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Glide.java +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.movement; - -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; - -public class Glide extends Module { - public Glide() { - super("Glide","Glides when falling for a smoother landing", Keyboard.KEY_NONE, Category.Movement); - } - - @SubscribeEvent - public void onPlayerTick(TickEvent.PlayerTickEvent e) { - if (mc.player.fallDistance != 0 && mc.player.motionY != 0) { - mc.player.motionY = -0.125; - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/GuiWalk.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/GuiWalk.java index 242af7c6..e9b8e808 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/GuiWalk.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/GuiWalk.java @@ -10,16 +10,18 @@ import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClickGuiScreen; import xyz.templecheats.templeclient.features.module.Module; public class GuiWalk extends Module { + /* + * Constants + */ private static final double DEFAULT_SPEED = 0.05; public GuiWalk() { - super("GuiWalk","Allows you to move while guis are open", Keyboard.KEY_NONE, Category.Movement); + super("GuiWalk", "Allows you to move while guis are open", Keyboard.KEY_NONE, Category.Movement); } @SubscribeEvent public void onClientTick(TickEvent.ClientTickEvent e) { if (!(mc.currentScreen instanceof GuiChat) && !(mc.currentScreen instanceof GuiContainer) && !(mc.currentScreen instanceof ClickGuiScreen)) { - mc.gameSettings.thirdPersonView = 0; return; } @@ -65,27 +67,26 @@ void moveRight(double speed) { mc.player.motionX -= (double)(MathHelper.cos(direction) * speed); } - void handleForward(double speed) { - if(!Keyboard.isKeyDown(mc.gameSettings.keyBindForward.getKeyCode())) + if (!Keyboard.isKeyDown(mc.gameSettings.keyBindForward.getKeyCode())) return; moveForward(speed); } void handleBack(double speed) { - if(!Keyboard.isKeyDown(mc.gameSettings.keyBindBack.getKeyCode())) + if (!Keyboard.isKeyDown(mc.gameSettings.keyBindBack.getKeyCode())) return; moveBack(speed); } void handleLeft(double speed) { - if(!Keyboard.isKeyDown(mc.gameSettings.keyBindLeft.getKeyCode())) + if (!Keyboard.isKeyDown(mc.gameSettings.keyBindLeft.getKeyCode())) return; moveLeft(speed); } void handleRight(double speed) { - if(!Keyboard.isKeyDown(mc.gameSettings.keyBindRight.getKeyCode())) + if (!Keyboard.isKeyDown(mc.gameSettings.keyBindRight.getKeyCode())) return; moveRight(speed); } @@ -111,13 +112,15 @@ public static float getDirection() { forward = -0.5f; } else if (mc.player.moveForward > 0.0F) { forward = 0.5f; - } if (mc.player.moveStrafing > 0.0f) { + } + if (mc.player.moveStrafing > 0.0f) { var1 -= 90.0f * forward; - } if (mc.player.moveStrafing < 0.0f) { + } + if (mc.player.moveStrafing < 0.0f) { var1 += 90.0f * forward; } var1 *= 0.017453292f; - return var1; + return var1; } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Jesus.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Jesus.java index cfd62328..8151aa44 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Jesus.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Jesus.java @@ -19,102 +19,101 @@ import xyz.templecheats.templeclient.event.events.player.MotionEvent; import xyz.templecheats.templeclient.event.events.world.LiquidCollisionEvent; import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.mixins.IMixinCPacketPlayer; +import xyz.templecheats.templeclient.mixins.accessor.IMixinCPacketPlayer; import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; public class Jesus extends Module { - /** * Settings */ - private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.NCP); - + private final EnumSetting < Mode > mode = new EnumSetting < > ("Mode", this, Mode.NCP); + /** * Constants */ private final static double OFFSET = 0.05; - + public Jesus() { super("Jesus", "Allows you to walk on water (amen)", Keyboard.KEY_NONE, Category.Movement); this.registerSettings(mode); } - + @Listener public void onLiquidCollision(LiquidCollisionEvent event) { - if(this.checkCollide() && mc.player.motionY < 0.1 && event.getBlockPos().getY() < mc.player.posY - OFFSET) { + if (this.checkCollide() && mc.player.motionY < 0.1 && event.getBlockPos().getY() < mc.player.posY - OFFSET) { final double offset = mc.player.getRidingEntity() != null ? OFFSET : this.mode.value() == Mode.Bounce ? 0.1 : 0; event.setBoundingBox(new AxisAlignedBB(0, 0, 0, 1, 1 - offset, 1)); } } - + @Listener public void onMotion(MotionEvent event) { - if(event.getStage() != EventStageable.EventStage.PRE) { + if (event.getStage() != EventStageable.EventStage.PRE) { return; } - - if(!mc.player.isSneaking() && !mc.player.noClip && !mc.gameSettings.keyBindJump.isKeyDown() && isInLiquid()) { + + if (!mc.player.isSneaking() && !mc.player.noClip && !mc.gameSettings.keyBindJump.isKeyDown() && isInLiquid()) { mc.player.motionY = 0.1; } } - + @Listener public void onPacketSend(PacketEvent.Send event) { if (mode.value() != Mode.Vanilla) return; - - if(!(event.getPacket() instanceof CPacketPlayer)) { + + if (!(event.getPacket() instanceof CPacketPlayer)) { return; } - + final CPacketPlayer packet = (CPacketPlayer) event.getPacket(); final IMixinCPacketPlayer accessor = (IMixinCPacketPlayer) packet; - - if(!accessor.isMoving()) { + + if (!accessor.isMoving()) { return; } - - if(mc.player.getRidingEntity() == null && !mc.gameSettings.keyBindJump.isKeyDown() && !isInLiquid() && isOnLiquid(OFFSET) && checkCollide() && mc.player.ticksExisted % 3 == 0) { + + if (mc.player.getRidingEntity() == null && !mc.gameSettings.keyBindJump.isKeyDown() && !isInLiquid() && isOnLiquid(OFFSET) && checkCollide() && mc.player.ticksExisted % 3 == 0) { accessor.setY(packet.getY(OFFSET) - OFFSET); } } - + @Override public String getHudInfo() { return this.mode.value().toString(); } - + public static boolean isInLiquid() { return isOnLiquid(0); } - + public static boolean isOnLiquid(double offset) { - if(getMountOrPlayer().fallDistance >= 3.0F) { + if (getMountOrPlayer().fallDistance >= 3.0F) { return false; } - + final AxisAlignedBB bb = getMountOrPlayer().getEntityBoundingBox().offset(0, -offset, 0); - - for(int x = MathHelper.floor(bb.minX); x < MathHelper.floor(bb.maxX + 1); x++) { - for(int z = MathHelper.floor(bb.minZ); z < MathHelper.floor(bb.maxZ + 1); z++) { + + for (int x = MathHelper.floor(bb.minX); x < MathHelper.floor(bb.maxX + 1); x++) { + for (int z = MathHelper.floor(bb.minZ); z < MathHelper.floor(bb.maxZ + 1); z++) { final Block block = mc.world.getBlockState(new BlockPos(x, (int) bb.minY, z)).getBlock(); - - if(block != Blocks.AIR) { + + if (block != Blocks.AIR) { return block instanceof BlockLiquid; } } } - + return false; } - + private boolean checkCollide() { - if(mc.player.isSneaking()) { + if (mc.player.isSneaking()) { return false; } - + return getMountOrPlayer().fallDistance < 3.0F; } - + private static Entity getMountOrPlayer() { return mc.player.getRidingEntity() != null ? mc.player.getRidingEntity() : mc.player; } @@ -124,4 +123,4 @@ private enum Mode { Vanilla, Bounce } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoFall.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoFall.java index 7c27756b..ff5b7597 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoFall.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoFall.java @@ -7,10 +7,13 @@ import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; public class NoFall extends Module { + /* + * Settings + */ private final DoubleSetting fallDistance = new DoubleSetting("Fall Distance", this, 0d, 3d, 1.5d); public NoFall() { - super("NoFall","Prevents fall damage", Keyboard.KEY_NONE, Module.Category.Movement); + super("NoFall", "Stops fall damage on some servers", Keyboard.KEY_NONE, Module.Category.Movement); registerSettings(fallDistance); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoSlow.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoSlow.java new file mode 100644 index 00000000..30a25419 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/NoSlow.java @@ -0,0 +1,70 @@ +package xyz.templecheats.templeclient.features.module.modules.movement; + +import net.minecraft.item.ItemFood; +import net.minecraft.network.play.client.CPacketHeldItemChange; +import net.minecraft.util.EnumHand; +import net.minecraftforge.client.event.InputUpdateEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.event.events.player.MotionEvent; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import java.util.stream.IntStream; + +public class NoSlow extends Module { + /* + * Settings + */ + private final EnumSetting < Mode > mode = new EnumSetting < > ("Mode", this, Mode.NCP); + public final IntSetting speed = new IntSetting("Speed", this, 1, 100, 100); + + + public NoSlow() { + super("NoSlow", "Removes item slow down", Keyboard.KEY_NONE, Category.Movement); + registerSettings(speed, mode); + } + + @SubscribeEvent + public void onInput(InputUpdateEvent e) { + if (!(mode.value() == Mode.StrictNCP && mode.value() == Mode.NCP) && mc.player.isHandActive() && !mc.player.isRiding()) { + mc.player.movementInput.moveForward *= (5f * (speed.intValue() / 100f)); + mc.player.movementInput.moveStrafe *= (5f * (speed.intValue() / 100f)); + } + + if (mode.value() == Mode.StrictNCP || mode.value() == Mode.NCP) { + if (mc.player.isHandActive() && !mc.player.isRiding() && !mc.player.isSneaking()) { + if (mode.value() == Mode.StrictNCP && (mc.player.getHeldItemMainhand().getItem() instanceof ItemFood || mc.player.getHeldItemOffhand().getItem() instanceof ItemFood)) + mc.player.connection.sendPacket(new CPacketHeldItemChange(mc.player.inventory.currentItem)); + mc.player.movementInput.moveForward /= 0.2; + mc.player.movementInput.moveStrafe /= 0.2; + } + } + + if (mode.value() == Mode.Matrix && mc.player.isHandActive()) { { + if (mc.player.onGround && !mc.gameSettings.keyBindJump.isKeyDown()) { + if (mc.player.ticksExisted % 2 == 0) { + mc.player.motionX *= 0.46; + mc.player.motionZ *= 0.46; + } + } else if ((double) mc.player.fallDistance > 0.2) { + mc.player.motionX *= 0.9100000262260437; + mc.player.motionZ *= 0.9100000262260437; + } + } + } + /*if (mode.value() == Mode.Grim && mc.player.isHandActive()) { + mc.player.connection.sendPacket(new CPacketHeldItemChange(mc.player.inventory.currentItem)); + mc.player.connection.sendPacket(new CPacketHeldItemChange(mc.player.inventory.currentItem < 8 ? mc.player.inventory.currentItem + 1 : mc.player.inventory.currentItem - 1)); + }*/ + } + + public enum Mode { + NCP, + StrictNCP, + Matrix, + //Grim + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/YawLock.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/RotationLock.java similarity index 74% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/YawLock.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/RotationLock.java index 686d4e57..29ab0dbc 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/YawLock.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/RotationLock.java @@ -5,9 +5,9 @@ import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; -public class YawLock extends Module { - public YawLock() { - super("YawLock","Locks your rotation for precision", Keyboard.KEY_NONE, Category.Movement); +public class RotationLock extends Module { + public RotationLock() { + super("RotationLock", "Lock your yaw and pitch", Keyboard.KEY_NONE, Category.Movement); } @SubscribeEvent @@ -17,4 +17,4 @@ public void onUpdate(RenderGameOverlayEvent.Post event) { } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Speed.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Speed.java deleted file mode 100644 index 08e84532..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Speed.java +++ /dev/null @@ -1,46 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.movement; - -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; -import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; - -public class Speed extends Module { - private final DoubleSetting speed = new DoubleSetting("Speed", this, 0d, 3d, 0.2d); - private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Vanilla); - - public Speed() { - super("Speed", "Allows you to move faster", Keyboard.KEY_NONE, Category.Movement); - - registerSettings(speed, mode); - } - - @SubscribeEvent - public void onPlayerTick(TickEvent.PlayerTickEvent e) { - if (TempleClient.settingsManager == null || mc.player == null) { - return; - } - - double sliderValue = speed.doubleValue() / 30.0; - - if (mc.player.onGround && mc.player.moveForward > 0 && !mc.player.isInWater() && !mc.player.isInLava()) { - mc.player.setSprinting(true); - float yaw = mc.player.rotationYaw * 0.017453292F; - - mc.player.motionX -= Math.sin(yaw) * sliderValue; - mc.player.motionZ += Math.cos(yaw) * sliderValue; - - if (mode.value() == Speed.Mode.BHop) { - mc.player.jump(); - } - } - } - - private enum Mode { - Vanilla, - BHop - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Spider.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Spider.java deleted file mode 100644 index 30a1b487..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Spider.java +++ /dev/null @@ -1,19 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.movement; - -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; - -public class Spider extends Module { - public Spider() { - super("Spider","Allows climbing on blocks", Keyboard.KEY_NONE, Category.Movement); - } - - @SubscribeEvent - public void onPlayerTick(TickEvent.PlayerTickEvent e) { - if (mc.player.collidedHorizontally) { - mc.player.motionY = 0.25; - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Sprint.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Sprint.java index d645c834..1991e234 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Sprint.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Sprint.java @@ -2,16 +2,22 @@ import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; public class Sprint extends Module { + private final BooleanSetting rage = new BooleanSetting("Rage", this, false); + public Sprint() { - super("Sprint","Automatically sprints for you", Keyboard.KEY_NONE, Category.Movement); + super("Sprint", "Automatically sprint", Keyboard.KEY_NONE, Category.Movement); + registerSettings(rage); } @Override public void onUpdate() { - if (mc.player.moveForward > 0 && !mc.player.collidedHorizontally) { + if (rage.booleanValue()) + if (mc.player.movementInput.moveForward != 0.0f || mc.player.movementInput.moveStrafe != 0.0f) + mc.player.setSprinting(true); + else if (mc.player.moveForward > 0 && !mc.player.collidedHorizontally) mc.player.setSprinting(true); - } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Step.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Step.java new file mode 100644 index 00000000..80f11735 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/Step.java @@ -0,0 +1,30 @@ +package xyz.templecheats.templeclient.features.module.modules.movement; + +import com.mojang.realmsclient.gui.ChatFormatting; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public class Step extends Module { + /* + * Settings + */ + public final IntSetting height = new IntSetting("Height", this, 0, 2, 1); + + public Step() { + super("Step", "Quickly step on blocks", Keyboard.KEY_NONE, Category.Movement); + registerSettings(height); + } + @Override + public void onDisable() { + mc.player.stepHeight = 0.6f; + } + @Override + public void onUpdate() { + mc.player.stepHeight = height.intValue(); + } + @Override + public String getHudInfo() { + return " [" + ChatFormatting.WHITE + "Vanilla, " + height.intValue() + ChatFormatting.RESET + "]"; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/TunnelSpeed.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/TunnelSpeed.java new file mode 100644 index 00000000..9dd36345 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/TunnelSpeed.java @@ -0,0 +1,25 @@ +package xyz.templecheats.templeclient.features.module.modules.movement; +//TODO: add a strict mode that spams the spacebar instead. +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; + +public class TunnelSpeed extends Module { + public TunnelSpeed() { + super("TunnelSpeed", "Makes you go fast in tunnels", Keyboard.KEY_NONE, Category.Movement); + } + + @Override + public void onUpdate() { + BlockPos pos = new BlockPos(mc.player.posX, mc.player.posY + 2.0, mc.player.posZ); + BlockPos pos2 = new BlockPos(mc.player.posX, mc.player.posY - 1.0, mc.player.posZ); + if (mc.world.getBlockState(pos).getBlock() != Blocks.AIR && mc.world.getBlockState(pos).getBlock() != Blocks.PORTAL && mc.world.getBlockState(pos).getBlock() != Blocks.END_PORTAL && mc.world.getBlockState(pos).getBlock() != Blocks.WATER && mc.world.getBlockState(pos).getBlock() != Blocks.FLOWING_WATER && mc.world.getBlockState(pos).getBlock() != Blocks.LAVA && mc.world.getBlockState(pos).getBlock() != Blocks.FLOWING_LAVA && mc.world.getBlockState(pos2).getBlock() != Blocks.ICE && mc.world.getBlockState(pos2).getBlock() != Blocks.FROSTED_ICE && mc.world.getBlockState(pos2).getBlock() != Blocks.PACKED_ICE && !mc.player.isInWater()) { + float yaw = (float) Math.toRadians(mc.player.rotationYaw); + if (mc.gameSettings.keyBindForward.isKeyDown() && !mc.gameSettings.keyBindSneak.isKeyDown() && mc.player.onGround) { + mc.player.motionX -= Math.sin(yaw) * 0.15; + mc.player.motionZ += Math.cos(yaw) * 0.15; + } + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/Speed.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/Speed.java new file mode 100644 index 00000000..cc01e472 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/Speed.java @@ -0,0 +1,14 @@ +package xyz.templecheats.templeclient.features.module.modules.movement.speed; + +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.movement.speed.sub.Bhop; +import xyz.templecheats.templeclient.features.module.modules.movement.speed.sub.Strafe; + +public class Speed extends Module { + + public Speed() { + super("Speed", "Speeds up the player", Category.Movement, true); + submodules.add(new Strafe()); + submodules.add(new Bhop()); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Bhop.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Bhop.java new file mode 100644 index 00000000..d5bf97e6 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Bhop.java @@ -0,0 +1,33 @@ +package xyz.templecheats.templeclient.features.module.modules.movement.speed.sub; + +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.player.PlayerUtil; +import xyz.templecheats.templeclient.util.world.EntityUtil; + +public class Bhop extends Module { + /* + * Variables + */ + private int counter = 0; + + public Bhop() { + super("Bhop", "Automatically makes the player jump", Keyboard.KEY_NONE, Category.Movement, true); + } + + @SubscribeEvent + public void onPlayerTick(TickEvent.PlayerTickEvent e) { + if (mc.player == null || mc.world == null) return; + if (mc.player.onGround && EntityUtil.isMoving()) { + if (counter < 2) { + counter++; + return; + } + + mc.player.jump(); + counter = 0; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Strafe.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Strafe.java new file mode 100644 index 00000000..a0c033e8 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/movement/speed/sub/Strafe.java @@ -0,0 +1,115 @@ +package xyz.templecheats.templeclient.features.module.modules.movement.speed.sub; + +import net.minecraft.init.MobEffects; +import net.minecraft.network.play.server.SPacketPlayerPosLook; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; +import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.event.events.network.PacketEvent; +import xyz.templecheats.templeclient.event.events.player.MoveEvent; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.world.EntityUtil; + +public class Strafe extends Module { + private final DoubleSetting speed = new DoubleSetting("Speed", this, 0, 10, 2.6); + private final BooleanSetting jump = new BooleanSetting("Jump", this, true); + private final BooleanSetting liquid = new BooleanSetting("Liquid", this, true); + + private double moveSpeed = 0; + private double lastDist = 0; + private int stage = 4; + + public Strafe() { + super("Strafe", "Allows you to move faster (but strafe)", Keyboard.KEY_NONE, Category.Movement, true); + + registerSettings(speed, jump, liquid); + } + + @SubscribeEvent + public void onClientTick(TickEvent.ClientTickEvent event) { + if (mc.player == null || mc.world == null) return; + if (!liquid.booleanValue() && (mc.player.isInLava() || mc.player.isInWater())) return; + lastDist = Math.sqrt(Math.pow(mc.player.posX - mc.player.prevPosX, 2) + Math.pow(mc.player.posZ - mc.player.prevPosZ, 2)); + } + + @Listener + public void onPlayerMove(MoveEvent event) { + if (EntityUtil.isMoving()) { + if (mc.player.onGround) stage = 2; + } + if (stage == 1 && (EntityUtil.isMoving())) { + stage = 2; + moveSpeed = 1.38 * (speed.doubleValue() / 10); + if (mc.player.isPotionActive(MobEffects.SPEED)) { + final int amplifier = mc.player.getActivePotionEffect(MobEffects.SPEED).getAmplifier(); + moveSpeed *= 1.0 + 0.2 * (amplifier + 1); + } + } else if (stage == 2) { + stage = 3; + if (jump.booleanValue()) { + mc.player.motionY = 0.3995f; + event.setY(0.3995f); + } + moveSpeed *= 2.149; + if (mc.player.isPotionActive(MobEffects.SPEED)) { + final int amplifier = mc.player.getActivePotionEffect(MobEffects.SPEED).getAmplifier(); + moveSpeed *= 1.0 + 0.2 * (amplifier + 1); + } + } else if (stage == 3) { + stage = 4; + moveSpeed = lastDist - (0.66 * (lastDist - (speed.doubleValue() / 10))); + if (mc.player.isPotionActive(MobEffects.SPEED)) { + final int amplifier = mc.player.getActivePotionEffect(MobEffects.SPEED).getAmplifier(); + moveSpeed *= 1.0 + 0.2 * (amplifier + 1); + } + } else { + if (mc.world.getCollisionBoxes(mc.player, mc.player.getEntityBoundingBox().offset(0.0, mc.player.motionY, 0.0)).size() > 0 || mc.player.collidedVertically) + stage = 1; + moveSpeed = lastDist - (lastDist / 159.0); + } + moveSpeed = Math.min(Math.max(moveSpeed, (speed.doubleValue() / 10)), 0.551); + + float forward = mc.player.movementInput.moveForward; + float strafe = mc.player.movementInput.moveStrafe; + float yaw = mc.player.rotationYaw; + if (!(EntityUtil.isMoving())) { + event.setX(0); + event.setZ(0); + } else if (forward != 0.0f) { + if (strafe >= 1.0f) { + yaw += (float) (forward > 0.0f ? -45 : 45); + strafe = 0.0f; + } else if (strafe <= -1.0f) { + yaw += (float) (forward > 0.0f ? 45 : -45); + strafe = 0.0f; + } + + if (forward > 0.0f) forward = 1.0f; + else if (forward < 0.0f) forward = -1.0f; + } + + final double sin = Math.sin(Math.toRadians(yaw + 90.0f)); + final double cos = Math.cos(Math.toRadians(yaw + 90.0f)); + + event.setX(((double) forward * moveSpeed * cos + (double) strafe * moveSpeed * sin)); + event.setZ(((double) forward * moveSpeed * sin - (double) strafe * moveSpeed * cos)); + if (!(EntityUtil.isMoving())) { + event.setX(0); + event.setZ(0); + } + } + + @Listener + public void onPacketReceive(PacketEvent.Receive e) { + if (e.getPacket() instanceof SPacketPlayerPosLook) { + moveSpeed = 0; + lastDist = 0; + stage = 4; + } + } + + +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/AutoEat.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/AutoEat.java new file mode 100644 index 00000000..13da38a8 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/AutoEat.java @@ -0,0 +1,67 @@ +package xyz.templecheats.templeclient.features.module.modules.player; + +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemFood; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.RayTraceResult; +import org.lwjgl.input.Keyboard; + +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.render.esp.sub.Block; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +public class AutoEat extends Module { + /* + * Settings + */ + private final IntSetting hungerThreshold = new IntSetting("Hunger", this, 0, 20, 10); + private final BooleanSetting gapples = new BooleanSetting("Golden Apples", this, false); + private final BooleanSetting poisonous = new BooleanSetting("Poisonous", this, false); + private final IntSetting healthThreshold = new IntSetting("Health", this, 1, 20, 10); + + /* + * Variables + */ + private int previousSlot = -1; + + public AutoEat() { + super("AutoEat", "Automatically eat when you are hungry", Keyboard.KEY_NONE, Category.Player); + this.registerSettings(gapples, poisonous, healthThreshold, hungerThreshold); + } + + @Override + public void onUpdate() { + if (mc.player == null || mc.world == null) return; + RayTraceResult ray = Block.mc.objectMouseOver; + if (ray != null && ray.typeOfHit == RayTraceResult.Type.BLOCK) { + if (mc.world.getBlockState(ray.getBlockPos()).getBlock() == Blocks.ENDER_CHEST || mc.world.getBlockState(ray.getBlockPos()).getBlock() == Blocks.CHEST || mc.world.getBlockState(ray.getBlockPos()).getBlock() == Blocks.ANVIL) + KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); + return; + } + if (mc.player.getHealth() <= healthThreshold.intValue() || mc.player.getFoodStats().getFoodLevel() <= hungerThreshold.intValue()) { + for (int i = 0; i < 9; i++) { + ItemStack stack = mc.player.inventory.getStackInSlot(i); + Item item = stack.getItem(); + if (item instanceof ItemFood && (gapples.booleanValue() || item != Items.GOLDEN_APPLE) && (!poisonous.booleanValue() || item != Items.SPIDER_EYE && item != Items.ROTTEN_FLESH && item != Items.POISONOUS_POTATO && !(item == Items.FISH && stack.getMetadata() == 3) && item != Items.CHICKEN)) { + previousSlot = mc.player.inventory.currentItem; + mc.player.inventory.currentItem = i; + KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), true); + KeyBinding.onTick(mc.gameSettings.keyBindUseItem.getKeyCode()); + break; + } + } + } else if (previousSlot != -1) { + KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); + mc.player.inventory.currentItem = previousSlot; + previousSlot = -1; + } + } + @Override + public void onDisable() { + KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Blink.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Blink.java index 39250313..b57cb78f 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Blink.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Blink.java @@ -13,12 +13,14 @@ import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; public final class Blink extends Module { - - private final Queue> packets = new ConcurrentLinkedQueue<>(); + /* + * Variables + */ + private final Queue < Packet < ? >> packets = new ConcurrentLinkedQueue < > (); private EntityOtherPlayerMP entity; public Blink() { - super("Blink","Holds packets until disabled", Keyboard.KEY_NONE, Category.Player); + super("Blink", "Holds packets until disabled", Keyboard.KEY_NONE, Category.Player); } @Override @@ -35,11 +37,10 @@ public void onEnable() { } } - @Listener public void sendPacket(PacketEvent.Send event) { if (event.getStage() == EventStageable.EventStage.PRE) { - final Packet packet = event.getPacket(); + final Packet < ? > packet = event.getPacket(); if (Minecraft.getMinecraft().world == null || Minecraft.getMinecraft().isSingleplayer()) { return; @@ -62,7 +63,7 @@ public void onDisable() { Minecraft.getMinecraft().world.removeEntity(this.entity); } if (!this.packets.isEmpty()) { - for (Packet packet : this.packets) { + for (Packet < ? > packet : this.packets) { Minecraft.getMinecraft().player.connection.sendPacket(packet); } this.packets.clear(); diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/FastXP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/FastUse.java similarity index 70% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/FastXP.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/player/FastUse.java index 2be6e1fa..587019de 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/combat/FastXP.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/FastUse.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.module.modules.combat; +package xyz.templecheats.templeclient.features.module.modules.player; import net.minecraft.init.Items; import net.minecraft.network.play.client.CPacketPlayerTryUseItem; @@ -6,10 +6,10 @@ import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; -public class FastXP extends Module { +public class FastUse extends Module { - public FastXP() { - super("FastXP","Increases XP throwing speed", Keyboard.KEY_NONE, Category.Combat); + public FastUse() { + super("FastUse", "Use items faster", Keyboard.KEY_NONE, Category.Player); } @Override diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Reach.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Reach.java index a05703a3..c83ff20e 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Reach.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/player/Reach.java @@ -8,7 +8,7 @@ public class Reach extends Module { public Reach() { - super("Reach","Extends the player's reach", Keyboard.KEY_NONE, Category.Player); + super("Reach", "Extends your interaction distance", Keyboard.KEY_NONE, Category.Player); } public void onEnable() { diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Ambience.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Ambience.java new file mode 100644 index 00000000..e5c7af8e --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Ambience.java @@ -0,0 +1,106 @@ +package xyz.templecheats.templeclient.features.module.modules.render; + +import net.minecraftforge.client.event.EntityViewRenderEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import java.awt.*; + +public class Ambience extends Module { + public static Ambience INSTANCE; + /* + * Settings + */ + + // LightMap + public final BooleanSetting LightMapState = new BooleanSetting("LightMapState", this, false); + + // Fog + private final BooleanSetting fogState = new BooleanSetting("FogColorState", this, false); + + // Time + // TODO: Change to better name + private final BooleanSetting timeState = new BooleanSetting("TimeState", this, false); + private final EnumSetting < Time > time = new EnumSetting < > ("Time", timeState.parent, Time.Midnight); + private final DoubleSetting timeCustom = new DoubleSetting("TimeCustom", timeState.parent, 4.0, 24000.0, 600.0); + private final BooleanSetting speedUp = new BooleanSetting("Speed Up", timeState.parent, false); + private final DoubleSetting speed = new DoubleSetting("Speed", timeState.parent, 0.0, 100.0, 1.0); + + /* + * Variables + */ + double counter = 0.0; + + public Ambience() { + super("Ambience", "Modify game environment", Keyboard.KEY_NONE, Category.Render); + INSTANCE = this; + registerSettings( + fogState, LightMapState, timeState, speedUp, speed, timeCustom, time + ); + } + + @SubscribeEvent + public void customTime(TickEvent.RenderTickEvent event) { + if (mc.world == null || mc.player == null) return; + + if (timeState.booleanValue()) { + long t = 0L; + switch (time.value()) { + case Day: + t = 1000L; + break; + case Sunset: + t = 12000; + break; + case Dawn: + t = 23000; + break; + case Night: + t = 13000; + break; + case Midnight: + t = 18000L; + break; + case Noon: + t = 6000L; + break; + case Custom: + counter += speed.doubleValue(); + + if (counter > 24000.0 || !speedUp.booleanValue()) { + counter = 0.0; + } + + t = (long)(timeCustom.doubleValue() + counter); + break; + } + mc.world.setWorldTime(t); + } + } + + @SubscribeEvent + public void fogColor(EntityViewRenderEvent.FogColors event) { + if (fogState.booleanValue()) { + Color fogColor = Colors.INSTANCE.getFogColor(); + event.setRed(fogColor.getRed() / 255F); + event.setGreen(fogColor.getGreen() / 255F); + event.setBlue(fogColor.getBlue() / 255F); + } + } + + enum Time { + Day, + Sunset, + Dawn, + Night, + Midnight, + Noon, + Custom + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Aspect.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Aspect.java new file mode 100644 index 00000000..a5a818f1 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Aspect.java @@ -0,0 +1,21 @@ +package xyz.templecheats.templeclient.features.module.modules.render; + +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; + +public class Aspect extends Module { + public static Aspect INSTANCE; + + /* + * Settings + */ + public final DoubleSetting width = new DoubleSetting("Width", this, 0.0, 16.0, 3.0); + public final DoubleSetting height = new DoubleSetting("Height", this, 0.0, 16.0, 3.0); + + public Aspect() { + super("Aspect", "Modify game screen width and height", Keyboard.KEY_NONE, Category.Render); + INSTANCE = this; + registerSettings(width, height); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/BlockOverlay.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/BlockOverlay.java deleted file mode 100644 index 0fee8300..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/BlockOverlay.java +++ /dev/null @@ -1,97 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.render; - -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.opengl.GL11; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; - - -public class BlockOverlay extends Module { - private final IntSetting red = new IntSetting("Red", this, 0, 255, 255); - private final IntSetting green = new IntSetting("Green", this, 0, 255, 0); - private final IntSetting blue = new IntSetting("Blue", this, 0, 255, 0); - - private boolean isRightFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(1, 0, 0)).getBlock().isAir(mc.world.getBlockState(pos.add(1, 0, 0)), mc.world, pos.add(1, 0, 0)); - } - private boolean isLeftFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(-1, 0, 0)).getBlock().isAir(mc.world.getBlockState(pos.add(-1, 0, 0)), mc.world, pos.add(-1, 0, 0)); - } - - private boolean isFrontFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(0, 0, 1)).getBlock().isAir(mc.world.getBlockState(pos.add(0, 0, 1)), mc.world, pos.add(0, 0, 1)); - } - - private boolean isBackFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(0, 0, -1)).getBlock().isAir(mc.world.getBlockState(pos.add(0, 0, -1)), mc.world, pos.add(0, 0, -1)); - } - - private boolean isBottomFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(0, -1, 0)).getBlock().isAir(mc.world.getBlockState(pos.add(0, -1, 0)), mc.world, pos.add(0, -1, 0)); - } - - private boolean isTopFaceVisible(BlockPos pos) { - return mc.world.getBlockState(pos.add(0, 1, 0)).getBlock().isAir(mc.world.getBlockState(pos.add(0, 1, 0)), mc.world, pos.add(0, 1, 0)); - } - - public BlockOverlay() { - super("BlockOverlay","Highlights the block at your cross-hair", 0, Category.Render); - - registerSettings(red, green, blue); - } - - @SubscribeEvent - public void onRenderWorldLast(RenderWorldLastEvent event) { - RayTraceResult rayTraceResult = mc.objectMouseOver; - if (rayTraceResult != null && rayTraceResult.typeOfHit == RayTraceResult.Type.BLOCK) { - BlockPos blockPos = rayTraceResult.getBlockPos(); - - GlStateManager.pushMatrix(); - GlStateManager.pushAttrib(); - - try { - GlStateManager.disableTexture2D(); - GlStateManager.disableDepth(); - GlStateManager.disableLighting(); - GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ZERO); - GlStateManager.color(red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - GlStateManager.glLineWidth(2.0F); - - AxisAlignedBB box = mc.world.getBlockState(rayTraceResult.getBlockPos()).getSelectedBoundingBox(mc.world, rayTraceResult.getBlockPos()).grow(0.0020000000949949026D).offset(-mc.getRenderManager().viewerPosX, -mc.getRenderManager().viewerPosY, -mc.getRenderManager().viewerPosZ); - - if (isRightFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.maxX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - if (isLeftFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.minX, box.minY, box.minZ, box.minX, box.maxY, box.maxZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - if (isFrontFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.minX, box.minY, box.maxZ, box.maxX, box.maxY, box.maxZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - if (isBackFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.minZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - if (isBottomFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.minX, box.minY, box.minZ, box.maxX, box.minY, box.maxZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - if (isTopFaceVisible(blockPos)) { - mc.renderGlobal.drawSelectionBoundingBox(new AxisAlignedBB(box.minX, box.maxY, box.minZ, box.maxX, box.maxY, box.maxZ), red.intValue() / 255.0F, green.intValue() / 255.0F, blue.intValue() / 255.0F, 0.4F); - } - - } finally { - GlStateManager.popAttrib(); - GlStateManager.popMatrix(); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ChinaHat.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ChinaHat.java new file mode 100644 index 00000000..146fcb62 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ChinaHat.java @@ -0,0 +1,147 @@ +package xyz.templecheats.templeclient.features.module.modules.render; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.color.ColorUtil; +import xyz.templecheats.templeclient.util.setting.impl.*; +import java.awt.*; + +import static org.lwjgl.opengl.GL11.*; +import static xyz.templecheats.templeclient.util.color.ColorUtil.lerpColor; +import static xyz.templecheats.templeclient.util.color.ColorUtil.setAlpha; +import static xyz.templecheats.templeclient.util.render.RenderUtil.interpolateEntity; +import static xyz.templecheats.templeclient.util.math.MathUtil.lerp; + +public class ChinaHat extends Module { + /* + * Settings + */ + private final BooleanSetting self = new BooleanSetting("Self", this, true); + private final BooleanSetting other = new BooleanSetting("Other", this, false); + private final BooleanSetting firstPerson = new BooleanSetting("FirstPerson", this, true); + private final DoubleSetting heightValue = new DoubleSetting("Height", this, 0.0, 0.7, 0.3); + private final DoubleSetting radiusValue = new DoubleSetting("Radius", this, 0.3, 2.0, 1.0); + private final DoubleSetting rotateSpeed = new DoubleSetting("Rotate Speed", this, 0.0, 10.0, 2.0); + private final BooleanSetting fill = new BooleanSetting("Fill", this, true); + private final BooleanSetting outline = new BooleanSetting("Outline", this, false); + private final DoubleSetting outlineWidth = new DoubleSetting("Outline Width", outline.parent, 1.0, 5.0, 2.0); + private final IntSetting outlineOpacity = new IntSetting("Outline Opacity", outline.parent, 0, 255, 255); + private final IntSetting fillOpacity1 = new IntSetting("fill1 Opacity", outline.parent, 0, 255, 255); + private final IntSetting fillOpacity2 = new IntSetting("fill2 Opacity", outline.parent, 0, 255, 255); + + public ChinaHat() { + super("ChinaHat", "Draw a traditional hats of some East and South Asian countries", Keyboard.KEY_NONE, Category.Render); + registerSettings(self, other, firstPerson, fill, outline, heightValue, radiusValue, rotateSpeed, outlineWidth, outlineOpacity, fillOpacity1, fillOpacity2); + } + + private boolean check() { + if (firstPerson.booleanValue() && mc.gameSettings.thirdPersonView == 0) { + return true; + } + else return mc.gameSettings.thirdPersonView != 0; + } + @Override + public void onRenderWorld(float partialTicks) { + if (mc.player == null || mc.world == null) return; + + for (EntityPlayer player : mc.world.playerEntities) { + if (player.isDead || player.isInvisible()) { + continue; + } + if ((other.booleanValue() && player.getEntityId() != mc.player.getEntityId()) || self.booleanValue() && player == mc.player && check()) { + float radius = (float) ((player.getEntityBoundingBox().maxX - player.getEntityBoundingBox().minX) * 0.9 * radiusValue.floatValue()); + + Vec3d pos = interpolateEntity(player); + + setup(); + GlStateManager.pushMatrix(); + GlStateManager.translate(0, pos.y + player.height, 0); + GlStateManager.translate(pos.x, 0.1 - (player.isSneaking() ? 0.23 : 0), pos.z); + GlStateManager.rotate((player.ticksExisted + mc.getRenderPartialTicks()) * -rotateSpeed.floatValue(), 0.0F, 1.0F, 0.0F); + if (fill.booleanValue()) { + drawHat(radius); + } + if (outline.booleanValue()) { + drawHatOutline(radius); + } + restore(); + GlStateManager.popMatrix(); + } + } + } + + private void drawHat(float radius) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.color(-1f, -1f, -1f, -1f); + buffer.begin(GL_TRIANGLE_FAN, DefaultVertexFormats.POSITION_COLOR); + buffer.pos(0.0, heightValue.doubleValue(), 0.0).color(1.0F, 1.0F, 1.0F, 1.0F).endVertex(); + for (int i = 0; i <= 360; i++) { + double percent = (double) i / 360; + double progress = ((percent > 0.5) ? 1.0 - percent : percent) * 2.0; + Color color = lerpColor(setAlpha(Colors.INSTANCE.getGradient()[1], fillOpacity1.intValue()), setAlpha(Colors.INSTANCE.getGradient()[0], fillOpacity2.intValue()), (float) progress); + + double dir = Math.toRadians(i - 180.0); + double x = -Math.sin(dir) * radius; + double z = Math.cos(dir) * radius; + buffer.pos(x, 0.0, z).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + } + buffer.pos(0.0, heightValue.doubleValue(), 0.0).color(0, 0 ,0 ,0).endVertex(); + tessellator.draw(); + } + + private void drawHatOutline(float radius) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.glLineWidth(outlineWidth.floatValue()); + GlStateManager.color(-1f, -1f, -1f, -1f); + buffer.begin(GL_LINE_LOOP, DefaultVertexFormats.POSITION_COLOR); + for (int i = 0; i <= 360; i++) { + double percent = (double) i / 360; + double progress = ((percent > 0.5) ? 1.0 - percent : percent) * 2.0; + Color color = ColorUtil.setAlpha(lerpColor(Colors.INSTANCE.getGradient()[1], Colors.INSTANCE.getGradient()[0], (float) progress), outlineOpacity.intValue()); + + double dir = Math.toRadians(i - 180.0); + double x = -Math.sin(dir) * radius; + double z = Math.cos(dir) * radius; + buffer.pos(x, 0.0, z).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + } + tessellator.draw(); + } + + private void setup() { + GlStateManager.pushMatrix(); + glDepthMask(false); + glEnable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + GlStateManager.enableBlend(); + GlStateManager.disableAlpha(); + GlStateManager.disableLighting(); + GlStateManager.disableTexture2D(); + GlStateManager.shadeModel(GL_SMOOTH); + GlStateManager.disableCull(); + } + + private void restore() { + GlStateManager.enableCull(); + GlStateManager.disableBlend(); + GlStateManager.enableDepth(); + GlStateManager.enableTexture2D(); + GlStateManager.enableAlpha(); + glDepthMask(true); + glDisable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.popMatrix(); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Freecam.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Freecam.java index 023aa433..0163d2b3 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Freecam.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Freecam.java @@ -12,9 +12,14 @@ import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; public class Freecam extends Module { + /* + * Settings + */ private final DoubleSetting horizontalSpeed = new DoubleSetting("Horizontal Speed", this, 0.1, 5d, 1d); private final DoubleSetting verticalSpeed = new DoubleSetting("Vertical Speed", this, 0.1, 5d, 1d); - + /* + * Variables + */ private EntityOtherPlayerMP fakePlayer; private float startYaw, startPitch; @@ -24,10 +29,9 @@ public Freecam() { this.registerSettings(horizontalSpeed, verticalSpeed); } - @Listener public void onPacketSend(PacketEvent.Send event) { - if(event.getPacket() instanceof CPacketPlayer) { + if (event.getPacket() instanceof CPacketPlayer) { event.setCanceled(true); } } @@ -40,10 +44,10 @@ public void onMove(MoveEvent event) { final double hSpeed = this.horizontalSpeed.doubleValue() * 2; - if(mc.gameSettings.keyBindForward.isKeyDown()) { + if (mc.gameSettings.keyBindForward.isKeyDown()) { mc.player.motionX = hSpeed * Math.cos(Math.toRadians(mc.player.rotationYaw + 90)); mc.player.motionZ = hSpeed * Math.sin(Math.toRadians(mc.player.rotationYaw + 90)); - } else if(mc.gameSettings.keyBindBack.isKeyDown()) { + } else if (mc.gameSettings.keyBindBack.isKeyDown()) { mc.player.motionX = -hSpeed * Math.cos(Math.toRadians(mc.player.rotationYaw + 90)); mc.player.motionZ = -hSpeed * Math.sin(Math.toRadians(mc.player.rotationYaw + 90)); } else { @@ -51,10 +55,10 @@ public void onMove(MoveEvent event) { mc.player.motionZ = 0; } - if(mc.gameSettings.keyBindLeft.isKeyDown()) { + if (mc.gameSettings.keyBindLeft.isKeyDown()) { mc.player.motionX += hSpeed * Math.cos(Math.toRadians(mc.player.rotationYaw)); mc.player.motionZ += hSpeed * Math.sin(Math.toRadians(mc.player.rotationYaw)); - } else if(mc.gameSettings.keyBindRight.isKeyDown()) { + } else if (mc.gameSettings.keyBindRight.isKeyDown()) { mc.player.motionX -= hSpeed * Math.cos(Math.toRadians(mc.player.rotationYaw)); mc.player.motionZ -= hSpeed * Math.sin(Math.toRadians(mc.player.rotationYaw)); } @@ -62,21 +66,21 @@ public void onMove(MoveEvent event) { @Listener public void onMotion(MotionEvent event) { - if(event.getStage() != EventStageable.EventStage.POST) { + if (event.getStage() != EventStageable.EventStage.POST) { return; } final double vSpeed = this.verticalSpeed.doubleValue() * 2; - if(mc.gameSettings.keyBindJump.isKeyDown()) { + if (mc.gameSettings.keyBindJump.isKeyDown()) { mc.player.motionY = vSpeed; - } else if(mc.gameSettings.keyBindSneak.isKeyDown()) { + } else if (mc.gameSettings.keyBindSneak.isKeyDown()) { mc.player.motionY = -vSpeed; } else { mc.player.motionY = 0; } - if(this.fakePlayer != null) { + if (this.fakePlayer != null) { this.fakePlayer.rotationYaw = this.fakePlayer.rotationYawHead = mc.player.rotationYaw; this.fakePlayer.rotationPitch = mc.player.rotationPitch; this.fakePlayer.inventory.copyInventory(mc.player.inventory); diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/FullBright.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/FullBright.java index 526b05cf..86af54a5 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/FullBright.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/FullBright.java @@ -1,23 +1,51 @@ package xyz.templecheats.templeclient.features.module.modules.render; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; public class FullBright extends Module { - private float originalGamma = 1.0f; + public final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Gamma); public FullBright() { - super("Fullbright", "Makes your world brighter <3", Keyboard.KEY_NONE, Category.Render); + super("Fullbright", "Makes the world bright", Keyboard.KEY_NONE, Category.Render); + registerSettings(mode); + } + + private void brightModify() { + if (mode.value() == Mode.Gamma) { + mc.gameSettings.gammaSetting = 100f; + if (mc.player.isPotionActive(Potion.getPotionById(16))) { + mc.player.removePotionEffect(Potion.getPotionById(16)); + } + } else if (mode.value() == Mode.Potion) { + mc.gameSettings.gammaSetting = 0; + mc.player.addPotionEffect(new PotionEffect(Potion.getPotionById(16), 9999, 1)); + } + } + + @Override + public void onUpdate() { + brightModify(); } @Override public void onEnable() { - originalGamma = mc.gameSettings.gammaSetting; - mc.gameSettings.gammaSetting = 12.0f; + brightModify(); } @Override public void onDisable() { - mc.gameSettings.gammaSetting = originalGamma; + mc.gameSettings.gammaSetting = 1.0f; + if (mc.player.isPotionActive(Potion.getPotionById(16))) { + mc.player.removePotionEffect(Potion.getPotionById(16)); + } + } + + private enum Mode { + Gamma, + Potion } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Hitmarker.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Hitmarker.java index 0d0b501f..2b4e7450 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Hitmarker.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Hitmarker.java @@ -14,28 +14,30 @@ import xyz.templecheats.templeclient.features.module.Module; public class Hitmarker extends Module { + /* + * Variables + */ private static final ResourceLocation hitmarkerTexture = new ResourceLocation("textures/icons/hitmarker.png"); private int hitmarkerDuration = 0; - + public Hitmarker() { - super("Hitmarker","Shows a hit-marker when dealing damage", Keyboard.KEY_NONE, Category.Render); + super("Hitmarker", "Hitmarkers from Call of Duty", Keyboard.KEY_NONE, Category.Render); } @SubscribeEvent public void onAttackEntity(AttackEntityEvent event) { - if(event.getEntityPlayer().equals(mc.player)) { + if (event.getEntityPlayer().equals(mc.player)) { this.hitmarkerDuration = 5; } } @SubscribeEvent - public void renderGameOverlay(RenderGameOverlayEvent.Post event) { - if(event.getType() != RenderGameOverlayEvent.ElementType.ALL) { + if (event.getType() != RenderGameOverlayEvent.ElementType.ALL) { return; } - if(this.hitmarkerDuration-- > 0) { + if (this.hitmarkerDuration--> 0) { ScaledResolution scaledResolution = new ScaledResolution(mc); int centerX = scaledResolution.getScaledWidth() / 2; int centerY = scaledResolution.getScaledHeight() / 2; diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ItemESP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ItemESP.java deleted file mode 100644 index dc5ece46..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ItemESP.java +++ /dev/null @@ -1,65 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.render; - -import net.minecraft.client.Minecraft; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.render.RenderUtil; - -public class ItemESP extends Module { - public ItemESP() { - super("ItemESP","Highlights items", Keyboard.KEY_NONE, Category.Render); - } - - @SubscribeEvent - public void onRender(RenderWorldLastEvent e) { - for (Entity entity : mc.world.loadedEntityList) { - if (entity instanceof EntityItem) { - EntityItem itemEntity = (EntityItem) entity; - String itemName = itemEntity.getItem().getDisplayName(); - - double x = itemEntity.lastTickPosX + (itemEntity.posX - itemEntity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks(); - double y = itemEntity.lastTickPosY + (itemEntity.posY - itemEntity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks(); - double z = itemEntity.lastTickPosZ + (itemEntity.posZ - itemEntity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks(); - - mc.fontRenderer.drawStringWithShadow(itemName, (float)x, (float)y, 0xFFFFFF); - AxisAlignedBB box = new AxisAlignedBB( - entity.getEntityBoundingBox().minX - - 0.05 - - entity.posX - + ((float) ((double) ((float) entity.lastTickPosX) + (entity.posX - entity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosX), - entity.getEntityBoundingBox().minY - - entity.posY - + ((float) ((double) ((float) entity.lastTickPosY) + (entity.posY - entity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosY), - entity.getEntityBoundingBox().minZ - - 0.05 - - entity.posZ - + ((float) ((double) ((float) entity.lastTickPosZ) + (entity.posZ - entity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosZ), - entity.getEntityBoundingBox().maxX - + 0.05 - - entity.posX - + ((float) ((double) ((float) entity.lastTickPosX) + (entity.posX - entity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosX), - entity.getEntityBoundingBox().maxY - + 0.1 - - entity.posY - + ((float) ((double) ((float) entity.lastTickPosY) + (entity.posY - entity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosY), - entity.getEntityBoundingBox().maxZ - + 0.05 - - entity.posZ - + ((float) ((double) ((float) entity.lastTickPosZ) + (entity.posZ - entity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() - .getRenderManager().viewerPosZ)); - - RenderUtil.FillOnlyLine(entity, box); - } - } - } -} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameProtect.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameProtect.java index eb3c3868..9b11d21d 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameProtect.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameProtect.java @@ -8,7 +8,7 @@ public class NameProtect extends Module { public NameProtect() { - super("NameProtect","Hides player names", Keyboard.KEY_NONE, Category.Render); + super("NameProtect", "Hides player names", Keyboard.KEY_NONE, Category.Render); } @SubscribeEvent @@ -16,10 +16,9 @@ public void onRenderLiving(RenderLivingEvent.Specials.Pre event) { if (isEnabled() && event.getEntity() != null) { EntityLivingBase entity = event.getEntity(); - // Check if the entity is a player and hide their name tag if (entity instanceof net.minecraft.entity.player.EntityPlayer) { event.setCanceled(true); } } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameTags.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameTags.java index ad32e158..ea36580f 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameTags.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NameTags.java @@ -1,5 +1,6 @@ package xyz.templecheats.templeclient.features.module.modules.render; +import xyz.templecheats.templeclient.TempleClient; import com.google.common.collect.Lists; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; @@ -15,159 +16,166 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; -import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.gui.font.FontUtils; +import xyz.templecheats.templeclient.features.gui.font.CFont; import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.mixins.IMixinRenderManager; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.features.module.modules.client.FontSettings; +import xyz.templecheats.templeclient.mixins.accessor.IMixinRenderManager; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; import java.awt.*; +import java.util.Comparator; import java.util.List; -import java.util.*; +import java.util.Objects; +import java.util.Set; +import java.util.TreeSet; public class NameTags extends Module { - private final BooleanSetting self = new BooleanSetting("Self", this, true); + /* + * Settings + */ + private final BooleanSetting border = new BooleanSetting("Border", this, true); private final BooleanSetting customFont = new BooleanSetting("Custom Font", this, false); private final BooleanSetting items = new BooleanSetting("Items", this, true); - private final BooleanSetting border = new BooleanSetting("Border", this, true); - private final IntSetting borderRed = new IntSetting("Border Red", this, 0, 255, 255); - private final IntSetting borderGreen = new IntSetting("Border Green", this, 0, 255, 255); - private final IntSetting borderBlue = new IntSetting("Border Blue", this, 0, 255, 255); - - private final Set players = new TreeSet<>(Comparator.comparing(player -> mc.player.getDistance((EntityPlayer) player)).reversed()); - + private final Set < EntityPlayer > players = new TreeSet < > (Comparator.comparing(player -> mc.player.getDistance((EntityPlayer) player)).reversed()); + private final CFont font = FontSettings.INSTANCE.getFont().setSize(18); public NameTags() { - super("Nametags", "Improves nametags", Keyboard.KEY_NONE, Category.Render); - - registerSettings(self, customFont, items, border, borderRed, borderGreen, borderBlue); + super("Nametags", "Renders nametags above entities", Keyboard.KEY_NONE, Category.Render); + registerSettings(border, customFont, items); } - + @Override public void onUpdate() { this.players.clear(); this.players.addAll(mc.world.playerEntities); } - + @SubscribeEvent - public void onRender(RenderLivingEvent.Specials.Pre event) { + public void onRender(RenderLivingEvent.Specials.Pre < ? > event) { final EntityLivingBase e = event.getEntity(); - - if(e instanceof EntityPlayer && ((this.self.booleanValue() && mc.gameSettings.thirdPersonView != 0) || !e.equals(mc.player)) && !e.isDead && e.getHealth() > 0 && !e.isInvisible()) { + + if (e instanceof EntityPlayer && (mc.gameSettings.thirdPersonView != 0 || !e.equals(mc.player)) && !e.isDead && e.getHealth() > 0 && !e.isInvisible()) { event.setCanceled(true); } } - + @Override public void onRenderWorld(float partialTicks) { - for(EntityPlayer player : this.players) { - if(((!this.self.booleanValue() || mc.gameSettings.thirdPersonView == 0) && player.equals(mc.player)) || player.isDead || player.getHealth() <= 0 || player.isInvisible()) { + for (EntityPlayer player: this.players) { + if (player.equals(mc.player) || player.isDead || player.getHealth() <= 0 || player.isInvisible()) { continue; } - + final double x = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks - ((IMixinRenderManager) mc.getRenderManager()).getRenderPosX(); final double y = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks - ((IMixinRenderManager) mc.getRenderManager()).getRenderPosY(); final double z = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks - ((IMixinRenderManager) mc.getRenderManager()).getRenderPosZ(); this.renderNametag(player, new Vec3d(x, y + player.height / 1.5, z)); } } - + private void renderNametag(EntityLivingBase entity, Vec3d pos) { final String name = entity.getDisplayName().getFormattedText(); final String health = " " + (int) Math.ceil(entity.getHealth() + entity.getAbsorptionAmount()); String ping = ""; try { ping = " " + Objects.requireNonNull(mc.getConnection()).getPlayerInfo(entity.getUniqueID()).getResponseTime() + "ms"; - } catch(Exception ignored) { - } - + } catch (Exception ignored) {} + GL11.glPushMatrix(); GL11.glTranslated(pos.x, pos.y + 1, pos.z); GL11.glRotatef(-mc.getRenderManager().playerViewY, 0, 1, 0); GL11.glRotatef((mc.gameSettings.thirdPersonView == 2 ? -1F : 1F) * mc.getRenderManager().playerViewX, 1, 0, 0); - + final float distance = mc.player.getDistance(entity); final float scale = (0.027F + distance / 600) * Math.min(3, Math.max(1, distance / 50)); GL11.glScalef(-scale, -scale, scale); - + GL11.glDisable(GL11.GL_DEPTH_TEST); GL11.glEnable(GL11.GL_BLEND); GL11.glDisable(GL11.GL_TEXTURE_2D); - + final int totalWidth = this.getStringWidth(name + health + ping) / 2; - final int fontHeight = (int) Math.ceil(FontUtils.getFontHeight(this.customFont.booleanValue())); + final int fontHeight = (int) Math.ceil(font.getFontHeight()); - if(this.border.booleanValue()) { + if (this.border.booleanValue()) { this.drawRoundedBorderedRect(-totalWidth - 2, -2, totalWidth + 1, fontHeight, 0x80000000, entity); } else { this.drawRect(-totalWidth - 1, -1, totalWidth, fontHeight - 1, 0, 0, 0, 128); } - + GL11.glEnable(GL11.GL_TEXTURE_2D); GL11.glDisable(GL11.GL_BLEND); - - FontUtils.drawString(name, -totalWidth, 0, 0xFFFFFF, true, this.customFont.booleanValue()); - FontUtils.drawString(health, -totalWidth + this.getStringWidth(name), 0, this.getHealthColor(entity), true, this.customFont.booleanValue()); - FontUtils.drawString(ping, -totalWidth + this.getStringWidth(name + health), 0, this.getPingColor(entity), true, this.customFont.booleanValue()); - - if(entity instanceof EntityPlayer && this.items.booleanValue()) { + + if (customFont.booleanValue()) { + font.drawString(name, -totalWidth, 0, 0xFFFFFF, true, 1.0f); + font.drawString(health, -totalWidth + this.getStringWidth(name), 0, this.getHealthColor(entity), true, 1.0f); + font.drawString(ping, -totalWidth + this.getStringWidth(name + health), 0, this.getPingColor(entity), true, 1.0f); + } else { + mc.fontRenderer.drawString(name, -totalWidth, 0, 0xFFFFFF, true); + mc.fontRenderer.drawString(health, -totalWidth + this.getStringWidth(name), 0, this.getHealthColor(entity), true); + mc.fontRenderer.drawString(ping, -totalWidth + this.getStringWidth(name + health), 0, this.getPingColor(entity), true); + } + if (entity instanceof EntityPlayer && this.items.booleanValue()) { final EntityPlayer player = (EntityPlayer) entity; - final List armor = Lists.reverse(player.inventory.armorInventory); - + final List < ItemStack > armor = Lists.reverse(player.inventory.armorInventory); + boolean hasDurability = false; int totalItemsWidth = 0; - for(ItemStack stack : armor) { - if(!stack.isEmpty()) { + for (ItemStack stack: armor) { + if (!stack.isEmpty()) { totalItemsWidth += 16; - if(stack.getItem().showDurabilityBar(stack)) { + if (stack.getItem().showDurabilityBar(stack)) { hasDurability = true; } } } - if(!player.getHeldItemMainhand().isEmpty()) { + if (!player.getHeldItemMainhand().isEmpty()) { totalItemsWidth += 16; - if(player.getHeldItemMainhand().getItem().showDurabilityBar(player.getHeldItemMainhand())) { + if (player.getHeldItemMainhand().getItem().showDurabilityBar(player.getHeldItemMainhand())) { hasDurability = true; } } - if(!player.getHeldItemOffhand().isEmpty()) { + if (!player.getHeldItemOffhand().isEmpty()) { totalItemsWidth += 16; - if(player.getHeldItemOffhand().getItem().showDurabilityBar(player.getHeldItemOffhand())) { + if (player.getHeldItemOffhand().getItem().showDurabilityBar(player.getHeldItemOffhand())) { hasDurability = true; } } - + int xOffset = -totalItemsWidth / 2; final int yOffset = hasDurability ? -28 : -15; - - if(!player.getHeldItemMainhand().isEmpty()) { + + if (!player.getHeldItemMainhand().isEmpty()) { this.renderItem(player.getHeldItemMainhand(), xOffset, yOffset); xOffset += 16; } - - for(ItemStack stack : armor) { - if(!stack.isEmpty()) { + + for (ItemStack stack: armor) { + if (!stack.isEmpty()) { this.renderItem(stack, xOffset, yOffset); xOffset += 16; } } - - if(!player.getHeldItemOffhand().isEmpty()) { + + if (!player.getHeldItemOffhand().isEmpty()) { this.renderItem(player.getHeldItemOffhand(), xOffset, yOffset); } } - + GL11.glEnable(GL11.GL_DEPTH_TEST); GL11.glPopMatrix(); } - + private void renderItem(ItemStack stack, int x, int y) { - final int durability = (int) ((stack.getMaxDamage() - stack.getItemDamage()) / (float) stack.getMaxDamage() * 100); - if(durability >= 0 && stack.getItem().showDurabilityBar(stack)) { + final int durability = (int)((stack.getMaxDamage() - stack.getItemDamage()) / (float) stack.getMaxDamage() * 100); + if (durability >= 0 && stack.getItem().showDurabilityBar(stack)) { final String duraString = String.valueOf(durability); - FontUtils.drawString(duraString, x, y + (-y - 10), stack.getItem().getRGBDurabilityForDisplay(stack), true, this.customFont.booleanValue()); + if (!customFont.booleanValue()) { + mc.fontRenderer.drawString(duraString, x, y + (-y - 10), stack.getItem().getRGBDurabilityForDisplay(stack), true); + } else + font.drawString(duraString, x, y + (-y - 10), stack.getItem().getRGBDurabilityForDisplay(stack), true, 1.0f); } - + GL11.glPushMatrix(); GL11.glDepthMask(true); GlStateManager.pushMatrix(); @@ -180,7 +188,7 @@ private void renderItem(ItemStack stack, int x, int y) { mc.getRenderItem().zLevel = -100.0F; GlStateManager.scale(1, 1, 0.01F); mc.getRenderItem().renderItemAndEffectIntoGUI(stack, x, (y / 2) - 12); - mc.getRenderItem().renderItemOverlays(mc.fontRenderer, stack, x, (y / 2) - 12); //durability + mc.getRenderItem().renderItemOverlays(mc.fontRenderer, stack, x, (y / 2) - 12); mc.getRenderItem().zLevel = 0.0F; GlStateManager.scale(1, 1, 1); RenderHelper.disableStandardItemLighting(); @@ -188,7 +196,7 @@ private void renderItem(ItemStack stack, int x, int y) { GlStateManager.disableBlend(); GlStateManager.disableLighting(); } - + private void drawRect(float left, float top, float right, float bottom, int r, int g, int b, int a) { final Tessellator tessellator = Tessellator.getInstance(); final BufferBuilder bufferbuilder = tessellator.getBuffer(); @@ -199,43 +207,45 @@ private void drawRect(float left, float top, float right, float bottom, int r, i bufferbuilder.pos(left, top, 0).color(r, g, b, a).endVertex(); tessellator.draw(); } - + private void drawHorizontalLine(int startX, int endX, int y, int r, int g, int b, int a) { this.drawRect(startX, y, endX + 1, y + 1, r, g, b, a); } - + private void drawVerticalLine(int x, final int startY, int endY, int r, int g, int b, int a) { this.drawRect(x, startY + 1, x + 1, endY, r, g, b, a); } private void drawRoundedBorderedRect(int left, int top, int right, int bottom, int insideColor, EntityLivingBase entity) { + boolean isFriend = TempleClient.friendManager.isFriend(entity.getName()); final int insideR = (insideColor >> 16 & 255); final int insideG = (insideColor >> 8 & 255); final int insideB = (insideColor & 255); final int insideA = (insideColor >> 24 & 255); this.drawRect(left + 1, top + 1, right - 1, bottom - 1, insideR, insideG, insideB, insideA); - int outsideR, outsideG, outsideB; - if (TempleClient.friendManager.isFriend(entity.getName())) { - outsideR = 0; - outsideG = 255; - outsideB = 0; + float outsideR, outsideG, outsideB; + if (isFriend) { + Color friendColor = Colors.INSTANCE.friendColor.getColor(); + outsideR = friendColor.getRed() / 255.0f; + outsideG = friendColor.getGreen() / 255.0f; + outsideB = friendColor.getBlue() / 255.0f; } else { - outsideR = this.borderRed.intValue(); - outsideG = this.borderGreen.intValue(); - outsideB = this.borderBlue.intValue(); + Color outsideColor = Colors.INSTANCE.staticColor.getColor(); + outsideR = outsideColor.getRed() / 255.0f; + outsideG = outsideColor.getGreen() / 255.0f; + outsideB = outsideColor.getBlue() / 255.0f; } - final int outsideA = (insideColor >> 24 & 255); - this.drawHorizontalLine(left, right - 1, top, outsideR, outsideG, outsideB, outsideA); - this.drawHorizontalLine(left, right - 1, bottom - 1, outsideR, outsideG, outsideB, outsideA); - this.drawVerticalLine(left, top, bottom - 1, outsideR, outsideG, outsideB, outsideA); - this.drawVerticalLine(right - 1, top, bottom - 1, outsideR, outsideG, outsideB, outsideA); + final int outsideA = insideA; + this.drawHorizontalLine(left, right - 1, top, (int)(outsideR * 255), (int)(outsideG * 255), (int)(outsideB * 255), outsideA); + this.drawHorizontalLine(left, right - 1, bottom - 1, (int)(outsideR * 255), (int)(outsideG * 255), (int)(outsideB * 255), outsideA); + this.drawVerticalLine(left, top, bottom - 1, (int)(outsideR * 255), (int)(outsideG * 255), (int)(outsideB * 255), outsideA); + this.drawVerticalLine(right - 1, top, bottom - 1, (int)(outsideR * 255), (int)(outsideG * 255), (int)(outsideB * 255), outsideA); } private int getHealthColor(EntityLivingBase entity) { - final int health = (int) ((entity.getMaxHealth() - (entity.getHealth() + entity.getAbsorptionAmount())) / entity.getMaxHealth() * 36); + final int health = (int)((entity.getMaxHealth() - (entity.getHealth() + entity.getAbsorptionAmount())) / entity.getMaxHealth() * 36); - //magic numbers yippee - switch(MathHelper.clamp(health, 0, 36) / 6) { + switch (MathHelper.clamp(health, 0, 36) / 6) { case 0: return Color.GREEN.getRGB(); case 1: @@ -252,33 +262,33 @@ private int getHealthColor(EntityLivingBase entity) { return 0xFFFFFF; } - + private int getPingColor(EntityLivingBase entity) { long ping; try { ping = Objects.requireNonNull(mc.getConnection()).getPlayerInfo(entity.getUniqueID()).getResponseTime(); - } catch(Exception ignored) { + } catch (Exception ignored) { return 0xFFFFFF; } - - if(ping >= 200) { + + if (ping >= 200) { return 11141120; - } else if(ping >= 150) { + } else if (ping >= 150) { return Color.RED.getRGB(); - } else if(ping >= 100) { + } else if (ping >= 100) { return 16755200; - } else if(ping >= 75) { + } else if (ping >= 75) { return Color.YELLOW.getRGB(); - } else if(ping >= 50) { + } else if (ping >= 50) { return 43520; - } else if(ping > 0) { + } else if (ping > 0) { return Color.GREEN.getRGB(); } else { return 0xFFFFFF; } } - + private int getStringWidth(String string) { - return (int) Math.ceil(FontUtils.getStringWidth(string, this.customFont.booleanValue())); + return (int) Math.ceil(font.getStringWidth(string)); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NoRender.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NoRender.java index 7cb80835..f4092fae 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NoRender.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/NoRender.java @@ -1,52 +1,120 @@ package xyz.templecheats.templeclient.features.module.modules.render; -import net.minecraftforge.client.event.RenderBlockOverlayEvent; +import net.minecraftforge.client.event.*; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.manager.ModuleManager; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import java.util.function.BooleanSupplier; + public class NoRender extends Module { - private final BooleanSetting fireOverlay = new BooleanSetting("Fire", this, false); - private final BooleanSetting waterOverlay = new BooleanSetting("Water", this, false); - private final BooleanSetting blindnessEffect = new BooleanSetting("Blindness", this, false); + public static NoRender INSTANCE; + /* + * Settings + */ + + // Overlay + private final BooleanSetting fire = new BooleanSetting("Fire", this, false); + private final BooleanSetting water = new BooleanSetting("Water", this, false); + private final BooleanSetting block = new BooleanSetting("Blocks", this, false); + private final BooleanSetting bossInfo = new BooleanSetting("BossInfo", this, false); + private final BooleanSetting pumpkin = new BooleanSetting("Pumpkin", this, false); + private final BooleanSetting portal = new BooleanSetting("Portal", this, false); + private final BooleanSetting vignette = new BooleanSetting("Vignette", this, false); + private final BooleanSetting totem = new BooleanSetting("Totem", this, false); + + // Effect private final BooleanSetting nauseaEffect = new BooleanSetting("Nausea", this, false); - private final BooleanSetting fog = new BooleanSetting("Fog", this, false); - private final BooleanSetting noHurtCam = new BooleanSetting("NoHurtCam", this, false); + private final BooleanSetting blindnessEffect = new BooleanSetting("Blindness", this, false); + private final BooleanSetting hurtCam = new BooleanSetting("NoHurtCam", this, false); + private final BooleanSetting bobbing = new BooleanSetting("NoBob", this, false); + + // Environment + public final BooleanSetting fog = new BooleanSetting("Fog", this, false); + private final BooleanSetting weather = new BooleanSetting("Weather", this, false); public NoRender() { - super("NoRender","Disables some rendering", Keyboard.KEY_NONE, Category.Render); + super("NoRender", "Prevents rendering of certain things", Keyboard.KEY_NONE, Category.Render); + INSTANCE = this; + registerSettings(fire, water, block, bossInfo, pumpkin, portal, vignette, totem, nauseaEffect, blindnessEffect, hurtCam, bobbing, fog, weather); + } - registerSettings(fireOverlay, waterOverlay, blindnessEffect, nauseaEffect, fog, noHurtCam); + @SubscribeEvent + public void onRenderGameOverlayPre(RenderGameOverlayEvent.Pre event ) { + if (event.getType() == RenderGameOverlayEvent.ElementType.BOSSINFO) { + event.setCanceled(bossInfo.booleanValue()); + } } @SubscribeEvent - public void onRenderFireOverlay(RenderBlockOverlayEvent event) { - if (event.getOverlayType() == RenderBlockOverlayEvent.OverlayType.FIRE) { - if (fireOverlay.booleanValue()) event.setCanceled(true); - } else if (event.getOverlayType() == RenderBlockOverlayEvent.OverlayType.WATER) { - if (waterOverlay.booleanValue()) event.setCanceled(true); + public void onRenderGameOverlay(RenderGameOverlayEvent event) { + if (!event.isCancelable()) { + return; + } + switch (event.getType()) { + case HELMET: { + event.setCanceled(pumpkin.booleanValue()); + break; + } + case PORTAL: { + event.setCanceled(portal.booleanValue()); + break; + } + case VIGNETTE: { + event.setCanceled(vignette.booleanValue()); + break; + } } } - public static boolean preventFog() { + @SubscribeEvent + public void onRenderBlockOverlay(RenderBlockOverlayEvent event) { + RenderBlockOverlayEvent.OverlayType overlayType = event.getOverlayType(); + switch (overlayType) { + case FIRE: + event.setCanceled(fire.booleanValue()); + break; + case WATER: + event.setCanceled(water.booleanValue()); + break; + case BLOCK: + event.setCanceled(block.booleanValue()); + break; + } + } + + public static boolean checkEffectEnabled(BooleanSupplier condition) { NoRender noRender = ModuleManager.getModule(NoRender.class); - return noRender != null && noRender.isEnabled() && noRender.fog.booleanValue(); + return noRender != null && noRender.isEnabled() && condition.getAsBoolean(); + } + + public static boolean preventFog() { + return checkEffectEnabled(() -> NoRender.INSTANCE.fog.booleanValue()); } public static boolean preventBlindness() { - NoRender noRender = ModuleManager.getModule(NoRender.class); - return noRender != null && noRender.isEnabled() && noRender.blindnessEffect.booleanValue(); + return checkEffectEnabled(() -> NoRender.INSTANCE.blindnessEffect.booleanValue()); } public static boolean preventNausea() { - NoRender noRender = ModuleManager.getModule(NoRender.class); - return noRender != null && noRender.isEnabled() && noRender.nauseaEffect.booleanValue(); + return checkEffectEnabled(() -> NoRender.INSTANCE.nauseaEffect.booleanValue()); } public static boolean preventHurtCam() { - NoRender noRender = ModuleManager.getModule(NoRender.class); - return noRender != null && noRender.isEnabled() && noRender.noHurtCam.booleanValue(); + return checkEffectEnabled(() -> NoRender.INSTANCE.hurtCam.booleanValue()); + } + + public static boolean preventBobbing() { + return checkEffectEnabled(() -> NoRender.INSTANCE.bobbing.booleanValue()); + } + + public static boolean preventWeather() { + return checkEffectEnabled(() -> NoRender.INSTANCE.weather.booleanValue()); + } + + public static boolean preventTotem() { + return checkEffectEnabled(() -> NoRender.INSTANCE.totem.booleanValue()); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PlayerESP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PlayerESP.java deleted file mode 100644 index 4a07a1bb..00000000 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PlayerESP.java +++ /dev/null @@ -1,91 +0,0 @@ -package xyz.templecheats.templeclient.features.module.modules.render; - -import net.minecraft.client.Minecraft; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraftforge.client.event.RenderWorldLastEvent; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import org.lwjgl.input.Keyboard; -import xyz.templecheats.templeclient.TempleClient; -import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.render.RenderUtil; -import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; - -import java.util.ArrayList; -import java.util.List; - -public class PlayerESP extends Module { - private static final List glowed = new ArrayList<>(); - private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Box); - private final IntSetting red = new IntSetting("Red", this, 0, 255, 255); - private final IntSetting green = new IntSetting("Green", this, 0, 255, 255); - private final IntSetting blue = new IntSetting("Blue", this, 0, 255, 255); - - public PlayerESP() { - super("PlayerESP","Highlights players", Keyboard.KEY_NONE, Category.Render); - - registerSettings(mode, red, green, blue); - } - - @SubscribeEvent - public void onRender(RenderWorldLastEvent e) { - for (Entity entity : Minecraft.getMinecraft().world.playerEntities) { - if (entity != Minecraft.getMinecraft().player && entity != null) { - float r, g, b; - if (TempleClient.friendManager.isFriend(entity.getName())) { - r = 0.0f; - g = 1.0f; - b = 0.0f; - } else { - r = red.intValue() / 255.0f; - g = green.intValue() / 255.0f; - b = blue.intValue() / 255.0f; - } - - if (mode.value() == Mode.Box) { - if (!glowed.isEmpty()) { - for (Entity glowEntity : glowed) { - glowEntity.setGlowing(false); - } - glowed.clear(); - } - AxisAlignedBB box = new AxisAlignedBB( - entity.getEntityBoundingBox().minX - 0.05 - entity.posX - + (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosX), - entity.getEntityBoundingBox().minY - entity.posY - + (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosY), - entity.getEntityBoundingBox().minZ - 0.05 - entity.posZ - + (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosZ), - entity.getEntityBoundingBox().maxX + 0.05 - entity.posX - + (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosX), - entity.getEntityBoundingBox().maxY + 0.1 - entity.posY - + (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosY), - entity.getEntityBoundingBox().maxZ + 0.05 - entity.posZ - + (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosZ) - ); - RenderUtil.FillOnlyLinePlayerESP(entity, box, r, g, b); - } else { - entity.setGlowing(true); - if (!glowed.contains(entity)) { - glowed.add(entity); - } - } - } - } - } - - @Override - public void onDisable() { - for (Entity entity : glowed) { - entity.setGlowing(false); - } - glowed.clear(); - super.onDisable(); - } - - private enum Mode { - Box, - Glow - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PopChams.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PopChams.java new file mode 100644 index 00000000..c5badb06 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/PopChams.java @@ -0,0 +1,131 @@ +package xyz.templecheats.templeclient.features.module.modules.render; + +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.network.play.server.SPacketEntityStatus; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.event.events.network.PacketEvent; +import xyz.templecheats.templeclient.event.events.render.ArmorEvent; +import xyz.templecheats.templeclient.event.events.render.FireEvent; +import xyz.templecheats.templeclient.event.events.render.HeldItemEvent; +import xyz.templecheats.templeclient.event.events.render.Render3DEvent; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; + +import static org.lwjgl.opengl.GL11.*; + +import java.util.HashMap; +import java.util.Map; + +public class PopChams extends Module { + /* + * Settings + */ + private final DoubleSetting lineWidth = new DoubleSetting("LineWidth", this, 0.0, 5.0, 1); + public static boolean rendering; + /* + * Variables + */ + private final HashMap < EntityPlayer, Long > playerList = new HashMap < > (); + public PopChams() { + super("PopChams", "Renders a totempop effect", Keyboard.KEY_NONE, Category.Render); + + registerSettings(lineWidth); + } + + + @Listener + public void onRender3d(Render3DEvent event) { //popchams will now be rendered AFTER shaderesp. fixing the render conflicts + if (mc.world == null) { + return; + } + for (final Map.Entry < EntityPlayer, Long > entry: new HashMap < > (playerList).entrySet()) { + final float alpha = (System.currentTimeMillis() - entry.getValue()) / 1000.0f; + if (alpha > 1.0f) { + playerList.remove(entry.getKey()); + continue; + } + rendering = false; + GradientShader.setup(Math.max(0.0f, 1.0f - alpha)); + rendering = true; + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + mc.getRenderManager().renderEntityStatic(entry.getKey(), mc.getRenderPartialTicks(), false); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glPopMatrix(); + + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glLineWidth((float) lineWidth.doubleValue()); + mc.getRenderManager().renderEntityStatic(entry.getKey(), mc.getRenderPartialTicks(), false); + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glPopMatrix(); + GradientShader.finish(); + rendering = false; + } + } + + @Listener + public void onPacketReceive(PacketEvent.Receive event) { + if (mc.world == null) { + return; + } + if (event.getPacket() instanceof SPacketEntityStatus) { + final SPacketEntityStatus packet = (SPacketEntityStatus) event.getPacket(); + final Entity entity = packet.getEntity(mc.world); + if (entity instanceof EntityPlayer && packet.getOpCode() == 35) { + invokeEntity((EntityPlayer) entity); + } + } + } + @Listener + public void onRenderArmor(ArmorEvent event) { + event.setCanceled(true); + } + @Listener + public void onRenderHeldItem(HeldItemEvent event) { + event.setCanceled(true); + } + @Listener + public void onRenderFire(FireEvent event) { + event.setCanceled(true); + } + @Override + public void onEnable() { + invokeEntity(mc.player); + } + private void invokeEntity(final EntityPlayer entityPlayer) { + if (entityPlayer.equals(mc.player)) { + return; + } + final EntityOtherPlayerMP player = new EntityOtherPlayerMP(mc.world, mc.player.getGameProfile()); + player.copyLocationAndAnglesFrom(entityPlayer); + + player.prevRotationYaw = player.rotationYaw; + player.prevRotationYawHead = player.rotationYawHead; + player.prevRotationPitch = player.rotationPitch; + + player.setEntityId(-1); + playerList.put(player, System.currentTimeMillis()); + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Tracers.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Tracers.java index 2a5c4e21..21843531 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Tracers.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Tracers.java @@ -6,32 +6,29 @@ import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; -import xyz.templecheats.templeclient.util.setting.impl.IntSetting; public class Tracers extends Module { /** * Settings */ private final BooleanSetting colorDistance = new BooleanSetting("Color Distance", this, false); - private final IntSetting red = new IntSetting("Red", this, 0, 255, 255); - private final IntSetting green = new IntSetting("Green", this, 0, 255, 255); - private final IntSetting blue = new IntSetting("Blue", this, 0, 255, 255); public Tracers() { - super("Tracers","Draws lines directing towards entities", Keyboard.KEY_NONE, Category.Render); + super("Tracers", "Draws lines to entities", Keyboard.KEY_NONE, Category.Render); - registerSettings(colorDistance, red, green, blue); + registerSettings(colorDistance); } @SubscribeEvent public void onRender(RenderWorldLastEvent e) { - for (Entity playerEntity : mc.world.playerEntities) { + for (Entity playerEntity: mc.world.playerEntities) { if (playerEntity != null && playerEntity != mc.player) { - float r = red.intValue() / 255.0f; - float g = green.intValue() / 255.0f; - float b = blue.intValue() / 255.0f; + float r = Colors.INSTANCE.getColor().getRed() / 255.0f; + float g = Colors.INSTANCE.getColor().getGreen() / 255.0f; + float b = Colors.INSTANCE.getColor().getBlue() / 255.0f; if (colorDistance.booleanValue()) { float distance = mc.player.getDistance(playerEntity); diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Trail.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Trail.java new file mode 100644 index 00000000..053a3dac --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/Trail.java @@ -0,0 +1,175 @@ +package xyz.templecheats.templeclient.features.module.modules.render; + +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.mixins.accessor.IMixinRenderManager; +import xyz.templecheats.templeclient.util.color.RainbowUtil; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import java.util.ArrayList; +import java.util.List; + +import static xyz.templecheats.templeclient.util.math.MathUtil.lerp; + +public class Trail extends Module { + public static Trail INSTANCE; + /* + * Settings + */ + private final DoubleSetting length = new DoubleSetting("Length", this, 1, 25, 10); + private final BooleanSetting firstPerson = new BooleanSetting("FirstPerson", this, true); + private final DoubleSetting lineWidth = new DoubleSetting("Line Width", this, 1.0, 10.0, 2.0); + private final EnumSetting < Mode > mode = new EnumSetting<>("Mode", this, Mode.Fill); + private final List points = new ArrayList<>(); + public final RainbowUtil rainbow = new RainbowUtil(); + + public Trail() { + super("Trail", "Draw trail behind player", Keyboard.KEY_NONE, Category.Render); + registerSettings( firstPerson, length, lineWidth, mode); + INSTANCE = this; + } + private enum Mode { + Line, + Fill + } + + private boolean check() { + if (firstPerson.booleanValue() && mc.gameSettings.thirdPersonView == 0) { + return true; + } + else return mc.gameSettings.thirdPersonView != 0; + } + + @Override + public void onRenderWorld(float partialTicks) { + long currentTime = System.currentTimeMillis(); + + points.removeIf(point -> (currentTime - point.time) > length.doubleValue() * 100); + if (mc.player == null || mc.world == null) return; + + for (EntityPlayer player : mc.world.playerEntities) { + if (player.isDead || player.isInvisible()) { + continue; + } + if (player == mc.player && check()) { + + double x = lerp((float) player.lastTickPosX, (float) player.posX, partialTicks); + double y = lerp((float) player.lastTickPosY, (float) player.posY, partialTicks); + double z = lerp((float) player.lastTickPosZ, (float) player.posZ, partialTicks); + + points.add(new Point(new Vec3d(x, y, z))); + setup(); + switch (mode.value()) { + case Line: + renderLineStrip(points, false); + break; + case Fill: + drawTrail(); + break; + } + restore(); + GL11.glColor4f(1,1,1,1); + } + } + } + + private void drawTrail() { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + buffer.begin(GL11.GL_QUAD_STRIP, DefaultVertexFormats.POSITION_COLOR); + + double x = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosX(); + double y = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosY(); + double z = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosZ(); + + int index = 0; + for (Point point : points) { + int color = rainbow.rainbowProgress(5, index, Colors.INSTANCE.gradientColor1.getColor().getRGB(), Colors.INSTANCE.gradientColor2.getColor().getRGB()); + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + float alpha = (float) index / (float) points.size() * 0.7f; + + Vec3d vec = point.pos.subtract(x, y, z); + + buffer.pos(vec.x, vec.y + mc.player.height, vec.z).color(red, green, blue, alpha).endVertex(); + buffer.pos(vec.x, vec.y, vec.z).color(red, green, blue, alpha).endVertex(); + index++; + } + tessellator.draw(); + + renderLineStrip(points, true); + renderLineStrip(points, false); + + } + + private void renderLineStrip(List points, boolean withHeight) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + GlStateManager.glLineWidth(lineWidth.floatValue()); + buffer.begin(GL11.GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + double x = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosX(); + double y = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosY(); + double z = ((IMixinRenderManager) mc.getRenderManager()).getRenderPosZ(); + + int index = 0; + for (Point point : points) { + int color = rainbow.rainbowProgress(5, index, Colors.INSTANCE.gradientColor1.getColor().getRGB(), Colors.INSTANCE.gradientColor2.getColor().getRGB()); + float red = (float) (color >> 16 & 255) / 255.0F; + float green = (float) (color >> 8 & 255) / 255.0F; + float blue = (float) (color & 255) / 255.0F; + float alpha = (float) index / (float) points.size() * 0.7f; + alpha = Math.min(alpha, 1); + + Vec3d vec = point.pos.subtract(x, y, z); + if (withHeight) { + buffer.pos(vec.x, vec.y + mc.player.height, vec.z).color(red, green, blue, alpha).endVertex(); + } + else { + buffer.pos(vec.x, vec.y, vec.z).color(red, green, blue, alpha).endVertex(); + } + index++; + } + + tessellator.draw(); + } + + private void setup() { + GlStateManager.pushMatrix(); + GlStateManager.disableTexture2D(); + GlStateManager.enableBlend(); + GlStateManager.disableCull(); + GlStateManager.disableAlpha(); + GL11.glColor4f(1, 1, 1, 0.5f); + + } + + private void restore() { + GlStateManager.enableAlpha(); + GlStateManager.enableCull(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.popMatrix(); + } + + static class Point { + public Vec3d pos; + public long time; + + public Point(Vec3d pos) { + this.pos = pos; + this.time = System.currentTimeMillis(); + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ViewModel.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ViewModel.java index 1ed15054..63d410ac 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ViewModel.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/ViewModel.java @@ -13,6 +13,11 @@ import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; public class ViewModel extends Module { + /** + * Settings + */ + public final BooleanSetting cancelEating = new BooleanSetting("No Eat", this, false); + private final DoubleSetting fov = new DoubleSetting("FOV", this, 70d, 200d, 130d); private final DoubleSetting xLeft = new DoubleSetting("Left X", this, -2d, 2d, 0d); private final DoubleSetting yLeft = new DoubleSetting("Left Y", this, -2d, 2d, 0.2); private final DoubleSetting zLeft = new DoubleSetting("Left Z", this, -2d, 2d, -1.2); @@ -22,14 +27,12 @@ public class ViewModel extends Module { private final DoubleSetting xScale = new DoubleSetting("X Scale", this, 0.1, 2d, 1d); private final DoubleSetting yScale = new DoubleSetting("Y Scale", this, 0.1, 2d, 1d); private final DoubleSetting zScale = new DoubleSetting("Z Scale", this, 0.1, 2d, 1d); - private final DoubleSetting fov = new DoubleSetting("FOV", this, 70d, 200d, 130d); - private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Value); - public final BooleanSetting cancelEating = new BooleanSetting("No Eat", this, false); + private final EnumSetting < Mode > mode = new EnumSetting < > ("Mode", this, Mode.Value); public ViewModel() { - super("ViewModel","Improves view-model positioning and size", Keyboard.KEY_NONE, Category.Render); + super("ViewModel", "Modify your viewmodel", Keyboard.KEY_NONE, Category.Render); - registerSettings(xLeft, yLeft, zLeft, xRight, yRight, zRight, xScale, yScale, zScale, fov, mode, cancelEating); + registerSettings(cancelEating, fov, xLeft, yLeft, zLeft, xRight, yRight, zRight, xScale, yScale, zScale, mode); } @Listener diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/ESP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/ESP.java new file mode 100644 index 00000000..dc07d6e0 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/ESP.java @@ -0,0 +1,19 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp; + +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.render.esp.sub.*; + +public class ESP extends Module { + + public ESP() { + super("ESP", "Highlights entities in the world", Category.Render, true); + submodules.add(new Block()); + submodules.add(new Hole()); + submodules.add(new Item()); + submodules.add(new Player()); + submodules.add(new Shader()); + submodules.add(new Spawner()); + submodules.add(new Storage()); + submodules.add(new Target()); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Block.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Block.java new file mode 100644 index 00000000..adde236b --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Block.java @@ -0,0 +1,72 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.EnumFacing; +import net.minecraftforge.client.event.DrawBlockHighlightEvent; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; + +import java.awt.*; + +//TODO: add linewidth setting +public class Block extends Module { + /* + * Settings + */ + private final BooleanSetting outline = new BooleanSetting("Outline", this, true); + private final BooleanSetting fill = new BooleanSetting("Fill", this, true); + private final BooleanSetting hitSideOnly = new BooleanSetting("FaceOnly", this, true); + private final DoubleSetting opacity = new DoubleSetting("Opacity", this, 0.0, 1.0, 0.5); + public static boolean rendering; + + public Block() { + super("Block", "Highlights the block at your crosshair", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(outline, fill, hitSideOnly, opacity); + } + + @SubscribeEvent + public void onRender3D(RenderWorldLastEvent event) { + RayTraceResult ray = Block.mc.objectMouseOver; + if (ray == null || ray.typeOfHit != RayTraceResult.Type.BLOCK) + return; + + BlockPos pos = ray.getBlockPos(); + EnumFacing sideHit = ray.sideHit; + rendering = false; + GradientShader.setup((float) opacity.doubleValue()); + rendering = true; + + if (fill.booleanValue()) { + if (hitSideOnly.booleanValue()) { + RenderUtil.boxFaceShader(pos, sideHit, Color.WHITE); + } else { + RenderUtil.boxShader(pos); + } + } + if (outline.booleanValue()) { + GL11.glLineWidth(1.5F); + if (hitSideOnly.booleanValue()) { + RenderUtil.outlineFaceShader(pos, sideHit, Color.WHITE); + } else { + RenderUtil.outlineShader(pos); + } + } + + GradientShader.finish(); + rendering = false; + } + + @SubscribeEvent + public void onHighlightBlock(DrawBlockHighlightEvent event) { + if (outline.booleanValue()) + event.setCanceled(true); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Hole.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Hole.java new file mode 100644 index 00000000..23a9d87a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Hole.java @@ -0,0 +1,139 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.event.ForgeEventManager; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.manager.HoleManager; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import net.minecraft.util.math.AxisAlignedBB; +import xyz.templecheats.templeclient.util.math.MathUtil; + +import java.awt.*; +import java.util.ArrayList; + + +public class Hole extends Module { + /* + * Settings + */ + + private final IntSetting range = new IntSetting("Range", this, 1, 20, 5); + private final IntSetting speed = new IntSetting("Speed", this, 1, 200, 50); + private final EnumSetting mode = new EnumSetting<>("Mode", this, Mode.Normal); + private final BooleanSetting slideAnimation = new BooleanSetting("Gradient", this, false); + + /* + * Variables + */ + private final ArrayList renderHoles = new ArrayList<>(); + + public Hole() { + super("Hole", "Highlights holes", Keyboard.KEY_NONE, Category.Render, true); + + registerSettings(range, speed, mode, slideAnimation); + } + + private boolean differentRenderType(final HoleManager.HolePos pos) { + return TempleClient.holeManager.getHoles().stream().filter(holePos -> holePos.getPos().equals(pos.getPos())).anyMatch(holePos -> !holePos.getHoleType().equals(pos.getHoleType())); + } + + private boolean holesContains(final HoleManager.HolePos pos) { + return renderHoles.stream().anyMatch(renderHole -> renderHole.holePos.getPos().equals(pos.getPos())); + } + + @SubscribeEvent + public void onRender3d(RenderWorldLastEvent event) { + TempleClient.holeManager.loadHoles(range.intValue()); + for (HoleManager.HolePos holePos : TempleClient.holeManager.getHoles()) { + final boolean diff = differentRenderType(holePos); + if (!holesContains(holePos) || diff) { + HoleInfo holeInfo1 = new HoleInfo(holePos); + renderHoles.add(holeInfo1); + } + } + new ArrayList<>(renderHoles).forEach(holeInfo -> { + if (!TempleClient.holeManager.holeManagerContains(holeInfo.holePos.getPos()) || differentRenderType(holeInfo.holePos)) { + holeInfo.out = true; + if (holeInfo.size <= 0.1f) { + renderHoles.remove(holeInfo); + return; + } + } + holeInfo.render(); + }); + } + + public class HoleInfo { + public final HoleManager.HolePos holePos; + public boolean out; + public long sys; + public float size; + + public HoleInfo(final HoleManager.HolePos holePos) { + this.holePos = holePos; + this.out = false; + this.sys = System.currentTimeMillis(); + this.size = 0.0f; + } + + public void render() { + size = MathUtil.lerp(size, out ? 0.0f : 1.0f, (0.02f * ForgeEventManager.deltaTime * speed.intValue() / 100.0f)); + final int index = holePos.isBedrock() ? 1 : 0; + final Color color = Colors.INSTANCE.getGradient()[index]; + final AxisAlignedBB bb = new AxisAlignedBB(holePos.getPos()); + if (mode.value() == Mode.Normal && !slideAnimation.booleanValue()) { + if (slideAnimation.booleanValue()) GradientShader.setup(0.5f); + if (holePos.isDouble()) { + if (holePos.isWestDouble()) { + RenderUtil.renderGradientLine(bb.minX - 1, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX - 1, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX - 1, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.boxShader(bb.minX - 1, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + + } else { + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ - 1, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ - 1, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ - 1, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.boxShader(bb.minX, bb.minY, bb.minZ - 1, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + + } + } else { + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.renderGradientLine(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + RenderUtil.boxShader(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY - 1 + size, bb.maxZ, color); + } + if (slideAnimation.booleanValue()) GradientShader.finish(); + } else { + GradientShader.setup(0.5f); + if (holePos.isDouble()) { + if (holePos.isWestDouble()) { + RenderUtil.outlineShader(bb.minX - 1, bb.minY, bb.minZ, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + RenderUtil.boxShader(bb.minX - 1, bb.minY, bb.minZ, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + } else { + RenderUtil.outlineShader(bb.minX, bb.minY, bb.minZ - 1, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + RenderUtil.boxShader(bb.minX, bb.minY, bb.minZ - 1, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + } + } else { + RenderUtil.outlineShader(bb.minX, bb.minY, bb.minZ, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + RenderUtil.boxShader(bb.minX, bb.minY, bb.minZ, bb.minX * (1.0f - size) + bb.maxX * size, bb.minY + 0.05f, bb.minZ * (1.0f - size) + bb.maxZ * size); + } + GradientShader.finish(); + } + } + } + + public enum Mode { + Normal, + Gradient + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Item.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Item.java new file mode 100644 index 00000000..47d00089 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Item.java @@ -0,0 +1,68 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.render.RenderUtil; + +public class Item extends Module { + public Item() { + super("Item", "Highlights items", Keyboard.KEY_NONE, Category.Render, true); + } + + @SubscribeEvent + public void onRender(RenderWorldLastEvent e) { + for (Entity entity: mc.world.loadedEntityList) { + if (entity instanceof EntityItem) { + EntityItem itemEntity = (EntityItem) entity; + String itemName = itemEntity.getItem().getDisplayName(); + + double x = itemEntity.lastTickPosX + (itemEntity.posX - itemEntity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks(); + double y = itemEntity.lastTickPosY + (itemEntity.posY - itemEntity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks(); + double z = itemEntity.lastTickPosZ + (itemEntity.posZ - itemEntity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks(); + + mc.fontRenderer.drawStringWithShadow(itemName, (float) x, (float) y, 0xFFFFFF); + AxisAlignedBB box = new AxisAlignedBB( + entity.getEntityBoundingBox().minX - + 0.05 - + entity.posX + + ((float)((double)((float) entity.lastTickPosX) + (entity.posX - entity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosX), + entity.getEntityBoundingBox().minY - + entity.posY + + ((float)((double)((float) entity.lastTickPosY) + (entity.posY - entity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosY), + entity.getEntityBoundingBox().minZ - + 0.05 - + entity.posZ + + ((float)((double)((float) entity.lastTickPosZ) + (entity.posZ - entity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosZ), + entity.getEntityBoundingBox().maxX + + 0.05 - + entity.posX + + ((float)((double)((float) entity.lastTickPosX) + (entity.posX - entity.lastTickPosX) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosX), + entity.getEntityBoundingBox().maxY + + 0.1 - + entity.posY + + ((float)((double)((float) entity.lastTickPosY) + (entity.posY - entity.lastTickPosY) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosY), + entity.getEntityBoundingBox().maxZ + + 0.05 - + entity.posZ + + ((float)((double)((float) entity.lastTickPosZ) + (entity.posZ - entity.lastTickPosZ) * Minecraft.getMinecraft().getRenderPartialTicks()) - Minecraft.getMinecraft() + .getRenderManager().viewerPosZ)); + + GradientShader.setup(0.5f); + RenderUtil.FillOnlyLine(entity, box); + GradientShader.finish(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Player.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Player.java new file mode 100644 index 00000000..363146c1 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Player.java @@ -0,0 +1,98 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class Player extends Module { + /* + * Settings + */ + private final EnumSetting < Mode > mode = new EnumSetting < > ("Mode", this, Mode.Box); + + /* + * Variables + */ + private static final List < Entity > glowed = new ArrayList < > (); + + public Player() { + super("Player", "Highlights players", Keyboard.KEY_NONE, Category.Render, true); + + registerSettings(mode); + } + + @SubscribeEvent + public void onRender(RenderWorldLastEvent e) { + for (Entity entity: Minecraft.getMinecraft().world.playerEntities) { + if (entity != Minecraft.getMinecraft().player && entity != null) { + float r, g, b; + if (TempleClient.friendManager.isFriend(entity.getName())) { + Color friendColor = Colors.INSTANCE.friendColor.getColor(); + r = friendColor.getRed() / 255.0f; + g = friendColor.getGreen() / 255.0f; + b = friendColor.getBlue() / 255.0f; + } else { + Color defaultColor = Colors.INSTANCE.staticColor.getColor(); + r = defaultColor.getRed() / 255.0f; + g = defaultColor.getGreen() / 255.0f; + b = defaultColor.getBlue() / 255.0f; + } + + if (mode.value() == Mode.Box) { + if (!glowed.isEmpty()) { + for (Entity glowEntity: glowed) { + glowEntity.setGlowing(false); + } + glowed.clear(); + } + AxisAlignedBB box = new AxisAlignedBB( + entity.getEntityBoundingBox().minX - 0.05 - entity.posX + + (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosX), + entity.getEntityBoundingBox().minY - entity.posY + + (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosY), + entity.getEntityBoundingBox().minZ - 0.05 - entity.posZ + + (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosZ), + entity.getEntityBoundingBox().maxX + 0.05 - entity.posX + + (entity.lastTickPosX + (entity.posX - entity.lastTickPosX) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosX), + entity.getEntityBoundingBox().maxY + 0.1 - entity.posY + + (entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosY), + entity.getEntityBoundingBox().maxZ + 0.05 - entity.posZ + + (entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * e.getPartialTicks() - Minecraft.getMinecraft().getRenderManager().viewerPosZ) + ); + RenderUtil.FillOnlyLinePlayerESP(entity, box, r, g, b); + } else { + entity.setGlowing(true); + if (!glowed.contains(entity)) { + glowed.add(entity); + } + } + } + } + } + + @Override + public void onDisable() { + for (Entity entity: glowed) { + entity.setGlowing(false); + } + glowed.clear(); + super.onDisable(); + } + + private enum Mode { + Box, + Glow + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Shader.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Shader.java new file mode 100644 index 00000000..7e25eb93 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Shader.java @@ -0,0 +1,189 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.shader.ShaderGroup; +import net.minecraft.entity.item.EntityEnderCrystal; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.client.event.*; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraft.entity.Entity; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL32; +import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.event.events.render.*; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.mixins.accessor.IEntityRenderer; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.render.RenderUtil; +import xyz.templecheats.templeclient.util.setting.impl.*; + +import static org.lwjgl.opengl.GL11.*; + +public class Shader extends Module { + /* + * Settings + */ + private final BooleanSetting crystal = new BooleanSetting("Crystals", this, false); + private final BooleanSetting player = new BooleanSetting("Players", this, false); + public final BooleanSetting hand = new BooleanSetting("Hand", this, false); + private final DoubleSetting lineWidth = new DoubleSetting("LineWidth", this, 0.0, 5.0, 1); + private final DoubleSetting opacity = new DoubleSetting("Opacity", this, 0.0, 1.0, 0.5); + public static boolean rendering; + public static Shader INSTANCE; + Framebuffer buffer = new Framebuffer(1, 1, false); + ShaderGroup shader; + public Shader() { + super("Shader", "Highlights players and crystals", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(player, crystal, hand, lineWidth, opacity); + INSTANCE = this; + } + + @Listener + public void onNamePlate(NamePlateEvent event) { + if (rendering && player.booleanValue()) + event.setCanceled(true); + } + + // ZANE will help me fix that <3 + public void drawHand(float partialTicks, int pass) { + if (mc.gameSettings.thirdPersonView != 0 || mc.world == null) { + return; + } + + // Clean up the frame buffer and bind it + // buffer.framebufferClear(); + //buffer.bindFramebuffer(false); + + rendering = true; + GradientShader.setup((float) opacity.doubleValue()); + try { + // Setup + RenderUtil.bindBlank(); + GlStateManager.pushMatrix(); + glLineWidth(1f); + glEnable(GL_LINE_SMOOTH); + glEnable(GL32.GL_DEPTH_CLAMP); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + GlStateManager.disableAlpha(); + GlStateManager.shadeModel(GL_SMOOTH); + GlStateManager.disableCull(); + GlStateManager.enableBlend(); + GlStateManager.depthMask(false); + GlStateManager.disableTexture2D(); + GlStateManager.disableLighting(); + + // Push matrix + GlStateManager.matrixMode(GL_PROJECTION); + GlStateManager.pushMatrix(); + GlStateManager.matrixMode(GL_MODELVIEW); + GlStateManager.pushMatrix(); + + // Re-enable blend because shader rendering will disable it at the end + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + + // Draw it on the main frame buffer + //RenderUtil.bindBlank(); + //mc.getFramebuffer().bindFramebuffer(false); + // buffer.framebufferRenderExt(mc.displayWidth, mc.displayHeight, false); + + ((IEntityRenderer) mc.entityRenderer).invokeRenderHand(partialTicks, pass); + + // Revert states + GlStateManager.enableBlend(); + GlStateManager.enableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.depthMask(false); + GlStateManager.disableCull(); + + // Revert matrix + GlStateManager.matrixMode(GL11.GL_PROJECTION); + GlStateManager.popMatrix(); + GlStateManager.matrixMode(GL11.GL_MODELVIEW); + GlStateManager.popMatrix(); + + // Restore + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + GlStateManager.shadeModel(GL11.GL_FLAT); + GlStateManager.enableAlpha(); + GlStateManager.depthMask(true); + GL11.glDisable(GL32.GL_DEPTH_CLAMP); + GL11.glDisable(GL11.GL_LINE_SMOOTH); + GlStateManager.color(1f, 1f, 1f, 1f); + GL11.glLineWidth(1f); + GlStateManager.popMatrix(); + } catch (Exception ignoredException) { + } + GradientShader.finish(); + rendering = false; + } + + @Listener + public void onRender3d(Render3DPreEvent event) { + if (mc.gameSettings.thirdPersonView != 0 || mc.world == null) { + return; + } + rendering = true; + for (final Entity entity : mc.world.loadedEntityList) { + if (entity != null && ((!entity.equals(mc.player) && entity instanceof EntityPlayer && player.booleanValue()) || (entity instanceof EntityEnderCrystal && crystal.booleanValue()))) { + GradientShader.setup((float) opacity.doubleValue()); + try { + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + mc.getRenderManager().renderEntityStatic(entity, mc.getRenderPartialTicks(), false); + + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glPopMatrix(); + + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + glEnable(GL_LINE_SMOOTH); + glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); + glLineWidth(lineWidth.floatValue()); + + mc.getRenderManager().renderEntityStatic(entity, mc.getRenderPartialTicks(), false); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + glPopMatrix(); + } catch (Exception ignoredException) { + } + GradientShader.finish(); + rendering = false; + } + } + } + + @SubscribeEvent + public void onRenderOverlay(RenderBlockOverlayEvent event) { + if (event.getOverlayType() == RenderBlockOverlayEvent.OverlayType.FIRE || event.getOverlayType() == RenderBlockOverlayEvent.OverlayType.WATER) { + event.setCanceled(true); + } + } + + @Listener + public void onRenderArmor(ArmorEvent event) { + event.setCanceled(true); + } + + @Listener + public void onRenderHeldItem(HeldItemEvent event) { + event.setCanceled(true); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/SpawnerESP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Spawner.java similarity index 73% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/render/SpawnerESP.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Spawner.java index df755cb5..36bfa7d4 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/SpawnerESP.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Spawner.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.module.modules.render; +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; import net.minecraft.tileentity.TileEntityMobSpawner; import net.minecraftforge.client.event.RenderWorldLastEvent; @@ -7,14 +7,14 @@ import xyz.templecheats.templeclient.features.module.Module; import xyz.templecheats.templeclient.util.render.RenderUtil; -public class SpawnerESP extends Module { - public SpawnerESP() { - super("SpawnerESP","Highlights mob spawners", Keyboard.KEY_NONE, Category.Render); +public class Spawner extends Module { + public Spawner() { + super("Spawner", "Highlights mob spawners", Keyboard.KEY_NONE, Category.Render, true); } @SubscribeEvent public void onRender(RenderWorldLastEvent e) { - for (Object c : mc.world.loadedTileEntityList) { + for (Object c: mc.world.loadedTileEntityList) { if (c instanceof TileEntityMobSpawner) { RenderUtil.blockESP(((TileEntityMobSpawner) c).getPos()); } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/StorageESP.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Storage.java similarity index 59% rename from src/main/java/xyz/templecheats/templeclient/features/module/modules/render/StorageESP.java rename to src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Storage.java index 346ccb56..7dc0dbb4 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/StorageESP.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Storage.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.features.module.modules.render; +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; import net.minecraft.tileentity.*; import net.minecraftforge.client.event.RenderWorldLastEvent; @@ -8,27 +8,29 @@ import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; -public class StorageESP extends Module { +public class Storage extends Module { + /* + * Settings + */ private final BooleanSetting chests = new BooleanSetting("Chests", this, true); - private final BooleanSetting eChests = new BooleanSetting("EChests", this, true); - private final BooleanSetting shulkers = new BooleanSetting("Shulkers", this, true); private final BooleanSetting dispensers = new BooleanSetting("Dispensers", this, true); + private final BooleanSetting eChests = new BooleanSetting("EChests", this, true); private final BooleanSetting furnaces = new BooleanSetting("Furnaces", this, true); + private final BooleanSetting shulkers = new BooleanSetting("Shulkers", this, true); - public StorageESP() { - super("StorageESP","Highlights different types of storage entities", Keyboard.KEY_NONE, Category.Render); - - registerSettings(chests, eChests, shulkers, dispensers, furnaces); + public Storage() { + super("Storage", "Highlights different types of storage entities", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(chests, dispensers, eChests, furnaces, shulkers); } @SubscribeEvent public void onRender(RenderWorldLastEvent e) { - for (TileEntity tileEntity : mc.world.loadedTileEntityList) { - if (chests.booleanValue() && tileEntity instanceof TileEntityChest - || eChests.booleanValue() && tileEntity instanceof TileEntityEnderChest - || shulkers.booleanValue() && tileEntity instanceof TileEntityShulkerBox - || dispensers.booleanValue() && tileEntity instanceof TileEntityDispenser - || furnaces.booleanValue() && tileEntity instanceof TileEntityFurnace) { + for (TileEntity tileEntity: mc.world.loadedTileEntityList) { + if (chests.booleanValue() && tileEntity instanceof TileEntityChest || + eChests.booleanValue() && tileEntity instanceof TileEntityEnderChest || + shulkers.booleanValue() && tileEntity instanceof TileEntityShulkerBox || + dispensers.booleanValue() && tileEntity instanceof TileEntityDispenser || + furnaces.booleanValue() && tileEntity instanceof TileEntityFurnace) { RenderUtil.blockESP(tileEntity.getPos()); } } diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Target.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Target.java new file mode 100644 index 00000000..2a5b5439 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/esp/sub/Target.java @@ -0,0 +1,184 @@ +package xyz.templecheats.templeclient.features.module.modules.render.esp.sub; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.*; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.Entity; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.setting.impl.*; +import java.awt.*; + +import static xyz.templecheats.templeclient.util.render.RenderUtil.interpolateEntity; +import static xyz.templecheats.templeclient.util.math.MathUtil.lerp; +import static xyz.templecheats.templeclient.util.render.RenderUtil.renderTexture; + +//TODO: Some openGl issue still need to be fix in someWhere +public class Target extends Module { + /* + * Settings + */ + private final EnumSetting < ESP > texture = new EnumSetting < > ("Texture", this, ESP.TRIANGLE_CAPTURE); + private final DoubleSetting scale = new DoubleSetting("Scnale", this, 0.3, 1.0, 0.75); + private final DoubleSetting maxSpin = new DoubleSetting("MaxSpin", this, 10.0, 30.0, 15.0); + private final DoubleSetting opacity = new DoubleSetting("Opacity", this, 0.1, 1, 0.5); + + // TODO: Rewrite this shit + /* + * Variables + */ + boolean flip = false; + float spinSpeed = 1.0f; + float prevSpinStep = 1.0f; + float spinStep = 1.0f; + + boolean isScaling = false; + float initialScale = 2.5F; + float defaultScale = 0.0F; + float targetScale = scale.floatValue(); + long scaleAnimationStartTime = 0L; + + public Target() { + super("Target", "Renders a image at players core", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(scale, maxSpin, opacity, texture); + } + + private void resetScale() { + isScaling = false; + defaultScale = targetScale; + } + + private void scaleAnimation() { + if (!isScaling /*&& TARGET != null*/ ) { + isScaling = true; + scaleAnimationStartTime = System.currentTimeMillis(); + } + + if (isScaling) { + float elapsed = System.currentTimeMillis() - scaleAnimationStartTime; + + if (elapsed < 1500L) { + defaultScale = initialScale - (initialScale - targetScale) * (elapsed / 1500L); + } else { + defaultScale = scale.floatValue(); + } + } + } + + private void spinAnimation() { + if (spinSpeed > maxSpin.floatValue() || spinSpeed < -maxSpin.floatValue()) { + flip = !flip; + } + + spinSpeed += flip ? -0.2F : 0.2F; + + prevSpinStep = spinStep; + spinStep += spinSpeed; + } + + @Override + public void onEnable() { + resetScale(); + } + + @Override + public void onDisable() { + resetScale(); + } + + @Override + public void onUpdate() { + if (mc.player == null || mc.world == null /*|| TARGET == null*/ ) { + resetScale(); + } + spinAnimation(); + scaleAnimation(); + } + + @Override + public void onRenderWorld(float partialTicks) { + if (mc.player == null || mc.world == null) { + return; + } + + Color baseColor = Colors.INSTANCE.getColor(); + int alpha = (int) Math.round(opacity.doubleValue() * 255); + Color colorWithOpacity = new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), alpha); + + for (Entity entity: mc.world.playerEntities) { + if (entity != Minecraft.getMinecraft().player && entity != null) { + spinTargetTexture( + texture.value().getTexture(), + entity, + prevSpinStep, + spinStep, + defaultScale, + colorWithOpacity + ); + } + } + } + + + private void spinTargetTexture( + ResourceLocation resourceLocation, + Entity entity, + Float prevSpinStep, + Float spinStep, + Float scale, + Color color + ) { + Vec3d pos = interpolateEntity(entity); + + setUp(); + GlStateManager.translate(pos.x, pos.y + 1, pos.z); + GlStateManager.rotate(-mc.getRenderManager().playerViewY, 0, 1, 0); + GlStateManager.rotate((mc.gameSettings.thirdPersonView == 2 ? -1F : 1F) * mc.getRenderManager().playerViewX, 1, 0, 0); + GlStateManager.rotate(lerp(prevSpinStep, spinStep, mc.getRenderPartialTicks()), 0.0F, 0.0F, 1.0F); + GlStateManager.scale(-scale, -scale, scale); + GlStateManager.translate(-0.75, -0.75, -0.01); + renderTexture(resourceLocation, color); + restore(); + } + + private void setUp() { + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.shadeModel(7425); + GlStateManager.disableCull(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); + } + + private void restore() { + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + GlStateManager.enableDepth(); + GlStateManager.enableAlpha(); + GlStateManager.popMatrix(); + } + + public enum ESP { + SQUARE_CAPTURE("textures/esp/square-capture.png"), + SQUARE_DASHED("textures/esp/square-dashes.png"), + TRIANGLE_CAPTURE("textures/esp/triangle-capture.png"), + TRIANGLE_DASHED("textures/esp/triangle-dashes.png"); + + private final ResourceLocation texture; + + ESP(String texturePath) { + this.texture = new ResourceLocation(texturePath); + } + + public ResourceLocation getTexture() { + return texture; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/Particle.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/Particle.java new file mode 100644 index 00000000..156816d7 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/Particle.java @@ -0,0 +1,13 @@ +package xyz.templecheats.templeclient.features.module.modules.render.particle; + +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.render.particle.sub.FireFlies; +import xyz.templecheats.templeclient.features.module.modules.render.particle.sub.HitParticle; + +public class Particle extends Module { + public Particle() { + super("Particle", "Renders particles around you (might reduce preformence)", Category.Render, true); + submodules.add(new FireFlies()); + submodules.add(new HitParticle()); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/impl/ParticleTickHandler.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/impl/ParticleTickHandler.java new file mode 100644 index 00000000..23ce03f1 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/impl/ParticleTickHandler.java @@ -0,0 +1,165 @@ +package xyz.templecheats.templeclient.features.module.modules.render.particle.impl; + +import net.minecraft.block.Block; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; + +import java.awt.*; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static xyz.templecheats.templeclient.util.math.MathUtil.*; +import static xyz.templecheats.templeclient.util.render.RenderUtil.renderTexture; + +public class ParticleTickHandler { + public Vec3d pos, prevPos; + public double motionX, motionY, motionZ; + public double gravityAmount, inertiaAmount; + public double size; + public int tickLiving = (int) random(100, 300); + public int maxTickLiving = tickLiving; + + public ParticleTickHandler(Vec3d posIn, double motionX, double motionY, double motionZ, double size, double gravityAmount, double inertiaAmount) { + this.pos = posIn; + this.prevPos = posIn; + this.motionX = motionX; + this.motionY = motionY; + this.motionZ = motionZ; + this.gravityAmount = gravityAmount; + this.inertiaAmount = inertiaAmount; + } + + public boolean tick() { + tickLiving = 0; + maxTickLiving = 100; + tickLiving -= mc.player.getDistanceSq(pos.x, pos.y, pos.z) > 4096 ? 8 : 1; + + if (tickLiving < 0) { + return true; + } else { + prevPos = pos; + pos = pos.add(motionX, motionY, motionZ); + + motionY -= gravityAmount * 0.01; + + motionX *= 0.9 + (inertiaAmount / 10.0); + motionY *= 0.9 + (inertiaAmount / 10.0); + motionZ *= 0.9 + (inertiaAmount / 10.0); + + if ( blockPos(pos.x, pos.y, pos.z) ) { + motionY = -motionY; + } else if ( collisionCheck(pos.x, pos.y, pos.z, size / 10f, MathHelper.sqrt(motionX * motionY + motionZ * motionZ) * 1) ) { + motionX = -motionX + motionZ; + motionZ = -motionZ + motionX; + } + + return false; + } + } + + public boolean collisionCheck(double x, double y, double z, double size, double sp) { + return blockPos(x, y, z) || + blockPos(x, y - size, z) || + blockPos(x, y + size, z) || + + blockPos(x - sp, y, z - sp) || + blockPos(x + sp, y, z + sp) || + blockPos(x + sp, y, z - sp) || + blockPos(x - sp, y, z + sp) || + blockPos(x + sp, y, z) || + blockPos(x - sp, y, z) || + blockPos(x, y, z + sp) || + blockPos(x, y, z - sp) || + + blockPos(x - sp, y - size, z - sp) || + blockPos(x + sp, y - size, z + sp) || + blockPos(x + sp, y - size, z - sp) || + blockPos(x - sp, y - size, z + sp) || + blockPos(x + sp, y - size, z) || + blockPos(x - sp, y - size, z) || + blockPos(x, y - size, z + sp) || + blockPos(x, y - size, z - sp) || + + blockPos(x - sp, y + size, z - sp) || + blockPos(x + sp, y + size, z + sp) || + blockPos(x + sp, y + size, z - sp) || + blockPos(x - sp, y + size, z + sp) || + blockPos(x + sp, y + size, z) || + blockPos(x - sp, y + size, z) || + blockPos(x, y + size, z + sp) || + blockPos(x, y + size, z - sp); + } + + public boolean blockPos(double x, double y, double z) { + Set excludedBlocks = new HashSet<>(Arrays.asList( + Blocks.AIR, Blocks.WATER, Blocks.LAVA, Blocks.BED, Blocks.CAKE, Blocks.TALLGRASS, + Blocks.FLOWER_POT, Blocks.RED_FLOWER, Blocks.YELLOW_FLOWER, Blocks.SAPLING, Blocks.VINE, + Blocks.ACACIA_FENCE, Blocks.ACACIA_FENCE_GATE, Blocks.BIRCH_FENCE, Blocks.BIRCH_FENCE_GATE, + Blocks.DARK_OAK_FENCE, Blocks.DARK_OAK_FENCE_GATE, Blocks.JUNGLE_FENCE, Blocks.JUNGLE_FENCE_GATE, + Blocks.NETHER_BRICK_FENCE, Blocks.OAK_FENCE, Blocks.OAK_FENCE_GATE, Blocks.SPRUCE_FENCE, + Blocks.SPRUCE_FENCE_GATE, Blocks.ENCHANTING_TABLE, Blocks.END_PORTAL_FRAME, Blocks.DOUBLE_PLANT, + Blocks.STANDING_SIGN, Blocks.WALL_SIGN, Blocks.SKULL, Blocks.DAYLIGHT_DETECTOR, + Blocks.DAYLIGHT_DETECTOR_INVERTED, Blocks.STONE_SLAB, Blocks.WOODEN_SLAB, Blocks.CARPET, + Blocks.DEADBUSH, Blocks.VINE, Blocks.REDSTONE_WIRE, Blocks.REEDS, Blocks.SNOW_LAYER + )); + Block block = mc.world.getBlockState(new BlockPos(x, y, z)).getBlock(); + return !excludedBlocks.contains(block); + } + + public void draw(double scale, Color color, Textures textures) { + setUp(); + + double x = lerp((float) prevPos.x, (float) pos.x, mc.getRenderPartialTicks()) - mc.getRenderManager().viewerPosX; + double y = lerp((float) prevPos.y, (float) pos.y, mc.getRenderPartialTicks()) - mc.getRenderManager().viewerPosY; + double z = lerp((float) prevPos.z, (float) pos.z, mc.getRenderPartialTicks()) - mc.getRenderManager().viewerPosZ; + + GlStateManager.translate(x, y, z); + GlStateManager.rotate(-mc.getRenderManager().playerViewY, 0, 1, 0); + GlStateManager.rotate((mc.gameSettings.thirdPersonView == 2 ? -1F : 1F) * mc.getRenderManager().playerViewX, 1, 0, 0); + + GlStateManager.scale(-scale / 10f, -scale / 10f, scale / 10f); + GlStateManager.translate(-0.75, -0.75, -0.01); + renderTexture(textures.getResourceLocation(), color); + restore(); + } + + private void setUp() { + GlStateManager.pushMatrix(); + GlStateManager.disableLighting(); + GlStateManager.enableBlend(); + GlStateManager.shadeModel(7425); + GlStateManager.disableCull(); + GlStateManager.disableAlpha(); + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); + } + + private void restore() { + GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); + GlStateManager.disableBlend(); + GlStateManager.enableCull(); + GlStateManager.enableAlpha(); + GlStateManager.popMatrix(); + } + + public enum Textures { + Normal(new ResourceLocation("textures/particles/circle.png")), + Text(new ResourceLocation("textures/particles/text.png")), + Heart(new ResourceLocation("textures/particles/heart.png")), + Dollar(new ResourceLocation("textures/particles/dollar.png")); + + private final ResourceLocation resourceLocation; + + Textures(ResourceLocation resourceLocation) { + this.resourceLocation = resourceLocation; + } + + public ResourceLocation getResourceLocation() { + return this.resourceLocation; + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/FireFlies.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/FireFlies.java new file mode 100644 index 00000000..99f0790c --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/FireFlies.java @@ -0,0 +1,128 @@ +package xyz.templecheats.templeclient.features.module.modules.render.particle.sub; + +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.features.module.modules.render.particle.impl.ParticleTickHandler; +import xyz.templecheats.templeclient.util.setting.impl.ColorSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Random; + +import static java.lang.Math.min; +import static xyz.templecheats.templeclient.util.color.ColorUtil.setAlpha; +import static xyz.templecheats.templeclient.util.math.MathUtil.*; +import static xyz.templecheats.templeclient.util.world.BlockUtil.air; + +public class FireFlies extends Module { + + private final EnumSetting textures = new EnumSetting<>("Texture", this, ParticleTickHandler.Textures.Text); + private final DoubleSetting size = new DoubleSetting("Size", this, 0.1, 5.0, 1.0); + private final IntSetting amount = new IntSetting("Amount", this, 3, 200, 30); + private final IntSetting maxAmount = new IntSetting("Max Amount", this, 100, 500, 250); + private final DoubleSetting duration = new DoubleSetting("Duration", this, 5.0, 50.0, 30.0); + private final DoubleSetting speedH = new DoubleSetting("Speed H", this, 0.1, 3.0, 1.0); + private final DoubleSetting speedV = new DoubleSetting("Speed V", this, 0.1, 3.0, 1.0); + private final DoubleSetting inertia = new DoubleSetting("Inertia Amount", this, 0.0, 1.0, 0.8); + private final DoubleSetting gravity = new DoubleSetting("Gravity Amount", this, 0.0, 1.0, 0.8); + + private final ArrayList fireFiles = new ArrayList<>(); + + public FireFlies() { + super("FireFlies", "Spawn random particle around u.", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(textures, size, amount, maxAmount, duration, speedH, speedV, inertia, gravity); + } + + @Override + public void onEnable() { + fireFiles.clear(); + } + + @Override + public void onUpdate() { + if(mc.player == null || mc.world == null) { + return; + } + + fireFiles.removeIf(ParticleTickHandler::tick); + while (fireFiles.size() < maxAmount.intValue()) { + Vec3d vec = mc.player.getPositionVector().add(random(-25f, 25f), random(2.0f, 15.0f), random(-25.0f, 25.0f)); + + Random random = new Random(); + + double motionX = (random.nextDouble() - 0.5) * 0.2 * speedH.doubleValue(); + double motionY = (random.nextDouble() - 0.5) * 0.2 * speedV.doubleValue(); + double motionZ = (random.nextDouble() - 0.5) * 0.2 * speedH.doubleValue(); + + FireFly fireFly = new FireFly(vec, motionX, motionY, motionZ, size.doubleValue(), gravity.doubleValue(), inertia.doubleValue()); + + fireFly.motionX *= random(0.5f, 1.5f); + fireFly.motionY *= random(0.5f, 1.5f); + fireFly.motionZ *= random(0.5f, 1.5f); + + fireFly.motionX += random(-0.1f, 0.1f); + fireFly.motionY += random(-0.1f, 0.1f); + fireFly.motionZ += random(-0.1f, 0.1f); + + fireFly.maxTickLiving = (int) (duration.doubleValue() * 10.0 + random.nextDouble() * 40.0); + + fireFiles.add(fireFly); + } + while (fireFiles.size() > maxAmount.intValue()) { fireFiles.remove(0); } + } + + @Override + public void onRenderWorld(float partialTicks) { + fireFiles.forEach(it -> { + double p1 = min(it.tickLiving, 10.0) / 10.0; + double p2 = MathHelper.clamp((it.maxTickLiving - it.tickLiving) / 10, 0, 1); + int alpha = (int) MathHelper.clamp((it.tickLiving <= 10 ? p1 : p2) * 255, 0, 255); + it.draw(size.floatValue(), setAlpha(Colors.INSTANCE.getColor(5), alpha), textures.value()); + }); + } + + private static class FireFly extends ParticleTickHandler { + public FireFly(Vec3d posIn, double motionX, double motionY, double motionZ, double size, double gravityAmount, double inertiaAmount) { + super(posIn, motionX, motionY, motionZ, size, gravityAmount, inertiaAmount); + } + + @Override + public boolean tick() { + if ( mc.player.getDistanceSq(pos.x, pos.y, pos.z) == 100 ) { + tickLiving -= 4; + } else { + tickLiving -= !air(new BlockPos(pos.x, pos.y, pos.z)) ? 8 : 1; + } + + if (tickLiving < 0) { + return true; + } else { + prevPos = pos; + pos = pos.add(motionX, motionY, motionZ); + + if (blockPos(pos.x, pos.y, pos.z)) { + motionY = -motionY; + } else if (collisionCheck(pos.x, pos.y, pos.z, size, MathHelper.sqrt(motionX * motionY + motionZ * motionZ) * 1)) { + motionX = -motionX + motionZ; + motionZ = -motionZ + motionX; + } + + motionY -= gravityAmount * 0.001; + + motionX *= 0.9 + (inertiaAmount / 10.0); + motionY *= 0.2 + (inertiaAmount / 10.0); + motionZ *= 0.9 + (inertiaAmount / 10.0); + + return false; + } + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/HitParticle.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/HitParticle.java new file mode 100644 index 00000000..f7f9e13b --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/particle/sub/HitParticle.java @@ -0,0 +1,118 @@ +package xyz.templecheats.templeclient.features.module.modules.render.particle.sub; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.features.module.modules.render.particle.impl.ParticleTickHandler; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; +import xyz.templecheats.templeclient.util.setting.impl.EnumSetting; +import xyz.templecheats.templeclient.util.setting.impl.IntSetting; + +import java.util.ArrayList; +import java.util.Random; + +import static java.lang.Math.min; +import static xyz.templecheats.templeclient.util.color.ColorUtil.setAlpha; +import static xyz.templecheats.templeclient.util.math.MathUtil.random; + +public class HitParticle extends Module { + + private final EnumSetting textures = new EnumSetting<>("Texture", this, ParticleTickHandler.Textures.Text); + private final DoubleSetting size = new DoubleSetting("Size", this, 0.1, 5.0, 1.0); + private final IntSetting amount = new IntSetting("Amount", this, 3, 200, 30); + private final IntSetting maxAmount = new IntSetting("Max Amount", this, 100, 500, 250); + private final DoubleSetting duration = new DoubleSetting("Duration", this, 5.0, 50.0, 30.0); + private final DoubleSetting speedH = new DoubleSetting("Speed H", this, 0.1, 3.0, 1.0); + private final DoubleSetting speedV = new DoubleSetting("Speed V", this, 0.1, 3.0, 1.0); + private final DoubleSetting inertia = new DoubleSetting("Inertia Amount", this, 0.0, 1.0, 0.8); + private final DoubleSetting gravity = new DoubleSetting("Gravity Amount", this, 0.0, 1.0, 0.8); + + private final ArrayList hitParticle = new ArrayList<>(); + + public HitParticle() { + super("HitParticle", "Spawn particle when entities hurt.", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(textures, size, amount, maxAmount, duration, speedH, speedV, inertia, gravity); + } + @Override + public void onEnable() { + hitParticle.clear(); + } + + @Override + public void onUpdate() { + if ( mc.player == null || mc.world == null ) { + return; + } + + for (Entity entity : mc.world.loadedEntityList) { + if (entity.hurtResistantTime > 1) { + for (int i = 0; i < amount.intValue(); i++) { + Vec3d vec = entity.getPositionVector().add(random(-0.5f, 0.5f), random(0.5f, entity.height), random(-0.5f, 0.5f)); + + Random random = new Random(); + + double motionX = (random.nextDouble() - 0.5) * 0.2 * speedH.doubleValue(); + double motionY = (random.nextDouble() - 0.5) * 0.2 * speedV.doubleValue(); + double motionZ = (random.nextDouble() - 0.5) * 0.2 * speedH.doubleValue(); + + Particle particle = new Particle(vec, motionX, motionY, motionZ, size.doubleValue(), gravity.doubleValue(), inertia.doubleValue()); + particle.maxTickLiving = (int) (duration.doubleValue() * 10.0 + random.nextDouble() * 40.0); + + hitParticle.add(particle); + } + } + } + hitParticle.forEach(ParticleTickHandler::tick); + hitParticle.removeIf(it -> it.tickLiving > it.maxTickLiving); + while (hitParticle.size() > maxAmount.intValue()) { + hitParticle.remove(0); + } + } + + @Override + public void onRenderWorld(float partialTicks) { + hitParticle.forEach(it -> { + double p1 = min(it.tickLiving, 10.0) / 10.0; + double p2 = MathHelper.clamp((it.maxTickLiving - it.tickLiving) / 10, 0, 1); + int alpha = (int) MathHelper.clamp((it.tickLiving <= 10 ? p1 : p2) * 255, 0, 255); + it.draw(size.floatValue(), setAlpha(Colors.INSTANCE.getColor(5), alpha), textures.value()); + }); + } + + private static class Particle extends ParticleTickHandler { + public Particle(Vec3d posIn, double motionX, double motionY, double motionZ, double size, double gravityAmount, double inertiaAmount) { + super(posIn, motionX, motionY, motionZ, size, gravityAmount, inertiaAmount); + } + + @Override + public boolean tick() { + tickLiving++; + + if (tickLiving < 0) { + return true; + } else { + prevPos = pos; + pos = pos.add(motionX, motionY, motionZ); + + motionY -= gravityAmount * 0.001; + + motionX *= 0.9 + (inertiaAmount / 10.0); + motionY *= 0.9 + (inertiaAmount / 10.0); + motionZ *= 0.9 + (inertiaAmount / 10.0); + + if (blockPos(pos.x, pos.y, pos.z)) { + motionY = -motionY / 1.0; + } else if (collisionCheck(pos.x, pos.y, pos.z, size, MathHelper.sqrt(motionX * motionY + motionZ * motionZ) * 1)) { + motionX = -motionX + motionZ; + motionZ = -motionZ + motionX; + } + + return false; + } + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/XRay.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/XRay.java new file mode 100644 index 00000000..31273eb1 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/XRay.java @@ -0,0 +1,25 @@ +package xyz.templecheats.templeclient.features.module.modules.render.xray; + +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.features.module.modules.render.xray.sub.Ores; + +public class XRay extends Module { + public XRay() { + super("XRay", "Allows you to filter what the world renders", 0, Category.Render); + submodules.add(new Ores()); + } + + @Override + public void onEnable() { + mc.renderGlobal.loadRenderers(); + } + + @Override + public void onUpdate() { + } + + @Override + public void onDisable() { + mc.renderGlobal.loadRenderers(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/sub/Ores.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/sub/Ores.java new file mode 100644 index 00000000..b7247b9a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/render/xray/sub/Ores.java @@ -0,0 +1,56 @@ +package xyz.templecheats.templeclient.features.module.modules.render.xray.sub; + +import org.lwjgl.input.Keyboard; +import xyz.templecheats.templeclient.features.module.Module; +import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; + +public class Ores extends Module { + /* + * Settings + */ + private final BooleanSetting renderDiamondOres = new BooleanSetting("Diamond Ores", this, true); + private final BooleanSetting renderIronOres = new BooleanSetting("Iron Ores", this, true); + private final BooleanSetting renderGoldOres = new BooleanSetting("Gold Ores", this, true); + private final BooleanSetting renderLapisOres = new BooleanSetting("Lapis Ores", this, true); + private final BooleanSetting renderRedstoneOres = new BooleanSetting("Redstone Ores", this, true); + private final BooleanSetting renderEmeraldOres = new BooleanSetting("Emerald Ores", this, true); + private final BooleanSetting renderCoalOres = new BooleanSetting("Coal Ores", this, true); + private final BooleanSetting renderQuartzOres = new BooleanSetting("Quartz Ores", this, true); + + public Ores() { + super("Ores", "Allows you to filter rendering of ores", Keyboard.KEY_NONE, Category.Render, true); + registerSettings(renderDiamondOres, renderIronOres, renderGoldOres, renderLapisOres, renderRedstoneOres, renderEmeraldOres, renderCoalOres, renderQuartzOres); + } + + public boolean shouldRenderDiamondOres() { + return renderDiamondOres.booleanValue(); + } + + public boolean shouldRenderIronOres() { + return renderIronOres.booleanValue(); + } + + public boolean shouldRenderGoldOres() { + return renderGoldOres.booleanValue(); + } + + public boolean shouldRenderLapisOres() { + return renderLapisOres.booleanValue(); + } + + public boolean shouldRenderRedstoneOres() { + return renderRedstoneOres.booleanValue(); + } + + public boolean shouldRenderEmeraldOres() { + return renderEmeraldOres.booleanValue(); + } + + public boolean shouldRenderCoalOres() { + return renderCoalOres.booleanValue(); + } + + public boolean shouldRenderQuartzOres() { + return renderQuartzOres.booleanValue(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Nuker.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Nuker.java index b96afe98..cc345730 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Nuker.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Nuker.java @@ -13,10 +13,13 @@ import java.util.Random; public class Nuker extends Module { + /* + * Variables + */ private static final Random random = new Random(); public Nuker() { - super("Nuker","Automatically mines blocks within reach", Keyboard.KEY_NONE, Category.World); + super("Nuker", "Destroy blocks around you", Keyboard.KEY_NONE, Category.World); } @SubscribeEvent @@ -38,8 +41,8 @@ private void breakRandomBlocksAroundPlayer() { BlockPos targetPos = playerPos.add(offsetX, offsetY, offsetZ); IBlockState state = mc.world.getBlockState(targetPos); - mc.playerController.onPlayerDamageBlock(targetPos, EnumFacing.UP); // You can adjust EnumFacing as needed + mc.playerController.onPlayerDamageBlock(targetPos, EnumFacing.UP); mc.player.swingArm(EnumHand.MAIN_HAND); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Scaffold.java b/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Scaffold.java index c39d426c..5ad7795c 100644 --- a/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Scaffold.java +++ b/src/main/java/xyz/templecheats/templeclient/features/module/modules/world/Scaffold.java @@ -1,124 +1,297 @@ package xyz.templecheats.templeclient.features.module.modules.world; -import net.minecraft.block.BlockLiquid; -import net.minecraft.entity.Entity; +import net.minecraft.block.Block; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.client.CPacketEntityAction; +import net.minecraft.network.play.client.CPacketHeldItemChange; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import org.lwjgl.input.Keyboard; import team.stiff.pomelo.impl.annotated.handler.annotation.Listener; +import xyz.templecheats.templeclient.event.EventStageable; import xyz.templecheats.templeclient.event.events.player.MotionEvent; import xyz.templecheats.templeclient.features.module.Module; -import xyz.templecheats.templeclient.util.rotation.RotationUtil; +import xyz.templecheats.templeclient.util.color.impl.GradientShader; +import xyz.templecheats.templeclient.util.render.RenderUtil; import xyz.templecheats.templeclient.util.setting.impl.BooleanSetting; +import xyz.templecheats.templeclient.util.setting.impl.DoubleSetting; import xyz.templecheats.templeclient.util.time.TimerUtil; +import xyz.templecheats.templeclient.util.world.BlockPosWithFacing; + +import java.awt.*; public class Scaffold extends Module { + /* + * Settings + */ + private final BooleanSetting rotate = new BooleanSetting("Rotate", this, true); + private final BooleanSetting autoSwap = new BooleanSetting("AutoSwap", this, true); + private final BooleanSetting eChestHolding = new BooleanSetting("eChestHolding", this, true); + private final BooleanSetting tower = new BooleanSetting("Tower", this, true); + private final BooleanSetting render = new BooleanSetting("Render", this, true); + private final DoubleSetting opacity = new DoubleSetting("RenderOpacity", this, 0.0, 1, 0.5); + private final BooleanSetting fill = new BooleanSetting("Box Fill", this, true); + private final BooleanSetting outline = new BooleanSetting("Box Outline", this, true); - private final TimerUtil timer = new TimerUtil(); - private BlockPos placePos; - private EnumFacing placeFace; + /* + * Variables + */ + private BlockPosWithFacing currentBlock; + private TimerUtil timer; public Scaffold() { - super("Scaffold","Automatically places blocks under your feet", Keyboard.KEY_NONE, Category.World); + super("Scaffold", "Automatically towers with blocks", Keyboard.KEY_NONE, Category.World); - registerSettings(tower); + registerSettings(rotate, autoSwap, eChestHolding, render, tower, opacity, fill, outline); + timer = new TimerUtil(); } - @Listener - public void onMotion(MotionEvent event) { - final EnumHand placeHand; - if(mc.player.getHeldItem(EnumHand.MAIN_HAND).getItem() instanceof ItemBlock) { - placeHand = EnumHand.MAIN_HAND; - } else if(mc.player.getHeldItem(EnumHand.OFF_HAND).getItem() instanceof ItemBlock) { - placeHand = EnumHand.MAIN_HAND; - } else { - return; + private boolean isBlockValid(Block block) { + return block.getDefaultState().getMaterial().isSolid(); + } + + private BlockPosWithFacing checkNearBlocks(BlockPos blockPos) { + if (isBlockValid(mc.world.getBlockState(blockPos.add(0, -1, 0)).getBlock())) + return new BlockPosWithFacing(blockPos.add(0, -1, 0), EnumFacing.UP); + else if (isBlockValid(mc.world.getBlockState(blockPos.add(-1, 0, 0)).getBlock())) + return new BlockPosWithFacing(blockPos.add(-1, 0, 0), EnumFacing.EAST); + else if (isBlockValid(mc.world.getBlockState(blockPos.add(1, 0, 0)).getBlock())) + return new BlockPosWithFacing(blockPos.add(1, 0, 0), EnumFacing.WEST); + else if (isBlockValid(mc.world.getBlockState(blockPos.add(0, 0, 1)).getBlock())) + return new BlockPosWithFacing(blockPos.add(0, 0, 1), EnumFacing.NORTH); + else if (isBlockValid(mc.world.getBlockState(blockPos.add(0, 0, -1)).getBlock())) + return new BlockPosWithFacing(blockPos.add(0, 0, -1), EnumFacing.SOUTH); + + return null; + } + private BlockPosWithFacing checkNearBlocksExtended(BlockPos blockPos) { // TODO FUCKING OPTIMIZE!!!!!! + BlockPosWithFacing ret = null; + + ret = checkNearBlocks(blockPos); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(-1, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(1, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(0, 0, 1)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(0, 0, -1)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(-2, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(2, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(0, 0, 2)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(0, 0, -2)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos.add(0, -1, 0)); + BlockPos blockPos2 = blockPos.add(0, -1, 0); + + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos2.add(1, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos2.add(-1, 0, 0)); + if (ret != null) return ret; + + ret = checkNearBlocks(blockPos2.add(0, 0, 1)); + if (ret != null) return ret; + + return checkNearBlocks(blockPos2.add(0, 0, -1)); + } + + private int findBlockToPlace() { + if (mc.player.getHeldItemMainhand().getItem() instanceof ItemBlock) { + if (isBlockValid(((ItemBlock) mc.player.getHeldItemMainhand().getItem()).getBlock())) + return mc.player.inventory.currentItem; } - switch(event.getStage()) { - case PRE: - Entity p = mc.player; - BlockPos bp = new BlockPos(p.posX, p.getEntityBoundingBox().minY - 1, p.posZ); + int n = 0; + int n2 = 0; - if(isValid(bp)) { - return; - } + while (true) { + if (n2 >= 9) break; - if(isValid(bp.down())) { - place(bp.down(), EnumFacing.UP); - } else if(isValid(bp.add(-1, 0, 0))) { - place(bp.add(-1, 0, 0), EnumFacing.EAST); - } else if(isValid(bp.add(1, 0, 0))) { - place(bp.add(1, 0, 0), EnumFacing.WEST); - } else if(isValid(bp.add(0, 0, -1))) { - place(bp.add(0, 0, -1), EnumFacing.SOUTH); - } else if(isValid(bp.add(0, 0, 1))) { - place(bp.add(0, 0, 1), EnumFacing.NORTH); - } else if(isValid(bp.add(1, 0, 1))) { - if(isValid(bp.add(0, 0, 1))) { - place(bp.add(0, 0, 1), EnumFacing.NORTH); - } else { - place(bp.add(1, 0, 1), EnumFacing.EAST); - } - } else if(isValid(bp.add(-1, 0, 1))) { - if(isValid(bp.add(-1, 0, 0))) { - place(bp.add(-1, 0, 0), EnumFacing.WEST); - } else { - place(bp.add(-1, 0, 1), EnumFacing.SOUTH); - } - } else if(isValid(bp.add(-1, 0, -1))) { - if(isValid(bp.add(0, 0, -1))) { - place(bp.add(0, 0, -1), EnumFacing.SOUTH); - } else { - place(bp.add(-1, 0, -1), EnumFacing.WEST); - } - } else if(isValid(bp.add(1, 0, -1))) { - if(isValid(bp.add(1, 0, 0))) { - place(bp.add(1, 0, 0), EnumFacing.EAST); - } else { - place(bp.add(1, 0, -1), EnumFacing.NORTH); + if (mc.player.inventory.getStackInSlot(n).getCount() != 0) { + if (mc.player.inventory.getStackInSlot(n).getItem() instanceof ItemBlock) { + if (!eChestHolding.booleanValue() || + (eChestHolding.booleanValue() && !mc.player.inventory.getStackInSlot(n).getItem().equals(Item.getItemFromBlock(Blocks.ENDER_CHEST)))) { + if (isBlockValid(((ItemBlock) mc.player.inventory.getStackInSlot(n).getItem()).getBlock())) + return n; } } + } - if(this.placePos != null) { - final float[] rotations = RotationUtil.rotations(this.placePos); - event.setYaw(rotations[0]); - event.setPitch(rotations[1]); - } - break; - case POST: - if(this.placePos != null) { - if(this.tower.booleanValue() && mc.player.movementInput.jump && mc.player.movementInput.moveForward == 0.0 && mc.player.movementInput.moveStrafe == 0.0) { - mc.player.motionX = 0; - mc.player.motionZ = 0; - mc.player.jump(); - - if(this.timer.hasReached(1000L)) { - mc.player.motionY = -0.3; - this.timer.reset(); - } - } + n2 = ++n; + } - mc.playerController.processRightClickBlock(mc.player, mc.world, this.placePos, this.placeFace, Vec3d.ZERO, placeHand); - mc.player.swingArm(placeHand); + return -1; + } + + private boolean blockCheck(int itemnum) { + Item item = mc.player.inventory.getStackInSlot(itemnum).getItem(); + + if (item instanceof ItemBlock) { + Vec3d vec3d = mc.player.getPositionVector(); + Block block = ((ItemBlock) item).getBlock(); + + return mc.world.rayTraceBlocks(vec3d, vec3d.add(0.0, -block.getDefaultState().getSelectedBoundingBox(mc.world, BlockPos.ORIGIN).maxY, 0.0), false, true, false) == null; + } - this.placePos = null; - this.placeFace = null; + return false; + } + + private int countValidBlocks() { + int n = 36; + int n2 = 0; + + while (true) { + if (n >= 45) break; + + if (mc.player.inventoryContainer.getSlot(n).getHasStack()) { + ItemStack itemStack = mc.player.inventoryContainer.getSlot(n).getStack(); + if (itemStack.getItem() instanceof ItemBlock) { + if (isBlockValid(((ItemBlock) itemStack.getItem()).getBlock())) + n2 += itemStack.getCount(); } - break; + } + + n++; } + + return n2; + } + + private Vec3d getEyePosition() { + return new Vec3d(mc.player.posX, mc.player.posY + mc.player.getEyeHeight(), mc.player.posZ); + } + + private float[] getRotations(BlockPos blockPos, EnumFacing enumFacing) { + Vec3d vec3d = new Vec3d((double) blockPos.getX() + 0.5, mc.world.getBlockState(blockPos).getSelectedBoundingBox(mc.world, blockPos).maxY - 0.01, (double) blockPos.getZ() + 0.5); + vec3d = vec3d.add(new Vec3d(enumFacing.getDirectionVec()).scale(0.5)); + + Vec3d vec3d2 = getEyePosition(); + + double d = vec3d.x - vec3d2.x; + double d2 = vec3d.y - vec3d2.y; + double d3 = vec3d.z - vec3d2.z; + double d4 = d; + double d5 = d3; + double d6 = Math.sqrt(d4 * d4 + d5 * d5); + + float f = (float)(Math.toDegrees(Math.atan2(d3, d)) - 90.0f); + float f2 = (float)(-Math.toDegrees(Math.atan2(d2, d6))); + + float[] ret = new float[2]; + ret[0] = mc.player.rotationYaw + MathHelper.wrapDegrees((float)(f - mc.player.rotationYaw)); + ret[1] = mc.player.rotationPitch + MathHelper.wrapDegrees((float)(f2 - mc.player.rotationPitch)); + + return ret; + } + + @SubscribeEvent + public void onRender(RenderWorldLastEvent e) { + if (render.booleanValue() && currentBlock != null) { + GradientShader.setup((float) opacity.doubleValue()); + if (fill.booleanValue()) + RenderUtil.boxShader(currentBlock.blockPos); + if (outline.booleanValue()) + RenderUtil.outlineShader(currentBlock.blockPos); + + GradientShader.finish(); + } + } + @Listener + public void onMotionUpdate(MotionEvent event) { + if (event.getStage() != EventStageable.EventStage.PRE) { + return; + } + + if (mc.player.isSneaking() || countValidBlocks() <= 0 || mc.player.posY > 256) { + this.currentBlock = null; + return; + } + + BlockPos blockPos = new BlockPos(mc.player.posX, mc.player.posY - 1.0, mc.player.posZ); + if (!mc.world.getBlockState(blockPos).getMaterial().isReplaceable()) { + return; + } + + this.currentBlock = this.checkNearBlocksExtended(blockPos); + if (this.currentBlock == null) { + return; + } + + if (rotate.booleanValue()) { + float[] rotations = getRotations(currentBlock.blockPos, currentBlock.enumFacing); + event.setYaw(rotations[0]); + event.setPitch(rotations[1]); + } + + if (tower.booleanValue() && mc.player.movementInput.jump && mc.player.moveForward == 0.0f && mc.player.moveStrafing == 0.0f) { + handleTowerMovement(); + } + + placeBlockUnderPlayer(); } - private void place(BlockPos pos, EnumFacing face) { - this.placePos = pos; - this.placeFace = face; + private void handleTowerMovement() { + mc.player.setVelocity(0.0, 0.42, 0.0); + if (timer.hasReached(1500)) { + mc.player.motionY = -0.28; + timer.reset(); + } } - private boolean isValid(BlockPos pos) { - return !(mc.world.getBlockState(pos).getBlock() instanceof BlockLiquid) && !mc.world.isAirBlock(pos); + private void placeBlockUnderPlayer() { + int originalSlot = mc.player.inventory.currentItem; + if (autoSwap.booleanValue()) { + int blockSlot = findBlockToPlace(); + if (blockSlot != -1 && blockSlot != originalSlot) { + mc.player.inventory.currentItem = blockSlot; + mc.player.connection.sendPacket(new CPacketHeldItemChange(blockSlot)); + } + } + + BlockPos blockPos = currentBlock.blockPos; + boolean actionResult = mc.world.getBlockState(blockPos).getBlock().onBlockActivated(mc.world, blockPos, mc.world.getBlockState(blockPos), mc.player, EnumHand.MAIN_HAND, EnumFacing.DOWN, 0.0f, 0.0f, 0.0f); + + if (actionResult) { + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.START_SNEAKING)); + } + + mc.playerController.processRightClickBlock(mc.player, mc.world, blockPos, currentBlock.enumFacing, new Vec3d(blockPos.getX() + Math.random(), mc.world.getBlockState(blockPos).getSelectedBoundingBox(mc.world, blockPos).maxY - 0.01, blockPos.getZ() + Math.random()), EnumHand.MAIN_HAND); + mc.player.swingArm(EnumHand.MAIN_HAND); + + if (actionResult) { + mc.player.connection.sendPacket(new CPacketEntityAction(mc.player, CPacketEntityAction.Action.STOP_SNEAKING)); + } + + if (autoSwap.booleanValue() && originalSlot != mc.player.inventory.currentItem) { + mc.player.inventory.currentItem = originalSlot; + mc.player.connection.sendPacket(new CPacketHeldItemChange(originalSlot)); + } } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/manager/CapeManager.java b/src/main/java/xyz/templecheats/templeclient/manager/CapeManager.java index 17b446a3..f1432569 100644 --- a/src/main/java/xyz/templecheats/templeclient/manager/CapeManager.java +++ b/src/main/java/xyz/templecheats/templeclient/manager/CapeManager.java @@ -18,18 +18,19 @@ import java.util.concurrent.CompletableFuture; public class CapeManager { - private final Map capeUsers; - private final Map capeTextures; - private static final String CAPE_UUIDS = "https://raw.githubusercontent.com/PhilipPanda/Temple-Client/main/github/assets/capes.txt"; - private static final String CAPE_DIR = "https://raw.githubusercontent.com/PhilipPanda/Temple-Client/main/github/assets/%s.png"; + private final Map < UUID, String > capeUsers; + private final Map < String, ResourceLocation > capeTextures; + private static final String CAPE_UUIDS = "https://raw.githubusercontent.com/TempleDevelopment/Temple-Client/main/github/assets/capes.txt"; + private static final String CAPE_DIR = "https://raw.githubusercontent.com/TempleDevelopment/Temple-Client/main/github/assets/%s.png"; public CapeManager() { - this.capeUsers = new HashMap<>(); - this.capeTextures = new HashMap<>(); + this.capeUsers = new HashMap < > (); + this.capeTextures = new HashMap < > (); CompletableFuture.runAsync(() -> { try (final BufferedReader reader = new BufferedReader(new InputStreamReader(new URL(CAPE_UUIDS).openStream(), StandardCharsets.UTF_8))) { - for (String line; (line = reader.readLine()) != null; ) { + for (String line; + (line = reader.readLine()) != null;) { final String[] split = line.split(":"); this.addCape(UUID.fromString(split[0]), split[1]); } @@ -41,18 +42,18 @@ public CapeManager() { public void addCape(UUID uuid, String capeName) { this.capeUsers.put(uuid, capeName); - if(!this.capeTextures.containsKey(capeName)) { - try { - final URL url = new URL(String.format(CAPE_DIR, capeName)); - final InputStream stream = url.openStream(); - final BufferedImage image = ImageIO.read(stream); - Minecraft.getMinecraft().addScheduledTask(() -> { + if (!this.capeTextures.containsKey(capeName)) { + Minecraft.getMinecraft().addScheduledTask(() -> { + try { + final URL url = new URL(String.format(CAPE_DIR, capeName)); + final InputStream stream = url.openStream(); + final BufferedImage image = ImageIO.read(stream); final DynamicTexture texture = new DynamicTexture(image); this.capeTextures.put(capeName, Minecraft.getMinecraft().getTextureManager().getDynamicTextureLocation(capeName, texture)); - }); - } catch(Exception e) { - e.printStackTrace(); - } + } catch (Exception e) { + e.printStackTrace(); + } + }); } } diff --git a/src/main/java/xyz/templecheats/templeclient/manager/CommandManager.java b/src/main/java/xyz/templecheats/templeclient/manager/CommandManager.java index aadc85a0..60f7242d 100644 --- a/src/main/java/xyz/templecheats/templeclient/manager/CommandManager.java +++ b/src/main/java/xyz/templecheats/templeclient/manager/CommandManager.java @@ -11,7 +11,7 @@ public CommandManager() { commandInit(); } - private final Map commands = new HashMap<>(); + private final Map < String, Command > commands = new HashMap < > (); public void registerCommand(Command command) { commands.put(command.getName(), command); @@ -34,5 +34,6 @@ public void commandInit() { registerCommand(new FriendCommand()); registerCommand(new HelpCommand()); registerCommand(new IpCommand()); + registerCommand(new NameMcCommand()); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/manager/HoleManager.java b/src/main/java/xyz/templecheats/templeclient/manager/HoleManager.java new file mode 100644 index 00000000..1aff3b17 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/manager/HoleManager.java @@ -0,0 +1,151 @@ +package xyz.templecheats.templeclient.manager; + +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.util.Globals; +import xyz.templecheats.templeclient.util.world.BlockUtil; + +import javax.annotation.Nullable; +import java.util.ArrayList; +import java.util.List; + +public class HoleManager implements Globals { + private static final Vec3i[] COMMON = { + new Vec3i(1, 0, 0), + new Vec3i(0, 0, 1), + new Vec3i(0, -1, 0) + }; + private static final Vec3i[] HOLE = { + new Vec3i(-1, 0, 0), + new Vec3i(0, 0, -1) + }; + private static final Vec3i[] DOUBLE_HOLE_NORTH = { + new Vec3i(0, 0, -2), + new Vec3i(-1, 0, -1), + new Vec3i(1, 0, -1), + new Vec3i(0, -1, -1), + new Vec3i(-1, 0, 0) + }; + private static final Vec3i[] DOUBLE_HOLE_WEST = { + new Vec3i(-2, 0, 0), + new Vec3i(-1, 0, 1), + new Vec3i(-1, 0, -1), + new Vec3i(-1, -1, 0), + new Vec3i(0, 0, -1) + }; + public String time; + private ArrayList holes = new ArrayList<>(); + + public void loadHoles(final int range) { + if (mc.world == null || mc.player == null) { + return; + } + final long sys = System.currentTimeMillis(); + holes = findHoles(range); + time = System.currentTimeMillis() - sys + "ms"; + } + + public boolean holeManagerContains(final BlockPos pos) { + return TempleClient.holeManager.getHoles().stream().anyMatch(holePos -> holePos.getPos().equals(pos)); + } + + private ArrayList findHoles(final int range) { + final ArrayList holes = new ArrayList<>(); + if (mc.player == null || mc.world == null) { + return holes; + } + for (final BlockPos pos: BlockUtil.getBlocksInRadius(range)) { + final HolePos holePos = getHolePos(pos); + if (holePos != null) { + holes.add(holePos); + } + } + return holes; + } + + @Nullable + public HolePos getHolePos(final BlockPos pos) { + if (mc.player == null || mc.world == null) return null; + + if (mc.world.getBlockState(pos).getBlock() != Blocks.AIR + || mc.world.getBlockState(pos.up()).getBlock() != Blocks.AIR + || mc.world.getBlockState(pos.up().up()).getBlock() != Blocks.AIR) { + return null; + } + + boolean obsidian = false; + + // Check block positions which are common to all 3 hole sizes + for (Vec3i vec3i : COMMON) { + Block block = mc.world.getBlockState(pos.add(vec3i)).getBlock(); + + if (block == Blocks.OBSIDIAN) obsidian = true; + else if (block != Blocks.BEDROCK) return null; + } + + // Test hole sizes individually + HolePos holePos = testHole(pos, obsidian, HOLE, Type.Obsidian, Type.Bedrock); + if (holePos == null) holePos = testHole(pos, obsidian, DOUBLE_HOLE_NORTH, Type.DoubleObsidianNorth, Type.DoubleBedrockNorth); + if (holePos == null) holePos = testHole(pos, obsidian, DOUBLE_HOLE_WEST, Type.DoubleObsidianWest, Type.DoubleBedrockWest); + + return holePos; + } + + @Nullable + private static HolePos testHole(BlockPos pos, boolean obsidian, Vec3i[] blocks, Type obsidianType, Type bedrockType) { + for (Vec3i vec3i : blocks) { + Block block = mc.world.getBlockState(pos.add(vec3i)).getBlock(); + + if (block == Blocks.OBSIDIAN) obsidian = true; + else if (block != Blocks.BEDROCK) return null; + } + + return new HolePos(pos, obsidian ? obsidianType : bedrockType); + } + + public List getHoles() { + return holes; + } + + public enum Type { + Bedrock, + Obsidian, + DoubleBedrockNorth, + DoubleBedrockWest, + DoubleObsidianNorth, + DoubleObsidianWest + } + + public static class HolePos { + private final BlockPos pos; + private final Type holeType; + + public HolePos(BlockPos pos, Type holeType) { + this.pos = pos; + this.holeType = holeType; + } + + public BlockPos getPos() { + return pos; + } + + public Type getHoleType() { + return holeType; + } + + public boolean isBedrock() { + return holeType.equals(Type.Bedrock) || holeType.equals(Type.DoubleBedrockWest) || holeType.equals(Type.DoubleBedrockNorth); + } + + public boolean isWestDouble() { + return holeType.equals(Type.DoubleBedrockWest) || holeType.equals(Type.DoubleObsidianWest); + } + + public boolean isDouble() { + return holeType.equals(HoleManager.Type.DoubleBedrockNorth) || holeType.equals(Type.DoubleBedrockWest) || holeType.equals(Type.DoubleObsidianNorth) || holeType.equals(Type.DoubleObsidianWest); + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/manager/ModuleManager.java b/src/main/java/xyz/templecheats/templeclient/manager/ModuleManager.java index 7f707eb9..23c5b693 100644 --- a/src/main/java/xyz/templecheats/templeclient/manager/ModuleManager.java +++ b/src/main/java/xyz/templecheats/templeclient/manager/ModuleManager.java @@ -10,11 +10,14 @@ import xyz.templecheats.templeclient.features.module.modules.combat.*; import xyz.templecheats.templeclient.features.module.modules.misc.*; import xyz.templecheats.templeclient.features.module.modules.movement.*; -import xyz.templecheats.templeclient.features.module.modules.player.Blink; -import xyz.templecheats.templeclient.features.module.modules.player.Reach; +import xyz.templecheats.templeclient.features.module.modules.movement.speed.Speed; +import xyz.templecheats.templeclient.features.module.modules.player.*; import xyz.templecheats.templeclient.features.module.modules.render.*; -import xyz.templecheats.templeclient.features.module.modules.world.Nuker; +import xyz.templecheats.templeclient.features.module.modules.render.esp.ESP; +import xyz.templecheats.templeclient.features.module.modules.render.particle.Particle; +import xyz.templecheats.templeclient.features.module.modules.render.xray.XRay; import xyz.templecheats.templeclient.features.module.modules.world.Scaffold; +import xyz.templecheats.templeclient.features.module.modules.world.Nuker; import java.util.ArrayList; import java.util.Collection; @@ -26,10 +29,16 @@ public ModuleManager() { initMods(); } - private static final Map, Module> MODULES = new Reference2ReferenceOpenHashMap<>(); + private static final Map < Class < ? extends Module > , Module > MODULES = new Reference2ReferenceOpenHashMap < > (); public static void addMod(Module mod) { MODULES.put(mod.getClass(), mod); + + if (!mod.submodules.isEmpty()) { + for (Module sub : mod.submodules) { + addMod(sub); + } + } } public static void initMods() { @@ -41,71 +50,77 @@ public static void initMods() { // Combat addMod(new AutoDisconnect()); addMod(new AutoCrystal()); - addMod(new AutoClicker()); - addMod(new AutoGapple()); + addMod(new BowAimbot()); + addMod(new BowSpam()); addMod(new AutoArmor()); addMod(new AutoTotem()); addMod(new Surround()); addMod(new Velocity()); - addMod(new AntiBots()); addMod(new AimAssist()); - addMod(new Trigger()); - addMod(new HitBox()); - addMod(new FastXP()); + addMod(new TriggerBot()); + addMod(new Offhand()); addMod(new Aura()); // Miscellaneous - addMod(new FakeCreative()); - addMod(new ChestStealer()); + addMod(new AutoClicker()); + addMod(new Gamemode()); + addMod(new ExtraChest()); addMod(new AutoRespawn()); addMod(new FakePlayer()); addMod(new Log4jAlert()); + addMod(new AutoMount()); addMod(new Hitmarker()); // Client addMod(new MiddleClick()); addMod(new Particles()); addMod(new ClickGUI()); addMod(new Panic()); - addMod(new Font()); + addMod(new Colors()); + addMod(new FontSettings()); addMod(new HUD()); // Movement addMod(new ElytraPlus()); + addMod(new TunnelSpeed()); addMod(new AutoWalk()); - addMod(new YawLock()); - addMod(new BoatFly()); + addMod(new RotationLock()); addMod(new GuiWalk()); + addMod(new NoSlow()); + addMod(new FastFall()); addMod(new Sprint()); - addMod(new Spider()); addMod(new NoFall()); addMod(new Speed()); - addMod(new Glide()); - addMod(new Jesus()); addMod(new Flight()); + addMod(new Jesus()); + addMod(new Step()); // Render - addMod(new BlockOverlay()); addMod(new DeathEffect()); addMod(new NameProtect()); addMod(new FullBright()); - addMod(new SpawnerESP()); - addMod(new StorageESP()); - addMod(new PlayerESP()); addMod(new ViewModel()); + addMod(new ChinaHat()); addMod(new NoRender()); + addMod(new Particle()); + addMod(new PopChams()); addMod(new NameTags()); - addMod(new ItemESP()); + addMod(new Ambience()); addMod(new Tracers()); + addMod(new Aspect()); + addMod(new Trail()); + addMod(new XRay()); + addMod(new ESP()); // World addMod(new Scaffold()); addMod(new Nuker()); // Player addMod(new Freecam()); + addMod(new AutoEat()); + addMod(new FastUse()); addMod(new Reach()); addMod(new Blink()); } - - public static ArrayList getModulesInCategory(Module.Category c) { - ArrayList mods = new ArrayList<>(); - for (Module m : MODULES.values()) { + public static ArrayList < Module > getModulesInCategory(Module.Category c) { + ArrayList < Module > mods = new ArrayList < > (); + for (Module m: MODULES.values()) { if (m.getCategory().name().equalsIgnoreCase(c.name())) { mods.add(m); } @@ -113,13 +128,13 @@ public static ArrayList getModulesInCategory(Module.Category c) { return mods; } - public static Collection getModules() { + public static Collection < Module > getModules() { return MODULES.values(); } - public static ArrayList getActiveModules() { - ArrayList active = new ArrayList<>(); - for (Module m : MODULES.values()) { + public static ArrayList < Module > getActiveModules() { + ArrayList < Module > active = new ArrayList < > (); + for (Module m: MODULES.values()) { if (m.isEnabled()) { active.add(m); } @@ -128,7 +143,7 @@ public static ArrayList getActiveModules() { } public static Module getModuleByName(String name) { - for (Module mod : MODULES.values()) { + for (Module mod: MODULES.values()) { if (mod.getName().equalsIgnoreCase(name)) { return mod; } @@ -137,12 +152,12 @@ public static Module getModuleByName(String name) { } @SuppressWarnings("unchecked") - public static T getModule(Class moduleClass) { + public static < T extends Module > T getModule(Class < T > moduleClass) { return (T) MODULES.get(moduleClass); } public static void keyPress(int key) { - for (Module m : MODULES.values()) { + for (Module m: MODULES.values()) { if (m.getKey() == key) { m.toggle(); } @@ -150,8 +165,8 @@ public static void keyPress(int key) { } public void onPlayerTick() { - for (Module module : MODULES.values()) { + for (Module module: MODULES.values()) { module.onUpdateInternal(); } } -} \ No newline at end of file +} diff --git a/src/main/java/xyz/templecheats/templeclient/manager/SongManager.java b/src/main/java/xyz/templecheats/templeclient/manager/SongManager.java index c53b2b39..8f16bf17 100644 --- a/src/main/java/xyz/templecheats/templeclient/manager/SongManager.java +++ b/src/main/java/xyz/templecheats/templeclient/manager/SongManager.java @@ -14,7 +14,7 @@ public class SongManager implements Globals { - private final List songs = Arrays.asList( + private final List < ISound > songs = Arrays.asList( Templeos.sound ); diff --git a/src/main/java/xyz/templecheats/templeclient/manager/ThreadManager.java b/src/main/java/xyz/templecheats/templeclient/manager/ThreadManager.java new file mode 100644 index 00000000..d1864408 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/manager/ThreadManager.java @@ -0,0 +1,12 @@ +package xyz.templecheats.templeclient.manager; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class ThreadManager { + private final ExecutorService executorService = Executors.newFixedThreadPool(2); + + public void invokeThread(final Runnable command) { + executorService.execute(command); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityRenderer.java b/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityRenderer.java deleted file mode 100644 index 8632eef2..00000000 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityRenderer.java +++ /dev/null @@ -1,41 +0,0 @@ -package xyz.templecheats.templeclient.mixins; - -import net.minecraft.client.renderer.EntityRenderer; -import net.minecraft.entity.EntityLivingBase; -import net.minecraft.potion.Potion; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.ModifyVariable; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import xyz.templecheats.templeclient.features.module.modules.render.NoRender; - -@Mixin(value = EntityRenderer.class) -public abstract class MixinEntityRenderer { - @Shadow protected abstract void hurtCameraEffect(float partialTicks); - - @Inject(method = "setupFog", at = @At("HEAD"), cancellable = true) - private void noRenderFog(int startCoords, float partialTicks, CallbackInfo ci) { - if (NoRender.preventFog()) ci.cancel(); - } - - @Redirect(method = "setupFog", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityLivingBase;isPotionActive(Lnet/minecraft/potion/Potion;)Z")) - private boolean noRenderBlindness(EntityLivingBase instance, Potion potion) { - if (NoRender.preventBlindness()) return false; - return instance.isPotionActive(potion); - } - - @ModifyVariable(method = "setupCameraTransform", index = 4, at = @At("STORE")) - private float noRenderNausea(float original) { - if (NoRender.preventNausea()) return 0.0f; - return original; - } - - @Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/EntityRenderer;hurtCameraEffect(F)V")) - private void noHurtCam(EntityRenderer instance, float partialTicks) { - if (NoRender.preventHurtCam()) return; - else this.hurtCameraEffect(partialTicks); - } -} diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/accessor/ICPacketUseEntity.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/ICPacketUseEntity.java new file mode 100644 index 00000000..8d8f8023 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/ICPacketUseEntity.java @@ -0,0 +1,14 @@ +package xyz.templecheats.templeclient.mixins.accessor; + +import net.minecraft.network.play.client.CPacketUseEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; +@Mixin(CPacketUseEntity.class) +public interface ICPacketUseEntity { + @Accessor("entityId") + void setEntityId(int id); + + @Accessor("action") + void setAction(CPacketUseEntity.Action action); + +} diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IEntityRenderer.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IEntityRenderer.java new file mode 100644 index 00000000..f77692fc --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IEntityRenderer.java @@ -0,0 +1,12 @@ +package xyz.templecheats.templeclient.mixins.accessor; + +import net.minecraft.client.renderer.EntityRenderer; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +@Mixin(EntityRenderer.class) +public interface IEntityRenderer { + + @Invoker + void invokeRenderHand(float partialTicks, int pass); +} diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinCPacketPlayer.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinCPacketPlayer.java similarity index 87% rename from src/main/java/xyz/templecheats/templeclient/mixins/IMixinCPacketPlayer.java rename to src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinCPacketPlayer.java index bb7e0ee1..373482a7 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinCPacketPlayer.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinCPacketPlayer.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.accessor; import net.minecraft.network.play.client.CPacketPlayer; import org.spongepowered.asm.mixin.Mixin; @@ -8,22 +8,22 @@ public interface IMixinCPacketPlayer { @Accessor("x") void setX(double x); - + @Accessor("y") void setY(double y); - + @Accessor("z") void setZ(double z); - + @Accessor("yaw") void setYaw(float yaw); - + @Accessor("pitch") void setPitch(float pitch); - + @Accessor("moving") boolean isMoving(); - + @Accessor("rotating") boolean isRotating(); -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinRenderManager.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinRenderManager.java similarity index 87% rename from src/main/java/xyz/templecheats/templeclient/mixins/IMixinRenderManager.java rename to src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinRenderManager.java index 8a8dfe19..ca530080 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinRenderManager.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinRenderManager.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.accessor; import net.minecraft.client.renderer.entity.RenderManager; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketEntityVelocity.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketEntityVelocity.java new file mode 100644 index 00000000..93e5129a --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketEntityVelocity.java @@ -0,0 +1,17 @@ +package xyz.templecheats.templeclient.mixins.accessor; + +import net.minecraft.network.play.server.SPacketEntityVelocity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(value = SPacketEntityVelocity.class) +public interface IMixinSPacketEntityVelocity { + @Accessor("motionX") + void setMotionX(int motionX); + + @Accessor("motionY") + void setMotionY(int motionY); + + @Accessor("motionZ") + void setMotionZ(int motionZ); +} diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinSPacketExplosion.java b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketExplosion.java similarity index 88% rename from src/main/java/xyz/templecheats/templeclient/mixins/IMixinSPacketExplosion.java rename to src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketExplosion.java index bbed158a..ab47fa1f 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/IMixinSPacketExplosion.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/accessor/IMixinSPacketExplosion.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.accessor; import net.minecraft.network.play.server.SPacketExplosion; import org.spongepowered.asm.mixin.Mixin; diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlock.java b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlock.java new file mode 100644 index 00000000..fea918fe --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlock.java @@ -0,0 +1,20 @@ +package xyz.templecheats.templeclient.mixins.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import xyz.templecheats.templeclient.manager.ModuleManager; + +@Mixin(Block.class) +public class MixinBlock { + + @Inject(method = "getLightValue(Lnet/minecraft/block/state/IBlockState;)I", at = @At("HEAD"), cancellable = true) + public void getLightValue(IBlockState state, CallbackInfoReturnable cir) { + if (ModuleManager.getModuleByName("XRay").isEnabled()) { + cir.setReturnValue(15); + } + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinBlockLiquid.java b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockLiquid.java similarity index 76% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinBlockLiquid.java rename to src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockLiquid.java index 0ec63d85..1a2334d2 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinBlockLiquid.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockLiquid.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.block; import net.minecraft.block.BlockLiquid; import net.minecraft.block.state.IBlockState; @@ -16,15 +16,15 @@ @Mixin(value = BlockLiquid.class) public class MixinBlockLiquid { @Inject(method = "getCollisionBoundingBox", at = @At("HEAD"), cancellable = true) - public void getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos, CallbackInfoReturnable callback) { - if(Minecraft.getMinecraft() == null || Minecraft.getMinecraft().player == null) { + public void getCollisionBoundingBox(IBlockState state, IBlockAccess world, BlockPos pos, CallbackInfoReturnable < AxisAlignedBB > callback) { + if (Minecraft.getMinecraft() == null || Minecraft.getMinecraft().player == null) { return; } - + final LiquidCollisionEvent event = new LiquidCollisionEvent(pos); TempleClient.eventBus.dispatchEvent(event); - if(event.getBoundingBox() != null && !event.getBoundingBox().equals(BlockLiquid.NULL_AABB)) { + if (event.getBoundingBox() != null && !event.getBoundingBox().equals(BlockLiquid.NULL_AABB)) { callback.setReturnValue(event.getBoundingBox()); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockRendererDispatcher.java b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockRendererDispatcher.java new file mode 100644 index 00000000..5717e8e4 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/block/MixinBlockRendererDispatcher.java @@ -0,0 +1,70 @@ +package xyz.templecheats.templeclient.mixins.block; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.renderer.BlockModelRenderer; +import net.minecraft.client.renderer.BlockRendererDispatcher; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.block.model.IBakedModel; +import net.minecraft.init.Blocks; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.IBlockAccess; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import xyz.templecheats.templeclient.features.module.modules.render.xray.sub.Ores; +import xyz.templecheats.templeclient.manager.ModuleManager; + +@Mixin(BlockRendererDispatcher.class) +public abstract class MixinBlockRendererDispatcher { + @Shadow + @Final + private BlockModelRenderer blockModelRenderer; + + @Shadow + public abstract IBakedModel getModelForState(IBlockState state); + + @Inject(method = "renderBlock", at = @At("HEAD"), cancellable = true) + public void renderBlock(IBlockState state, BlockPos pos, IBlockAccess blockAccess, BufferBuilder bufferBuilderIn, CallbackInfoReturnable info) { + if (ModuleManager.getModuleByName("XRay").isEnabled()) { + Block block = state.getBlock(); + Ores oresModule = (Ores) ModuleManager.getModuleByName("Ores"); + if (oresModule.isEnabled() && isOre(block) && shouldRenderOre(block, oresModule)) { + info.setReturnValue(this.blockModelRenderer.renderModel(blockAccess, getModelForState(state), state, pos, bufferBuilderIn, false)); + } else { + info.setReturnValue(false); + } + } + } + + private boolean isOre(Block block) { + return block == Blocks.DIAMOND_ORE || block == Blocks.IRON_ORE || block == Blocks.GOLD_ORE || block == Blocks.LAPIS_ORE + || block == Blocks.REDSTONE_ORE || block == Blocks.EMERALD_ORE || block == Blocks.COAL_ORE + || block == Blocks.QUARTZ_ORE || block == Blocks.REDSTONE_ORE || block == Blocks.LIT_REDSTONE_ORE; + } + + private boolean shouldRenderOre(Block block, Ores oresModule) { + if (block == Blocks.DIAMOND_ORE) { + return oresModule.shouldRenderDiamondOres(); + } else if (block == Blocks.IRON_ORE) { + return oresModule.shouldRenderIronOres(); + } else if (block == Blocks.GOLD_ORE) { + return oresModule.shouldRenderGoldOres(); + } else if (block == Blocks.LAPIS_ORE) { + return oresModule.shouldRenderLapisOres(); + } else if (block == Blocks.REDSTONE_ORE || block == Blocks.LIT_REDSTONE_ORE) { + return oresModule.shouldRenderRedstoneOres(); + } else if (block == Blocks.EMERALD_ORE) { + return oresModule.shouldRenderEmeraldOres(); + } else if (block == Blocks.COAL_ORE) { + return oresModule.shouldRenderCoalOres(); + } else if (block == Blocks.QUARTZ_ORE) { + return oresModule.shouldRenderQuartzOres(); + } else { + return false; + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntity.java b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntity.java similarity index 80% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinEntity.java rename to src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntity.java index 10018e6a..692409c8 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntity.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntity.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.entity; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -19,11 +19,11 @@ public void move(MoverType type, double x, double y, double z) { } @Inject(method = "isEntityInsideOpaqueBlock", at = @At("HEAD"), cancellable = true) - public void isEntityInsideOpaqueBlock(CallbackInfoReturnable callback) { - if(Minecraft.getMinecraft() != null && Minecraft.getMinecraft().player != null) { + public void isEntityInsideOpaqueBlock(CallbackInfoReturnable < Boolean > callback) { + if (Minecraft.getMinecraft() != null && Minecraft.getMinecraft().player != null) { Freecam freecam = ModuleManager.getModule(Freecam.class); - if(freecam != null && freecam.isEnabled()) { + if (freecam != null && freecam.isEnabled()) { callback.setReturnValue(false); } } diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayer.java b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayer.java similarity index 85% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayer.java rename to src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayer.java index e6755827..6b4ea35c 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayer.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayer.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.entity; import com.mojang.authlib.GameProfile; import net.minecraft.entity.player.EntityPlayer; diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayerSP.java b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayerSP.java similarity index 90% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayerSP.java rename to src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayerSP.java index 3c594873..e3716de5 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinEntityPlayerSP.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/entity/MixinEntityPlayerSP.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.entity; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.AbstractClientPlayer; @@ -29,7 +29,7 @@ private void onUpdateWalkingPlayerHead(CallbackInfo callback) { final MotionEvent event = new MotionEvent(player.posX, player.posY, player.posZ, player.rotationYaw, player.rotationPitch, EventStageable.EventStage.PRE); TempleClient.eventBus.dispatchEvent(event); - if(event.isCanceled()) { + if (event.isCanceled()) { callback.cancel(); return; } @@ -51,11 +51,11 @@ private void onUpdateWalkingPlayerTail(CallbackInfo callback) { } @Inject(method = "pushOutOfBlocks", at = @At("HEAD"), cancellable = true) - public void pushOutOfBlocks(double x, double y, double z, CallbackInfoReturnable callback) { - if(Minecraft.getMinecraft() != null && Minecraft.getMinecraft().player != null) { + public void pushOutOfBlocks(double x, double y, double z, CallbackInfoReturnable < Boolean > callback) { + if (Minecraft.getMinecraft() != null && Minecraft.getMinecraft().player != null) { Freecam freecam = ModuleManager.getModule(Freecam.class); - if(freecam != null && freecam.isEnabled()) { + if (freecam != null && freecam.isEnabled()) { callback.setReturnValue(false); } } @@ -65,7 +65,7 @@ public void pushOutOfBlocks(double x, double y, double z, CallbackInfoReturnable public void move(AbstractClientPlayer player, MoverType type, double x, double y, double z) { final MoveEvent event = new MoveEvent(x, y, z); TempleClient.eventBus.dispatchEvent(event); - if(event.isCanceled()) { + if (event.isCanceled()) { return; } diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinGuiChat.java b/src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinGuiChat.java similarity index 88% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinGuiChat.java rename to src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinGuiChat.java index 5c33208d..20f0bab9 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinGuiChat.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinGuiChat.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.gui; import org.lwjgl.input.Keyboard; import org.lwjgl.opengl.GL11; @@ -15,7 +15,9 @@ import static xyz.templecheats.templeclient.util.Globals.mc; import static org.lwjgl.opengl.GL11.*; -@Mixin(value={GuiChat.class}) +@Mixin(value = { + GuiChat.class +}) public abstract class MixinGuiChat { private boolean shouldDrawOutline; @@ -57,9 +59,9 @@ public void drawScreenHook(int mouseX, int mouseY, float partialTicks, CallbackI glDisable(GL_BLEND); glDisable(GL_TEXTURE_2D); - float red = (ClickGUI.INSTANCE.getStartColor() >> 16 & 0xFF) / 255.0f; - float green = (ClickGUI.INSTANCE.getStartColor() >> 8 & 0xFF) / 255.0f; - float blue = (ClickGUI.INSTANCE.getStartColor() & 0xFF) / 255.0f; + float red = (ClickGUI.INSTANCE.getStartColor().getRGB() >> 16 & 0xFF) / 255.0f; + float green = (ClickGUI.INSTANCE.getStartColor().getRGB() >> 8 & 0xFF) / 255.0f; + float blue = (ClickGUI.INSTANCE.getStartColor().getRGB() & 0xFF) / 255.0f; GL11.glColor3f(red, green, blue); diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinPotionOverlay.java b/src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinPotionOverlay.java similarity index 92% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinPotionOverlay.java rename to src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinPotionOverlay.java index 9f52355a..07e67d8a 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinPotionOverlay.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/gui/MixinPotionOverlay.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.gui; import net.minecraft.client.gui.GuiIngame; import org.spongepowered.asm.mixin.Mixin; @@ -15,4 +15,4 @@ public void renderPotionEffects(CallbackInfo ci) { ci.cancel(); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinNetworkManager.java b/src/main/java/xyz/templecheats/templeclient/mixins/network/MixinNetworkManager.java similarity index 82% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinNetworkManager.java rename to src/main/java/xyz/templecheats/templeclient/mixins/network/MixinNetworkManager.java index 00f09084..9978c71a 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinNetworkManager.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/network/MixinNetworkManager.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.network; import io.netty.channel.ChannelHandlerContext; import net.minecraft.network.NetworkManager; @@ -13,20 +13,20 @@ @Mixin(value = NetworkManager.class) public class MixinNetworkManager { @Inject(method = "channelRead0", at = @At("HEAD"), cancellable = true) - public void IchannelRead0(ChannelHandlerContext context, Packet packet, CallbackInfo callback) { + public void IchannelRead0(ChannelHandlerContext context, Packet < ? > packet, CallbackInfo callback) { final PacketEvent.Receive event = new PacketEvent.Receive(packet); TempleClient.eventBus.dispatchEvent(event); - if(event.isCanceled()) { + if (event.isCanceled()) { callback.cancel(); } } @Inject(method = "sendPacket(Lnet/minecraft/network/Packet;)V", at = @At("HEAD"), cancellable = true) - public void IsendPacket(Packet packet, CallbackInfo callback) { + public void IsendPacket(Packet < ? > packet, CallbackInfo callback) { final PacketEvent.Send event = new PacketEvent.Send(packet); TempleClient.eventBus.dispatchEvent(event); - if(event.isCanceled()) { + if (event.isCanceled()) { callback.cancel(); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinAbstractClientPlayer.java b/src/main/java/xyz/templecheats/templeclient/mixins/player/MixinAbstractClientPlayer.java similarity index 79% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinAbstractClientPlayer.java rename to src/main/java/xyz/templecheats/templeclient/mixins/player/MixinAbstractClientPlayer.java index 1710b64f..1960bf61 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinAbstractClientPlayer.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/player/MixinAbstractClientPlayer.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.player; import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.network.NetworkPlayerInfo; @@ -9,6 +9,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.mixins.entity.MixinEntityPlayer; import javax.annotation.Nullable; @@ -19,14 +20,14 @@ public abstract class MixinAbstractClientPlayer extends MixinEntityPlayer { protected abstract NetworkPlayerInfo getPlayerInfo(); @Inject(method = "getLocationCape", at = @At("HEAD"), cancellable = true) - public void preGetLocationCape(CallbackInfoReturnable callback) { + public void preGetLocationCape(CallbackInfoReturnable < ResourceLocation > callback) { final NetworkPlayerInfo info = this.getPlayerInfo(); - if(info == null) { + if (info == null) { return; } final ResourceLocation resourceLocation = TempleClient.capeManager.getCapeByUuid(getGameProfile().getId()); - if(resourceLocation != null) { + if (resourceLocation != null) { callback.setReturnValue(resourceLocation); } } diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinEntityRenderer.java b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinEntityRenderer.java new file mode 100644 index 00000000..2c784aad --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinEntityRenderer.java @@ -0,0 +1,142 @@ +package xyz.templecheats.templeclient.mixins.render; + +import net.minecraft.client.renderer.*; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import org.lwjgl.util.glu.Project; +import org.spongepowered.asm.mixin.*; +import org.spongepowered.asm.mixin.injection.*; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.features.module.modules.render.*; +import xyz.templecheats.templeclient.features.module.modules.render.esp.sub.Shader; + +import javax.vecmath.Vector3f; +import java.awt.*; + +@Mixin(value = EntityRenderer.class) +public abstract class MixinEntityRenderer { + @Shadow protected abstract void hurtCameraEffect(float partialTicks); + @Shadow private ItemStack itemActivationItem; + @Shadow @Final private int[] lightmapColors; + @Unique float aspect; + + @Inject(method = "renderWorldPass", at = @At("RETURN")) + private void renderWorldPassPost(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { + if (Shader.INSTANCE.isEnabled() && Shader.INSTANCE.hand.booleanValue()) { + Shader.INSTANCE.drawHand(partialTicks, pass); + } + } + + @Inject(method = "renderItemActivation", at = @At("HEAD"), cancellable = true) + public void noRenderItemActivation(CallbackInfo info) { + if (itemActivationItem != null && itemActivationItem.getItem().equals(Items.TOTEM_OF_UNDYING)) { + if (NoRender.preventTotem()) { + info.cancel(); + } + } + } + + @Inject(method = "setupFog", at = @At("HEAD"), cancellable = true) + private void noRenderFog(int startCoords, float partialTicks, CallbackInfo ci) { + if (NoRender.preventFog()) { + GlStateManager.setFogDensity(0.0f); + ci.cancel(); + } + } + + @Redirect(method = "setupFog", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/EntityLivingBase;isPotionActive(Lnet/minecraft/potion/Potion;)Z")) + private boolean noRenderBlindness(EntityLivingBase instance, Potion potion) { + if (NoRender.preventBlindness()) return false; + return instance.isPotionActive(potion); + } + + @ModifyVariable(method = "setupCameraTransform", index = 4, at = @At("STORE")) + private float noRenderNausea(float original) { + if (NoRender.preventNausea()) return 0.0f; + return original; + } + + @Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/EntityRenderer;hurtCameraEffect(F)V")) + private void noHurtCam(EntityRenderer instance, float partialTicks) { + if (NoRender.preventHurtCam()) return; + else this.hurtCameraEffect(partialTicks); + } + + @Inject(method = "applyBobbing", at = @At("HEAD"), cancellable = true) + private void noCameraBob(float partialTicks, CallbackInfo ci) { + if(NoRender.preventBobbing()) { + ci.cancel(); + } + } + + @Inject(method = "renderRainSnow", at = @At("HEAD"), cancellable = true) + private void cancelWeather(float partialTicks, CallbackInfo ci) { + if (NoRender.preventWeather()) { + ci.cancel(); + } + } + + @Redirect(method = "setupCameraTransform", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V")) + private void onSetupCameraTransform(float fovy, float aspect, float zNear, float zFar) { + aspectControl(fovy, aspect, zNear, zFar); + } + + @Redirect(method = "renderWorldPass", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V")) + private void onRenderWorldPass(float fovy, float aspect, float zNear, float zFar) { + aspectControl(fovy, aspect, zNear, zFar); + } + + @Redirect(method = "renderCloudsCheck", at = @At(value = "INVOKE", target = "Lorg/lwjgl/util/glu/Project;gluPerspective(FFFF)V")) + private void onRenderCloudsCheck(float fovy, float aspect, float zNear, float zFar) { + aspectControl(fovy, aspect, zNear, zFar); + } + + @Unique + private void aspectControl(float fov, float aspect, float zNear, float zFar) { + if (Aspect.INSTANCE.isEnabled()) { + this.aspect = Aspect.INSTANCE.width.floatValue() / Aspect.INSTANCE.height.floatValue(); + } else { + this.aspect = aspect; + } + Project.gluPerspective(fov, this.aspect, zNear, zFar); + } + + @Inject(method = "updateLightmap", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/renderer/texture/DynamicTexture;updateDynamicTexture()V", shift = At.Shift.BEFORE)) + private void updateLightMapHook(float partialTicks, CallbackInfo ci) { + if (Ambience.INSTANCE.isEnabled() && Ambience.INSTANCE.LightMapState.booleanValue()) { + for (int i = 0; i < this.lightmapColors.length; ++i) { + Color ambientColor = Colors.INSTANCE.getLightMapColor(); + Vector3f finalValues = temple_Client_Development$getVector3f(ambientColor, i); + int red = (int) (finalValues.x * 255.0f); + int green = (int) (finalValues.y * 255.0f); + int blue = (int) (finalValues.z * 255.0f); + this.lightmapColors[i] = 0xFF000000 | red << 16 | green << 8 | blue; + } + } + } + + // TODO: Move these thing to some where + @Unique + private Vector3f temple_Client_Development$getVector3f(Color ambientColor, int i) { + int alpha = ambientColor.getAlpha(); + float modifier = (float) alpha / 255.0f; + int color = this.lightmapColors[i]; + int[] bgr = temple_Client_Development$toRGBAArray(color); + Vector3f values = new Vector3f((float) bgr[2] / 255.0f, (float) bgr[1] / 255.0f, (float) bgr[0] / 255.0f); + Vector3f newValues = new Vector3f((float) ambientColor.getRed() / 255.0f, (float) ambientColor.getGreen() / 255.0f, (float) ambientColor.getBlue() / 255.0f); + return temple_Client_Development$mix(values, newValues, modifier); + } + + @Unique + private int[] temple_Client_Development$toRGBAArray(int colorBuffer) { + return new int[]{colorBuffer >> 16 & 0xFF, colorBuffer >> 8 & 0xFF, colorBuffer & 0xFF}; + } + + @Unique + private Vector3f temple_Client_Development$mix(Vector3f first, Vector3f second, float factor) { + return new Vector3f(first.x * (1.0f - factor) + second.x * factor, first.y * (1.0f - factor) + second.y * factor, first.z * (1.0f - factor) + first.z * factor); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinItemRenderer.java b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinItemRenderer.java similarity index 97% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinItemRenderer.java rename to src/main/java/xyz/templecheats/templeclient/mixins/render/MixinItemRenderer.java index e69d66ea..e829b523 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinItemRenderer.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinItemRenderer.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.render; import net.minecraft.client.renderer.ItemRenderer; import net.minecraft.item.ItemStack; diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinLayerHeldItem.java b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinLayerHeldItem.java new file mode 100644 index 00000000..c5e6b6b5 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinLayerHeldItem.java @@ -0,0 +1,30 @@ +package xyz.templecheats.templeclient.mixins.render; + +import net.minecraft.client.renderer.block.model.ItemCameraTransforms; +import net.minecraft.client.renderer.entity.layers.LayerHeldItem; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHandSide; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.event.events.render.HeldItemEvent; +import xyz.templecheats.templeclient.util.Globals; + +@Mixin(LayerHeldItem.class) +public class MixinLayerHeldItem implements Globals { + + @Inject(method = "renderHeldItem", at = @At("HEAD"), cancellable = true) + private void renderHeldItem(EntityLivingBase entity, ItemStack item, ItemCameraTransforms.TransformType transformType, EnumHandSide handSide, CallbackInfo ci) { + if (entity instanceof EntityPlayer && !entity.equals(mc.player)) { + final HeldItemEvent event = new HeldItemEvent(); + TempleClient.eventBus.dispatchEvent(event); + if (event.isCanceled()) { + ci.cancel(); + } + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRender.java b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRender.java new file mode 100644 index 00000000..9fb3ae16 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRender.java @@ -0,0 +1,34 @@ +package xyz.templecheats.templeclient.mixins.render; + +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.entity.Entity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.event.events.render.FireEvent; +import xyz.templecheats.templeclient.util.Globals; +import xyz.templecheats.templeclient.event.events.render.NamePlateEvent; + +@Mixin(Render.class) +public class MixinRender < T extends Entity > implements Globals { + + @Inject(method = "renderEntityOnFire", at = @At("HEAD"), cancellable = true) + private void renderEntityOnFire(Entity entity, double x, double y, double z, float partialTicks, CallbackInfo ci) { + final FireEvent fireEvent = new FireEvent(); + TempleClient.eventBus.dispatchEvent(fireEvent); + if (fireEvent.isCanceled()) { + ci.cancel(); + } + } + + @Inject(method = "renderLivingLabel", at = @At("HEAD"), cancellable = true) + private void renderLivingLabel(T entityIn, String str, double x, double y, double z, int maxDistance, CallbackInfo ci) { + final NamePlateEvent nameplateEvent = new NamePlateEvent(entityIn); + TempleClient.eventBus.dispatchEvent(nameplateEvent); + if (nameplateEvent.isCanceled()) { + ci.cancel(); + } + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRenderArmor.java b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRenderArmor.java new file mode 100644 index 00000000..de1f7564 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/mixins/render/MixinRenderArmor.java @@ -0,0 +1,20 @@ +package xyz.templecheats.templeclient.mixins.render; + +import net.minecraft.client.model.ModelRenderer; +import net.minecraft.client.renderer.entity.layers.LayerBipedArmor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; +import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.event.events.render.ArmorEvent; + +@Mixin(LayerBipedArmor.class) +public class MixinRenderArmor { + + @Redirect(method = "setModelSlotVisible(Lnet/minecraft/client/model/ModelBiped;Lnet/minecraft/inventory/EntityEquipmentSlot;)V", at = @At(value = "FIELD", target = "Lnet/minecraft/client/model/ModelRenderer;showModel:Z")) + private void showModel(ModelRenderer instance, boolean value) { + final ArmorEvent armorEvent = new ArmorEvent(); + TempleClient.eventBus.dispatchEvent(armorEvent); + instance.showModel = !armorEvent.isCanceled(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/mixins/MixinWorldClient.java b/src/main/java/xyz/templecheats/templeclient/mixins/world/MixinWorldClient.java similarity index 88% rename from src/main/java/xyz/templecheats/templeclient/mixins/MixinWorldClient.java rename to src/main/java/xyz/templecheats/templeclient/mixins/world/MixinWorldClient.java index 3a265258..56c71f4b 100644 --- a/src/main/java/xyz/templecheats/templeclient/mixins/MixinWorldClient.java +++ b/src/main/java/xyz/templecheats/templeclient/mixins/world/MixinWorldClient.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.mixins; +package xyz.templecheats.templeclient.mixins.world; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.entity.Entity; @@ -14,19 +14,19 @@ public class MixinWorldClient { @Inject(method = "addEntityToWorld", at = @At("TAIL")) public void addEntityToWorld(int entityID, Entity entityToSpawn, CallbackInfo callback) { - if(entityToSpawn != null) { + if (entityToSpawn != null) { final EntityEvent.Add event = new EntityEvent.Add(entityToSpawn); TempleClient.eventBus.dispatchEvent(event); } } - + @Inject(method = "removeEntityFromWorld", at = @At("HEAD")) - public void removeEntityFromWorld(int entityID, CallbackInfoReturnable callback) { + public void removeEntityFromWorld(int entityID, CallbackInfoReturnable < Entity > callback) { final Entity entity = WorldClient.class.cast(this).getEntityByID(entityID); - - if(entity != null) { + + if (entity != null) { final EntityEvent.Delete event = new EntityEvent.Delete(entity); TempleClient.eventBus.dispatchEvent(event); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACHelper.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACHelper.java index 62414def..3b8ce8ff 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACHelper.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACHelper.java @@ -9,6 +9,7 @@ import net.minecraft.util.math.Vec3d; import xyz.templecheats.templeclient.TempleClient; import xyz.templecheats.templeclient.util.autocrystal.threads.ACCalculate; +import xyz.templecheats.templeclient.util.world.EntityUtil; import java.util.ArrayList; import java.util.List; @@ -17,135 +18,131 @@ public enum ACHelper { INSTANCE; - + private static final Minecraft mc = Minecraft.getMinecraft(); - private static final List EMPTY_LIST = new ArrayList<>(); + private static final List < CrystalInfo.PlaceInfo > EMPTY_LIST = new ArrayList < > (); public static final ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newCachedThreadPool(); - + private static final ExecutorService mainExecutors = Executors.newSingleThreadExecutor(); - private Future> mainThreadOutput; - + private Future < List < CrystalInfo.PlaceInfo >> mainThreadOutput; + private ACSettings settings = null; - private List possiblePlacements = new ArrayList<>(); - private List targetableCrystals = new ArrayList<>(); - private final List targetsInfo = new ArrayList<>(); - - private List threadPlacements = new ArrayList<>(); - + private List < BlockPos > possiblePlacements = new ArrayList < > (); + private List < EntityEnderCrystal > targetableCrystals = new ArrayList < > (); + private final List < PlayerInfo > targetsInfo = new ArrayList < > (); + + private List < BlockPos > threadPlacements = new ArrayList < > (); + public void startCalculations(long timeout) { - if(mainThreadOutput != null) { + if (mainThreadOutput != null) { mainThreadOutput.cancel(true); } mainThreadOutput = mainExecutors.submit(new ACCalculate(settings, targetsInfo, threadPlacements, timeout)); } - - public List getOutput(boolean wait) { - if(mainThreadOutput == null) { + + public List < CrystalInfo.PlaceInfo > getOutput(boolean wait) { + if (mainThreadOutput == null) { return EMPTY_LIST; } - - if(wait) { - while(!(mainThreadOutput.isDone() || mainThreadOutput.isCancelled())) { - } + + if (wait) { + while (!(mainThreadOutput.isDone() || mainThreadOutput.isCancelled())) {} } else { - if(!(mainThreadOutput.isDone())) { + if (!(mainThreadOutput.isDone())) { return null; } - if(mainThreadOutput.isCancelled()) { + if (mainThreadOutput.isCancelled()) { return EMPTY_LIST; } } - - List output = EMPTY_LIST; + + List < CrystalInfo.PlaceInfo > output = EMPTY_LIST; try { output = mainThreadOutput.get(); - } catch(InterruptedException | ExecutionException ignored) { - } - + } catch (InterruptedException | ExecutionException ignored) {} + mainThreadOutput = null; return output; } - + public void recalculateValues(ACSettings settings, PlayerInfo self, float armourPercent, double enemyDistance) { this.settings = settings; - + final double entityRangeSq = (enemyDistance) * (enemyDistance); - List targets = mc.world.playerEntities.stream() - .filter(entity -> self.entity.getDistanceSq(entity) <= entityRangeSq) - .filter(entity -> !EntityUtil.basicChecksEntity(entity)) - .filter(entity -> entity.getHealth() > 0.0f) - .collect(Collectors.toList()); - + List < EntityPlayer > targets = mc.world.playerEntities.stream() + .filter(entity -> self.entity.getDistanceSq(entity) <= entityRangeSq) + .filter(entity -> !EntityUtil.basicChecksEntity(entity)) + .filter(entity -> entity.getHealth() > 0.0f) + .collect(Collectors.toList()); + targetableCrystals = mc.world.loadedEntityList.stream() - .filter(entity -> entity instanceof EntityEnderCrystal) - .map(entity -> (EntityEnderCrystal) entity).collect(Collectors.toList()); - - + .filter(entity -> entity instanceof EntityEnderCrystal) + .map(entity -> (EntityEnderCrystal) entity).collect(Collectors.toList()); + targetableCrystals.removeIf(crystal -> { float damage = DamageUtil.calculateDamageThreaded(crystal.posX, crystal.posY, crystal.posZ, self); - if(damage > settings.maxSelfDamage) { + if (damage > settings.maxSelfDamage) { return true; } else { return (damage > self.health) || self.entity.getDistanceSq(crystal) >= settings.breakRangeSq; } }); - + possiblePlacements = CrystalUtil.findCrystalBlocks(settings.placeRange, settings.server); - + possiblePlacements.removeIf(pos -> { float damage = DamageUtil.calculateDamageThreaded((double) pos.getX() + 0.5d, (double) pos.getY() + 1.0d, (double) pos.getZ() + 0.5d, settings.player); - - if(damage > settings.maxSelfDamage || damage > settings.player.health) { + + if (damage > settings.maxSelfDamage || damage > settings.player.health) { return true; } - + EnumFacing validFace = mc.player.posY + mc.player.getEyeHeight() > pos.getY() + 0.5 || !mc.world.isAirBlock(pos.down()) ? EnumFacing.UP : EnumFacing.DOWN; - - if(settings.raytrace) { + + if (settings.raytrace) { validFace = null; - - + final Vec3d vec = new Vec3d(pos.getX() + 0.5, pos.getY() - 0.5, pos.getZ() + 0.5); final RayTraceResult result = mc.world.rayTraceBlocks(mc.player.getPositionEyes(1.0F), vec); - - if(result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && mc.world.isAirBlock(pos.offset(result.sideHit))) { + + if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && mc.world.isAirBlock(pos.offset(result.sideHit))) { validFace = result.sideHit; } } - + return validFace == null; }); - + threadPlacements = CrystalUtil.findCrystalBlocksExcludingCrystals(settings.placeRange, settings.server); - + targetsInfo.clear(); - for(EntityPlayer target : targets) { + for (EntityPlayer target: targets) { targetsInfo.add(new PlayerInfo(target, armourPercent)); } } - + public void onEnable() { TempleClient.eventBus.addEventListener(this); } - + public void onDisable() { TempleClient.eventBus.removeEventListener(this); - - if(mainThreadOutput != null) { + + if (mainThreadOutput != null) { mainThreadOutput.cancel(true); } } - + public ACSettings getSettings() { return settings; } - - public List getPossiblePlacements() { + + public List < BlockPos > getPossiblePlacements() { return possiblePlacements; } - - public List getTargetableCrystals() { + + public List < EntityEnderCrystal > getTargetableCrystals() { return targetableCrystals; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACSettings.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACSettings.java index 99c105ad..018b48df 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACSettings.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACSettings.java @@ -8,37 +8,37 @@ public class ACSettings { public final double breakRangeSq; public final double wallsRangeSq; public final float placeRange; - + public final float minDamage; public final float minFacePlaceDamage; public final float maxSelfDamage; public final float facePlaceHealth; - + public final boolean raytrace; - + public final AutoCrystal.Server server; public final AutoCrystal.Priority crystalPriority; - + public final PlayerInfo player; public final Vec3d playerPos; - + public ACSettings(double enemyRange, double range, double wallsRange, double minDamage, double minFacePlaceDamage, double maxSelfDamage, double facePlaceHealth, boolean raytrace, AutoCrystal.Server server, AutoCrystal.Priority crystalPriority, PlayerInfo player, Vec3d playerPos) { this.enemyRangeSq = enemyRange * enemyRange; this.breakRangeSq = range * range; this.wallsRangeSq = wallsRange * wallsRange; this.placeRange = (float) range; - + this.minDamage = (float) minDamage; this.minFacePlaceDamage = (float) minFacePlaceDamage; this.maxSelfDamage = (float) maxSelfDamage; this.facePlaceHealth = (float) facePlaceHealth; - + this.raytrace = raytrace; - + this.server = server; this.crystalPriority = crystalPriority; - + this.player = player; this.playerPos = playerPos; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACUtil.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACUtil.java index 66c637cd..867709f5 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/ACUtil.java @@ -6,61 +6,61 @@ import java.util.List; public class ACUtil { - public static CrystalInfo.PlaceInfo calculateBestPlacement(ACSettings settings, PlayerInfo target, List possibleLocations) { + public static CrystalInfo.PlaceInfo calculateBestPlacement(ACSettings settings, PlayerInfo target, List < BlockPos > possibleLocations) { double x = settings.playerPos.x; double y = settings.playerPos.y; double z = settings.playerPos.z; - + BlockPos best = null; float bestDamage = 0f; - for(BlockPos pos : possibleLocations) { - if(target.entity.getDistanceSq((double) pos.getX() + 0.5, (double) pos.getY() + 1.0, (double) pos.getZ() + 0.5) <= settings.enemyRangeSq) { + for (BlockPos pos: possibleLocations) { + if (target.entity.getDistanceSq((double) pos.getX() + 0.5, (double) pos.getY() + 1.0, (double) pos.getZ() + 0.5) <= settings.enemyRangeSq) { float currentDamage = DamageUtil.calculateDamageThreaded(pos, target); - if(currentDamage == bestDamage) { - if(best == null || pos.distanceSq(x, y, z) < best.distanceSq(x, y, z)) { + if (currentDamage == bestDamage) { + if (best == null || pos.distanceSq(x, y, z) < best.distanceSq(x, y, z)) { bestDamage = currentDamage; best = pos; } - } else if(currentDamage > bestDamage) { + } else if (currentDamage > bestDamage) { bestDamage = currentDamage; best = pos; } } } - - if(best != null) { - if(bestDamage >= settings.minDamage || ((target.health <= settings.facePlaceHealth || target.lowArmour) && bestDamage >= settings.minFacePlaceDamage)) { + + if (best != null) { + if (bestDamage >= settings.minDamage || ((target.health <= settings.facePlaceHealth || target.lowArmour) && bestDamage >= settings.minFacePlaceDamage)) { return new CrystalInfo.PlaceInfo(bestDamage, target, best); } } - + return null; } - - public static CrystalInfo.BreakInfo calculateBestBreakable(ACSettings settings, PlayerInfo target, List crystals) { + + public static CrystalInfo.BreakInfo calculateBestBreakable(ACSettings settings, PlayerInfo target, List < EntityEnderCrystal > crystals) { double x = settings.playerPos.x; double y = settings.playerPos.y; double z = settings.playerPos.z; - + EntityEnderCrystal best = null; float bestDamage = 0f; - for(EntityEnderCrystal crystal : crystals) { + for (EntityEnderCrystal crystal: crystals) { float currentDamage = DamageUtil.calculateDamageThreaded(crystal, target); - if(currentDamage == bestDamage) { - if(best == null || crystal.getDistanceSq(x, y, z) < best.getDistanceSq(x, y, z)) { + if (currentDamage == bestDamage) { + if (best == null || crystal.getDistanceSq(x, y, z) < best.getDistanceSq(x, y, z)) { bestDamage = currentDamage; best = crystal; } - } else if(currentDamage > bestDamage) { + } else if (currentDamage > bestDamage) { bestDamage = currentDamage; best = crystal; } } - - if(best != null) { + + if (best != null) { return new CrystalInfo.BreakInfo(bestDamage, target, best); } - + return null; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalInfo.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalInfo.java index ca15eb0d..f8c32750 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalInfo.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalInfo.java @@ -6,28 +6,28 @@ public class CrystalInfo { public final float damage; public final PlayerInfo target; - + private CrystalInfo(float damage, PlayerInfo target) { this.damage = damage; this.target = target; - + } - + public static class BreakInfo extends CrystalInfo { public final EntityEnderCrystal crystal; - + public BreakInfo(float damage, PlayerInfo target, EntityEnderCrystal crystal) { super(damage, target); this.crystal = crystal; } } - + public static class PlaceInfo extends CrystalInfo { public final BlockPos pos; - + public PlaceInfo(float damage, PlayerInfo target, BlockPos pos) { super(damage, target); this.pos = pos; } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalUtil.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalUtil.java index be58a778..50d47d39 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/CrystalUtil.java @@ -9,58 +9,59 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import xyz.templecheats.templeclient.features.module.modules.combat.AutoCrystal; +import xyz.templecheats.templeclient.util.world.EntityUtil; import java.util.List; import java.util.stream.Collectors; public class CrystalUtil { private static final Minecraft mc = Minecraft.getMinecraft(); - + public static boolean canPlaceCrystal(BlockPos blockPos, AutoCrystal.Server server, boolean ignoreCrystals) { - if(notValidBlock(mc.world.getBlockState(blockPos).getBlock())) return false; - + if (notValidBlock(mc.world.getBlockState(blockPos).getBlock())) return false; + BlockPos posUp = blockPos.up(); - - if(server != AutoCrystal.Server.OneTwelve) { - if(!mc.world.isAirBlock(posUp)) return false; + + if (server != AutoCrystal.Server.OneTwelve) { + if (!mc.world.isAirBlock(posUp)) return false; } else { - if(notValidMaterial(mc.world.getBlockState(posUp).getMaterial()) - || notValidMaterial(mc.world.getBlockState(posUp.up()).getMaterial())) { + if (notValidMaterial(mc.world.getBlockState(posUp).getMaterial()) || + notValidMaterial(mc.world.getBlockState(posUp.up()).getMaterial())) { return false; } } - + AxisAlignedBB box = new AxisAlignedBB( posUp.getX(), posUp.getY(), posUp.getZ(), posUp.getX() + 1.0, posUp.getY() + (server == AutoCrystal.Server.Crystalpvp_cc ? 1.0 : 2.0), posUp.getZ() + 1.0 ); - - if(ignoreCrystals) { + + if (ignoreCrystals) { return mc.world.getEntitiesWithinAABB(Entity.class, box, entity -> !(entity.isDead || entity instanceof EntityEnderCrystal)).isEmpty(); } else { return mc.world.getEntitiesWithinAABB(Entity.class, box, Entity::isEntityAlive).isEmpty(); } } - + public static boolean notValidBlock(Block block) { return block != Blocks.BEDROCK && block != Blocks.OBSIDIAN; } - + public static boolean notValidMaterial(Material material) { return material.isLiquid() || !material.isReplaceable(); } - - public static List findCrystalBlocks(float placeRange, AutoCrystal.Server server) { + + public static List < BlockPos > findCrystalBlocks(float placeRange, AutoCrystal.Server server) { return EntityUtil.getSphere(mc.player.getPosition(), placeRange, (int) placeRange, false, true, 0) - .stream() - .filter(pos -> CrystalUtil.canPlaceCrystal(pos, server, false)) - .collect(Collectors.toList()); + .stream() + .filter(pos -> CrystalUtil.canPlaceCrystal(pos, server, false)) + .collect(Collectors.toList()); } - - public static List findCrystalBlocksExcludingCrystals(float placeRange, AutoCrystal.Server server) { + + public static List < BlockPos > findCrystalBlocksExcludingCrystals(float placeRange, AutoCrystal.Server server) { return EntityUtil.getSphere(mc.player.getPosition(), placeRange, (int) placeRange, false, true, 0) - .stream() - .filter(pos -> CrystalUtil.canPlaceCrystal(pos, server, true)) - .collect(Collectors.toList()); + .stream() + .filter(pos -> CrystalUtil.canPlaceCrystal(pos, server, true)) + .collect(Collectors.toList()); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/DamageUtil.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/DamageUtil.java index c4a0a917..01716e16 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/DamageUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/DamageUtil.java @@ -9,15 +9,15 @@ public class DamageUtil { private static final Minecraft mc = Minecraft.getMinecraft(); - + public static float calculateDamageThreaded(EntityEnderCrystal crystal, PlayerInfo playerInfo) { return calculateDamageThreaded(crystal.posX, crystal.posY, crystal.posZ, playerInfo); } - + public static float calculateDamageThreaded(BlockPos pos, PlayerInfo playerInfo) { return calculateDamageThreaded(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5, playerInfo); } - + public static float calculateDamageThreaded(double posX, double posY, double posZ, PlayerInfo playerInfo) { float finalDamage = 1.0f; try { @@ -25,28 +25,27 @@ public static float calculateDamageThreaded(double posX, double posY, double pos double distancedSize = playerInfo.entity.getDistance(posX, posY, posZ) / (double) doubleExplosionSize; double blockDensity = playerInfo.entity.world.getBlockDensity(new Vec3d(posX, posY, posZ), playerInfo.entity.getEntityBoundingBox()); double v = (1.0D - distancedSize) * blockDensity; - float damage = (float) ((int) ((v * v + v) / 2.0D * 7.0D * (double) doubleExplosionSize + 1.0D)); - + float damage = (float)((int)((v * v + v) / 2.0D * 7.0D * (double) doubleExplosionSize + 1.0D)); + finalDamage = getBlastReductionThreaded(playerInfo, getDamageMultiplied(damage)); - } catch(NullPointerException ignored) { - } - + } catch (NullPointerException ignored) {} + return finalDamage; } - + public static float getBlastReductionThreaded(PlayerInfo playerInfo, float damage) { damage = CombatRules.getDamageAfterAbsorb(damage, playerInfo.totalArmourValue, playerInfo.armourToughness); - + float f = MathHelper.clamp(playerInfo.enchantModifier, 0.0F, 20.0F); damage *= 1.0F - f / 25.0F; - - if(playerInfo.hasResistance) { + + if (playerInfo.hasResistance) { damage = damage - (damage / 4); } damage = Math.max(damage, 0.0F); return damage; } - + private static float getDamageMultiplied(float damage) { int diff = mc.world.getDifficulty().getId(); return damage * (diff == 0 ? 0 : (diff == 2 ? 1 : (diff == 1 ? 0.5f : 1.5f))); diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/InventoryUtil.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/InventoryUtil.java index 46405f1d..bd75f198 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/InventoryUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/InventoryUtil.java @@ -8,19 +8,19 @@ public class InventoryUtil { private static final Minecraft mc = Minecraft.getMinecraft(); - - public static int findFirstItemSlot(Class itemToFind, int lower, int upper) { + + public static int findFirstItemSlot(Class < ? extends Item > itemToFind, int lower, int upper) { int slot = -1; - List mainInventory = mc.player.inventory.mainInventory; - - for(int i = lower; i <= upper; i++) { + List < ItemStack > mainInventory = mc.player.inventory.mainInventory; + + for (int i = lower; i <= upper; i++) { ItemStack stack = mainInventory.get(i); - - if(stack == ItemStack.EMPTY || !(itemToFind.isInstance(stack.getItem()))) { + + if (stack == ItemStack.EMPTY || !(itemToFind.isInstance(stack.getItem()))) { continue; } - - if(itemToFind.isInstance(stack.getItem())) { + + if (itemToFind.isInstance(stack.getItem())) { slot = i; break; } diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/PlayerInfo.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/PlayerInfo.java index f34857d6..3cf5750c 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/PlayerInfo.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/PlayerInfo.java @@ -32,7 +32,7 @@ public PlayerInfo(EntityPlayer entity, float armorPercent) { this.hasResistance = entity.isPotionActive(RESISTANCE); boolean i = false; - for (ItemStack stack : entity.getArmorInventoryList()) { + for (ItemStack stack: entity.getArmorInventoryList()) { if ((1.0f - ((float) stack.getItemDamage() / (float) stack.getMaxDamage())) < armorPercent) { i = true; break; @@ -53,4 +53,4 @@ public PlayerInfo(EntityPlayer entity, boolean lowArmour) { this.lowArmour = lowArmour; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/RotationUtil.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/RotationUtil.java index bea7196e..5954a345 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/RotationUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/RotationUtil.java @@ -7,35 +7,35 @@ public class RotationUtil { private static final Minecraft mc = Minecraft.getMinecraft(); - + public static Vec2f getRotationTo(Vec3d posTo) { EntityPlayerSP player = mc.player; return player != null ? getRotationTo(player.getPositionEyes(1.0f), posTo) : Vec2f.ZERO; } - + public static Vec2f getRotationTo(Vec3d posFrom, Vec3d posTo) { return getRotationFromVec(posTo.subtract(posFrom)); } - + public static Vec2f getRotationFromVec(Vec3d vec) { double lengthXZ = Math.hypot(vec.x, vec.z); double yaw = normalizeAngle(Math.toDegrees(Math.atan2(vec.z, vec.x)) - 90.0); double pitch = normalizeAngle(Math.toDegrees(-Math.atan2(vec.y, lengthXZ))); - + return new Vec2f((float) yaw, (float) pitch); } - + public static double normalizeAngle(double angle) { angle %= 360.0; - - if(angle >= 180.0) { + + if (angle >= 180.0) { angle -= 360.0; } - - if(angle < -180.0) { + + if (angle < -180.0) { angle += 360.0; } - + return angle; } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/threads/ACCalculate.java b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/threads/ACCalculate.java index aa629dee..e85b2754 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/threads/ACCalculate.java +++ b/src/main/java/xyz/templecheats/templeclient/util/autocrystal/threads/ACCalculate.java @@ -15,16 +15,16 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Future; -public class ACCalculate implements Callable> { +public class ACCalculate implements Callable < List < CrystalInfo.PlaceInfo >> { private final ACSettings settings; - private final List targets; - private final List blocks; + private final List < PlayerInfo > targets; + private final List < BlockPos > blocks; private final long globalTimeoutTime; - public ACCalculate(ACSettings settings, List targets, List blocks, long globalTimeoutTime) { + public ACCalculate(ACSettings settings, List < PlayerInfo > targets, List < BlockPos > blocks, long globalTimeoutTime) { this.settings = settings; this.targets = targets; @@ -34,24 +34,24 @@ public ACCalculate(ACSettings settings, List targets, List } @Override - public List call() { + public List < CrystalInfo.PlaceInfo > call() { return getPlayers(startThreads()); } @Nonnull - private List> startThreads() { - List> output = new ArrayList<>(); + private List < Future < CrystalInfo.PlaceInfo >> startThreads() { + List < Future < CrystalInfo.PlaceInfo >> output = new ArrayList < > (); - for (PlayerInfo target : targets) { + for (PlayerInfo target: targets) { output.add(ACHelper.executor.submit(new ACSubThread(settings, blocks, target))); } return output; } - private List getPlayers(List> input) { - List place = new ArrayList<>(); - for (Future future : input) { + private List < CrystalInfo.PlaceInfo > getPlayers(List < Future < CrystalInfo.PlaceInfo >> input) { + List < CrystalInfo.PlaceInfo > place = new ArrayList < > (); + for (Future < CrystalInfo.PlaceInfo > future: input) { while (!future.isDone() && !future.isCancelled()) { if (System.currentTimeMillis() > globalTimeoutTime) { break; @@ -61,8 +61,7 @@ private List getPlayers(List getPlayers(List { +public class ACSubThread implements Callable < CrystalInfo.PlaceInfo > { private final ACSettings settings; - private final List possibleLocations; + private final List < BlockPos > possibleLocations; private final PlayerInfo target; - public ACSubThread(ACSettings setting, List possibleLocations, PlayerInfo target) { + public ACSubThread(ACSettings setting, List < BlockPos > possibleLocations, PlayerInfo target) { this.settings = setting; this.possibleLocations = possibleLocations; @@ -34,4 +34,4 @@ private CrystalInfo.PlaceInfo getPlacement() { return ACUtil.calculateBestPlacement(settings, target, possibleLocations); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/ColorUtil.java b/src/main/java/xyz/templecheats/templeclient/util/color/ColorUtil.java new file mode 100644 index 00000000..521a32a9 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/ColorUtil.java @@ -0,0 +1,142 @@ +package xyz.templecheats.templeclient.util.color; + +import java.awt.Color; + +import static xyz.templecheats.templeclient.util.math.MathUtil.lerp; + +public class ColorUtil { + + /** + * Converts a position on the slider to a Color object. + * Assumes the slider width represents a full range of hues (0 to 360 degrees). + * + * @param position The position on the slider. + * @param sliderWidth The total width of the slider. + * @return The Color object corresponding to the position on the slider. + */ + public static Color getColorFromPosition(int position, int sliderWidth) { + float hue = (float) position / sliderWidth; + return Color.getHSBColor(hue, 1.0f, 1.0f); + } + + /** + * Converts a position on the slider to an alpha value. + * Assumes the slider width represents a full range of alpha values (0 to 255). + * + * @param position The position on the slider. + * @param sliderWidth The total width of the slider. + * @return The alpha value corresponding to the position on the slider. + */ + public static int getAlphaFromPosition(int position, int sliderWidth) { + return (int) ((float) position / sliderWidth * 255); + } + + /** + * Converts an alpha value to a position on the slider based on alpha range (0 to 255). + * + * @param alpha The alpha value. + * @param sliderWidth The total width of the slider. + * @return The position on the slider corresponding to the alpha value. + */ + public static float getPositionFromAlpha(int alpha, float sliderWidth) { + return (float) alpha * sliderWidth / 255; + } + + /** + * Converts a Color object to a position on the slider based on saturation and brightness. + * + * @param color The Color object. + * @param sliderWidth The total width of the slider. + * @param sliderHeight The total height of the slider. + * @return An array containing the y positions on the slider corresponding to the saturation and brightness of the color. + */ + public static float[] getPositionFromColor(Color color, float sliderWidth, float sliderHeight) { + float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); + float saturationPosition = hsb[1] * sliderWidth; + float brightnessPosition = (1.0f - hsb[2]) * sliderHeight; + return new float[] { + saturationPosition, + brightnessPosition + }; + } + + /** + * Converts a Color object to a position on the slider. + * Useful for initializing the slider position based on an existing color. + * + * @param color The Color object. + * @param sliderWidth The total width of the slider. + * @return The position on the slider that corresponds to the color. + */ + public static float getPositionFromColor(Color color, float sliderWidth) { + float[] hsb = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), null); + return hsb[0] * sliderWidth; + } + + /** + * Converts a Color object to a hexadecimal String. + * + * @param color The Color object. + * @return The hexadecimal String representing the color. + */ + public static String toHexString(Color color) { + return String.format("#%02x%02x%02x", color.getRed(), color.getGreen(), color.getBlue()); + } + + public static Color setAlpha(Color color, int alpha) { + return new Color(color.getRed(), color.getGreen(), color.getBlue(), alpha); + } + + public static Color getColor(Color color, float alpha) { + float red = (float)color.getRed() / 255.0f; + float green = (float)color.getGreen() / 255.0f; + float blue = (float)color.getBlue() / 255.0f; + return new Color(red, green, blue, alpha); + } + + public static Color lerpColor(Color current, Color target, float lerp) { + int red = (int) lerp(current.getRed(), target.getRed(), lerp); + int green = (int) lerp(current.getGreen(), target.getGreen(), lerp); + int blue = (int) lerp(current.getBlue(), target.getBlue(), lerp); + int alpha = (int) lerp(current.getAlpha(), target.getAlpha(), lerp); + + return new Color(red, green, blue, alpha); + } + + public static int lerpColor(int color1, int color2, float amount) { + amount = Math.min(1, Math.max(0, amount)); + + int red1 = getRed(color1); + int green1 = getGreen(color1); + int blue1 = getBlue(color1); + int alpha1 = getAlpha(color1); + + int red2 = getRed(color2); + int green2 = getGreen(color2); + int blue2 = getBlue(color2); + int alpha2 = getAlpha(color2); + + int interpolatedRed = (int) lerp(red1, red2, amount); + int interpolatedGreen = (int) lerp(green1, green2, amount); + int interpolatedBlue = (int) lerp(blue1, blue2, amount); + int interpolatedAlpha = (int) lerp(alpha1, alpha2, amount); + + return (interpolatedAlpha << 24) | (interpolatedRed << 16) | (interpolatedGreen << 8) | interpolatedBlue; + } + + public static int getRed(final int hex) { + return hex >> 16 & 255; + } + + public static int getGreen(final int hex) { + return hex >> 8 & 255; + } + + public static int getBlue(final int hex) { + return hex & 255; + } + + public static int getAlpha(final int hex) { + return hex >> 24 & 255; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/RainbowUtil.java b/src/main/java/xyz/templecheats/templeclient/util/color/RainbowUtil.java index 400d492f..e5601aba 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/color/RainbowUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/color/RainbowUtil.java @@ -2,13 +2,28 @@ import java.awt.*; +import static xyz.templecheats.templeclient.util.color.ColorUtil.lerpColor; + public class RainbowUtil { private int rainbowColor; + //Gradient with more than two colors. + public int rainbowProgress(int speed, int index, int... colors) { + int angle = (int) ((System.currentTimeMillis() / speed + index) % 360); + angle = (angle > 180 ? 360 - angle : angle) + 180; + int colorIndex = (int) (angle / 360f * colors.length); + if (colorIndex == colors.length) { + colorIndex--; + } + int color1 = colors[colorIndex]; + int color2 = colors[colorIndex == colors.length - 1 ? 0 : colorIndex + 1]; + return lerpColor(color1, color2, angle / 360f * colors.length - colorIndex); + } + public void updateRainbow() { double rainbowState = Math.ceil((System.currentTimeMillis() + 1) / 20.0); rainbowState %= 360; - rainbowColor = Color.getHSBColor((float) (rainbowState / 360.0f), 0.5f, 1f).getRGB(); + rainbowColor = Color.getHSBColor((float)(rainbowState / 360.0f), 0.5f, 1f).getRGB(); } public int getRainbowColor() { diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/ShaderUtil.java b/src/main/java/xyz/templecheats/templeclient/util/color/ShaderUtil.java new file mode 100644 index 00000000..4a0a98dd --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/ShaderUtil.java @@ -0,0 +1,114 @@ +package xyz.templecheats.templeclient.util.color; + +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.util.Globals; + +import java.awt.*; +import java.io.BufferedReader; +import java.io.InputStream; +import java.io.InputStreamReader; + +import static org.lwjgl.opengl.GL20.*; + +public class ShaderUtil implements Globals { + private final int programID; + + public ShaderUtil(String shader) { + int program = glCreateProgram(); + try { + int fragmentShaderID = createShader(mc.getResourceManager().getResource(new ResourceLocation("textures/shaders/" + shader + ".frag")).getInputStream(), GL_FRAGMENT_SHADER); + glAttachShader(program, fragmentShaderID); + + int vertexShaderID = createShader(mc.getResourceManager().getResource(new ResourceLocation("textures/shaders/vertex.vsh")).getInputStream(), GL_VERTEX_SHADER); + glAttachShader(program, vertexShaderID); + } catch (Exception ignored) { + } + + glLinkProgram(program); + int status = glGetProgrami(program, GL_LINK_STATUS); + + if (status == 0) { + throw new IllegalStateException("Shader failed to link!"); + } + this.programID = program; + } + + public void attachShader() { + glUseProgram(programID); + } + + public void releaseShader() { + glUseProgram(0); + } + + public void colorUniform(String name, Color color) { + setUniformf(name, color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f, color.getAlpha() / 255.0f); + } + + public void setUniformf(String name, float... args) { + int loc = glGetUniformLocation(programID, name); + switch (args.length) { + case 1: + glUniform1f(loc, args[0]); + break; + case 2: + glUniform2f(loc, args[0], args[1]); + break; + case 3: + glUniform3f(loc, args[0], args[1], args[2]); + break; + case 4: + glUniform4f(loc, args[0], args[1], args[2], args[3]); + break; + } + } + + public void setUniformi(String name, int... args) { + int loc = glGetUniformLocation(programID, name); + if (args.length > 1) { + glUniform2i(loc, args[0], args[1]); + } else { + glUniform1i(loc, args[0]); + } + } + + private int createShader(InputStream inputStream, int shaderType) { + int shader = glCreateShader(shaderType); + glShaderSource(shader, readInputStream(inputStream)); + glCompileShader(shader); + if (glGetShaderi(shader, GL_COMPILE_STATUS) == 0) { + throw new IllegalStateException(String.format("Shader (%s) failed to compile!", shaderType)); + } + return shader; + } + + + public String readInputStream(InputStream inputStream) { + StringBuilder stringBuilder = new StringBuilder(); + try { + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); + String line; + while ((line = bufferedReader.readLine()) != null) { + stringBuilder.append(line).append('\n'); + } + + } catch (Exception e) { + e.printStackTrace(); + } + return stringBuilder.toString(); + } + + public void render(float x, float y, float width, float height) { + GL11.glBegin(GL11.GL_QUADS); + GL11.glTexCoord2f(0.0f, 0.0f); + GL11.glVertex2f(x, y); + GL11.glTexCoord2f(0.0f, 1.0f); + GL11.glVertex2f(x, (y + height)); + GL11.glTexCoord2f(1.0f, 1.0f); + GL11.glVertex2f((x + width), (y + height)); + GL11.glTexCoord2f(1.0f, 0.0f); + GL11.glVertex2f((x + width), y); + GL11.glEnd(); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/impl/BlackShader.java b/src/main/java/xyz/templecheats/templeclient/util/color/impl/BlackShader.java new file mode 100644 index 00000000..27ad25db --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/impl/BlackShader.java @@ -0,0 +1,39 @@ +package xyz.templecheats.templeclient.util.color.impl; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.shader.Framebuffer; +import xyz.templecheats.templeclient.util.color.ShaderUtil; +import xyz.templecheats.templeclient.util.Globals; +import xyz.templecheats.templeclient.util.render.RenderUtil; + +import static org.lwjgl.opengl.GL11.*; +import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D; + +public class BlackShader implements Globals { + private final static ShaderUtil shader = new ShaderUtil("black"); + private static Framebuffer framebuffer = new Framebuffer(1, 1, false); + + public static void setupUniforms() { + shader.setUniformi("texture", 0); + } + + public static void setup() { + GlStateManager.enableBlend(); + GlStateManager.color(1, 1, 1, 1); + GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); + + framebuffer = RenderUtil.createFrameBuffer(framebuffer); + + mc.getFramebuffer().bindFramebuffer(true); + shader.attachShader(); + setupUniforms(); + + glBindTexture(GL_TEXTURE_2D, framebuffer.framebufferTexture); + } + + public static void finish() { + shader.releaseShader(); + GlStateManager.color(1, 1, 1, 1); + GlStateManager.bindTexture(0); + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/impl/GradientShader.java b/src/main/java/xyz/templecheats/templeclient/util/color/impl/GradientShader.java new file mode 100644 index 00000000..022f9879 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/impl/GradientShader.java @@ -0,0 +1,66 @@ +package xyz.templecheats.templeclient.util.color.impl; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.shader.Framebuffer; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.util.Globals; +import xyz.templecheats.templeclient.util.color.ShaderUtil; +import xyz.templecheats.templeclient.util.render.RenderUtil; + +import java.awt.*; + +import static org.lwjgl.opengl.GL11.*; + +public class GradientShader implements Globals { + private final static ShaderUtil shader = new ShaderUtil("gradient"); + private static Framebuffer framebuffer = new Framebuffer(1, 1, false); + + public static void setupUniforms(final float step, final float speed, final Color color, final Color color2, final float opacity) { + shader.setUniformi("texture", 0); + shader.setUniformf("rgb", color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f); + shader.setUniformf("rgb1", color2.getRed() / 255.0f, color2.getGreen() / 255.0f, color2.getBlue() / 255.0f); + shader.setUniformf("step", 300 * step); + shader.setUniformf("offset", (float) ((((double) System.currentTimeMillis() * (double) speed) % (mc.displayWidth * mc.displayHeight)) / 10.0f)); + shader.setUniformf("mix", opacity); + } + + public static void setup() { + setup(Colors.INSTANCE.step.floatValue(), Colors.INSTANCE.speed.floatValue(), Colors.INSTANCE.getGradient()[0], Colors.INSTANCE.getGradient()[1]); + } + + public static void setup(final float opacity) { + setup(Colors.INSTANCE.step.floatValue(), Colors.INSTANCE.speed.floatValue(), Colors.INSTANCE.getGradient()[0], Colors.INSTANCE.getGradient()[1], opacity); + } + + public static void setup(final float step, final float speed, final Color color, final Color color2) { + setup(step, speed, color, color2, 1.0f); + } + + public static void setup(final float step, final float speed, final Color color, final Color color2, final float opacity) { + RenderUtil.bindBlank(); + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.color(1, 1, 1, 1); + //GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); + + framebuffer = RenderUtil.createFrameBuffer(framebuffer); + + mc.getFramebuffer().bindFramebuffer(true); + shader.attachShader(); + setupUniforms(step, speed, color, color2, opacity); + + GlStateManager.bindTexture(GL_TEXTURE_2D); + //glBindTexture(GL_TEXTURE_2D, framebuffer.framebufferTexture); + } + + public static void finish() { + shader.releaseShader(); + GlStateManager.color(1, 1, 1, 1); + GlStateManager.bindTexture(0); + //glBindTexture(0, framebuffer.framebufferTexture); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/impl/RectBuilder.java b/src/main/java/xyz/templecheats/templeclient/util/color/impl/RectBuilder.java new file mode 100644 index 00000000..dc15c345 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/impl/RectBuilder.java @@ -0,0 +1,140 @@ +package xyz.templecheats.templeclient.util.color.impl; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.util.color.ShaderUtil; +import xyz.templecheats.templeclient.util.math.Quad; +import xyz.templecheats.templeclient.util.math.Vec2d; + +import java.awt.*; + +import static net.minecraft.client.renderer.GlStateManager.resetColor; +import static org.lwjgl.opengl.GL11.*; + +public class RectBuilder { + private final Vec2d pos1; + private final Vec2d pos2; + private final static ShaderUtil rectShader = new ShaderUtil("rect"); + private Quad colorIn = new Quad<>(Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE); + private Quad colorOut = new Quad<>(Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE); + private float roundRadius = 0.0f; + private float outlineWidth = 0.0f; + + public RectBuilder(Vec2d pos1, Vec2d pos2) { + this.pos1 = pos1; + this.pos2 = pos2; + } + + public void draw(RectBuilder block) { + block.draw(); + } + + // region color + public RectBuilder color(Color leftTop, Color rightTop, Color leftBottom, Color rightBottom) { + this.colorIn = new Quad<>(leftTop, rightTop, leftBottom, rightBottom); + return this; + } + + public RectBuilder color(Color color) { + return color(color, color, color, color); + } + + public RectBuilder colorV(Color top, Color bottom) { + return color(top, top, bottom, bottom); + } + + public RectBuilder colorH(Color left, Color right) { + return color(left, right, left, right); + } + // endregion + + // region outlineColor + public RectBuilder outlineColor(Color leftTop, Color rightTop, Color leftBottom, Color rightBottom) { + colorOut = new Quad<>(leftTop, rightTop, leftBottom, rightBottom); + return this; + } + + public RectBuilder outlineColor(Color color) { + return outlineColor(color, color, color, color); + } + + public RectBuilder outlineColorV(Color top, Color bottom) { + return outlineColor(top, top, bottom, bottom); + } + + public RectBuilder outlineColorH(Color left, Color right) { + return outlineColor(left, right, left, right); + } + // endregion + + public RectBuilder radius(double value) { + roundRadius = (float) value; + return this; + } + + public RectBuilder width(double value) { + outlineWidth = (float) value; + return this; + } + + public RectBuilder draw() { + Minecraft mc = Minecraft.getMinecraft(); + ScaledResolution sr = new ScaledResolution(mc); + + float x1 = (float) pos1.x; + float y1 = (float) pos1.y; + float x2 = (float) pos2.x; + float y2 = (float) pos2.y; + + if (x1 > x2) { + float i = x1; + x1 = x2; + x2 = i; + } + + if (y1 > y2) { + float j = y1; + y1 = y2; + y2 = j; + } + + float x = x1; + float y = y1; + float width = x2 - x1; + float height = y2 - y1; + float scale = sr.getScaleFactor(); + float radius = Math.min(roundRadius, Math.min(width, height) / 2.0f); + + resetColor(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL_ALPHA_TEST); + + rectShader.attachShader(); + rectShader.setUniformf("size", width * scale, height * scale); + rectShader.setUniformf("roundRadius", radius * scale); + rectShader.setUniformf("smoothFactor", 1.2f); + rectShader.setUniformf("outlineWidth", outlineWidth * scale); + + rectShader.colorUniform("colorIn1", colorIn.getFirst()); + rectShader.colorUniform("colorIn2", colorIn.getThird()); + rectShader.colorUniform("colorIn3", colorIn.getSecond()); + rectShader.colorUniform("colorIn4", colorIn.getFourth()); + + rectShader.colorUniform("colorOut1", colorOut.getFirst()); + rectShader.colorUniform("colorOut2", colorOut.getThird()); + rectShader.colorUniform("colorOut3", colorOut.getSecond()); + rectShader.colorUniform("colorOut4", colorOut.getFourth()); + + float s = 0.4f; + rectShader.render(x - s, y - s, width + s * 2.0f, height + s * 2.0f); + rectShader.releaseShader(); + + GL11.glEnable(GL_ALPHA_TEST); + GlStateManager.disableBlend(); + + return this; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/color/impl/RoundedTexture.java b/src/main/java/xyz/templecheats/templeclient/util/color/impl/RoundedTexture.java new file mode 100644 index 00000000..87a24250 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/color/impl/RoundedTexture.java @@ -0,0 +1,38 @@ +package xyz.templecheats.templeclient.util.color.impl; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import xyz.templecheats.templeclient.util.color.ShaderUtil; + +import static net.minecraft.client.renderer.GlStateManager.resetColor; +import static org.lwjgl.opengl.GL11.*; + +public class RoundedTexture { + + private final static ShaderUtil rectTexture = new ShaderUtil("roundedtex"); + + public void drawRoundTextured(float x, float y, float width, float height, float radius, float alpha) { + resetColor(); + GlStateManager.enableAlpha(); + GlStateManager.alphaFunc(GL_GREATER, (float) (0 * .01)); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + rectTexture.attachShader(); + rectTexture.setUniformi("textureIn", 0); + setupRoundedRectUniforms(x, y, width, height, radius, rectTexture); + rectTexture.setUniformf("alpha", alpha); + rectTexture.render(x - 1, y - 1, width + 2, height + 2); + rectTexture.releaseShader(); + GlStateManager.disableBlend(); + } + + + private void setupRoundedRectUniforms(float x, float y, float width, float height, float radius, ShaderUtil roundedTexturedShader) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + roundedTexturedShader.setUniformf("location", x * sr.getScaleFactor(), (Minecraft.getMinecraft().displayHeight - (height * sr.getScaleFactor())) - (y * sr.getScaleFactor())); + roundedTexturedShader.setUniformf("rectSize", width * sr.getScaleFactor(), height * sr.getScaleFactor()); + roundedTexturedShader.setUniformf("radius", radius * sr.getScaleFactor()); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/friend/FriendManager.java b/src/main/java/xyz/templecheats/templeclient/util/friend/FriendManager.java index 7deaec51..3148ea22 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/friend/FriendManager.java +++ b/src/main/java/xyz/templecheats/templeclient/util/friend/FriendManager.java @@ -4,10 +4,10 @@ import java.util.List; public class FriendManager { - private List friends; + private List < Friend > friends; public FriendManager() { - this.friends = new ArrayList<>(); + this.friends = new ArrayList < > (); } public void addFriend(String name) { @@ -22,7 +22,7 @@ public boolean isFriend(String name) { return this.friends.stream().anyMatch(friend -> friend.getName().equalsIgnoreCase(name)); } - public List getFriends() { + public List < Friend > getFriends() { return this.friends; } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/keys/KeyUtil.java b/src/main/java/xyz/templecheats/templeclient/util/keys/KeyUtil.java index e73d3c70..d125cbb8 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/keys/KeyUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/keys/KeyUtil.java @@ -5,7 +5,7 @@ import net.minecraftforge.fml.common.gameevent.InputEvent; import org.lwjgl.input.Keyboard; import xyz.templecheats.templeclient.features.gui.clickgui.basic.ClickGuiScreen; -import xyz.templecheats.templeclient.features.gui.clickgui.csgo.ClientCsgoGuiScreen; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.CsgoGuiScreen; import xyz.templecheats.templeclient.features.gui.clickgui.hud.HudEditorScreen; import xyz.templecheats.templeclient.features.module.modules.client.ClickGUI; import xyz.templecheats.templeclient.features.module.modules.client.HUD; @@ -21,7 +21,7 @@ public void onKeyInput(InputEvent.KeyInputEvent e) { if (ClickGUI.INSTANCE.theme.value() != ClickGUI.Theme.CSGO) { Minecraft.getMinecraft().displayGuiScreen(ClickGuiScreen.getInstance()); } else { - Minecraft.getMinecraft().displayGuiScreen(ClientCsgoGuiScreen.getInstance()); + Minecraft.getMinecraft().displayGuiScreen(CsgoGuiScreen.getInstance()); } return; } @@ -30,8 +30,8 @@ public void onKeyInput(InputEvent.KeyInputEvent e) { Minecraft.getMinecraft().displayGuiScreen(HudEditorScreen.getInstance()); return; } - + ModuleManager.keyPress(key); } } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/system/MathUtil.java b/src/main/java/xyz/templecheats/templeclient/util/math/MathUtil.java similarity index 80% rename from src/main/java/xyz/templecheats/templeclient/util/system/MathUtil.java rename to src/main/java/xyz/templecheats/templeclient/util/math/MathUtil.java index f39dacd8..92136143 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/system/MathUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/math/MathUtil.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.util.system; +package xyz.templecheats.templeclient.util.math; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -10,10 +10,6 @@ import java.math.BigDecimal; import java.math.RoundingMode; - -/** - * This math util is pasted because I don't fuck with java math. - */ public final class MathUtil { public static final Minecraft mc = Minecraft.getMinecraft(); @@ -23,13 +19,16 @@ public static Vec3d interpolateEntity(Entity entity, float time) { entity.lastTickPosY + (entity.posY - entity.lastTickPosY) * time, entity.lastTickPosZ + (entity.posZ - entity.lastTickPosZ) * time); } - + public static float gaussian(float x, float s) { + double output = 1.0 / Math.sqrt(2.0 * Math.PI * (s * s)); + return (float)(output * Math.exp(-(x * x) / (2.0 * (s * s)))); + } public static double radToDeg(double rad) { - return rad * (float) (180.0f / Math.PI); + return rad * (float)(180.0f / Math.PI); } public static double degToRad(double deg) { - return deg * (float) (Math.PI / 180.0f); + return deg * (float)(Math.PI / 180.0f); } public static Vec3d direction(float yaw) { @@ -43,11 +42,13 @@ public static float[] calcAngle(Vec3d from, Vec3d to) { final double dist = MathHelper.sqrt(difX * difX + difZ * difZ); - return new float[]{(float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difZ, difX)) - 90.0f), (float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difY, dist)))}; + return new float[] { + (float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difZ, difX)) - 90.0f), (float) MathHelper.wrapDegrees(Math.toDegrees(Math.atan2(difY, dist))) + }; } public static EnumFacing calcSide(BlockPos pos) { - for (EnumFacing side : EnumFacing.values()) { + for (EnumFacing side: EnumFacing.values()) { BlockPos sideOffset = pos.offset(side); IBlockState offsetState = mc.world.getBlockState(sideOffset); if (!offsetState.getBlock().canCollideCheck(offsetState, false)) continue; @@ -81,7 +82,14 @@ public static double[] directionSpeed(double speed) { final double cos = Math.cos(Math.toRadians(yaw + 90)); final double posX = (forward * speed * cos + side * speed * sin); final double posZ = (forward * speed * sin - side * speed * cos); - return new double[]{posX, posZ}; + return new double[] { + posX, + posZ + }; + } + + public static float random(float min, float max) { + return (float) (Math.random() * (max - min) + min); } public static Vec3d mult(Vec3d factor, Vec3d multiplier) { @@ -107,6 +115,10 @@ public static double round(double value, int places) { return new BigDecimal(value).setScale(places, RoundingMode.HALF_UP).doubleValue(); } + public static double normalize(double value, double minIn, double maxIn, double minOut, double maxOut) { + return lerp((float) minOut, (float) maxOut, (float) ((value - minIn) / (maxIn - minIn))); + } + public static float clamp(float val, float min, float max) { if (val <= min) { val = min; @@ -120,9 +132,9 @@ public static float clamp(float val, float min, float max) { public static float wrap(float val) { val = val % 360.0f; if (val >= 180.0f) - val -= 360.0f; + val -= 360.0f; if (val < -180.0f) - val += 360.0f; + val += 360.0f; return val; } @@ -166,7 +178,12 @@ public static double[] calcIntersection(double[] line, double[] line2) { final double delta = a1 * b2 - a2 * b1; - return new double[]{(b2 * c1 - b1 * c2) / delta, (a1 * c2 - a2 * c1) / delta}; + return new double[] { + (b2 * c1 - b1 * c2) / delta, (a1 * c2 - a2 * c1) / delta + }; + } + public static float lerp(float current, float target, float lerp) { + current -= (current - target) * clamp(lerp, 0, 1); + return current; } - } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/math/Quad.java b/src/main/java/xyz/templecheats/templeclient/util/math/Quad.java new file mode 100644 index 00000000..b2edfcb3 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/math/Quad.java @@ -0,0 +1,56 @@ +package xyz.templecheats.templeclient.util.math; + +public class Quad { + private final T first; + private final T second; + private final T third; + private final T fourth; + + public Quad(T first, T second, T third, T fourth) { + this.first = first; + this.second = second; + this.third = third; + this.fourth = fourth; + } + + public T getFirst() { + return first; + } + + public T getSecond() { + return second; + } + + public T getThird() { + return third; + } + + public T getFourth() { + return fourth; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (obj == null || getClass() != obj.getClass()) return false; + Quad quad = (Quad) obj; + return first.equals(quad.first) && + second.equals(quad.second) && + third.equals(quad.third) && + fourth.equals(quad.fourth); + } + + @Override + public int hashCode() { + int result = first.hashCode(); + result = 31 * result + second.hashCode(); + result = 31 * result + third.hashCode(); + result = 31 * result + fourth.hashCode(); + return result; + } + + @Override + public String toString() { + return "Quad{" + "first=" + first + ", second=" + second + ", third=" + third + ", fourth=" + fourth + '}'; + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/math/Vec2d.java b/src/main/java/xyz/templecheats/templeclient/util/math/Vec2d.java new file mode 100644 index 00000000..f8044677 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/math/Vec2d.java @@ -0,0 +1,77 @@ +package xyz.templecheats.templeclient.util.math; + +import net.minecraft.util.math.Vec2f; +public class Vec2d { + public final double x; + public final double y; + + public Vec2d(double x, double y) { + this.x = x; + this.y = y; + } + + public Vec2d(int x, int y) { + this.x = (double) x; + this.y = (double) y; + } + + public Vec2d div(Vec2d vec2d) { + return div(vec2d.x, vec2d.y); + } + + public Vec2d div(double divider) { + return div(divider, divider); + } + + public Vec2d div(double x, double y) { + return new Vec2d(this.x / x, this.y / y); + } + + public Vec2d times(Vec2d vec2d) { + return times(vec2d.x, vec2d.y); + } + + public Vec2d times(double multiplier) { + return times(multiplier, multiplier); + } + + public Vec2d times(double x, double y) { + return new Vec2d(this.x * x, this.y * y); + } + + public Vec2d minus(Vec2d vec2d) { + return minus(vec2d.x, vec2d.y); + } + + public Vec2d minus(double sub) { + return minus(sub, sub); + } + + public Vec2d minus(double x, double y) { + return new Vec2d(this.x - x, this.y - y); + } + + public Vec2d plus(Vec2d vec2d) { + return plus(vec2d.x, vec2d.y); + } + + public Vec2d plus(double add) { + return plus(add, add); + } + + public Vec2d plus(double x, double y) { + return new Vec2d(this.x + x, this.y + y); + } + + public Vec2f toVec2f() { + return new Vec2f((float) x, (float) y); + } + + @Override + public String toString() { + return "Vec2d[" + x + ", " + y + "]"; + } + + public static final Vec2d ZERO = new Vec2d(0.0, 0.0); +} + diff --git a/src/main/java/xyz/templecheats/templeclient/util/player/PlayerUtil.java b/src/main/java/xyz/templecheats/templeclient/util/player/PlayerUtil.java index 5116e8b2..bfad26af 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/player/PlayerUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/player/PlayerUtil.java @@ -13,10 +13,10 @@ public static float[] getPlayerFacingRotations(double posX, double posY, double double deltaX = posX - mc.player.posX; double deltaY = posY - mc.player.posY - mc.player.getEyeHeight(); double deltaZ = posZ - mc.player.posZ; - double deltaGround = Math.sqrt(deltaX*deltaX + deltaZ*deltaZ); + double deltaGround = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ); - float pitch = (float) - Math.toDegrees(Math.atan(deltaY/deltaGround)); - float yaw = (float) - Math.toDegrees(Math.atan(deltaX/deltaZ)); + float pitch = (float) - Math.toDegrees(Math.atan(deltaY / deltaGround)); + float yaw = (float) - Math.toDegrees(Math.atan(deltaX / deltaZ)); if (deltaZ <= 0) { if (deltaX > 0) { @@ -26,7 +26,10 @@ public static float[] getPlayerFacingRotations(double posX, double posY, double } } - return new float[] {pitch, yaw}; + return new float[] { + pitch, + yaw + }; } public static double[] getPlayerMoveVec() { @@ -37,7 +40,10 @@ public static double[] getPlayerMoveVec() { float strafe = mc.player.moveStrafing; if (forward == 0 && strafe == 0) { - return new double[] {0, 0}; + return new double[] { + 0, + 0 + }; } if (forward > 0) { @@ -66,7 +72,9 @@ public static double[] getPlayerMoveVec() { } } - return new double[] {-Math.sin(Math.toRadians(yaw)), Math.cos(Math.toRadians(yaw))}; + return new double[] { + -Math.sin(Math.toRadians(yaw)), Math.cos(Math.toRadians(yaw)) + }; } public static void swapContainerItems(int slot1, int slot2) { diff --git a/src/main/java/xyz/templecheats/templeclient/util/render/Easing.java b/src/main/java/xyz/templecheats/templeclient/util/render/Easing.java new file mode 100644 index 00000000..75605cbe --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/render/Easing.java @@ -0,0 +1,50 @@ +/* + * This Easing was made by LavaHack, and was rewritten in java. + */ +package xyz.templecheats.templeclient.util.render; + +import java.util.function.DoubleUnaryOperator; + +import static java.lang.Math.sqrt; +import static java.lang.StrictMath.pow; +public enum Easing { + LINEAR(x -> x), + IN_SINE(x -> 1 - Math.cos((x * Math.PI) / 2)), + OUT_SINE(x -> Math.sin((x * Math.PI) / 2)), + IN_OUT_SINE(x -> -(Math.cos(Math.PI * x) - 1) / 2), + IN_QUAD(x -> x * x), + OUT_QUAD(x -> 1 - (1 - x) * (1 - x)), + IN_OUT_QUAD(x -> x < 0.5 ? 2 * x * x : 1 - Math.pow(-2 * x + 2, 2) / 2), + IN_CUBIC(x -> x * x * x), + OUT_CUBIC(x -> 1 - Math.pow(1 - x, 3)), + IN_OUT_CUBIC(x -> x < 0.5 ? 4 * x * x * x : 1 - Math.pow(-2 * x + 2, 3) / 2), + InQuart(it -> it * it * it * it), + OutQuart(it -> 1.0 - pow(1.0 - it, 4)), + InOutQuart(it -> it < 0.5 ? 8 * pow(it, 4) : 1.0 - pow(-2 * it + 2, 4) / 2), + InQuint(it -> it * it * it * it * it), + OutQuint(it -> 1.0 - pow(1.0 - it, 5)), + InOutQuint(it -> it < 0.5 ? 16 * pow(it, 5) : 1.0 - pow(-2 * it + 2, 5) / 2), + InExpo(it -> it == 0.0 ? 0.0 : pow(2, 10 * it - 10)), + OutExpo(it -> it == 1.0 ? 1.0 : 1.0 - pow(2, -10 * it)), + InOutExpo(it -> it == 0.0 || it == 1.0 ? it : it < 0.5 ? pow(2, 20 * it - 10) / 2 : (2 - pow(2, -20 * it + 10)) / 2), + InCircle(it -> 1.0 - sqrt(1.0 - it * it)), + OutCircle(it -> sqrt(1.0 - pow(it - 1.0, 2))), + InOutCircle(it -> it < 0.5 ? (1.0 - sqrt(1.0 - 2 * it * 2 * it)) / 2 : (sqrt(1.0 - pow(-2 * it + 2, 2)) + 1) / 2.0), + InSin(Math::sin), + OutSin(it -> 1.0 - Math.sin(1.0 - it)); + + private final DoubleUnaryOperator function; + + Easing(DoubleUnaryOperator function) { + this.function = function; + } + + public double inc(double value) { + double x = Math.min(Math.max(value, 0.0), 1.0); + return function.applyAsDouble(x); + } + + public double dec(double value) { + return 1.0 - inc(value); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/render/RenderUtil.java b/src/main/java/xyz/templecheats/templeclient/util/render/RenderUtil.java index 431499cf..d4bc116f 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/render/RenderUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/render/RenderUtil.java @@ -1,164 +1,150 @@ package xyz.templecheats.templeclient.util.render; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.inventory.GuiInventory; -import net.minecraft.client.renderer.BufferBuilder; -import net.minecraft.client.renderer.GlStateManager; -import net.minecraft.client.renderer.RenderGlobal; -import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.entity.AbstractClientPlayer; import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.client.shader.Framebuffer; +import net.minecraft.client.renderer.*; import net.minecraft.entity.Entity; -import net.minecraft.entity.EntityLivingBase; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.ResourceLocation; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import org.lwjgl.opengl.GL11; +import xyz.templecheats.templeclient.features.module.modules.client.Colors; +import xyz.templecheats.templeclient.mixins.accessor.IMixinRenderManager; +import xyz.templecheats.templeclient.util.Globals; +import xyz.templecheats.templeclient.util.math.Vec2d; -public class RenderUtil { +import static org.lwjgl.opengl.GL11.*; + +import java.awt.*; + +public class RenderUtil implements Globals { + public static final IMixinRenderManager renderManager = (IMixinRenderManager) mc.getRenderManager(); + private static final ResourceLocation blank = new ResourceLocation("textures/blank.png"); + public static final Color transparent = new Color(0, 0, 0, 0); + + /** + * Renders + */ public static void trace(Minecraft mc, Entity e, float partialTicks, int mode, float red, float green, float blue) { if (mc.getRenderManager().renderViewEntity != null) { - GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glDisable(GL11.GL_LIGHTING); - GL11.glLineWidth(2F); + glDisable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glLineWidth(2F); - GL11.glPushMatrix(); - GL11.glDepthMask(false); - GL11.glColor4d(0, 0, 1, 1); + glPushMatrix(); + glDepthMask(false); + glColor4d(0, 0, 1, 1); - GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glBegin(GL11.GL_LINES); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glDisable(GL_TEXTURE_2D); + glBegin(GL_LINES); - GL11.glColor4d(red, green, blue, 1); + glColor4d(red, green, blue, 1); RenderManager renderManager = mc.getRenderManager(); Vec3d v = new Vec3d(0.0D, 0.0D, 1.0D).rotatePitch(-((float) Math.toRadians((double) mc.player.rotationPitch))).rotateYaw(-((float) Math.toRadians((double) mc.player.rotationYaw))); - GL11.glVertex3d(v.x, mc.player.getEyeHeight() + v.y, v.z); + glVertex3d(v.x, mc.player.getEyeHeight() + v.y, v.z); double x = e.lastTickPosX + (e.posX - e.lastTickPosX) * partialTicks; double y = e.lastTickPosY + (e.posY - e.lastTickPosY) * partialTicks; double z = e.lastTickPosZ + (e.posZ - e.lastTickPosZ) * partialTicks; - GL11.glVertex3d(x - renderManager.viewerPosX, y - renderManager.viewerPosY + 0.25, z - renderManager.viewerPosZ); + glVertex3d(x - renderManager.viewerPosX, y - renderManager.viewerPosY + 0.25, z - renderManager.viewerPosZ); - GL11.glEnd(); - GL11.glDepthMask(true); - GL11.glEnable(GL11.GL_DEPTH_TEST); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glColor4d(1.0, 1.0, 1.0, 1.0); - GL11.glPopMatrix(); + glEnd(); + glDepthMask(true); + glEnable(GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glColor4d(1.0, 1.0, 1.0, 1.0); + glPopMatrix(); } } + public static void FillOnlyLine(Entity entity, AxisAlignedBB box) { - GL11.glBlendFunc(770, 771); - GL11.glEnable(GL11.GL_BLEND); - GL11.glLineWidth(2.0F); - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glDepthMask(false); + glBlendFunc(770, 771); + glEnable(GL_BLEND); + glLineWidth(2.0F); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); RenderGlobal.drawSelectionBoundingBox(box, 1, 0, 0, 1); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glEnable(GL11.GL_DEPTH_TEST); - GL11.glDepthMask(true); - GL11.glDisable(GL11.GL_BLEND); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + glDisable(GL_BLEND); } public static void FillOnlyLinePlayerESP(Entity entity, AxisAlignedBB box, float r, float g, float b) { - GL11.glBlendFunc(770, 771); - GL11.glEnable(GL11.GL_BLEND); - GL11.glLineWidth(2.0F); - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glDepthMask(false); + glPushMatrix(); + glBlendFunc(770, 771); + glEnable(GL_BLEND); + glLineWidth(2.0F); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDepthMask(false); RenderGlobal.drawSelectionBoundingBox(box, r, g, b, 1); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glEnable(GL11.GL_DEPTH_TEST); - GL11.glDepthMask(true); - GL11.glDisable(GL11.GL_BLEND); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDepthMask(true); + glDisable(GL_BLEND); + glPopMatrix(); } + public static void blockESP(BlockPos blockPos) { - GL11.glPushMatrix(); + glPushMatrix(); double x = - blockPos.getX() - - Minecraft.getMinecraft().getRenderManager().viewerPosX; + blockPos.getX() - + Minecraft.getMinecraft().getRenderManager().viewerPosX; double y = - blockPos.getY() - - Minecraft.getMinecraft().getRenderManager().viewerPosY; + blockPos.getY() - + Minecraft.getMinecraft().getRenderManager().viewerPosY; double z = - blockPos.getZ() - - Minecraft.getMinecraft().getRenderManager().viewerPosZ; + blockPos.getZ() - + Minecraft.getMinecraft().getRenderManager().viewerPosZ; - GL11.glBlendFunc(770, 771); - GL11.glEnable(GL11.GL_BLEND); + glBlendFunc(770, 771); + glEnable(GL_BLEND); - GL11.glDisable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_DEPTH_TEST); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); - GL11.glDepthMask(false); + glDepthMask(false); RenderGlobal.renderFilledBox(new AxisAlignedBB(x, y, z, x + 1.0, y + 1.0, z + 1.0), 1, 1, 0, 0.5F); - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glEnable(GL11.GL_DEPTH_TEST); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); - GL11.glDepthMask(true); + glDepthMask(true); - GL11.glDisable(GL11.GL_BLEND); - GL11.glPopMatrix(); - } - - public static void blockESP(BlockPos blockPos, boolean fill, boolean outline, boolean depthTest, float r, float g, float b) { - GL11.glPushMatrix(); - GL11.glBlendFunc(770, 771); - GL11.glEnable(GL11.GL_BLEND); - GL11.glDisable(GL11.GL_TEXTURE_2D); - - if(depthTest) { - GL11.glDisable(GL11.GL_DEPTH_TEST); - GL11.glDepthMask(false); - } - - double x = blockPos.getX() - Minecraft.getMinecraft().getRenderManager().viewerPosX; - double y = blockPos.getY() - Minecraft.getMinecraft().getRenderManager().viewerPosY; - double z = blockPos.getZ() - Minecraft.getMinecraft().getRenderManager().viewerPosZ; - final AxisAlignedBB box = new AxisAlignedBB(x - 0.0001, y - 0.0001, z - 0.0001, x + 1.0001, y + 1.0001, z + 1.0001); - if(fill) { - RenderGlobal.renderFilledBox(box, r, g, b, 0.5F); - } - if(outline) { - RenderGlobal.drawSelectionBoundingBox(box, r, g, b, 1); - } - - if(depthTest) { - GL11.glDepthMask(true); - GL11.glEnable(GL11.GL_DEPTH_TEST); - } - - GL11.glEnable(GL11.GL_TEXTURE_2D); - GL11.glDisable(GL11.GL_BLEND); - GL11.glPopMatrix(); + glDisable(GL_BLEND); + glPopMatrix(); } /** - * Stuff below here is all for exeter gui + * ClickGUI */ public static void drawRect(float left, float top, float right, float bottom, int color) { - if(left < right) { + if (left < right) { float i = left; left = right; right = i; } - if(top < bottom) { + if (top < bottom) { float j = top; top = bottom; bottom = j; @@ -184,10 +170,11 @@ public static void drawRect(float left, float top, float right, float bottom, in GlStateManager.disableBlend(); } - public static void drawGradientRect(float left, float top, float right, float bottom, int startColor, int endColor) { + public static void drawGradientRect(float left, float top, float right, float bottom, int startColor, + int endColor) { float f = (float) (startColor >> 24 & 255) / 255.0F; float f1 = (float) (startColor >> 16 & 255) / 255.0F; - float f2 = (float) (startColor >> 8 & 255) / 255.0F; + float f2 = (float) (startColor >> 8 & 255) / 255.F; float f3 = (float) (startColor & 255) / 255.0F; float f4 = (float) (endColor >> 24 & 255) / 255.0F; float f5 = (float) (endColor >> 16 & 255) / 255.0F; @@ -212,7 +199,8 @@ public static void drawGradientRect(float left, float top, float right, float bo GlStateManager.enableTexture2D(); } - public static void drawHorizontalGradientRect(float left, float top, float right, float bottom, int startColor, int endColor) { + public static void drawHorizontalGradientRect(float left, float top, float right, float bottom, + int startColor, int endColor) { float f = (float) (startColor >> 24 & 255) / 255.0F; float f1 = (float) (startColor >> 16 & 255) / 255.0F; float f2 = (float) (startColor >> 8 & 255) / 255.0F; @@ -239,33 +227,432 @@ public static void drawHorizontalGradientRect(float left, float top, float right GlStateManager.enableAlpha(); GlStateManager.enableTexture2D(); } - public static void drawHorizontalLine(float startX, float endX, float y, int color) { - drawRect(startX, y, endX + 1, y + 1, color); + + public static void drawOutBorderedRect(int left, int top, int right, int bottom, int borderWidth, int color) { + RenderUtil.drawRect(left - borderWidth, top - borderWidth, right + borderWidth, top, color); + RenderUtil.drawRect(left - borderWidth, bottom, right + borderWidth, bottom + borderWidth, color); + RenderUtil.drawRect(left - borderWidth, top - borderWidth, left, bottom + borderWidth, color); + RenderUtil.drawRect(right, top - borderWidth, right + borderWidth, bottom + borderWidth, color); + } + + public static void drawInBorderedRect(int left, int top, int right, int bottom, int borderWidth, int color) { + RenderUtil.drawRect(left + borderWidth, top + borderWidth, right - borderWidth, top, color); + RenderUtil.drawRect(left + borderWidth, bottom, right - borderWidth, bottom - borderWidth, color); + RenderUtil.drawRect(left + borderWidth, top + borderWidth, left, bottom - borderWidth, color); + RenderUtil.drawRect(right, top + borderWidth, right - borderWidth, bottom - borderWidth, color); + } + + /** + * Shaders + */ + + public static void outlineShader(final BlockPos pos) { + if (pos != null) { + final AxisAlignedBB bb = new AxisAlignedBB(pos); + outlineShader(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); + } } - public static void drawVerticalLine(float x, final float startY, float endY, int color) { - drawRect(x, startY + 1, x + 1, endY, color); + public static void outlineShader(final double minX, final double minY, final double minZ, final double maxX, + final double maxY, final double maxZ) { + final AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(RenderUtil.renderOffset()); + bindBlank(); + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glLineWidth(1.5f); + glColor(Colors.INSTANCE.getColor()); + glBegin(GL_LINE_STRIP); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.maxZ); + glVertex3d(bb.minX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.minX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.minZ); + glVertex3d(bb.maxX, bb.minY, bb.minZ); + glVertex3d(bb.maxX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glEnd(); + glColor(Color.WHITE); + glLineWidth(1.0f); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glPopMatrix(); } - public static void drawBorderedRectReliant(float x, float y, float x1, float y1, float lineWidth, int inside, int border) { - drawRect(x, y, x1, y1, inside); + public static void outlineFaceShader(final BlockPos pos, EnumFacing face, Color color) { + if (pos != null) { + final AxisAlignedBB bb = new AxisAlignedBB(pos).offset(RenderUtil.renderOffset()); + bindBlank(); + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor(color); + + glBegin(GL_LINES); + switch (face) { + case DOWN: + case UP: + double y = (face == EnumFacing.DOWN) ? bb.minY : bb.maxY; + glVertex3d(bb.minX, y, bb.minZ); + glVertex3d(bb.maxX, y, bb.minZ); + glVertex3d(bb.maxX, y, bb.minZ); + glVertex3d(bb.maxX, y, bb.maxZ); + glVertex3d(bb.maxX, y, bb.maxZ); + glVertex3d(bb.minX, y, bb.maxZ); + glVertex3d(bb.minX, y, bb.maxZ); + glVertex3d(bb.minX, y, bb.minZ); + break; + case NORTH: + case SOUTH: + double z = (face == EnumFacing.NORTH) ? bb.minZ : bb.maxZ; + glVertex3d(bb.minX, bb.minY, z); + glVertex3d(bb.maxX, bb.minY, z); + glVertex3d(bb.maxX, bb.minY, z); + glVertex3d(bb.maxX, bb.maxY, z); + glVertex3d(bb.maxX, bb.maxY, z); + glVertex3d(bb.minX, bb.maxY, z); + glVertex3d(bb.minX, bb.maxY, z); + glVertex3d(bb.minX, bb.minY, z); + break; + case WEST: + case EAST: + double x = (face == EnumFacing.WEST) ? bb.minX : bb.maxX; + glVertex3d(x, bb.minY, bb.minZ); + glVertex3d(x, bb.maxY, bb.minZ); + glVertex3d(x, bb.maxY, bb.minZ); + glVertex3d(x, bb.maxY, bb.maxZ); + glVertex3d(x, bb.maxY, bb.maxZ); + glVertex3d(x, bb.minY, bb.maxZ); + glVertex3d(x, bb.minY, bb.maxZ); + glVertex3d(x, bb.minY, bb.minZ); + break; + } + glEnd(); + + glColor(Color.WHITE); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glPopMatrix(); + } } - public static void drawGradientBorderedRectReliant(float x, float y, float x1, float y1, float lineWidth, int border, int bottom, int top) { - drawGradientRect(x, y, x1, y1, top, bottom); + public static void boxShader(final BlockPos pos) { + if (pos != null) { + final AxisAlignedBB bb = new AxisAlignedBB(pos); + boxShader(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ); + } } - public static void drawOutBorderedRect(int left, int top, int right, int bottom, int borderWidth, int color) { - RenderUtil.drawRect(left-borderWidth, top-borderWidth, right+borderWidth, top, color); - RenderUtil.drawRect(left-borderWidth, bottom, right+borderWidth, bottom+borderWidth, color); - RenderUtil.drawRect(left-borderWidth, top-borderWidth, left, bottom+borderWidth, color); - RenderUtil.drawRect(right, top-borderWidth, right+borderWidth, bottom+borderWidth, color); + public static void boxShader(final double minX, final double minY, final double minZ, final double maxX, + final double maxY, final double maxZ) { + final AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(RenderUtil.renderOffset()); + bindBlank(); + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glColor(Colors.INSTANCE.getColor()); + glBegin(GL_TRIANGLE_STRIP); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.maxZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.maxZ); + glVertex3d(bb.minX, bb.maxY, bb.maxZ); + glVertex3d(bb.minX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.minZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.minZ); + glVertex3d(bb.maxX, bb.maxY, bb.minZ); + glVertex3d(bb.maxX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.minZ); + glVertex3d(bb.maxX, bb.minY, bb.minZ); + glVertex3d(bb.minX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.maxX, bb.minY, bb.maxZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.minZ); + glVertex3d(bb.minX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.minZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + glVertex3d(bb.maxX, bb.maxY, bb.maxZ); + + glEnd(); + glColor(Color.WHITE); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glDisable(GL_BLEND); + glPopMatrix(); } - public static void drawInBorderedRect(int left, int top, int right, int bottom, int borderWidth, int color) { - RenderUtil.drawRect(left+borderWidth, top+borderWidth, right-borderWidth, top, color); - RenderUtil.drawRect(left+borderWidth, bottom, right-borderWidth, bottom-borderWidth, color); - RenderUtil.drawRect(left+borderWidth, top+borderWidth, left, bottom-borderWidth, color); - RenderUtil.drawRect(right, top+borderWidth, right-borderWidth, bottom-borderWidth, color); + public static void boxShader(final double minX, final double minY, final double minZ, final double maxX, + final double maxY, final double maxZ, final Color color) { + final AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(RenderUtil.renderOffset()); + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.disableDepth(); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.disableCull(); + GlStateManager.shadeModel(GL_SMOOTH); + + final BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); + bufferBuilder.begin(GL_QUADS, DefaultVertexFormats.POSITION_COLOR); + + //bottom + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + + //top + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + + //front + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + + //back + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + + //left + bufferBuilder.pos(bb.minX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.minX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.minX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + + //right + bufferBuilder.pos(bb.maxX, bb.minY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.minZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.maxY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), 0).endVertex(); + bufferBuilder.pos(bb.maxX, bb.minY, bb.maxZ).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + + Tessellator.getInstance().draw(); + + GlStateManager.shadeModel(GL_FLAT); + GlStateManager.enableCull(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + + + public static void renderGradientLine(final double minX, final double minY, final double minZ, + final double maxX, final double maxY, final double maxZ, final Color color) { + final AxisAlignedBB bb = new AxisAlignedBB(minX, minY, minZ, maxX, maxY, maxZ).offset(RenderUtil.renderOffset()); + + GlStateManager.pushMatrix(); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.disableDepth(); + GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 1, 0); + GlStateManager.disableCull(); + GlStateManager.shadeModel(GL_SMOOTH); + GlStateManager.glLineWidth(1.0F); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + bufferBuilder.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION_COLOR); + addVertexWithColor(bufferBuilder, bb.minX, bb.minY, bb.minZ, color); + addVertexWithColor(bufferBuilder, bb.maxX, bb.minY, bb.minZ, color); + addVertexWithColor(bufferBuilder, bb.maxX, bb.minY, bb.maxZ, color); + addVertexWithColor(bufferBuilder, bb.minX, bb.minY, bb.maxZ, color); + addVertexWithColor(bufferBuilder, bb.minX, bb.minY, bb.minZ, color); + tessellator.draw(); + + bufferBuilder.begin(GL_LINES, DefaultVertexFormats.POSITION_COLOR); + addGradientLine(bufferBuilder, bb.minX, bb.minY, bb.minZ, bb.minX, bb.maxY, bb.minZ, color); + addGradientLine(bufferBuilder, bb.maxX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.minZ, color); + addGradientLine(bufferBuilder, bb.maxX, bb.minY, bb.maxZ, bb.maxX, bb.maxY, bb.maxZ, color); + addGradientLine(bufferBuilder, bb.minX, bb.minY, bb.maxZ, bb.minX, bb.maxY, bb.maxZ, color); + tessellator.draw(); + + GlStateManager.shadeModel(GL_FLAT); + GlStateManager.enableCull(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + } + + private static void addVertexWithColor(BufferBuilder bufferBuilder, double x, double y, double z, Color color) { + bufferBuilder.pos(x, y, z).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + } + + private static void addGradientLine(BufferBuilder bufferBuilder, double startX, double startY, double startZ, + double endX, double endY, double endZ, Color color) { + Color transparent = new Color(color.getRed(), color.getGreen(), color.getBlue(), 0); // Assuming you want to fade to transparent + addVertexWithColor(bufferBuilder, startX, startY, startZ, color); + addVertexWithColor(bufferBuilder, endX, endY, endZ, transparent); + } + + + public static void boxFaceShader(final BlockPos pos, EnumFacing face, Color color) { + if (pos != null) { + final AxisAlignedBB bb = new AxisAlignedBB(pos).offset(RenderUtil.renderOffset()); + bindBlank(); + glPushMatrix(); + glEnable(GL_BLEND); + glDisable(GL_TEXTURE_2D); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glColor(Colors.INSTANCE.getColor()); + + glBegin(GL_QUADS); + switch (face) { + case DOWN: + case UP: + double y = (face == EnumFacing.DOWN) ? bb.minY : bb.maxY; + glVertex3d(bb.minX, y, bb.minZ); + glVertex3d(bb.minX, y, bb.maxZ); + glVertex3d(bb.maxX, y, bb.maxZ); + glVertex3d(bb.maxX, y, bb.minZ); + break; + case NORTH: + case SOUTH: + double z = (face == EnumFacing.NORTH) ? bb.minZ : bb.maxZ; + glVertex3d(bb.minX, bb.minY, z); + glVertex3d(bb.minX, bb.maxY, z); + glVertex3d(bb.maxX, bb.maxY, z); + glVertex3d(bb.maxX, bb.minY, z); + break; + case WEST: + case EAST: + double x = (face == EnumFacing.WEST) ? bb.minX : bb.maxX; + glVertex3d(x, bb.minY, bb.minZ); + glVertex3d(x, bb.minY, bb.maxZ); + glVertex3d(x, bb.maxY, bb.maxZ); + glVertex3d(x, bb.maxY, bb.minZ); + break; + } + glEnd(); + + glColor(Color.WHITE); + glEnable(GL_TEXTURE_2D); + glEnable(GL_DEPTH_TEST); + glEnable(GL_CULL_FACE); + glDisable(GL_BLEND); //boom + glPopMatrix(); + } + } + public static Vec3d renderOffset() { + return new Vec3d(-mc.getRenderManager().viewerPosX, -mc.getRenderManager().viewerPosY, -mc.getRenderManager().viewerPosZ); + } + + public static void renderTexture(ResourceLocation resourceLocation, Color color) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + + mc.getTextureManager().bindTexture(resourceLocation); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); + + buffer.pos(0.0F, 1.5F, 0.0F).tex(0F, 1F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + buffer.pos(1.5F, 1.5F, 0.0F).tex(1F, 1F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + buffer.pos(1.5F, 0.0F, 0.0F).tex(1F, 0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + buffer.pos(0.0F, 0.0F, 0.0F).tex(0F, 0F).color(color.getRed(), color.getGreen(), color.getBlue(), color.getAlpha()).endVertex(); + + tessellator.draw(); + } + + public static void drawHead(Entity entity, Vec2d pos1, Vec2d pos2) { + if (entity instanceof AbstractClientPlayer) { + AbstractClientPlayer player = (AbstractClientPlayer) entity; + ResourceLocation skin = player.getLocationSkin(); + Color headColor = Color.WHITE; + + glColor3d(headColor.getRed() / 255.0, headColor.getGreen() / 255.0, headColor.getBlue() / 255.0); + mc.getTextureManager().bindTexture(skin); + + Vec2d uv1 = new Vec2d(8.0F, 8.0F); // head left top + Vec2d uv2 = new Vec2d(16.0F, 16.0F); // head right bottom + + float textureSize = 64.0F; + + // normalized uv cords + Vec2d nuv1 = uv1.div(textureSize); + Vec2d nuv2 = uv2.div(textureSize); + + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(GL_QUADS, DefaultVertexFormats.POSITION_TEX); + + buffer.pos(pos1.x, pos2.y, 0.0).tex(nuv1.x, nuv2.y).endVertex(); + buffer.pos(pos2.x, pos2.y, 0.0).tex(nuv2.x, nuv2.y).endVertex(); + buffer.pos(pos2.x, pos1.y, 0.0).tex(nuv2.x, nuv1.y).endVertex(); + buffer.pos(pos1.x, pos1.y, 0.0).tex(nuv1.x, nuv1.y).endVertex(); + + tessellator.draw(); + } + } + + public static void bind(final ResourceLocation resourceLocation) { + mc.getTextureManager().bindTexture(resourceLocation); + } + + public static void bindBlank() { + bind(blank); + } + + public static void glColor(final Color color) { + glColor4f(color.getRed() / 255.0f, color.getGreen() / 255.0f, color.getBlue() / 255.0f, color.getAlpha() / 255.0f); + } + + public static Framebuffer createFrameBuffer(final Framebuffer framebuffer) { + if (framebuffer == null || framebuffer.framebufferWidth != mc.displayWidth || framebuffer.framebufferHeight != mc.displayHeight) { + if (framebuffer != null) { + framebuffer.deleteFramebuffer(); + } + return new Framebuffer(mc.displayWidth, mc.displayHeight, true); + } + return framebuffer; + } + + public static double interpolateLastTickPos(double pos, double lastPos) { + return lastPos + (pos - lastPos) * mc.getRenderPartialTicks(); + } + + public static Vec3d interpolateEntity(Entity entity) { + double x; + double y; + double z; + x = interpolateLastTickPos(entity.posX, entity.lastTickPosX) - mc.getRenderManager().viewerPosX; + y = interpolateLastTickPos(entity.posY, entity.lastTickPosY) - mc.getRenderManager().viewerPosY; + z = interpolateLastTickPos(entity.posZ, entity.lastTickPosZ) - mc.getRenderManager().viewerPosZ; + return new Vec3d(x, y, z); } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/render/StencilUtil.java b/src/main/java/xyz/templecheats/templeclient/util/render/StencilUtil.java new file mode 100644 index 00000000..5728a735 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/render/StencilUtil.java @@ -0,0 +1,62 @@ +package xyz.templecheats.templeclient.util.render; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.shader.Framebuffer; +import org.lwjgl.opengl.EXTFramebufferObject; +import org.lwjgl.opengl.EXTPackedDepthStencil; +import org.lwjgl.opengl.GL11; + +public class StencilUtil { + private static final Minecraft mc = Minecraft.getMinecraft(); + + public static void checkSetupFBO(Framebuffer framebuffer) { + if (framebuffer != null) { + if (framebuffer.depthBuffer > -1) { + setupFBO(framebuffer); + framebuffer.depthBuffer = -1; + } + } + } + + /** + * @implNote Sets up the Framebuffer for Stencil use + */ + public static void setupFBO(Framebuffer framebuffer) { + EXTFramebufferObject.glDeleteRenderbuffersEXT(framebuffer.depthBuffer); + int stencilDepthBufferID = EXTFramebufferObject.glGenRenderbuffersEXT(); + EXTFramebufferObject.glBindRenderbufferEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, stencilDepthBufferID); + EXTFramebufferObject.glRenderbufferStorageEXT(EXTFramebufferObject.GL_RENDERBUFFER_EXT, EXTPackedDepthStencil.GL_DEPTH_STENCIL_EXT, mc.displayWidth, mc.displayHeight); + EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_STENCIL_ATTACHMENT_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, stencilDepthBufferID); + EXTFramebufferObject.glFramebufferRenderbufferEXT(EXTFramebufferObject.GL_FRAMEBUFFER_EXT, EXTFramebufferObject.GL_DEPTH_ATTACHMENT_EXT, EXTFramebufferObject.GL_RENDERBUFFER_EXT, stencilDepthBufferID); + } + + /** + * @implNote Initializes the Stencil Buffer to write to + */ + public static void initStencilToWrite() { + //init + mc.getFramebuffer().bindFramebuffer(false); + checkSetupFBO(mc.getFramebuffer()); + GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 1); + GL11.glStencilOp(GL11.GL_REPLACE, GL11.GL_REPLACE, GL11.GL_REPLACE); + GL11.glColorMask(false, false, false, false); + } + + /** + * @param ref (usually 1) + * @implNote Reads the Stencil Buffer and stencils it onto everything until + * @see StencilUtil.uninitStencilBuffer + */ + public static void readStencilBuffer(int ref) { + GL11.glColorMask(true, true, true, true); + GL11.glStencilFunc(GL11.GL_EQUAL, ref, 1); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + } + + public static void uninitStencilBuffer() { + GL11.glDisable(GL11.GL_STENCIL_TEST); + } +} + diff --git a/src/main/java/xyz/templecheats/templeclient/util/rotation/RotationUtil.java b/src/main/java/xyz/templecheats/templeclient/util/rotation/RotationUtil.java index afa31716..1dff3424 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/rotation/RotationUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/rotation/RotationUtil.java @@ -16,10 +16,13 @@ public static float[] rotations(Entity entity) { double u = MathHelper.sqrt(x * x + z * z); - float u2 = (float) (MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); - float u3 = (float) (-MathHelper.atan2(y, u) * (180D / Math.PI)); + float u2 = (float)(MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); + float u3 = (float)(-MathHelper.atan2(y, u) * (180D / Math.PI)); - return new float[]{u2, u3}; + return new float[] { + u2, + u3 + }; } public static float[] rotations(BlockPos pos) { @@ -31,10 +34,13 @@ public static float[] rotations(BlockPos pos) { double u = MathHelper.sqrt(x * x + z * z); - float u2 = (float) (MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); - float u3 = (float) (-MathHelper.atan2(y, u) * (180D / Math.PI)); + float u2 = (float)(MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); + float u3 = (float)(-MathHelper.atan2(y, u) * (180D / Math.PI)); - return new float[]{u2, u3}; + return new float[] { + u2, + u3 + }; } public static float[] getRotations(EntityLivingBase entity) { double x = entity.posX - mc.player.posX; @@ -43,9 +49,12 @@ public static float[] getRotations(EntityLivingBase entity) { double u = MathHelper.sqrt(x * x + z * z); - float yaw = (float) (MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); - float pitch = (float) (-MathHelper.atan2(y, u) * (180D / Math.PI)); + float yaw = (float)(MathHelper.atan2(z, x) * (180D / Math.PI) - 90.0F); + float pitch = (float)(-MathHelper.atan2(y, u) * (180D / Math.PI)); - return new float[]{yaw, pitch}; + return new float[] { + yaw, + pitch + }; } } \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/Setting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/Setting.java index 7ac54319..68816ec7 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/Setting.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/Setting.java @@ -1,8 +1,10 @@ package xyz.templecheats.templeclient.util.setting; import com.google.gson.JsonObject; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; -public abstract class Setting { +public abstract class Setting < T > { public final String name; public final SettingHolder parent; public boolean visible; @@ -18,6 +20,6 @@ public Setting(String name, SettingHolder parent) { public abstract void serialize(JsonObject jsonObject); public abstract void deserialize(JsonObject jsonObject); - public abstract xyz.templecheats.templeclient.features.gui.clickgui.basic.Item createBasicButton(xyz.templecheats.templeclient.features.gui.clickgui.basic.Button parent); - public abstract xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button parent); -} + public abstract Item createBasicButton(Button parent); + public abstract xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent); +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/SettingHolder.java b/src/main/java/xyz/templecheats/templeclient/util/setting/SettingHolder.java index bc0d6e59..4828fdbe 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/SettingHolder.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/SettingHolder.java @@ -1,21 +1,26 @@ package xyz.templecheats.templeclient.util.setting; import xyz.templecheats.templeclient.TempleClient; +import xyz.templecheats.templeclient.features.module.Module; public class SettingHolder { private final String name; - + + public static Class[] modules() { + return new Class[0]; + } + public SettingHolder(String name) { this.name = name; } - - protected void registerSettings(Setting... settings) { - for(Setting setting : settings) { + + protected void registerSettings(Setting...settings) { + for (Setting setting: settings) { TempleClient.settingsManager.rSetting(setting); } } - + public String getName() { return this.name; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/SettingsManager.java b/src/main/java/xyz/templecheats/templeclient/util/setting/SettingsManager.java index 85d9857e..b92ff51c 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/SettingsManager.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/SettingsManager.java @@ -6,19 +6,19 @@ import java.util.List; public class SettingsManager { - private final List> settings = new ReferenceArrayList<>(); - - public void rSetting(Setting in) { + private final List < Setting < ? >> settings = new ReferenceArrayList < > (); + + public void rSetting(Setting < ? > in) { this.settings.add(in); } - - public List> getSettings() { + + public List < Setting < ? >> getSettings() { return this.settings; } - - public List> getSettingsByMod(SettingHolder mod) { - List> out = new ReferenceArrayList<>(); - for (Setting s : getSettings()) { + + public List < Setting < ? >> getSettingsByMod(SettingHolder mod) { + List < Setting < ? >> out = new ReferenceArrayList < > (); + for (Setting < ? > s : getSettings()) { if (s.parent == mod) out.add(s); } return out; @@ -29,8 +29,8 @@ public List> getSettingsByMod(SettingHolder mod) { */ @Deprecated @Nullable - public Setting getSetting(SettingHolder mod, String name) { - for (Setting set : getSettings()) { + public Setting < ? > getSetting(SettingHolder mod, String name) { + for (Setting < ? > set : getSettings()) { if (set.parent == mod && set.name.equals(name)) return set; } return null; @@ -41,12 +41,12 @@ public Setting getSetting(SettingHolder mod, String name) { */ @Deprecated @Nullable - public Setting getSettingByName(String mod, String name) { - for (Setting set : getSettings()) { + public Setting < ? > getSettingByName(String mod, String name) { + for (Setting < ? > set : getSettings()) { if (set.name.equalsIgnoreCase(name) && set.parent.getName().equalsIgnoreCase(mod)) { return set; } } return null; } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/BooleanSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/BooleanSetting.java index 60b97bdc..a3413f26 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/BooleanSetting.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/BooleanSetting.java @@ -1,10 +1,13 @@ package xyz.templecheats.templeclient.util.setting.impl; import com.google.gson.JsonObject; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.BooleanButton; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; import xyz.templecheats.templeclient.util.setting.Setting; import xyz.templecheats.templeclient.util.setting.SettingHolder; -public class BooleanSetting extends Setting { +public class BooleanSetting extends Setting < Boolean > { private boolean value; public BooleanSetting(String name, SettingHolder parent, boolean defaultValue) { @@ -43,12 +46,12 @@ public void deserialize(JsonObject jsonObject) { } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.basic.Item createBasicButton(xyz.templecheats.templeclient.features.gui.clickgui.basic.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.basic.properties.BooleanButton(this, parent); + public Item createBasicButton(Button parent) { + return new BooleanButton(this, parent); } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.BooleanButton(this, parent); + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.BooleanButton(this, parent); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/ColorSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/ColorSetting.java new file mode 100644 index 00000000..70baf98b --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/ColorSetting.java @@ -0,0 +1,79 @@ +package xyz.templecheats.templeclient.util.setting.impl; + +import com.google.gson.JsonObject; +import java.awt.Color; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.ColorButton; +import xyz.templecheats.templeclient.util.setting.Setting; +import xyz.templecheats.templeclient.util.setting.SettingHolder; + +public class ColorSetting extends Setting { + private Color value; + public String name; + + public ColorSetting(String name, SettingHolder parent, Color defaultValue) { + super(name, parent); + this.name = name; + this.value = defaultValue; + } + + public String getName() { + return this.name; + } + + public Color getColor() { + return this.value; + } + + public void setColor(Color value) { + this.value = value; + } + + public void setAlpha(int alpha) { + this.value = new Color(this.value.getRed(), this.value.getGreen(), this.value.getBlue(), Math.min(255, Math.max(0, alpha))); + } + + @Deprecated + @Override + public Color value() { + return this.value; + } + + @Deprecated + @Override + public void setValue(Color value) { + this.value = value; + } + + @Override + public void serialize(JsonObject jsonObject) { + JsonObject colorObject = new JsonObject(); + colorObject.addProperty("red", this.value.getRed()); + colorObject.addProperty("green", this.value.getGreen()); + colorObject.addProperty("blue", this.value.getBlue()); + colorObject.addProperty("alpha", this.value.getAlpha()); + jsonObject.add(this.name, colorObject); + } + + @Override + public void deserialize(JsonObject jsonObject) { + JsonObject colorObject = jsonObject.getAsJsonObject(this.name); + int red = colorObject.get("red").getAsInt(); + int green = colorObject.get("green").getAsInt(); + int blue = colorObject.get("blue").getAsInt(); + int alpha = colorObject.get("alpha").getAsInt(); + + this.value = new Color(red, green, blue, alpha); + } + + @Override + public Item createBasicButton(Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.ColorButton(this, parent); + } + + @Override + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new ColorButton(this, parent); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/DoubleSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/DoubleSetting.java index 7a6ea173..b592507d 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/DoubleSetting.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/DoubleSetting.java @@ -1,11 +1,15 @@ package xyz.templecheats.templeclient.util.setting.impl; import com.google.gson.JsonObject; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.DoubleSlider; import xyz.templecheats.templeclient.util.setting.Setting; import xyz.templecheats.templeclient.util.setting.SettingHolder; -public class DoubleSetting extends Setting { - public final double min, max; +public class DoubleSetting extends Setting < Double > { + public final double min, + max; private double value; public DoubleSetting(String name, SettingHolder parent, double min, double max, double defaultValue) { @@ -50,12 +54,12 @@ public void deserialize(JsonObject jsonObject) { } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.basic.Item createBasicButton(xyz.templecheats.templeclient.features.gui.clickgui.basic.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.basic.properties.DoubleSlider(this, parent); + public Item createBasicButton(Button parent) { + return new DoubleSlider(this, parent); } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.DoubleSlider(this, parent); + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.slider.DoubleSlider(this, parent); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/EnumSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/EnumSetting.java index 77e2fc83..ec336333 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/EnumSetting.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/EnumSetting.java @@ -1,10 +1,13 @@ package xyz.templecheats.templeclient.util.setting.impl; import com.google.gson.JsonObject; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.EnumButton; import xyz.templecheats.templeclient.util.setting.Setting; import xyz.templecheats.templeclient.util.setting.SettingHolder; -public class EnumSetting> extends Setting { +public class EnumSetting < T extends Enum < T >> extends Setting < T > { private T value; public EnumSetting(String name, SettingHolder parent, T defaultValue) { @@ -42,7 +45,7 @@ public void serialize(JsonObject jsonObject) { @Override public void deserialize(JsonObject jsonObject) { String valueName = jsonObject.getAsJsonPrimitive(this.name).getAsString(); - for (T enumValue : this.value.getDeclaringClass().getEnumConstants()) { + for (T enumValue: this.value.getDeclaringClass().getEnumConstants()) { if (enumValue.name().equals(valueName)) { this.value = enumValue; return; @@ -51,12 +54,12 @@ public void deserialize(JsonObject jsonObject) { } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.basic.Item createBasicButton(xyz.templecheats.templeclient.features.gui.clickgui.basic.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.basic.properties.EnumButton<>(this, parent); + public Item createBasicButton(Button parent) { + return new EnumButton< >(this, parent); } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.EnumButton<>(this, parent); + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.enumB.EnumButton< >(this, parent); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/IntSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/IntSetting.java index 99ef8907..23666113 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/IntSetting.java +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/IntSetting.java @@ -1,14 +1,15 @@ package xyz.templecheats.templeclient.util.setting.impl; import com.google.gson.JsonObject; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Button; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.Item; -import xyz.templecheats.templeclient.features.gui.clickgui.basic.properties.IntSlider; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.IntSlider; import xyz.templecheats.templeclient.util.setting.Setting; import xyz.templecheats.templeclient.util.setting.SettingHolder; -public class IntSetting extends Setting { - public final int min, max; +public class IntSetting extends Setting < Integer > { + public final int min, + max; private int value; public IntSetting(String name, SettingHolder parent, int min, int max, int defaultValue) { @@ -54,7 +55,7 @@ public Item createBasicButton(Button parent) { } @Override - public xyz.templecheats.templeclient.features.gui.clickgui.csgo.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.Button parent) { - return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.IntSlider(this, parent); + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.slider.IntSlider(this, parent); } -} +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/setting/impl/StringSetting.java b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/StringSetting.java new file mode 100644 index 00000000..b45e5b01 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/setting/impl/StringSetting.java @@ -0,0 +1,60 @@ +package xyz.templecheats.templeclient.util.setting.impl; + +import com.google.gson.JsonObject; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.Item; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.Button; +import xyz.templecheats.templeclient.features.gui.clickgui.basic.panels.items.buttons.StringButton; +import xyz.templecheats.templeclient.util.setting.Setting; +import xyz.templecheats.templeclient.util.setting.SettingHolder; + +public class StringSetting extends Setting { + private String value; + private final String name; + + public StringSetting(String name, SettingHolder parent, String value) { + super(name, parent); + this.name = name; + this.value = value; + } + + public String getName() { + return this.name; + } + + public String getStringValue() { + return this.value; + } + + @Override + public String value() { + return this.value; + } + + @Override + public void setValue(String value) { + this.value = value; + } + + @Override + public void serialize(JsonObject jsonObject) { + JsonObject stringObject = new JsonObject(); + stringObject.addProperty("string", this.getStringValue().replace(" ", "_")); + jsonObject.add(this.name, stringObject); + } + + @Override + public void deserialize(JsonObject jsonObject) { + JsonObject stringObject = jsonObject.getAsJsonObject(this.name); + this.value = stringObject.get("string").getAsString(); + } + + @Override + public Item createBasicButton(Button parent) { + return new StringButton(name, parent, this); + } + + @Override + public xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.Item createCsgoButton(xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.Button parent) { + return new xyz.templecheats.templeclient.features.gui.clickgui.csgo.properties.items.buttons.StringButton(name, parent, this); + } +} diff --git a/src/main/java/xyz/templecheats/templeclient/util/world/BlockPosWithFacing.java b/src/main/java/xyz/templecheats/templeclient/util/world/BlockPosWithFacing.java new file mode 100644 index 00000000..cd803f04 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/world/BlockPosWithFacing.java @@ -0,0 +1,14 @@ +package xyz.templecheats.templeclient.util.world; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +public class BlockPosWithFacing { + public BlockPos blockPos; + public EnumFacing enumFacing; + + public BlockPosWithFacing(BlockPos blockPos, EnumFacing enumFacing) { + this.blockPos = blockPos; + this.enumFacing = enumFacing; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/world/BlockUtil.java b/src/main/java/xyz/templecheats/templeclient/util/world/BlockUtil.java new file mode 100644 index 00000000..3ab0f7f6 --- /dev/null +++ b/src/main/java/xyz/templecheats/templeclient/util/world/BlockUtil.java @@ -0,0 +1,202 @@ +package xyz.templecheats.templeclient.util.world; + +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.item.EntityEnderCrystal; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.network.play.client.CPacketEntityAction; +import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock; +import net.minecraft.util.CombatRules; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.*; +import net.minecraft.world.Explosion; +import xyz.templecheats.templeclient.util.Globals; + +import java.util.*; + +public class BlockUtil implements Globals { + private static final Vec3i[] hole = new Vec3i[] { + new Vec3i(-1, 0, 0), + new Vec3i(1, 0, 0), + new Vec3i(0, 0, 1), + new Vec3i(0, 0, -1), + new Vec3i(0, -1, 0), + }; + + public static boolean valid(BlockPos pos, boolean updated) { + return mc.world.getBlockState(pos.up()).getBlock().equals(Blocks.AIR) && + (mc.world.getBlockState(pos.up().up()).getBlock().equals(Blocks.AIR) || updated) && + (mc.world.getBlockState(pos).getBlock().equals(Blocks.OBSIDIAN) || + mc.world.getBlockState(pos).getBlock().equals(Blocks.BEDROCK)); + } + + public static BlockPos center() { + return new BlockPos(Math.floor(mc.player.posX), Math.floor(mc.player.posY), Math.floor(mc.player.posZ)); + } + public static BlockPos getPosition() { + return new BlockPos(Math.floor(mc.player.posX), Math.floor(mc.player.posY), Math.floor(mc.player.posZ)); + } + public static boolean empty(BlockPos pos) { + return mc.world.getEntitiesWithinAABB(EntityPlayer.class, new AxisAlignedBB(new BlockPos(pos.getX() + 0.5f, pos.getY() + 1.0f, pos.getZ() + 0.5f))).isEmpty(); + } + public static boolean isReplaceable(BlockPos pos) { + return mc.world.getBlockState(pos).getMaterial().isReplaceable(); + } + + public static BlockPos getPosition(EntityPlayer entityPlayer) { + return new BlockPos(Math.floor(entityPlayer.posX), Math.floor(entityPlayer.posY), Math.floor(entityPlayer.posZ)); + } + + public static boolean hasCrystal(BlockPos pos) { + return !mc.world.getEntitiesWithinAABB(EntityEnderCrystal.class, new AxisAlignedBB(new BlockPos(pos.getX() + 0.0f, pos.getY() + 1.5f, pos.getZ() + 0.0f))).isEmpty(); + } + + public static float distance(BlockPos pos) { + return (float) Math.sqrt(mc.player.getDistanceSq(pos)); + } + public static BlockPos center(BlockPos pos) { + return pos.add(0.5f, 0.5f, 0.5f); + } + public static boolean is(BlockPos pos, Block block) { + return mc.world.getBlockState(pos).getBlock().equals(block); + } + public static boolean isPlayerSafe(EntityPlayer entityPlayer) { + final BlockPos pos = entityPlayer.getPosition(); + if (isNotIntersecting(entityPlayer)) { + return isImmuneToExplosion(pos.north()) && isImmuneToExplosion(pos.east()) && isImmuneToExplosion(pos.south()) && isImmuneToExplosion(pos.west()) && isImmuneToExplosion(pos.down()); + } else { + return isIntersectingSafe(entityPlayer); + } + } + public static boolean isNotIntersecting(EntityPlayer entityPlayer) { + final BlockPos pos = entityPlayer.getPosition(); + final AxisAlignedBB bb = entityPlayer.getEntityBoundingBox(); + return (!air(pos.north()) || !bb.intersects(new AxisAlignedBB(pos.north()))) && (!air(pos.east()) || !bb.intersects(new AxisAlignedBB(pos.east()))) && (!air(pos.south()) || !bb.intersects(new AxisAlignedBB(pos.south()))) && (!air(pos.west()) || !bb.intersects(new AxisAlignedBB(pos.west()))); + } + + public static boolean isIntersectingSafe(EntityPlayer entityPlayer) { + final BlockPos pos = entityPlayer.getPosition(); + final AxisAlignedBB bb = entityPlayer.getEntityBoundingBox(); + if (air(pos.north()) && bb.intersects(new AxisAlignedBB(pos.north()))) { + final BlockPos pos1 = pos.north(); + if (!isImmuneToExplosion(pos1.north()) || !isImmuneToExplosion(pos1.east()) || !isImmuneToExplosion(pos1.west()) || !isImmuneToExplosion(pos1.down())) + return false; + } + if (air(pos.east()) && bb.intersects(new AxisAlignedBB(pos.east()))) { + final BlockPos pos1 = pos.east(); + if (!isImmuneToExplosion(pos1.north()) || !isImmuneToExplosion(pos1.east()) || !isImmuneToExplosion(pos1.south()) || !isImmuneToExplosion(pos1.down())) + return false; + } + if (air(pos.south()) && bb.intersects(new AxisAlignedBB(pos.south()))) { + final BlockPos pos1 = pos.south(); + if (!isImmuneToExplosion(pos1.east()) || !isImmuneToExplosion(pos1.south()) || !isImmuneToExplosion(pos1.west()) || !isImmuneToExplosion(pos1.down())) + return false; + } + if (air(pos.west()) && bb.intersects(new AxisAlignedBB(pos.west()))) { + final BlockPos pos1 = pos.west(); + return isImmuneToExplosion(pos1.north()) && isImmuneToExplosion(pos1.south()) && isImmuneToExplosion(pos1.west()) && isImmuneToExplosion(pos1.down()); + } + return true; + } + public static boolean isImmuneToExplosion(final BlockPos pos) { + return mc.world.getBlockState(pos).getBlockHardness(mc.world, pos) == -1; + } + + public static boolean air(final BlockPos pos) { + return mc.world.getBlockState(pos).getBlock().equals(Blocks.AIR); + } + + public static float calculateEntityDamage(final EntityEnderCrystal crystal, final EntityPlayer entityPlayer) { + return calculatePosDamage(crystal.posX, crystal.posY, crystal.posZ, entityPlayer); + } + + public static float calculatePosDamage(final BlockPos position, final EntityPlayer entityPlayer) { + return calculatePosDamage(position.getX() + 0.5, position.getY() + 1.0, position.getZ() + 0.5, entityPlayer); + } + + @SuppressWarnings("ConstantConditions") + public static float calculatePosDamage(final double posX, final double posY, final double posZ, final Entity entity) { + final float doubleSize = 12.0F; + final double size = entity.getDistance(posX, posY, posZ) / doubleSize; + final Vec3d vec3d = new Vec3d(posX, posY, posZ); + final double blockDensity = entity.world.getBlockDensity(vec3d, entity.getEntityBoundingBox()); + final double value = (1.0D - size) * blockDensity; + final float damage = (float)((int)((value * value + value) / 2.0D * 7.0D * doubleSize + 1.0D)); + double finalDamage = 1.0D; + + if (entity instanceof EntityLivingBase) { + finalDamage = getBlastReduction((EntityLivingBase) entity, getMultipliedDamage(damage), new Explosion(mc.world, null, posX, posY, posZ, 6.0F, false, true)); + } + + return (float) finalDamage; + } + + public static List < EnumFacing > getPossibleSides(BlockPos pos) { + ArrayList < EnumFacing > facings = new ArrayList < > (); + if (mc.world == null || pos == null) { + return facings; + } + for (EnumFacing side: EnumFacing.values()) { + BlockPos neighbour = pos.offset(side); + IBlockState blockState = mc.world.getBlockState(neighbour); + if (!blockState.getBlock().canCollideCheck(blockState, false) || blockState.getMaterial().isReplaceable()) + continue; + facings.add(side); + } + return facings; + } + + public static EnumFacing getFirstFacing(BlockPos pos) { + Iterator < EnumFacing > iterator = BlockUtil.getPossibleSides(pos).iterator(); + if (iterator.hasNext()) { + return iterator.next(); + } + return null; + } + + private static float getMultipliedDamage(final float damage) { + return damage * (mc.world.getDifficulty().getId() == 0 ? 0.0F : (mc.world.getDifficulty().getId() == 2 ? 1.0F : (mc.world.getDifficulty().getId() == 1 ? 0.5F : 1.5F))); + } + + public static float getBlastReduction(final EntityLivingBase entity, final float damageI, final Explosion explosion) { + float damage = damageI; + final DamageSource ds = DamageSource.causeExplosionDamage(explosion); + damage = CombatRules.getDamageAfterAbsorb(damage, entity.getTotalArmorValue(), (float) entity.getEntityAttribute(SharedMonsterAttributes.ARMOR_TOUGHNESS).getAttributeValue()); + int k = 0; + try { + k = EnchantmentHelper.getEnchantmentModifierDamage(entity.getArmorInventoryList(), ds); + } catch (Exception ignored) {} + damage = damage * (1.0F - MathHelper.clamp(k, 0.0F, 20.0F) / 25.0F); + + if (entity.isPotionActive(MobEffects.RESISTANCE)) { + damage = damage - (damage / 4); + } + + return damage; + } + + public static List getBlocksInRadius(final double range) { + if (mc.player == null) return Collections.emptyList(); + List positions = new ArrayList<>(); + + for (int x = MathHelper.floor(mc.player.posX - range), maxX = MathHelper.ceil(mc.player.posX + range); x < maxX; x++) { + for (int y = MathHelper.floor(mc.player.posY - range), maxY = MathHelper.ceil(mc.player.posY + range); y < maxY; y++) { + for (int z = MathHelper.floor(mc.player.posZ - range), maxZ = MathHelper.ceil(mc.player.posZ + range); z < maxZ; z++) { + if (mc.player.getDistanceSq(x + 0.5, y + 1, z + 0.5) <= range * range) { + positions.add(new BlockPos(x, y, z)); + } + } + } + } + + return positions; + } +} \ No newline at end of file diff --git a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/EntityUtil.java b/src/main/java/xyz/templecheats/templeclient/util/world/EntityUtil.java similarity index 66% rename from src/main/java/xyz/templecheats/templeclient/util/autocrystal/EntityUtil.java rename to src/main/java/xyz/templecheats/templeclient/util/world/EntityUtil.java index eec8bccd..e964e9c4 100644 --- a/src/main/java/xyz/templecheats/templeclient/util/autocrystal/EntityUtil.java +++ b/src/main/java/xyz/templecheats/templeclient/util/world/EntityUtil.java @@ -1,4 +1,4 @@ -package xyz.templecheats.templeclient.util.autocrystal; +package xyz.templecheats.templeclient.util.world; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -9,17 +9,17 @@ public class EntityUtil { private static final Minecraft mc = Minecraft.getMinecraft(); - + public static List getSphere(BlockPos loc, float r, int h, boolean hollow, boolean sphere, int plus_y) { List circleBlocks = new ArrayList<>(); int cx = loc.getX(); int cy = loc.getY(); int cz = loc.getZ(); - for(int x = cx - (int) r; x <= cx + r; x++) { - for(int z = cz - (int) r; z <= cz + r; z++) { - for(int y = (sphere ? cy - (int) r : cy); y < (sphere ? cy + r : cy + h); y++) { + for (int x = cx - (int) r; x <= cx + r; x++) { + for (int z = cz - (int) r; z <= cz + r; z++) { + for (int y = (sphere ? cy - (int) r : cy); y < (sphere ? cy + r : cy + h); y++) { double dist = (cx - x) * (cx - x) + (cz - z) * (cz - z) + (sphere ? (cy - y) * (cy - y) : 0); - if(dist < r * r && !(hollow && dist < (r - 1) * (r - 1))) { + if (dist < r * r && !(hollow && dist < (r - 1) * (r - 1))) { BlockPos l = new BlockPos(x, y + plus_y, z); circleBlocks.add(l); } @@ -28,8 +28,12 @@ public static List getSphere(BlockPos loc, float r, int h, boolean hol } return circleBlocks; } - + public static boolean basicChecksEntity(Entity pl) { return pl.getName().equals(mc.player.getName()) || pl.isDead; } + + public static boolean isMoving() { + return (double) mc.player.moveForward != 0.0 || (double) mc.player.moveStrafing != 0.0; + } } \ No newline at end of file diff --git a/src/main/resources/assets/minecraft/FSEX300.ttf b/src/main/resources/assets/minecraft/font/FSEX300.ttf similarity index 100% rename from src/main/resources/assets/minecraft/FSEX300.ttf rename to src/main/resources/assets/minecraft/font/FSEX300.ttf diff --git a/src/main/resources/assets/minecraft/bold.ttf b/src/main/resources/assets/minecraft/font/bold.ttf similarity index 100% rename from src/main/resources/assets/minecraft/bold.ttf rename to src/main/resources/assets/minecraft/font/bold.ttf diff --git a/src/main/resources/assets/minecraft/calibri-bold.ttf b/src/main/resources/assets/minecraft/font/calibri-bold.ttf similarity index 100% rename from src/main/resources/assets/minecraft/calibri-bold.ttf rename to src/main/resources/assets/minecraft/font/calibri-bold.ttf diff --git a/src/main/resources/assets/minecraft/smooth.ttf b/src/main/resources/assets/minecraft/font/smooth.ttf similarity index 100% rename from src/main/resources/assets/minecraft/smooth.ttf rename to src/main/resources/assets/minecraft/font/smooth.ttf diff --git a/src/main/resources/assets/minecraft/texts/splashes.txt b/src/main/resources/assets/minecraft/texts/splashes.txt index b10505b1..e4fcd658 100644 --- a/src/main/resources/assets/minecraft/texts/splashes.txt +++ b/src/main/resources/assets/minecraft/texts/splashes.txt @@ -1,4 +1,4 @@ -§bTemple Client 1.8.6 +§bTemple Client 1.8.8 §bTemple Client on top! §bThank you for using Temple Client! §bThank you interloper! \ No newline at end of file diff --git a/src/main/resources/assets/minecraft/textures/blank.png b/src/main/resources/assets/minecraft/textures/blank.png new file mode 100644 index 0000000000000000000000000000000000000000..cbdf4ae908507bfcfcc5602f48c2752047dce8e7 GIT binary patch literal 70 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≶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

IiL{}D-{3;;bxZqxsIH141n9R9u%avxi8=|3 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 z z!6y&ywA+nEELXIhTCcB!j!rRPi8Y!I6=uq+qaD$cr30bzgR3L_m5}&;M?P547nHjz zgmddfu&F`L*YsM!I8{CoomaMmhBbi!i|^aC?X(7q^i9PaHu4k>>*iq{DmJ1Sn;+L+ zTe`;k&_`^z3#*rTRo?$BYZkSr?(D^~dv63Ale$7YKw@+Qy=Q0nWTT&$Hrt050)arGKZbM19 z=v+o>JDE%S_ovY%5>|^z8_YO3-uEMb22?yy>@O?u8Eo$Qw9-L@3Nl6dS>h!K6w)r8 zNMaqJP;t?>OR$TEK;nll9dUgivB5g^ap+#uT5!8v@MCpecrZ~F8=CH7gW-(HeLvZ4 zuHnQma@_chA-pwK!_0^B?85*ZT8pM`2qxb;qjrW^4O41y@bp*a?NTI;b$#VL$5LCAM;eoO1o98UAb34E+f002zLR84Qtsy zAQy#gEOU?xoY3RAXmxsHFSb{S(osGgdlXNocE_*|BHsw&kpvONr{)Ak!*KS zvp!*6A`C<+enkTfTm18x*`oz7!@yqzJrm^XD*-Scv&so5q4VB1Ph|M$GJWx#eq8~3 zWMmN2ogB7GRV89eGdGg&*-{#YScC3cx8+kW2oyz?Uger^NPlgXD*eaJs>Bc2g4V&zt#cLrRz8Ky7zfbxmKCx8N+{oTo!S3>&9BOAAa{6{ zg$b-e?32VMn3_uW+$BTqIovthdLctP@(PQTBikxA2|Axp!%JT1orIZU4+P8xojTQnzH9cO0Gk4j`;U| zmhYpf1JlHiqi*;;S!vDrq{Ie=vZ+{Et3=pJ5%poo8`ZM8?&r&iH)>|V${8rHm!!wC z^kqlAZ|O(D2*vBn5mTYlOYsySmsCw!HD(Ym4A`XIGV@7)8fkWeNOHx%>=PS^?K=M2 z9emsy?EBjMX!Z3Bg*y+EO2qWJu?nscxvW6^1mVW^HNitc0B|sO)G5p*%OtEkC zJFg$xz}U5&JhUhI$(bqtti=*^&H)Rmt#kG7D|_OPs~(H&D@gXi+(ECs_|R81>)v%M zL-2*QOYErX{kc8P=a*&qPj&Hz6vxD0K_$I4ugv0RKpMtRVw2TZ19h8b$0_N;;paLf z^hH%wX1sUi5!L2Q9@gJ%upA)7Dz2uK?co2aHj$c(WuECn)@*nb5h;Jxs)B)g?@ zR8*xQ-hM@~6m=*fUz zQF|SQUv+V@WraULUwO0N38sCS%&Do1_4Oqt*e&(sjWSm6j(-O(y*) zYS`_WuNQg`Jb?UTwlXmg)Lo_c+xSj=Vx3K#&rhA>Q$3B;%BUlB&}C?RL_Q?S&X*uo z@2oo3RkB1{OKAGS!9-+_yT>*I_SHR2Zc#=g2e zK~*^2B$&o0)1`Yao4P$1=(0{e+H~a>gmIsK5OwksfATyke+py1+E3PvF=$b`fx4=S zZ+uiSi!}*$;Xvl@EdCK<*<3QX?U-^|ZZ0N&Olx>WSFLpem9@yUHfGBkGI&$4D;`4?1;J4Y> zagHx8MrE(mKOj*^S*p}f1_3B>Qlk?U;qR|K_*wHGyw*D)#H3ZDLL$BWX%ZXiaF>*F z4+lh5936R*Duzykmdf!FL+O-ZwZlVWv8!t-x$CcP*~j^pjV>4ValRkQy8X!u4yyZ~ zXo0VE-KWEfb%F5%Vxy~9FN6%eDPKA zoVy>#_Xa!G{fc#@%Eq=UW~P0vti@>CCR&91;|Ho^H`1GF@G^GGwh1o(iM?!tK`L9~ ziaEh($p*(ALSmhMr`q}$E8 z+G^OW%yr_J1**j2k}{oE)z0frM|tC?vA&hr8`GBU#mA296FkRV+My7dh;<6L=Ys;L zXIje5==QhMculO&A!A3zbjq|gb1JTp+7b)NG(&`*1)ed2M`Rwu9K$!0$D-NzT1<&; zb2r(o2<%EJu~-nq`N#!BimC!?Uj6(nSDxR7RT|nyylM<|PfO2?#=rKIcmtawFh@Fv zb7hRjx9;#=V;*ce*w2}Efe7UYoyNfBHY|oQ;3O4P=SvWt4o>+T`(|67^=fab}@8VYnGNIq)M5i2yBNfZtdrrNd!-NG9b7Fu=LfVP}k7*uoW(S)B6H3Tn zMO}YV9&SaQCCWk67$fjcsO$CL)J$9nJHz#YXRt0FGJdQWw8+Q42ndiAXs zFYDIQi9jhxyL*~;(~C&q57!{^N(#UlTYF^m1^c3K4e~n=<^Q0CNhVe^yseicJ9_~| zYiaRMEsBq-5&BQF-2hf(UGJzPb+?hLh0MQh7RUaHyv|#0nfA!6%Jig}z08_WoT*iw zEw(&k*(s<r22euW0PP?@c395A9xa;0ad{GBv0fkrSo zsVtR9eUrmsqb5TeT>74_^R4YZuOL1ek6joFtIV8R`1(CLwV)*;wM(?9_P%%S^Ib|) z78!UjnsEJqmU3y4&^(_L^wKtloiO`G^JnzqC(3n4^VdD;@B`vrvm%4NS#%71-c)Pr z>UsrnXJbKx&v#B?x@)Rr3o>*4U0wRS+Hzz2P=x)~sKkK~T-6V)M1j?wY7(B``OuA*l8$+z}rIfp?m%|^RobsYa$+X%-b zt@DfTCxCkX1Ux{H`_-^Yl*U(zu8A>Aj!wLEh)(>&&OVurazB(Jg1cxwaYivyPwTf7 z3+0XM*C?duY}vW|5D+wO7u?gT+O)+ltp1Z@z@=qW=mv};#|q!(#S<}Q>e3{ zunbO{u1F3|^s3bR|6$`FZ%adOeXm zI8i9a!;j?JG7X@4ZIHch%6F1(XA^*jHsb$`X;*soq~%C_+P_>$Yxq0S_%uWB0JT!pp4N5$ zDqqH)q8WE}=?|%fX<%;tQ9k!gV|4RO8&)Cnmad?dG^}u9$Jz+|qiS1u1MxACEFzg1 zm&!M#;Via!#lfuDo0si{ko8Z$NHC2_gdJwIjR$bs@R|nbwlSSZx0in9^MQM0^TO}2 zCq2x|GURptx@fxW?Zty(YsVCC%Apq3`KrE3ydLMG&~t1ExA-?Pi(QztZrgqkQiC~) z?^Ou3&4p!yKh!1{Fa5666+G1`8L|`UDco!vq96X>sfs9gOl@6z$#ZA3VDz}&kV~(- zZUpJq%&Rx3KN5n`FnN%BmU`>;ed-h|_|_$rU;eRz(T|P)JSTroc@mRveGH1>Tl+h@ zEFR-}lEkL>vHDKl1$pF}%AU^t{!7IZ&DMyU*6IIrRr^jNos}<3JsY!QtsSo3f;k(z zDAb;Cno?cJJ5(j2VQkU5NuY7a5zXs%cTv@+M79{+M1=7qbN4Qk7c+0fg~!V^G-#v6 zwls3mm`4I6{6B#eLp_<=0FJ&EMX>>u%+-b0Ua z=R@9t%VcGTI`iD}NH58sZ-a?ha!c!B;+L@d{?gA|E#HjC`qSP8D&BBBi|G3G%k5Iu z%Qf7!Ma6b4ux?-bNuV>X82;)IHzr-GSq@ALpG*f8YnQ7EGRk@{pyk-bM#txDe>9V1oz^YUA^NXJMDs)VN$CXh!vR*&(;dMS%6!hNt52Xz}fEHdtF zeURF5Qg%>7u+Qi`Xl&TIFn@@|Jh3)T%Q}D0XxJh7yWhPA>mGOCXoX$&-Xg}eZ6~67 zy^w?EFtVARgQ&LD1fKvIDpzB)Ra#2&NIP5P==Bz<8g#h&vw5)@Y=AV>YK#A{ zJY$e;1c>6=f`JN#JbtT|@P5}QbK!Yb&9kfeu0J+aC3D4u`<~OT4~0oCuY@b0wE3Ks zqC~rz@W(H;_~=~Lrmnh0WVUOZ>-U4I*NEJ%yGh%l+s*lzKLvZQZWRT|{ZmPxJos}g z<|^vH@zei_?+E(#TK4mHPyV6&hpxWOxAk^L+{XN|i3m$P*b8XR6ypk;sVU)9OVSE?c0*9<*>gDL2-Df1dnp&M;iy2(N z+ibxdcz($EG6Qx?uNW^L@~o-`YqL*=K45=PqMOwzV~+Z}ST7&?B@IHLCmF=+O?d;CCj#^}SZONjAf|zz z@2({!*1CGMn9>tC+-dohRvC#*8}U~ZjdYZ=B2jR8ucM=T5j8?gKd1R%dZtQTzxNslT)HTP?kA9!y2c)oO-H$ zorjbOeOEp+Lg9W#1w59uW02pb>_RVB63`5`V9ReC{M$gxxv4yOZjENs31ia3{=K;| zCs#cCX)E4eoN-I9NoP`_Zn%l#RU2=k!4aHX)jqW5!qE3;dI6mGBAULnf-!mEHhfe; zCpwZ+j{(P8QpMP*b&~{sje+r!fl0JW}Q4Eej6a|s1C}VwQCf~ygfvetTej|a23%|gk#7@c7C`m*PbNuu$SiqrVmHq*- zxNWje=klcRwEivdSAqfasa!zB;Rz2MQJW_2~;+$ znV)X_IC+s<>QO}IOb`{;740))zUw+@hDoyKwlxNtG0!TU=yarcA*os!^tyeAIjxp= zBc7GUObu>Mk@CTg_mIU)2{#^+-x&pPOs(@kpm2==Rdv6V7ud;z60E}-4aEnXsuVHdUw#9s>i2f+M{L|9LqQkJJ41#X@lretT~8qAf-#C>JORPoVGOhcm|G z@PP(C>$TH)t^KB*r<<-!bQSIO0oII)D^%;dUJv~~rjfPmAUf&n@w7# z)LC$ObDt_Y&5(*2inw9*pVp^e(QpWG9}Ld6da?1TL<7U>;jTwyz!LLs;s!gjcd@A@ z_oaMza&hge=(*#M<~9=nsCnzSN^P;g5!DWM7YI+P={v6QQ&F-RakAOn@NUeIq#b=} zPwr{JE5^o`sAlnZHMoLE^H!Cw#iYasqouzEdv_t3O7duWUJ&#dc_Un@P-jrnZr&wS zxKgF^JWA%!pV*Y#Cs?P4{OT$5eO9xzve}2hFCxx!HpP0w)DJ%c?qnZg3t+R@Q!)e* znOFZ5)PVf<7eSXZI{RB%{mDF2d`>~gFrM_5p_U#&4zfXA#mn@F(}{C&Wa>ecvGLit zLEVXPDX+OW_~k{%C4Zt+Ms53QwqLEu(UI88S$m?h*WSuXuG+70)+RI`|6j(Hc8rtZ z4nx-fkioQZYTu~UV`fkg(Q>#mO{`QSIE`HI`Ab~AqoiMvs%u=>8#uykRRrY%X~ZrL zHjVK&Y^Sl}0{MF^LG)l+7Bp>NpH{D4jprG77s#cEbb4~{yh#un`3^!1!w*Up=2p@N z7mDZX$7r4GjkiU(9m#dV_9O4XaBqc+>baMo{A6#r;+mvL{g+>e)|!xL@B$?7KFYq{ z8*`%ktqR|(4KGq=n-~^0w@(?O?LR)&h&x>Y_~gzxL$sGuUG1^-eR)1TmAB7?9KB#@ z^v*a&E^F2BeH>}G(NUv+U(K{y95M7%mf?9n(p|SJ4#odf>sPWVt7LlM%76PRi963w z+9Pak13>~$Ey)q!<1~|yz4>d1(K?|n&AsxH(yz<$0QmF;=>4!l?F6d) zkezb16|s7zO|&z_3XTu`?4Kl^+3|)kFj7RuzUv`}0_f)BBl1^D!u_QCx3j7>1^!Z6 zoOG1tS3L8 z`U-CKlFo0PI`g!GNl6-!ov-?1HIh4tletdaw8cfO5L29!k>_0F$ZtQ7#KByBJ z=Bjy0JTC`T!Lr?EfF@6vT9F^|%y~T9goo_=4Gzo$RR5^65Ktl)=r)Eo$wnBl*Ovbz z^n?{f;gmmp6s7AGHEVjyef8vF#YfIOc5p&PdTV#fcYDX4GVot$U8)w(x77ieEf%!i zSN`Sxoq6I#^{wd_u(_7}O$|AR1V>&^Q_raB6Tx8t|A`{`Y}s+-eM8-b7^%g-zc4md zwIhz56XqFcAko(18k?FJh`-UH^M*KhdpPZJrR&5kb?p!kKm~`Ip7u|Fe1m|<85?cy zP-D||72E^i@>kYoPwZ9`x$VP6oLSasto}Qy&#dr$6~3PL03+AkkB{K%jPE z^II~i0dI_{Ejfp@C_gkl&#!F)GCxzO#9ANn;hUvf7rmLyEV9|-EJ@Eb+__=t(RdM4 zOpj{((^pseNU$T~KXCB;_WQSXY_%gUD1)6nnqACpAZ%+8B8q0jBHy|B0Alcbyws?@ zvEb?{_pPGspO*iA&!{I}m*aTT+k$-dt##6ugfer0KR&9Wt zHw(w!$&=%6U*m}5Q!-46sqHKw1$Sv5brT!w4pPeH74ZycqjNTm*IN+o&W%2MLl(l2 zVk;k0C6XsTD8FT^n}Y}4yJD4ao2HNu+)cs{8-v_t;lK}usc#Pe7AwaCdcybgz!^eB zLE;!nCq4~J=8@P&o>kd1hTPG>ex-~TvBbSNv%GpDZ#=$C@xqTzvTw5uJm-~fH+LXM zUP?9Cv06^u(Fh|^PWfEvW1VWPV3Q6a+Sh=R%4vR(kduxweuRbC)?hxD@;AFu7W}X$x=r@8`-JcCYa0 zmc_AidH0&FS4QJbGA%TNP5i+l%{srG!s&w{Yi#z$P#=W3Se0Kgfgl^wmqwENDc0`3 z4Myg2av84ZawAbe%dA?HoW;bQDJvSTU%nNyC0pSQWU#&Zh+m^a4XoT3%9FG;nP!)i zLc84pG3(ZW=orkwv|eu~&d51kbc)~_9%3vxBu}kJb}=R8Q}X-F!b3K*3N2%&OeZY5 zVQyl$3uldJx3#6`W!{?j=#E?GDZPc^I_8(!cD!nD{iYJt&hs~xoEs7P<{cDU_j)YO zM?Sx6-?}lxAJeboN231-SExLbz0J!Jfy!K%t&pQHJK&qlpio%ju`?P1N<5usLeagq z9!TNayzqt9vAB_(R9feJs-?|CWmIAg&1eYy&tm!sa=W||Zhle{qE>#%AmvY6bHMtv zX_7)3Q_+G~4e~#~A(k8miGWHO$vF2I6PR;mW;DAe+<#-*WFnIPad0m~evIf{iFZY2 zu46ApgOMS@!&fk=p}q|v@#L~ca*VlMT9GaTg~cJXfjBq^C#xOaHTr1mY9o2fcRI@R z*t(k6AG{(Nl>5JIF)e1!@1R1}Zc=MD31+Yl>;F?u`k~dFvBZR_Gt~}-$xODTVo%@u z1Qmz_r>{=qENHl6o#rQJBF|LyY+noZXI%3Lti)p6xs0~qa56&32Tn$O_;VZpdWSRw zjoaL*@emt`Ava+9G+}Bnsi$F#YlSZtRd!i2#E!zdpZMP|9XP{CD;BRiuXW}i5)z!~ z#d`_rR5fpY?5Cn4-IcOge7<(&4J!i;;J~8u7_)NGTu_TpX$XK{st24@$3VoSJn*I4 z8nRL-D$+yLB*M9=MC?1rg#8-YOKPatnEQ*pHVget&U56;mwyrYE--%W+x2Js4rU#p zUx9kk{H2hz12Axfx_fMVl#mL_8^$rBq74>gCNJ}W!**(pX*ijB#Ho7@D-n8azQjX` z&xCm?p6kAHdQk@ZHG7M1vt1|eXq8WaP16pY9X9ex*Nwv?21+(U{52FJHm?XX;zI6L zme!V|r2K<=nt#^IHV`WJiB*$#e8L5_dwzId1#EvN?igz1EHt=XfrH3xx*!9&O9Jp5 z`2A_;VRHY{Vz5&12Yi8|zl8`Ne>KN^0g@-FHd{7s_(Xa1nJO6@Xji(9EAqA?E#sMa zu4eqrr+fBs%DFszs4%ZB3mgg=$0U<+o$lxy{8ZAq)v|Jr6VGjS>BW$J#vh*We!X*Wz`EMurzi&t8bZ28}Ff=_Ceo0|W zBi8N=Y7oqO^j?Gi*%h-Y$~TKnuLR)e}tJw7%3RA zL`#rM3wF#KIV;s}&0X1_ROB;g4io$WFQKv5Fjo%X|7He@vxHYN2JB|FlYEjdk8poB z=a+1TK~|~_xpHVRTP}Yy=O3s=fmy=Bp2fhm0KM~mRjPx?jKylVp@K$`Ay-~elxLHh){*+x4h@b_7ek9Brl8!+t z(CIn-F}~~upQ1~rVPULD$*i}?)8k@YGH$7h56hbXK^^|j_eZcJ=Aj;Z!MrP(Ujx+a z%w6zrkK*ol9@d04V07Ix8Dw7A_(>XjV=gR|47LH!12 zBjC$xUx6==7;B%nE;Mh;3pVBM#L+miANEQ_BA(B4fi!Jz@TJkq2P&fyLD3=ww_g7R zfXCw$j^2p@tZ>m6kE=UOq8so%;A#KOU++MJ1=PTU`E_&j3kQ*{^PQ)cxZ$bg?~cJD zWTL~nY2w4|8=s6nX8it%9aGe`8{1tuX?lkE!w4F(?>np#{kv~(K|<;nBJLFUGCDUm zSBj3(>Ng`82wpf$0bOUR6qJf86tarNKK-mz?*X%F-?v-6PJNKex1qaoqCpUVh6i@6 zF*oUf^6eL}kinkEF;uN(62(5JKh4sk6W_q!3fsgk!?P|6z2dzdrdnS1qW2?H~-A8c7_nB%XzG6SjGXvmF#@ zuH)_JqqrzVUK&6HF;q7)QtDK6J87MbK8Tx%nhP-VI9g@#kj>|*`GurS2pYz*vT=M2Yx!jh*Kl=HQO zFFFc_eg`A6ZHSdDgb#o4xafslb)KYCP4F#!E||F(oekIvxIjAyW>lPU+EbUbEEHx| zHgUIfS;;q8XhAgQb^mlYYodJ2X$j)K6@@YTU8*|w2%8mOcygIfnmwVs*F1e8_o2A( zeydB~dczdS%GpyX8*cUkMk$-9oIgRH)kwz%Gdd1_%_$o+K9y``QwB+ID%mMHSPdDg zB7n=hA^6hSfO$c>5eOzSpgm5BDbSMpM}M~C3Vd_FTUQ)vX45$7M5=KPHOX|ftz50# z;w*9_W4gE*wbtY7#WE7812-L(=st6;T1CwGjB_}7&B5bHc^ifC{(bo1+_#oeIuS1h zb~?)yyy2GtWX$GH8D-+d_@vcYb;_CoSW-ZpcBkHEx4+v8&KZyDyfcl}gZ2btH(ane zixL+G5nEat2q7_rYbzz8yR%lwxL0!D#$73eh1GvY0wy~}wuI40!BxwrxJBSZa5r+# zIML@|1vNH(qGN}pefA*jgM;)k9LnzNt=@w|f2BP>wz2uq3=%rXh#GA?QR)n?Nj_Hw zbpnG=Unoi95Mm%P!Qe@38Pz~UU!Qij z{Koc@6Hz$x?_Zt->vOy2j$OR&ytalz^rPT%OxKB>3W?;e@uYCe0n0r4fWm9Tv{Exy z`IH#_BNJCz&0>Q(;Aa9UYc#f-qdF6g{JS(u!C%9;?{gjR|@m z7HGts>81=y&A;&T3&Tb1<2q5gPJl|iSB|`znHPYyTLXFS@5X$4+lVNhn~%p#Jz~^ z2!Z|ugp}@K=Vp-ZvgF}j3fQW^k^OE-9mqkilD9yuaijhWl_9!inJe^%;YKh?vbRRp zM9$x2--YMnJs*AK^*ee=llaOoME~`*F`9Y7=S`Tax81Y4t!$6H>(Q-z=0B_x{!MXEztgr4KUuLwIo-ka}107kYk}6qR)MQVLt(`YJCA=>f`HTOW%5B&0%7#V~uwt)*dYtkQC# z3baJt4fg4zXPu{`>Nj;RRH;mRySdWZ0=Z)1wK+uAj<`|Tc*Z34fl*q#%S7(LWdpFA z^JL8kgQ0DLT(C)z*Zm0iUXBJX88lbe+i4AetQgbR|B$A4ZOTPt@%1wV1olBfeC`zn z|2=vQWO}zRNhzP{W>DVd_Z|a86w9}+3f-B)yQEHqe6U+5*3I4Es)usM7{kRFJSCxr zLSk*F*E>#vj7M;VHw7^I^o-1AK%cBmFE$(HzVDrDv*I&gpEdUqTQ>8b)AC#IrQdo1 z!~TT#=?|rI#Fk_n6jDC(3qxbK@0$skN-Zyl)!-}Sdm#sK=NXK^6sjvCd^2n@=%g05 zL3zf54ePWg>!5)0H63-?A0B3$wE?_$q1do`wPH|9J@P1K}g z;~2~GvA24?WRy|UiuGf@BSOr;oQO!}!serL(Ug3xT=&}LIkp3*nv~r~cO`kw4g?;e z(_kh8w^oe;suwH=uaegEd*>IkunL%i@6q%uvrBuYY;e*1P*BXt0O^Pp%E>LF?P?FI z!#pL1=3@KE!Wmc*FQeG4mj1%fEP|JGk*cieqHB|jel@YIY@h%e6VUo1mb&WV+?lHi z7Z)7wp<3cZ8jQ{56p?>F(W9jqTBEOz4w*#HJg#*#iN0OFN{N@!E3&)*i>USF{^Nvv z+WvXExx>1T2J7EV5H86)kR#P{^fbf=8Vfyev@1-vY7E`<(qt{*uZUN`T?BLxK|%yx zcFGN7F8oWTr}FZwE*hv?OFIbXFtA_JS9vJWQJO>hj2tzEIog9eX>LX28qV%r5X%6H z=`()-D_2eW)Q(+Q!2($NewdgRoC)eZ5{KP_Y5Leqa4_yXjqaL2T_!eTQ!dRtN+uE2nV~aEduW8c zh!2`dWyeD9GQ1hwOpBCU$@p+I-4sVo)Q-KRlwHgh$v2rOBDZj89{5tv%gJ@`=1%^J zqtp_z7h69^9-W3=--Eb3E;<#eGIXawmC zuN6Kn(Q6RCH}C2KgP2!tcoPSl+LI z`_^OjK%R4+1l2U9{RE(!LB0l(ch*)A5?<>Gn7YM)^%S#pV((eVFj4(~KlXHbgx7D| zv>;lc^7g!&*Ezw7E~o=I`?KhE=74gxaB+{A`7rlNXHHei(VJZ%St?#L^5GesvU@nw z5i{^8{!tDy#-~Ltu3y2^@Rj4&`@MzEiXQ`O=NM}7YZuPU(5cfzkOvCvktl4>i545N z{F>2BEAut`u&&{J-ZTd7>NpX7DWEORz1NOSKwMnD4|}$i%!ag@cPr01 zQM03RoGLHnxW)w{C+7;PP;llMU>h{QeAsM}##-1HsZ7n2{GwDY=VV#0`$XNezK&78 zUnjJJJ)jLj0Mq=!WH}jPQy;}@+&^iqBpA7krQrG%Oj?+F`N8@i+=Gg^CY!`rrU8-> zjnjT#qa3=GO_l)3P9t>Uo7CT!JXPCc;`eGUgnjtT`Alg4Debva$MKw^6dAnKp`s*` zqWOMDziF>4LCd#PMi-yYZgIaDwjcDQ&t%8hj9d?{Cw#vmu*IcrTk)D~q~TLc z=ry8R2tRWQq>N)2&E>dJe0r3lmzO4+-!)X&LJ-M=d@J!qV>x<_pJL^hXOl#PtNa9dO+b9feSIxr za^4;ugF*$sQc&0Y?WkVZMfK@qXK7Sbc?7GYUonnIYW9N%JUeCJ*&ib--4&f63FOZG zK>#tAO38*)?Ah>C6g`2KlTIA^_d*+`;Won`D zil2GwSWmDI5P0|Yu3iJ)?6)nUp1LzSck%Q9j%=OUA^wqt zb?4Tp7~>fzUr=k+?B4ehUD)f9$c@EC>#KR!agsWzvQF7^g-_p~|2>S?VL!TP7a%}n zdcVt#H=kI#TtniU|KUVWa0f!XnO|xr)wy}sw93JWf?dpl8J6UaMHexpjlQJef@S*8 zZJkfCv)Wu)PF4IGSMMf9p2FCj!PB0V6VH)zXz>8^1% z@b{!&U5J(1M}XmZx4DqSQu8m`GtF?ozU}4o6GV=1qNS#?Cbn|)P63V{8no4s0Q|V1 zz)QIZW9p%3DEhfy(lvT0V9|n;#VMD7E<8V8_nr|;i*AbV+F(*^KUWvm++0YhHB0+c zNwtox;`s#X6>_roLuZ>ptgOpK+{|r((owc%zL-!FM!%9?9ZzM|#Xg!3vSdS-AZ0i# zEU^@jY}+*!)!+!S&`ebUVon((9pO`uPJ{_>TGp5BvJ$zpxh|tdFh3)e{Bf;y&-(ND zWPV(=CVcVHN$w%-u1y~&ML$t4T5|XXfOu>JbEfDA4<7gfPR6fI6+XM*Ihgw4qAT*8 zgY%NEg{E$&(=yroP2HB>I1!z$%GoeU&chj5UdlIE&d@7Y&6Uc1ub=-N+F^X$2&7oe7!)r~SzQ8D_+*>r%n z96eu3ht^OI+zo&9v9>?mavyFnB(Z|bGLZuu9om4?!Cq;pU|65Sj^g-KqgNZFP@a`W zD654{EvQ(%Iw;87OXhVNz{D5FX4V0z)-If_#<}CDWTJdlR7ErTfqjcysL#XZf49vy zs45#)&hJ-MHavuS3HN4m#05z`hq1M<9jFC->}HI9Im}BwUFMH==C)utrr}&4ORA&sPc>_U&s2>C$}hjbIh61o>uH?!u3VG43bXwJ?9YTCxdetZ zJ+o7vVj$}}(I&GkacsgM3kKFs+arQNK>&M`3!`&p>DR|)Ad7nMOy~{J5~2a_GnIHc zYGJ_fe;#-vC)zspM_!;i_X~kk`JIVt}!lkkHDC}cu)aTjIK+>zA_q$GzLyVoRM z=LQqDFr1SSf(Lt64K?zD(@2}z-ht}h;oAI4nCsb-*nIG9l1*|JLdr8S!CeAt8 z#)mn~jKO1#e53^R)j8g^jLWVz38NNL`ADz{U5rG5-D-nIF11xX5)tI4BJwjlsi^yr zC)PttOY6asF6d*6cV}(ji~XcLiTU&q6W5Mwz{5TR&-O+tY>1|NYo3qHCa>2B3Tqpwd^hpoaLC!ha2vk9m{j_I4t8UjnbL2j44U8d$r z{!QI`Y;p@@lJY~T;t0Bf;Z1>oxJ)I9r(ga|N4n|&vWHxVd)kD*ac?(FaO71##4=>8 zT`fo-05-d)cH&mC__~ZM-)1?GQ)o93k{7I6*J}xYs8R&*A@79y%=>%_PH5L=Xq&)} zdvl*3lTmM#;{i&*Uf&Y)t>PoUMv^7I%$*(S4SzrC_>e+vwtod%)o@cQp_C<7bzgjj zaxzvBaHwf-CXRDw)_m4^0#oM&D6uFE>H}216bIoWG6&Q(6kfXyOnY!Y0S84kEERNm za}g);qaVBwwjyu3ggp^Y@pmDTwllUd~m-Eg?`Vv8!G2S^JCT<(%CBXfw|Hz{=~eHWMzESU6?;m`?AHJnq9UEO(ZoD$S3R4LIykWa&o@{c`Eb~ zSL|Uz@PCM~1q_9wVHleikObq8nYCcJH0I1|Fv_F30ZBKCwvjrQ@)HK$ z^pY@uI|Z!@tO@&GiP&ug-^cJasSk!B+dmY`rK)byS2sTK&KOg2rP-Y&Rdq>em%TzG z8rmnNzbEB?m!syP%s#vj{(7q`Xv}>W4w+%@05G~w=RhDNA$Oh$-=NxRF4RaXEAm{` z5=>!=nPoOujdwf*&8~jc5>%ugXqCOOM%Uw^adE{EFB{t}%xk;<7BVVMpAHHM(Q0^e z*3PQ_UBH27={)vmUb~SwcrJj-1UdSztr zbiX0(ZXx%tXDPE3rt87XTe?A>XL6|axrHll&z+R#2!gd~4QM!>W0_H3P6!EZ8pRh3 z3VJzx%#z1TqZ?qEMGnxG@x7&qRQa-@gN5@Wo~kViA$#SUl3EO>64qhi$1D|$&~9Gm zo`WeI7<~W0+}WK}Hp{HHn|r*NJ)l!~1re3(2dU9HV#4$=C&hhzGdiSqMlVZ{$K)RV3=Vp*-5LS-49t^ur)3Rs;o|YdM!rdE z_7GCfW*pu%X7V)OY_JMF6xFLakFWcmAAA&MA2O}b0na#A+nE`fZH`z$qoxP`!`+$J z!;Ay8nXuqP;B)d!DuD2FLW$cMQz-nsFk<#p>dl zt#3RyKw}KRP-H_>&k9n3-N_Hb$4 zc?_soYdz<~wg2A(dgK!5lHm?BDU=}(D5z}4)^~#Og|)GIiLb({pZ-{x}JNNmqLu0#_{8Oe>}IH^yCoq^(gRHzUHvSx@aYc2^9D? z|2>?qJR;s=hkE?b&34wsE2QrCBoGpmZ$>G0;Yqa&9T2W$PJAbjz8HCmjuV3s;JnHO zc_{BISQG43>87X5844MJ@>07ag9ic?#lBB?urT7Cln>41db???juVW1rg;E1s)- z9tU?JlqR3@DqRmFNFQWvfn|3=5>8~fw(p4CPGih66+Ak^9Z|61!d?LDzc5YnYFUWZ zm?g}E?ed=MVp23htGvt)Hy?F+M4+yX-#sG!foxjl;{BuQ|^mc|I(38%?70D%-43lqLU1&ubq5+W?2Ck4Q0I z`bsWtumnI!&!fe9%x1BaY6qsP_$SL-q_huudx%|IBD_Vn$R%RZU~pMeDB4glFXaY< z`0Kaf-+*|(%RWNGVm0Z|o`>?M`HvpW#t2`OWALX}-@+dPQ9NJy#aRQmCIqPv#a*j8 zSB5gYAIRVSH*3_K`=!9BDYh_4OnBxz%wDoKRgJdA$Tlub{t2k(|DUH1HCACgoi03z}Ec!6qMO&ie~Ewn7y@V;a|4I=xOj*G@v{ z=?2luOYr$1%-;dBrk}%GuCD(tc)!?IUypl(ige=1(b=zWSmU=eSoVyCwTKSnDB6Re zUUk6VA*2`We;+yNSqtON3j_n@4Ddo4p0pAgt-h&b$0|%t`q1K4%Xtp3&#UPS2{z#( z`ulyMct%B>wPf=^VsT>MA%RZ6LO`d6p%uWSa%@5K+D8-w*?$@ih5s$VqPH((AB$^A z8ua?(%n&RUWD6BA?SQyLUl3W5Kw}St?hl!>J068FoRmdGn8M%mCa>vjAuIUfh$`TJ&o6#J-h_ z7JXZE@$x%{+WkOdH$Nq1I^nGIE8)mNpAu4btJHRUGq-L~{+Bq_YmxM}M7jJi~O`?}cURw5tX$FOd)(BShFIu!n zTH*#~(V}ZBFV;ro1r1-Q?Jwzc+fps~?ow3rho(jy(Xr9uag(cV2jc7!+&0xN_Luce zC+1~!j7;8SuY2c=CR!}#;~V;Q)^{D>X=7m|lovX0uQpj*t*M}_ThKvopCI(NOj6;4 z{4H1YA)oiyp^b2%rFr@JCrr)t-N%Pz2d9U9+w&4px4m$~az0nD{QgbQO`m|`D8O;UM9LEjhO{JhfF4hA*ceV$)`jPp$Mc;ENlbI*C5*V#&_lFk2io5 zT(Lib5YRY98$utU1eLNsydtq$V0AMEV5pVp$o@TaL;~R_G~UlYi`U%U5I1z&-ErkG zL@5CGR13{_vhv?uv2O?x6~#0JiTy8>V!6J*p#+nMA6MkL#-FJxqDAAL9Oxw9 z@DE~mo6v%wIxWgPDfZ$=Uh8Ld^;&bjbaP_XC6}WYhjJl|Z11Ga*D~#~{iMAngI|Aj zLopf!&23;9h@pQe&AB0&yaX}IpnThvd<35~lqRk?6NU;qs@=|bc-w7jna47J)K0ne zB9L~HSB+|yvDYv2Gc&77ZyYp*Cy>dBcTG|57Z{%|VB_clJH>_SDfab`Xi z4fH+49k0^V;=@gcJW9~X{Ob!RU}uAVJZc5bEcF}hEg5WkQ_sG;?%J*`ye&8ySCtp- zO&^I(5Fk?k2mClE4C(AF=?PW&OBTO0*;sZQx%8Ij&rC>WJh)37YI;zPztLcA)QM#LLK83NE-xe&p$)-%x4w;Ov~rPiCIb3iN+N zwEtX*{xL^0+t3)ktWN&g-2PwJMwhU?xhzkKaDCv^KbbXqP*u z;Xat{GD!$Rh~wSirlZ{c7>rH(>QN88jdZ4u7>j>;t;;i_P1ZP{V!KK!(a{#V)9WfQ zmY26wRCRS2h9yWL*4TJG`}Mm4yuuEhb5HY#xV&B!kg#cFL#pzmjSOpr5~B!pV$ie@ zZ(v`bw5Mg$@q3j%DtZYzBl`0OOiodv5u?0)GGLjA#jG}qVI`GOb~^kVy*+yc5IT3Q zR!uFbiYJy%2EgS50SaYh=Re3t6D~Y>w3Jld@{E&1RMjI_ac7i?Ky{-!S^DU0gpG-C1RJk12_Td*totMnKrKZu^nJ6DD_Z{t|RV8W;b zQI{7u!x^AyO%>bbk8!YsXB#eSA56JU)r8#jJ^r$)8M~k8T_i^&9n9oBw=z#Q;A%(1)_=4gjFl1ufEJWwRmlx>A@blgHQlj-^vjgf5t zC)SR%k?~vTopaSmVMr>Nu6V`_jbGW%D(`LMT@u=H1f4lbYnh^9c5&eEhl!2X9rGMe zDQGMC*o(;N@){ptwo~Cc$&0S7vIe&JPIU&c)Q))A8Rbk(~{VQ3d79kfS?LQM?H zEw9<%1v{%h{}mDZaLk>#N}R3F2!+KG5u|`ld&H!@+Fv{-hSaofy3KlsWJn0Xt% zk5Y32V*g3S{th>O`!SFI7x7H6d0QmiQ`C6U-N{tUoy)<1l!nAzu&lzJM^9+q&&@45 z5l=t&TY0Mo({G9;3wye_`B#k1OW3O3w@?9$StBK=uQ)g4YC1TLK|ah9k)q|1?Ceqi z(6r^TlQv3EPL-kthE`tT1;mRG!@}v#PKe@HhH__dU4h(x*yj2b!7i142!nCg84KmF zy3Ls=TlSDU(l6TW2ZP7RjOzas@gCqFEbF|P4h49Wn|wSm-zg{Z3*JqqpSzs%XY25QURc5iXti?63ZQqDdJRp8 zudRIFuN2z-o>0qSS+e;<4vs{ex8oYTcS9C z%PO`1ixVuMKhCAUpcKFz3XKxi5P|piuTv8H?!eyMKMAoPcv`+fbmVAtAY!{tPI7)UM9(%LZ$`eb z0f_+7noilsw|O6+{V3G%gY!$Qcp#+-9F4&-GydJ9!&nH zVyri;49(yx1JIcRVTwnNjLe?<(WiFiayc>FECa1+6kXOGA}XA4f2{9zfHT*aU1iNB zj8O-V(kCU#ajxCDchK7ayn;h)bZCJOk4#w0u$s1+jF^DO$SmCW*z!6EF(#SIv8?wp zj9<5T(HRo2yTA@o^X76|Pj!LUWnivXQ8u>ZF`%ICmv2QRH37i=;Pi%5|8PQZr%XlZ z=Sg_=qxpD`no)H7F&9D7W?}??9e>%HG6a)4dmW6YxuLLC@50+S(Vd2* zfkrLBY^&$O&NiKdiL4H5F`lHhhms6_8XP!a=_xe8@}w#R1JIS)>e6RtFU0*KXrElI z0Hl=v@#C%O;h%pY8Flw=4kZP3TU}qDo|53n5GhB9|5W%CKPS}PO!;&zC6BeKS?cG` zsY#{RGOL&Qi;l%uU#H{$V;4&#DzHDkPLGBxeca*T$p`v#k8v!Y0xUJaJz1wip3#3* z>hH1V#zSuK5buXO@en(|TC%8WBqTWyy^9$*jK4bUgySr=l%1o>m+rNer)qq3b~^2Z zxBEliBa&069qPV?aEK}~!5(e8&h`Xd)SC(g(UD(!ysN9K20BV!Fi)GZ(d{3-Lx(}p zH(`|p>-n7fboRsQDc*EcowyJoiF`da)_FU;edQdGwJ2sC_PH;O|%I=}vyIH}1pbX0e=dWEYU| zDq0x0<6&!^r5z5~_#K}!sajLT>Xb>?`Lhd^j4&D^aTbnc1*yN3{*V_?)}6Gds^LYe zx=W9~|MdQC8p}XsWGcfN2ADqMMt88X!Cp*fLG3i^GAgYRz6*x4LKThz4^C?RDvf37Ek31#gyD8G zR@tGD79kN#bT=u<3yt7MIyzw2^ds^(sZ5B3xMX*VC}J=_uRN=cm(=jymU2icj-pX^ z)`IuxelZXn=Y82?6aFzPIq;hf16PAIBB`8*1$y_f^D&yXf$~?Kto7;XtQg2B%A!q{ z0GwA~hX+@^1*=B?rH2%6Gx0e8&Z-S`Iq1ThHhrGIaJ1&S$1bbcP0}Q^V})6q%Kseh zYsnf+nIxRInJPs7iID~34dHe_dq?z-Ey|oYRlzGKArn+5X;H9?jXIj&Lf{L0;rn9PttD$5pu0!LEP}b%MvdTERV83R|1pFp$wPWnwjo+`JG?Ej3@tkL3h|s{M;fwO%U}%iOv=YPa_KnG0A4Ga53Kt-BGqU9M&n9AM_7^G*)~59qlE61LFSY z4=FoyQ{HW4)t_Q9WaIt{+j_NmJgNN3??8J}M4j1U)$^_Wy~=Y&Xwx3D6m=G zNp{~?Z>46$uIo06o=sZVd@A;k{_a%E^;^XH*$!-*r`eicxeb+0NvZYll6;(dl^{?p zyfdArsGC7*t&&3pSbfq47bdQ>CY*wc8iEGs|hbR?Z0$g0B#U_Q#<=E_ov|8cG=^CfP7F~$+vdg_U3$2gEtEe z3kAl_UOS`5+efoRPW=8KM5&uKS&lpM`>#)5zWgsn^Kqi*`t?tsQuL={!{%qVtYzHK z1QurWTpVyyP&QK@mnng7!^L5;z=jk&xvB&$I$J}h(pzcJ?XpInt6EQ`o}sr+4Es7p z8M34-U>0d(HP-Qfo^zfXPCLAN8-ICom0b9iFor?BcbHF>G)Ot8_{&htjF^ZssH$w` z0E&BpZ-@a13enFw0pT$H2>$INKe__@oB8{Zl!N!g>#l7D-n!(RcGuB8`gg9}2qY-* z_qbLru70w*zFl1^x4={sHKAeG81Ssmk4iPSp(Bnf(G5Uw5tN)`aDd9fIkGsZo85Pi ziIhvLPgrB#0ze}D7F}>!boA-q18$)j0^s4t+;hQS1C-6Xu0u8CmLn~kFK?j?-vHUz z^1Y0V^@fSFt}sWsFpAjnxQaz=ys5e<{fW8)%H(I$OC(kYmCGM;Q%;!z7G}b(PdR&N zi>R}(XUlyP#aPF^o7WrGf+OjZYkaMaYL0;oNmlA*)0S(WO|+4ZooeSOamSA_+VYGa zp`THC-sDE-I@jamZ-BY$q?JhgPaqD%Q9DJQf6|5Lr5$k7`LPZvT||?2?wW3ANln5@&o2yA`L3RuU?NTW}3+MrS`<# z{T$%V*>C*DTL0GU^s5oM3U<}qJF{yZ+fkLv_nC)q;_?7lSU90_2$*tBgGBN^g{%2I zNpK4I3aK-6TN(c_v(w&Qys#EeEBpspd)s>SLj)^;b(z8|rf2t@@UFAHN*6;7Wyp5n z32(J*ao#B*cwHMnhr=+v&tKS!$R~*dCd$R7H&~$%{O9vT1ljIa<>7{eBIhO?5k4!8 zE&gBhH;zU8Y|3|So%zzfhVXhJaLy)oRkSp&mhOx0X{(0{%P2=tqF=-CTr<-Q31ZCa0qsFyYHQ%z!{FXg4L9R;~G@m|H@CVC}#w7^3eL*3!#jU1Y- zh`nzG%%zTZm$F&Te|Z8j!dt$Yn2`a(pO;C`2E`WI7wh6js9mFdOD1~Zt{~+Ew_YV$ zlymy>U|;A;>1;*IVV9#>xWu-qX=rh4B0<~++YqbXL0wVa`L&FT{Ihf}r_>^vBVaLO ziSPD%_9Oz0HJj%eQMg7<8&$lwYz&)4mrZ7Tw@hnhRO|JsYQ4OQded=r3pK&p{G5f}4*l{a6i5+llHx@KEt) z6x{D{VGQwO(zx6uJP81f;XleGLHCf>G5|8n!tGYkb0SrUzyK~VutY-dhga$6A!~1O zU|bG~l@zAB8KSevYu8;!=+PdZ0T^=?PC;@bd9?@b60`PiX;);f7Q{FYMFbv4S-fGB zc^EKOU{h@j=t1;AJo#pH^q+-GrGP5rsvcFzV~bpqEZ40I2IJsIYYfyFMmDho@a*qs zQV+&|v{o1wXLg<_@0#!ggr{(ex7cs&^SaGrFJy^~BIP1a?r*BUrxAZ>OC0n%kG{G{wmH zBf&GxfdNsBRkg-Y5HGP0S_pr7?H&W!7G@S>Isy#eeq-6krf1-co0IfJN8(FE0w;Kg zJTr=3i*%=jLPLnxUWkDSd3S`OXqU}953|^WqQ%Q-`W#v&`PXHhB(6~3Mz(?H8|W3@ z+-G=!z^2e4`em`zogSK#mL!*d^yl5pNyywpKO_Ma1J>+UShF;&Ea7#yys@Li0 z0Tlzz*u@JuzGA1kb%g3Hhinrvs`dyB6XKh+v5bFW&kUSuuAJN}Rol)VIK>~?IuQ;W zh0QJZE$<0A(U41-iO6GS1cWAvoXwg6nTE$lfbweKkox8>dA+;`$V9-HKmF7+q}?&b zL&tt3;=M_MqM&_rH|{ipvb$m=AK6Y4{Jk~b^(L}exVZr-Vn3w+XM;uh&702v_*-)& zLz@B?Czd|;COPxYAt(s1K-Py;Ypu^s0z>##(jId(pq5kAUxDoKhXFvBZjkk z+uRuNfvz3XNfJu0PSxm(h^z@ZXzq{u&84n!YQQ60R)B2gL{y0}*G1|7B?Z#ocnFiE zIQ8fK=l?@}l4NfTeC%VUjodBxQ)U&2^Q`59^z)#U{@%QI3Ky9@z>YcPm8;oyb}E77 zyp6A_(8x1lzS0@=DV-9U4)IKnD2=AEuXcnEIK|McqiBpWUWO5lJIJ^of+l}CdPquL zAeiP5>zSFRvazc~SO^gjSK3ww-SC!oM7|g+60mBkZRN3pXejG?gPnz>D%4ubJEv+g zb&6q)hqAVDVx7n>mzk8;C#URe^}H$P|8#0ztNW6&lbUwO2zTj*SKR2rL=|lijn8 zON)ut@@RSC&)F1BLPr7oauHHUDxn~|LHr9xs+#;|yX#kxfIep5?_F5uIt|!4gH6Ud z?RvnmG@9U@cogGDe-R7BJcvHU`ym%VO$k`8#*7V(%6@JJ`rPfU}Shv+e=;5kV>896)wAY9lMJb-~Hhl@lOb<8JR@;vLZy zd0MWbPj2CTjhD9y2jshwb<={tIF=dmR#m)f)ZA>|M%7CQm~$OHNRY!&k|pQNk01@9#za2xzd4J&K3)T4i{DXJllRkXX8wnGp?$ z%0&${X;Wc6>any@Z&ls()Z$78Zb$z{rS&kEeYaG>R#~bRDsN2Xu_^P7$>qMJVhvRV zm&~l=kHDe<3bl^0&L-}%;@u-)c}6&>EKKwP1SiI>f^b8a%TX~hoY!%EAw?v=8uMSB z)>xyDscd@Wn~DTxn^a7v_Tb12iHE3Q#;GEPKS?YZw7Rrj+T`wdjrXR%CgME+#_Xhj z*qQH^JAl;)YaJ?p!C?wU4?8eY={eCPXLn~j%HN%LeT}Vb+Z>23583PBPsk?S?QfaS zC;Blq&j<^r22S_QLWjMcz)XA4qyZ}`5x-|PpO<>U`vjZ?oZdQ2Mhxscec5T#7akxC zcg)FUZ0wmA2zyx1)ndX-SMjiL)bD@+k^lPcT9h5gC@B?P@=iZW{$`r38}uMs$b~ft(p2-9!)urIQI+a(?xH|4Mb| z$N{*>Bj)?3k+1EIyU{PoOA6`FiMAsjH(?Unp+CK!)B_YjFKVBh*CN*tOP#XcGKTDw zfuX37(OC@8*tQ8q_{$UgeA?6XtmfF1=qbp~iJ;DnhHV29Sh_!(&e(~ua;P{);43R{ zK)95C#4}P(jAh%zEx7r7JsNS95pu4T+`i?fvb;ngbk}nR7YD!NKalbp* zi~2M7UMGg9adlcbA{nx8(x`aajs##825_(O+ktpt9Ki$dzkn$##9{K?EDAWZ`hay6 zTdCqW<~j}Hf@K?sT1+fn({9GVRmb`m7?rnFR>k8$5YKUvHi&g@n_oHA-NE5{&__-h zB}-WzX3?!*C70fTGKj+V+}+^b@MxgOAMf9=-jLu2f|j1lVq2NS1ye>vHh_*l7W?~< z*@SYfl6`&Ne%(6!3G=-v<>;@7I$gU?x51Em^nmq19lS56*ZDELg@fJ^PrN$Q)*F&B?Z?d9CL|7wYznX_1}LVmvy@&E zkP$;_g5c#zJ9Pg29-W0W@N_I^lo3R!yWH#HX5p&&(rJ9}u^t4Ew6%X64tj&otlupj z^l`kV{P3>7=94;QNxf#IH+($>@8$!1GMH^PQT-BSzLraKNP;mg_P}H2U6~f^R^k+m zmx6OfEGCY?y^c>+KsH*WuKg15a&Su*(!=D#cUgAI9EcQ# z>PBV>t!oLlDdwW|Bv@BZJQ*XS1l1rrNVa3xPsl(&Z8YcjGmnT#rxeKpaC}qISn?QDhH<#Id)pf@^=>=$Nf`k6l%Dbt zf6?<-h$>QRofr>h3=t9h2`VR`ANk}EKGHv}9`>RK>%_=xzXuZzLyZc}4V{Y0(;wl6 zkv#TY$gGS{KF;b4%ZS5_Bg7}h9>`)iWS0hk)kR{7_*}4>HuLdgL!zsC!&PGaYFKv9 zT2FdUW@K=GL)_NkO0O~#U}RLSASNbmug(Sz8W6+$9lEf;0eZFW{G$H>>>MZ6ON}eb z*KDr~oU)#XX`<|utAguzND6Gc$Bs~JGOXCF;Sqx#U0l}$2F(GnhYclbCKo;7emg35 z{lZh!sXkF}IG8Sa)QqF=iCFi0+v))_p2pYo|N3j~)ttM)d!c2!V8QHuSXq|d2*`}q< z4fv6#&LD$%Nf}M6>k0)3P4T#!O5Dv6d@EMyw3yNe>BOCC$F5HT0 zTCguV5dXo?kp*Afj0Mz0BWWwjoHo%>$7LH~OL4boa{wSN@Q|x;%KU*hHq~FY0q!!6ZTs%Ni18}oxXL}MmBU9jZel!YG+NgLpW2BM6w>bX z%;jRz10nk3d@)Mi3+!<9NI(+7rD$sVTpA#2xp8;@r2`CLdK6p#Yb%>o4M^=+Q{~5n zQ_sYeZG34(5Rs5xI9Nk*A;0sqHvRe=*BRKG-BF9*YH@7v(!A(>_tDLrT$n0Xh&2mN z{u~CReH(kd+YBCj#*_PS{4UJ6Lx2eJbRyZM!YGB?=*q--!G(?coq6M+HtbgqYz+9(Y?iNm(zyIxKimD*)8;_#6SfCysgx+WW*`0$pTkiq@0Gpk3>CO`kiX-YjU;D{~?Mg}en=n$i7KqDEPxI6Wf{bE7uF8Qns5M|7!f(T;JX3ZMgQP#cp~_mJv0-!q7iN@ z|ByfkqG;iT6x}Q@+AfM~{cy1mFE2tdWkncfgMZYU&o||uDUS9<)QDOara@my`()6U za?>gH!~qU;Otp<+!#ham9XOe0Uq}`eGIL@q20+Ts`!DLh38G;J^pb=?mC(%C;1~>G z=KAOGEVGKL4DXm2u#6>5Zslz@SCJTdr8UaUlkzXihJZxMJF67^lW`G@UBL|rW%asQ?CoowgOVnEarE5XDow#r&=l5{D!xs3-Ri<^~bTV zaFBHDH`E1G@iWA7FlOX5Q>5#-w8~!vBfAVhf(4%s?gfjnM$JHa--fYQkPpUGC1@PpEHetX3y-|N51szpXig8&? zA!SF!2$h|QhUKor!<3echZlD3<#iDhM83-)tBZK1C64EEnkPN~7F@}D01Q&JgM3c9 zkdFeM=~G>brtZ_iRLW+hF!|;&;OLpPd8Nk^53>TK<&UM6hrOS;Fs>^D&i5T_`jT%f zi}5Nje#7l!>G>m{|6{2mP9c}{VNI)8dB0MOP@hQAYz;Eij8 zX2Z;l;)s(TITtM2BBLvI?F4~K=pigvUVF7ON&g+QdiV!*KNtbIV3CeUcLxV|5VMbg zis<<1KXGT^2~z<`F8eR(d7g?_DT2g)yFSJ7Fx4pK#l<)Ak5ZP36ddPaDUbY~GW6xA zWHoPS67f<I=z{UNqjnh5QhN$GwxS_>~-goTf14P<8$vnWyjg|&|xW(zQYoEp_QD;Fk7YsLa zjo*!K8d^}1wFdd3=83p?dG%!SCott>?l6bY7--JtEZF@>tWng)@Y63_HVRKLkdGrx zj*}lDTaLU#J(qo6_dxXKq0zCVZl>uF0KT9K_!(5n$s$DgP-r_Cb$zZMyWmSUap zm*Mh$T4)*zBs&tL7~>NytHk`>$;Nv?lm3knk3988$!yA8`joYFee;sKHSJz|=N*cz zk1p^}genBxh4L#-WH-j^9s>|VWx0fbFnoFpbe6zxI^N2DUD8{Gg zz<(W5;%gj^60n&RI<{vss$`5NM?WjfI43RWwyjSjBJ+^i5Mk4O#NtMXlPN(N6_HSAm8yWj6>dpyi!*=GFV% zOCNT>uW(zKc(NM)-3v~9Oeu}S*|me$m(zNcoX~U$Aj*sg%VyG~9m|rR9>;}@F3cvG zpUyh$uv|+&4$tYe7GW!Dwmb(oTQ_8PiAZX49 zzvCaymJ5nnwL^j~0u8Di6umq7{Y`(t(pumPU7Q*70=W7=S{CBstU?&nj7(#Kq!u3# zzh3K|w%e5NA@2Y{V)gKw*N0P_bmFql z4m|X`bmr&A3@qpb7crIF9tK(>)+B)p`gavYVD?u+G+F?M!~4Z42?^Y~#>LUu4;x(W zs+m)yNe}`}B4C)sOac!##wB<)1UII99QXYK+Wg)~`O=zlOW>+`*S6$ee_N|_1jS3I zd_OHM&M)z=c$)8t6oYp1*|3W}%87!612(V9RWjOyhgtkAw=~3i3M05MX*2WXx}!Mg zmmeb3$Dw1joBZ_JrtZ6cg{>2BScM>1zK(PRJ)>jhT*ZEUA?=12U|%V(uoG@4cw?AT zm@VaJ@_EH3U70Rp5M{{M1^GmqFL6`$=9hmoAZ+^vKo?%!Bn-@y)7q*a04M}SF3u(_ z?){x<#3331EFzZyE_!3kNHnyKB}A7(*)4g2nZyNc`$;s>RJ+1 z;jjRH8W<#$#{16ZQJRp!wyP^O4{1Bqa!U~QUXwY|xcYlAmKPYVLIibUrU?8gEY@JB zPcVJ6$XTT6oqfFgz*iu`AL=uim8%CS8Ry+I&BW_CxATPmS(v+CAxq=;-ZHEjI-KO z$fp|hlz=_dl(N}v@lz;(M6TPm#fdTR&bp0v7fXf^NrgXOTtC?pYWInL==84}u7*M} z3=>)TfbUp=(=~{|I}!E0CrFABH~t3FqjVxf*c{-m)hXm(7vDEfoaKP6UEoB4Hghju z{(inrT!RBXW6dy#qNQ-qMTTEn>=#Bv3-Y!iO@I8rwTnIt0*Rna=Esk*%#C4BeMXKa zZDJ_sYQEslGeNFL*$o}av3StdkIAm@(2QvkHkwX9+)RB$ihMYKMdI(1)T@TGJ(Obz$#R1JpCrJvimJ+{sh|a&WbI4EpTM`cRLQ)TtJb z0CvU~_)we2+J(pNTmIO4klwb(hW;D`@@GE$EN_?D;_KWxuY(M_m5(u|^)VP1r2Da? zPC?L$!=~d{M~8tpVXU+fc76TE_K3baq$wi4Wz+hFnPD0uMx0J04c;?(8N1Z$YC2rr za-a}!Z#;u)qtN*vcL&qS{lBg^ya;U*AUY!}`wcTK8z-9lEZay;t@8qd%ev&MI$gNI zKz%ENs5<>CHQk5OIrd9!TQh9M9ux*};D|pgV7;l#jMT`6pv|?(9eaF=A1wBE`DBSw zt25#PFevvH%WPSk=`=crYD9ue!$r>@@{8z0y!s&kU^#VoU5EE{!YX_*(3t!Vab!+#H$*z`~MHL zv=-}`MFPb}-i-gy&BE+%wMRo4UbFM-H25u;>9U*{&QIVx8zoa$xbu%#36K$iV=o$= z;k9urYdO54|OxbzO*dyD)^1N=~-Nq_kj zxG3SIpsIw5d^Yh52a54db20q}l(zVPm;p(KBHY?zIn#o&TTrt0Pq*LWr^i~pmT~6$ ziEMPy6!37myjD1wPAjG!Ptu!EYE7J2Me?@FZ6caC${ujX@_-$=U~k;VjfRPlV{SF2 zZxfPD`_Nq#8b#bf#Dl@6WR)atC}$BiQ?E&a>%Ac95p68hKym?d!Y>O%VlzVmUlo^p`2R~n0w|V)4fSq}Q zY9$L1#-P%3NV8l*@g|W0WHL_kJ>Cw>qYq^*E@IZoGdcI53{T*enm-pB;J$w`u~$^| zkdW2lS_fqiNO%!CX8Q+JvkNTV=j(WRJPZNeeHWRWV*43oV<4iS;L70zs&SN*GcdWaEC=^e@GHb$L&IyxqlDHylk>A8Le?*B7=tOfI*) zD4aS;mr2NzT7>nIWOhgDw$k!@Qc2-rFAirQyK0q>Bk%wjjKzC&M*!LS@Rm@m49L5q8>J?{>K?XKTWR87JsIhMM6%$tjGXuglhKC zjr`-$k*7t5hwVJ+ThXSSXjv|@1yqr_6*u zctOdTEP5Vsid1Y;gf;-BjcWN7_M>v6h=fc!jjoCDMw`EjyoglecAy*X4hFl?`B`+L zTtTkfDv3X=wY3In6Fv44oLeQ!oNzj7^JHJ%i#C>|SQus3^)fX605iA5KdC5zVA_ub z(Da)^8a6H4TjEJv^w2U3?giEE^#?&D&DK9Dox?7V^bTO5ot;&{@2Nxfxso*|V)Hfa7ury9~nqTN!AOt=sO&GL_jnR;ugBOs3iRE>xqj9nTQxXxg zi45|fCl9-+(NLJo>PwG6va!dYXCYIf>2}f`)RS%7J}rF&Pa-uD`~7%*+b;ak{MHYk z{w>UZu@@9?jm^m$xrL&RwY#!JN%2eEpR(lh2~!eCB*2YZs^1ZA7X_;)$hl0AxZCZT zRLmW!GGa(^KO{f1-$z|8e{;?&?F4Nf~?zJ


@!Z|D&S-Z;$@g47`o(yf{PH9B<23-o2%BhOxS_4 zkoaT}WkIRY+O&}(siu2M3vHSg4(oK*0Ry|yZY&+j`5Spz)(D-fHaY|Q^6JhmL65OL z$X%H`de!vxhk6qM+MrTUDyTj~4LUBM<7RpER`e1Tko{>k20!@YYKl;RzOT%(eW7BY{P=xfiW@9z!Oe$YjO z4{H_!40Bu2(YZ{gL)eGd)!bJ)4NVpuIr{cbtU@{iHDK?i1F7Rb{cDCkLITfUO9 zaMR@=EtmX1fue8p0B`=?yv3|$e0fiTo3t-(14*Lo(bH<%!ws*CN!`Q1(_;71c1Es%YU29 z?(d)vF$PghZyz-!5BZhoo$Bd5U2WQYiHoTohXj>an_%4d=vcLkJ8<$9>vrtq4kE+k z$-WRG<7bTccv7*L02@39p^?ktoirs!k8=cXYcN+{Z>sHit zbGtR&5>CP+eim`pE>a&Q17kTB*(D!q=QR5imqDT=5^r(*v(zWq-gHPIj~SwyOkr6i z8kfFM%daBORgCII|x16Hq<)HrUTpZ@65(qN16qUxf#JG%164LC<2SEUmpd5hhcLpe%hjNuyp7bd`I_1CO zNrH0LIs zbc`#?bOq}$lx&~mS_nrm_s*}zbiomOt16*zejVEq-v-6hVcuit*9)S59$a?EnIsnOEm5I zgvk{co{=VEnu3^X<~YZA^9LXlZ{!QCjx#SOHwp~w5?X0qg>?|h*8|)CHNFNRFo7sA8oQ-aMe}r7%*ct4ti}9{w&Hti~3@b3Y2*{qx=%+qg^G#IfEw2qPCQM#mV-|y1HEylu z0#RCqS!h&zo|nd*L2IvhAz<0vRuBXEz6+26rE6i^_yeb~M}m^vuwig+ZpJ0pr5@$& zIZ@YbYn^@lx1O%~vae%BYefqOSo_z6x|9TTvM+APC&LXBor_)N&?*V3G8x%+$*hnb-81c-#hLqG0KQ@*0MzEvoKe1VDA?u= zS2<1|r;WyT_D*R9%ivqxMpIX?jOiw6-uSHzhvep7kaz+ z(jHdzyTgwxUra0xw4HQY0;3{K_JSlP30s%-X>d@_oBZe$HH$WV@bS~jmoEl3o@OugginL_ z(~;`>frqbHyx5Y$z+iC<_PWUM_H4pzVs)`slk)fQ-~*zR_DDsb#e5{Po`!2FSdh{wI<*6LX)Qe=Ki{& zHlHefc#>HK=y(qREnUyl24U8(nVKF;`CTRoE# zJ1@bUkXz3wC=GIE3fjVc=F)Y0zuOXx+8@yqRwULNl$WVvWgf@B( z1L_A1h7ag<4pm%v1@}FFf=%D#40uQ$n+}He?6y5X7g4ck{#g?o)t5(287b2E+5B1C zKHTU#C$$Sn7*lG@fjKJ1+9w*JZBPcDOQ5m-a7gqP)xRYzfmt?4iR{9{C6brApNBuP zMe9=i-+Jg5r)H_p#B#3h&34$Q0$L1F6VqUn2tCBp4hxbppapIDaZ7z@{r$=eqTTBl zVJOL~u~^K11&Rj_6@!%0Hn>9+q$)OE2jBtit*$GD0s3dXk6Qw!8ym4_aJE=nO!}Rg5Y5sn!WicVnn7 zO`=&Jt~P*4A588#Du%siTPQ{Tg*hnala>|J>w6a9BJT+PL<3jQjpz(pd&)-hu|9}i z)WeGGWnm1=FF4kDx!YmP_cGJNFd~c_=y!3

TIa@sZ*qS)Hb%Sh~-GN~?^9|JL6- z`oA2r5aJ5%^(R|?Q48P3dz-RA9U7)tK3EJ$aYQOx=r?SO_OkNaf*53GI?2_b0 z{mfS}t<^e>qOW2%h@OO%c7~aE0jntFrh3ySKNeW9Nj2lxu0F%09A0K(GFke+s(h^K zw0Sv4$qAKywtLY7>~U;6$?0dGG;#MY9C-240j2hPhxh3Tr22KlC-6G9Nki>6FF|{J zRDa`1L64GDBll2B>}LIy3%rOVPMX=7XFr z@7q^e;NnuHmL2@JV$&eHl)t{~c6iqg5%QsG3ixXGe{pZ9vId!1RFdW0+gFYv+@S&N zD;7Og`O#wAH)#!3pNTi0osBA@LeAmglD&r{lF-&_t(2tF|5ZYL<6~VUkU4U$v-h2o zsZ#RU^1LuVCLw5Hb->07b!@R)T}7kG(c%X|L~lC`LL~Yettzrq$r@^`A(Q7=@$ov4 zq+p$eG12ZHrEgWz%-C<{(P^qu%$*AgG|j*cBeMj+G@KbP7pn$U9HlLSyZ9RW(DxG} zFbvB(ZeG-x?;>izMqli(_1UTetpu}r?AXHP6H>%Tz95vr9LmC;K6YrAfq0%$N?6MEmLA zqr^Yg?3EW7V@93nctX#KBT2(*|JYDSX+__;Ti#OBjy)1TC^-6~PL)FcKCP(@-@PvU z`HnKvhgD0R`Nc0MvXn^mC1K=`YKF@*H?OZOtXRHQyFr4j{-vm2#fy*d;ZcMT2RpL2 zytWE7j0hUSM4b9Bia9lyHHR5{->wT>8L0GW;s)xXjG$8E8jdKhhA)*LxID5~kXZCX zUar}F%>Gllt|gi&dQ6lXB?MZR2=4+{PJ4kQv z4i7{gq?X}N8kTuW{-UBH}8iDYxqgwS}eslUcW6QYiRFJf%tDnm{r-UW|1+P2g literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/minecraft/textures/esp/square-dashes.png b/src/main/resources/assets/minecraft/textures/esp/square-dashes.png new file mode 100644 index 0000000000000000000000000000000000000000..15515736decc3b7b844a61936bea427721bc5156 GIT binary patch literal 48169 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