diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..64a98df --- /dev/null +++ b/.clang-format @@ -0,0 +1,11 @@ +--- +BasedOnStyle: Google +UseTab: ForContinuationAndIndentation +IndentWidth: 4 +TabWidth: 4 +IndentCaseLabels: false +ColumnLimit: 0 +BreakBeforeBraces: Attach +AccessModifierOffset: -4 +--- +Language: Cpp \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 0000000..cd83d85 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,30 @@ +--- +name: Bug report +about: Create a report to help us improve +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**To Reproduce** +Steps to reproduce the behavior: +1. Go to '...' +2. Click on '....' +3. Scroll down to '....' +4. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..11fc491 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/conce.png b/.github/conce.png new file mode 100644 index 0000000..f313a67 Binary files /dev/null and b/.github/conce.png differ diff --git a/.github/horion-banner.png b/.github/horion-banner.png new file mode 100644 index 0000000..4665b54 Binary files /dev/null and b/.github/horion-banner.png differ diff --git a/.github/workflows/msbuild.yml b/.github/workflows/msbuild.yml new file mode 100644 index 0000000..9ca1403 --- /dev/null +++ b/.github/workflows/msbuild.yml @@ -0,0 +1,32 @@ +name: MSBuild + +on: [pull_request] + +env: + # Path to the solution file relative to the root of the project. + SOLUTION_FILE_PATH: . + + # Configuration type to build. + # You can convert this to a build matrix if you need coverage of multiple configuration types. + # https://docs.github.com/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix + BUILD_CONFIGURATION: Release + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v2 + + - name: Add MSBuild to PATH + uses: microsoft/setup-msbuild@v1.0.2 + + - name: Restore NuGet packages + working-directory: ${{env.GITHUB_WORKSPACE}} + run: nuget restore ${{env.SOLUTION_FILE_PATH}} + + - name: Build + working-directory: ${{env.GITHUB_WORKSPACE}} + # Add additional options to the MSBuild command line here (like platform or verbosity level). + # See https://docs.microsoft.com/visualstudio/msbuild/msbuild-command-line-reference + run: msbuild /m /p:Configuration=${{env.BUILD_CONFIGURATION}} ${{env.SOLUTION_FILE_PATH}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9c5c736 --- /dev/null +++ b/.gitignore @@ -0,0 +1,497 @@ + +# Created by https://www.toptal.com/developers/gitignore/api/cmake,clion+all,visualstudio,c++ +# Edit at https://www.toptal.com/developers/gitignore?templates=cmake,clion+all,visualstudio,c++ + +### C++ ### +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a + +# Executables +*.exe +*.out +*.app + +### CLion+all ### +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Generated files +.idea/**/contentModel.xml + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# Gradle and Maven with auto-import +# When using Gradle or Maven with auto-import, you should exclude module files, +# since they will be recreated, and may cause churn. Uncomment if using +# auto-import. +# .idea/artifacts +# .idea/compiler.xml +# .idea/jarRepositories.xml +# .idea/modules.xml +# .idea/*.iml +# .idea/modules +# *.iml +# *.ipr + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# Android studio 3.1+ serialized cache file +.idea/caches/build_file_checksums.ser + +### CLion+all Patch ### +# Ignores the whole .idea folder and all .iml files +# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360 + +.idea/ + +# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 + +*.iml +modules.xml +.idea/misc.xml +*.ipr + +# Sonarlint plugin +.idea/sonarlint + +### CMake ### +CMakeLists.txt.user +CMakeCache.txt +CMakeFiles +CMakeScripts +Testing +Makefile +cmake_install.cmake +install_manifest.txt +compile_commands.json +CTestTestfile.cmake +_deps + +### CMake Patch ### +# External projects +*-prefix/ + +### VisualStudio ### +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. +## +## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore + +# User-specific files +*.rsuser +*.suo +*.user +*.userosscache +*.sln.docstates + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Mono auto generated files +mono_crash.* + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +[Aa][Rr][Mm]/ +[Aa][Rr][Mm]64/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ +[Ll]ogs/ + +# Visual Studio 2015/2017 cache/options directory +.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# Visual Studio 2017 auto generated files +Generated\ Files/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUnit +*.VisualState.xml +TestResult.xml +nunit-*.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# Benchmark Results +BenchmarkDotNet.Artifacts/ + +# .NET Core +project.lock.json +project.fragment.lock.json +artifacts/ + +# StyleCop +StyleCopReport.xml + +# Files built by Visual Studio +*_i.c +*_p.c +*_h.h +*.ilk +*.meta +*.iobj +*.pdb +*.ipdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*_wpftmp.csproj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# Visual Studio Trace Files +*.e2e + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# AxoCover is a Code Coverage Tool +.axoCover/* +!.axoCover/settings.json + +# Coverlet is a free, cross platform Code Coverage Tool +coverage*[.json, .xml, .info] + +# Visual Studio code coverage results +*.coverage +*.coveragexml + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# Note: Comment the next line if you want to checkin your web deploy settings, +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +# NuGet Symbol Packages +*.snupkg +# The packages folder can be ignored because of Package Restore +**/[Pp]ackages/* +# except build/, which is used as an MSBuild target. +!**/[Pp]ackages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/[Pp]ackages/repositories.config +# NuGet v3's project.json files produces more ignorable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt +*.appx +*.appxbundle +*.appxupload + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!?*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.jfm +*.pfx +*.publishsettings +orleans.codegen.cs + +# Including strong name files can present a security risk +# (https://github.com/github/gitignore/pull/2483#issue-259490424) +#*.snk + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm +ServiceFabricBackup/ +*.rptproj.bak + +# SQL Server files +*.mdf +*.ldf +*.ndf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings +*.rptproj.rsuser +*- [Bb]ackup.rdl +*- [Bb]ackup ([0-9]).rdl +*- [Bb]ackup ([0-9][0-9]).rdl + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat +node_modules/ + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio 6 auto-generated workspace file (contains which files were open etc.) +*.vbw + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# CodeRush personal settings +.cr/personal + +# Python Tools for Visual Studio (PTVS) +__pycache__/ +*.pyc + +# Cake - Uncomment if you are using it +# tools/** +# !tools/packages.config + +# Tabs Studio +*.tss + +# Telerik's JustMock configuration file +*.jmconfig + +# BizTalk build output +*.btp.cs +*.btm.cs +*.odx.cs +*.xsd.cs + +# OpenCover UI analysis results +OpenCover/ + +# Azure Stream Analytics local run output +ASALocalRun/ + +# MSBuild Binary and Structured Log +*.binlog + +# NVidia Nsight GPU debugger configuration file +*.nvuser + +# MFractors (Xamarin productivity tool) working folder +.mfractor/ + +# Local History for Visual Studio +.localhistory/ + +# BeatPulse healthcheck temp database +healthchecksdb + +# Backup folder for Package Reference Convert tool in Visual Studio 2017 +MigrationBackup/ + +# Ionide (cross platform F# VS Code tools) working folder +.ionide/ + +# End of https://www.toptal.com/developers/gitignore/api/cmake,clion+all,visualstudio,c++ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..3d663ed --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,348 @@ +cmake_minimum_required(VERSION 3.12) +project(Horion) + +set(CMAKE_CXX_STANDARD 17) + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + add_compile_options(-Wno-dynamic-class-memaccess -Wno-microsoft-goto -Wno-delete-incomplete /EHsc /Ob1) +elseif (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + add_compile_options(/MP /Ob1) +endif() + +add_compile_definitions(WIN32_LEAN_AND_MEAN) +add_compile_definitions(NOMINMAX) +if(CMAKE_BUILD_TYPE MATCHES Release) + +elseif(CMAKE_BUILD_TYPE MATCHES BetaConf) + add_compile_definitions(_BETA) +endif() + +include_directories(.) +include_directories(include) +include_directories(include/glm/) + +link_directories(minhook) + +add_library(Horion SHARED + Horion/Command/Commands/BindCommand.cpp + Horion/Command/Commands/BindCommand.h + Horion/Command/Commands/BruhCommand.cpp + Horion/Command/Commands/BruhCommand.h + Horion/Command/Commands/CommandBlockExploitCommand.cpp + Horion/Command/Commands/CommandBlockExploitCommand.h + Horion/Command/Commands/ConfigCommand.cpp + Horion/Command/Commands/ConfigCommand.h + Horion/Command/Commands/CoordsCommand.cpp + Horion/Command/Commands/CoordsCommand.h + Horion/Command/Commands/DamageCommand.cpp + Horion/Command/Commands/DamageCommand.h + Horion/Command/Commands/DupeCommand.cpp + Horion/Command/Commands/DupeCommand.h + Horion/Command/Commands/EjectCommand.cpp + Horion/Command/Commands/EjectCommand.h + Horion/Command/Commands/EnchantCommand.cpp + Horion/Command/Commands/EnchantCommand.h + Horion/Command/Commands/ExecuteCommand.cpp + Horion/Command/Commands/ExecuteCommand.h + Horion/Command/Commands/FriendListCommand.cpp + Horion/Command/Commands/FriendListCommand.h + Horion/Command/Commands/GameModeCommand.cpp + Horion/Command/Commands/GameModeCommand.h + Horion/Command/Commands/GiveCommand.cpp + Horion/Command/Commands/GiveCommand.h + Horion/Command/Commands/HelpCommand.cpp + Horion/Command/Commands/HelpCommand.h + Horion/Command/Commands/HideCommand.cpp + Horion/Command/Commands/HideCommand.h + Horion/Command/Commands/ICommand.cpp + Horion/Command/Commands/ICommand.h + Horion/Command/Commands/ModulesCommand.cpp + Horion/Command/Commands/ModulesCommand.h + Horion/Command/Commands/NameSpoofCommand.cpp + Horion/Command/Commands/NameSpoofCommand.h + Horion/Command/Commands/NbtCommand.cpp + Horion/Command/Commands/NbtCommand.h + Horion/Command/Commands/PanicCommand.cpp + Horion/Command/Commands/PanicCommand.h + Horion/Command/Commands/PlayerTeleportCommand.cpp + Horion/Command/Commands/PlayerTeleportCommand.h + Horion/Command/Commands/RelativeTeleportCommand.cpp + Horion/Command/Commands/RelativeTeleportCommand.h + Horion/Command/Commands/SayCommand.cpp + Horion/Command/Commands/SayCommand.h + Horion/Command/Commands/ScriptCommand.cpp + Horion/Command/Commands/ScriptCommand.h + Horion/Command/Commands/ServerCommand.cpp + Horion/Command/Commands/ServerCommand.h + Horion/Command/Commands/setoffhandCommand.cpp + Horion/Command/Commands/setoffhandCommand.h + Horion/Command/Commands/SetprefixCommand.cpp + Horion/Command/Commands/SetprefixCommand.h + Horion/Command/Commands/SpammerCommand.cpp + Horion/Command/Commands/SpammerCommand.h + Horion/Command/Commands/TeleportCommand.cpp + Horion/Command/Commands/TeleportCommand.h + Horion/Command/Commands/TestCommand.cpp + Horion/Command/Commands/TestCommand.h + Horion/Command/Commands/ToggleCommand.cpp + Horion/Command/Commands/ToggleCommand.h + Horion/Command/Commands/UnbindCommand.cpp + Horion/Command/Commands/UnbindCommand.h + Horion/Command/CommandMgr.cpp + Horion/Command/CommandMgr.h + Horion/Config/AccountInformation.cpp + Horion/Config/AccountInformation.h + Horion/Config/ConfigManager.cpp + Horion/Config/ConfigManager.h + Horion/FriendList/FriendList.cpp + Horion/FriendList/FriendList.h + Horion/Menu/ClickGui.cpp + Horion/Menu/ClickGui.h + Horion/Menu/TabGui.cpp + Horion/Menu/TabGui.h + Horion/Module/Modules/Aimbot.cpp + Horion/Module/Modules/Aimbot.h + Horion/Module/Modules/AirJump.cpp + Horion/Module/Modules/AirJump.h + Horion/Module/Modules/AirStuck.cpp + Horion/Module/Modules/AirStuck.h + Horion/Module/Modules/AirSwim.cpp + Horion/Module/Modules/AirSwim.h + Horion/Module/Modules/AntiBot.cpp + Horion/Module/Modules/AntiBot.h + Horion/Module/Modules/AntiVoid.cpp + Horion/Module/Modules/AntiVoid.h + Horion/Module/Modules/AutoArmor.cpp + Horion/Module/Modules/AutoArmor.h + Horion/Module/Modules/AutoClicker.cpp + Horion/Module/Modules/AutoClicker.h + Horion/Module/Modules/AutoGapple.cpp + Horion/Module/Modules/AutoGapple.h + Horion/Module/Modules/AutoSneak.cpp + Horion/Module/Modules/AutoSneak.h + Horion/Module/Modules/AutoSprint.cpp + Horion/Module/Modules/AutoSprint.h + Horion/Module/Modules/AutoTotem.cpp + Horion/Module/Modules/AutoTotem.h + Horion/Module/Modules/Bhop.cpp + Horion/Module/Modules/Bhop.h + Horion/Module/Modules/Blink.cpp + Horion/Module/Modules/Blink.h + Horion/Module/Modules/BowAimbot.cpp + Horion/Module/Modules/BowAimbot.h + Horion/Module/Modules/ChestAura.cpp + Horion/Module/Modules/ChestAura.h + Horion/Module/Modules/ChestESP.cpp + Horion/Module/Modules/ChestESP.h + Horion/Module/Modules/ChestStealer.cpp + Horion/Module/Modules/ChestStealer.h + Horion/Module/Modules/ClickGuiMod.cpp + Horion/Module/Modules/ClickGuiMod.h + Horion/Module/Modules/Crasher.cpp + Horion/Module/Modules/Crasher.h + Horion/Module/Modules/Criticals.cpp + Horion/Module/Modules/Criticals.h + Horion/Module/Modules/CrystalAura.cpp + Horion/Module/Modules/CrystalAura.h + Horion/Module/Modules/CubeGlide.cpp + Horion/Module/Modules/CubeGlide.h + Horion/Module/Modules/Derp.cpp + Horion/Module/Modules/Derp.h + Horion/Module/Modules/EditionFaker.cpp + Horion/Module/Modules/EditionFaker.h + Horion/Module/Modules/ESP.cpp + Horion/Module/Modules/ESP.h + Horion/Module/Modules/FastEast.cpp + Horion/Module/Modules/FastEat.h + Horion/Module/Modules/FastLadder.cpp + Horion/Module/Modules/FastLadder.h + Horion/Module/Modules/Fly.cpp + Horion/Module/Modules/Fly.h + Horion/Module/Modules/Freecam.cpp + Horion/Module/Modules/Freecam.h + Horion/Module/Modules/Fucker.cpp + Horion/Module/Modules/Fucker.h + Horion/Module/Modules/FullBright.cpp + Horion/Module/Modules/FullBright.h + Horion/Module/Modules/Glide.cpp + Horion/Module/Modules/Glide.h + Horion/Module/Modules/Godmode.cpp + Horion/Module/Modules/Godmode.h + Horion/Module/Modules/HighJump.cpp + Horion/Module/Modules/HighJump.h + Horion/Module/Modules/Hitbox.cpp + Horion/Module/Modules/Hitbox.h + Horion/Module/Modules/HudModule.cpp + Horion/Module/Modules/HudModule.h + Horion/Module/Modules/ExtendedBlockReach.cpp + Horion/Module/Modules/ExtendedBlockReach.h + Horion/Module/Modules/InfiniteReach.cpp + Horion/Module/Modules/InfiniteReach.h + Horion/Module/Modules/InstaBreak.cpp + Horion/Module/Modules/InstaBreak.h + Horion/Module/Modules/InventoryCleaner.cpp + Horion/Module/Modules/InventoryCleaner.h + Horion/Module/Modules/InventoryMove.cpp + Horion/Module/Modules/InventoryMove.h + Horion/Module/Modules/JavascriptModule.cpp + Horion/Module/Modules/JavascriptModule.h + Horion/Module/Modules/Jesus.cpp + Horion/Module/Modules/Jesus.h + Horion/Module/Modules/Jetpack.cpp + Horion/Module/Modules/Jetpack.h + Horion/Module/Modules/Killaura.cpp + Horion/Module/Modules/Killaura.h + Horion/Module/Modules/MidClick.cpp + Horion/Module/Modules/MidClick.h + Horion/Module/Modules/Module.cpp + Horion/Module/Modules/Module.h + Horion/Module/Modules/NameTags.cpp + Horion/Module/Modules/NameTags.h + Horion/Module/Modules/Nbt.cpp + Horion/Module/Modules/Nbt.h + Horion/Module/Modules/NightMode.cpp + Horion/Module/Modules/NightMode.h + Horion/Module/Modules/NoFall.cpp + Horion/Module/Modules/NoFall.h + Horion/Module/Modules/NoFriends.cpp + Horion/Module/Modules/NoFriends.h + Horion/Module/Modules/NoPacket.cpp + Horion/Module/Modules/NoPacket.h + Horion/Module/Modules/NoPaintingCrash.cpp + Horion/Module/Modules/NoPaintingCrash.h + Horion/Module/Modules/NoSlowDown.cpp + Horion/Module/Modules/NoSlowDown.h + Horion/Module/Modules/NoSwing.cpp + Horion/Module/Modules/NoSwing.h + Horion/Module/Modules/NoWeb.cpp + Horion/Module/Modules/NoWeb.h + Horion/Module/Modules/Nuker.cpp + Horion/Module/Modules/Nuker.h + Horion/Module/Modules/PacketLogger.cpp + Horion/Module/Modules/PacketLogger.h + Horion/Module/Modules/Phase.cpp + Horion/Module/Modules/Phase.h + Horion/Module/Modules/RainbowSky.cpp + Horion/Module/Modules/RainbowSky.h + Horion/Module/Modules/Reach.cpp + Horion/Module/Modules/Reach.h + Horion/Module/Modules/Scaffold.cpp + Horion/Module/Modules/Scaffold.h + Horion/Module/Modules/Spammer.cpp + Horion/Module/Modules/Spammer.h + Horion/Module/Modules/Speed.cpp + Horion/Module/Modules/Speed.h + Horion/Module/Modules/StackableItem.cpp + Horion/Module/Modules/StackableItem.h + Horion/Module/Modules/Step.cpp + Horion/Module/Modules/Step.h + Horion/Module/Modules/Teams.cpp + Horion/Module/Modules/Teams.h + Horion/Module/Modules/Teleport.cpp + Horion/Module/Modules/Teleport.h + Horion/Module/Modules/TestModule.cpp + Horion/Module/Modules/TestModule.h + Horion/Module/Modules/Timer.cpp + Horion/Module/Modules/Timer.h + Horion/Module/Modules/Tower.cpp + Horion/Module/Modules/Tower.h + Horion/Module/Modules/Tracer.cpp + Horion/Module/Modules/Tracer.h + Horion/Module/Modules/TriggerBot.cpp + Horion/Module/Modules/TriggerBot.h + Horion/Module/Modules/Velocity.cpp + Horion/Module/Modules/Velocity.h + Horion/Module/Modules/Xray.cpp + Horion/Module/Modules/Xray.h + Horion/Module/Modules/Zoom.cpp + Horion/Module/Modules/Zoom.h + Horion/Module/ModuleManager.cpp + Horion/Module/ModuleManager.h + Horion/Scripting/Functions/CommandManagerFunctions.cpp + Horion/Scripting/Functions/CommandManagerFunctions.h + Horion/Scripting/Functions/EntityFunctions.cpp + Horion/Scripting/Functions/EntityFunctions.h + Horion/Scripting/Functions/GameFunctions.cpp + Horion/Scripting/Functions/GameFunctions.h + Horion/Scripting/Functions/GlobalFunctions.cpp + Horion/Scripting/Functions/GlobalFunctions.h + Horion/Scripting/Functions/HorionFunctions.cpp + Horion/Scripting/Functions/HorionFunctions.h + Horion/Scripting/Functions/LocalPlayerFunctions.cpp + Horion/Scripting/Functions/LocalPlayerFunctions.h + Horion/Scripting/Functions/ModuleManagerFunctions.cpp + Horion/Scripting/Functions/ModuleManagerFunctions.h + Horion/Scripting/Functions/Vector3Functions.cpp + Horion/Scripting/Functions/Vector3Functions.h + Horion/Scripting/JsScriptModule.cpp + Horion/Scripting/JsScriptModule.h + Horion/Scripting/ScriptInstance.cpp + Horion/Scripting/ScriptInstance.h + Horion/Scripting/ScriptManager.cpp + Horion/Scripting/ScriptManager.h + Horion/DrawUtils.cpp + Horion/DrawUtils.h + Horion/GuiUtils.cpp + Horion/GuiUtils.h + Horion/ImmediateGui.cpp + Horion/ImmediateGui.h + Horion/Loader.cpp + Horion/Loader.h + include/chakra/ChakraCommon.h + include/chakra/ChakraCommonWindows.h + include/chakra/ChakraCore.h + include/chakra/ChakraCoreWindows.h + include/chakra/ChakraDebug.h + include/atlrx.h + include/d3dx11.h + include/d3dx11async.h + include/d3dx11core.h + include/d3dx11effect.h + include/RegExp.h + include/StringProcess.h + include/WinHttpClient.h + Memory/GameData.cpp + Memory/GameData.h + Memory/Hooks.cpp + Memory/Hooks.h + Memory/MinHook.h + Memory/SlimMem.cpp + Memory/SlimMem.h + SDK/CBlockLegacy.h + SDK/CChestBlockActor.h + SDK/CClientInstance.h + SDK/CClientInstanceScreenModel.h + SDK/CComplexInventoryTransaction.h + SDK/CEntity.h + SDK/CEntityList.h + SDK/CGameMode.h + SDK/CGameSettingsInput.h + SDK/CHIDController.h + SDK/CInventory.h + SDK/CInventoryTransaction.h + SDK/CItem.h + SDK/CLoopbackPacketSender.h + SDK/CMinecraftUIRenderContext.h + SDK/CMoveInputHandler.h + SDK/CPacket.h + SDK/CRakNetInstance.h + SDK/CUIScene.h + SDK/MojangsonToken.h + SDK/Tag.h + SDK/TextHolder.h + Utils/ChakraHelper.h + Utils/DllHelper.h + Utils/HMath.h + Utils/Json.hpp + Utils/Logger.cpp + Utils/Logger.h + Utils/SkinUtil.cpp + Utils/SkinUtil.h + Utils/Target.cpp + Utils/Target.h + Utils/TextFormat.cpp + Utils/TextFormat.h + Utils/Utils.cpp + Utils/Utils.h + Utils/xorstr.h + resource.h SDK/TextHolder.cpp SDK/CChestBlockActor.cpp SDK/Tag.cpp Utils/keys.h SDK/CBlockLegacy.cpp SDK/CItem.cpp SDK/CInventory.cpp SDK/CInventoryTransaction.cpp SDK/CEntity.cpp SDK/CComplexInventoryTransaction.cpp SDK/CPacket.cpp SDK/CMinecraftUIRenderContext.cpp SDK/CClientInstance.cpp SDK/CMoveInputHandler.cpp SDK/CImageBuffer.h Horion/Module/Modules/Freelook.cpp Horion/Module/Modules/Freelook.h SDK/CCamera.h SDK/CCamera.cpp Horion/Module/Modules/NoHurtcam.cpp Horion/Module/Modules/NoHurtcam.h Horion/Module/Modules/AntiImmobile.cpp Horion/Module/Modules/AntiImmobile.h Horion/path/JoePathFinder.cpp Horion/path/JoePathFinder.h Horion/path/JoePath.cpp Horion/path/JoePath.h Horion/path/JoeSegment.cpp Horion/path/JoeSegment.h Horion/path/JoeMovementController.cpp Horion/path/JoeMovementController.h Horion/path/goals/JoeGoal.cpp Horion/path/goals/JoeGoal.h Horion/path/goals/JoeGoalXYZ.cpp Horion/path/goals/JoeGoalXYZ.h Horion/path/goals/JoeGoalXZ.cpp Horion/path/goals/JoeGoalXZ.h Horion/path/JoeConstants.h Horion/path/goals/JoeGoalY.cpp Horion/path/goals/JoeGoalY.h Horion/Module/Modules/FollowPathModule.cpp Horion/Module/Modules/FollowPathModule.h Horion/Command/Commands/PathCommand.cpp Horion/Command/Commands/PathCommand.h Horion/path/JoeConstants.cpp Horion/Scripting/Functions/LevelFunctions.cpp Horion/Scripting/Functions/LevelFunctions.h Horion/Scripting/Functions/DrawFunctions.cpp Horion/Scripting/Functions/DrawFunctions.h "Horion/Module/Modules/Twerk.cpp" "Horion/Module/Modules/Twerk.h") diff --git a/CppProperties.json b/CppProperties.json new file mode 100644 index 0000000..659bf4e --- /dev/null +++ b/CppProperties.json @@ -0,0 +1,21 @@ +{ + "configurations": [ + { + "inheritEnvironments": [ + "msvc_x86" + ], + "name": "x86-Debug", + "includePath": [ + "${env.INCLUDE}", + "${workspaceRoot}\\**" + ], + "defines": [ + "WIN32", + "_DEBUG", + "UNICODE", + "_UNICODE" + ], + "intelliSenseMode": "windows-msvc-x86" + } + ] +} \ No newline at end of file diff --git a/Horion.rc b/Horion.rc new file mode 100644 index 0000000..b38bc5a --- /dev/null +++ b/Horion.rc @@ -0,0 +1,76 @@ +// Microsoft Visual C++ generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Franais (France) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_FRA) +LANGUAGE LANG_FRENCH, SUBLANG_FRENCH +#pragma code_page(1252) + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// TEXT +// + +IDR_TEXT1 TEXT "resources\\coolroblox.json" + + +///////////////////////////////////////////////////////////////////////////// +// +// RCDATA +// + +IDR_STEVE RCDATA "resources\\Steve.dat" + + +#endif + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Horion.sln b/Horion.sln new file mode 100644 index 0000000..8863aa4 --- /dev/null +++ b/Horion.sln @@ -0,0 +1,37 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29123.88 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Horion", "Horion.vcxproj", "{499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + BetaConf|x64 = BetaConf|x64 + BetaConf|x86 = BetaConf|x86 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.BetaConf|x64.ActiveCfg = BetaConf|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.BetaConf|x64.Build.0 = BetaConf|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.BetaConf|x86.ActiveCfg = BetaConf|Win32 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.BetaConf|x86.Build.0 = BetaConf|Win32 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Debug|x64.ActiveCfg = Debug|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Debug|x64.Build.0 = Debug|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Debug|x86.ActiveCfg = Debug|Win32 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Debug|x86.Build.0 = Debug|Win32 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Release|x64.ActiveCfg = Release|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Release|x64.Build.0 = Release|x64 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Release|x86.ActiveCfg = Release|Win32 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD}.Release|x86.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {704429D9-0B78-4294-8BFD-0DD00BDF9CE0} + EndGlobalSection +EndGlobal diff --git a/Horion.vcxproj b/Horion.vcxproj new file mode 100644 index 0000000..10008cb --- /dev/null +++ b/Horion.vcxproj @@ -0,0 +1,656 @@ + + + + + BetaConf + Win32 + + + BetaConf + x64 + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 15.0 + {499784D2-7EA3-4CBE-BD93-EC0DBBC42FCD} + Win32Proj + 10.0 + + + + DynamicLibrary + true + v142 + false + + + DynamicLibrary + false + v141 + + + DynamicLibrary + false + v141 + + + DynamicLibrary + true + v142 + Unicode + false + true + + + DynamicLibrary + false + v142 + Unicode + true + false + + + DynamicLibrary + false + v142 + Unicode + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + true + + + true + + + true + + + C:\Program Files %28x86%29\Microsoft DirectX SDK %28June 2010%29\Lib\x64;D:\ProgrammeX\Dxx\Lib\x64;$(ProjectDir)minhook;$(LibraryPath) + D:\ProgrammeX\Dxx\Include;$(ProjectDir)include\glm;$(IncludePath) + + + C:\Program Files %28x86%29\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64;$(ProjectDir)minhook;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)include\glm + + + C:\Program Files %28x86%29\Microsoft Visual Studio\2017\Community\VC\Tools\MSVC\14.16.27023\lib\x64;$(ProjectDir)minhook;$(VC_LibraryPath_x64);$(WindowsSDK_LibraryPath_x64);$(NETFXKitsDir)Lib\um\x64 + $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)include\glm + + + + WIN32;_DEBUG;_WINDOWS;_USRDLL;HORION_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDebugDLL + Level3 + ProgramDatabase + Disabled + + + MachineX86 + true + Windows + true + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;HORION_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + WIN32;NDEBUG;_WINDOWS;_USRDLL;HORION_EXPORTS;%(PreprocessorDefinitions) + MultiThreadedDLL + Level3 + ProgramDatabase + + + MachineX86 + true + Windows + true + true + + + + + stdcpp17 + Level3 + ProgramDatabase + true + false + MultiThreadedDebugDLL + /Zc:__cplusplus %(AdditionalOptions) + NOMINMAX;%(PreprocessorDefinitions) + OnlyExplicitInline + + + + Default + + + + + + + stdcpp17 + true + None + /Zc:__cplusplus %(AdditionalOptions) + AnySuitable + false + _WINDLL;NOMINMAX;%(PreprocessorDefinitions) + + + false + + + + + stdcpp17 + true + None + /Zc:__cplusplus %(AdditionalOptions) + _BETA;NOMINMAX;%(PreprocessorDefinitions) + AnySuitable + false + + + false + + + + + + + + + + + Document + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Ce projet fait référence à des packages NuGet qui sont manquants sur cet ordinateur. Utilisez l'option de restauration des packages NuGet pour les télécharger. Pour plus d'informations, consultez http://go.microsoft.com/fwlink/?LinkID=322105. Le fichier manquant est : {0}. + + + + + diff --git a/Horion/Command/CommandMgr.cpp b/Horion/Command/CommandMgr.cpp new file mode 100644 index 0000000..a96f189 --- /dev/null +++ b/Horion/Command/CommandMgr.cpp @@ -0,0 +1,100 @@ +#include "CommandMgr.h" + +CommandMgr::CommandMgr(GameData* gm) { + this->gameData = gm; +} + +CommandMgr::~CommandMgr() { + for (int i = 0; i < commandList.size(); i++) { + delete commandList[i]; + commandList[i] = nullptr; + } +} + +void CommandMgr::initCommands() { + logF("Initializing commands"); + + commandList.push_back(new EjectCommand()); + commandList.push_back(new TeleportCommand()); + commandList.push_back(new BindCommand()); + commandList.push_back(new RelativeTeleportCommand()); + commandList.push_back(new ToggleCommand()); + commandList.push_back(new PlayerTeleportCommand()); + commandList.push_back(new GameModeCommand()); + commandList.push_back(new FriendListCommand()); + commandList.push_back(new UnbindCommand()); + commandList.push_back(new EnchantCommand()); + commandList.push_back(new HelpCommand()); + commandList.push_back(new ModulesCommand()); + commandList.push_back(new PanicCommand()); + commandList.push_back(new HideCommand()); + commandList.push_back(new GiveCommand()); + commandList.push_back(new BruhCommand()); + commandList.push_back(new ServerCommand()); + commandList.push_back(new SetOffhandCommand()); + commandList.push_back(new CoordsCommand()); + commandList.push_back(new SayCommand()); + commandList.push_back(new SpammerCommand()); + commandList.push_back(new DupeCommand()); + commandList.push_back(new DamageCommand()); + commandList.push_back(new ConfigCommand()); + commandList.push_back(new SetPrefixCommand()); + commandList.push_back(new NbtCommand()); + commandList.push_back(new WaypointCommand()); + commandList.push_back(new TopCommand()); + commandList.push_back(new XpCommand()); + commandList.push_back(new CommandBlockExploitCommand()); + commandList.push_back(new NameSpoofCommand()); + commandList.push_back(new ExecuteCommand()); + commandList.push_back(new ScriptCommand()); + commandList.push_back(new PathCommand()); + +#ifdef _DEBUG + commandList.push_back(new TestCommand()); +#endif +} + +void CommandMgr::disable() { +} + +std::vector* CommandMgr::getCommandList() { + return &commandList; +} + +void CommandMgr::execute(char* message) { + if (message != nullptr) { + std::vector args; + std::string msgStr = message + 1; + size_t pos = msgStr.find(" "), initialPos = 0; + while (pos != std::string::npos) { + args.push_back(msgStr.substr(initialPos, pos - initialPos)); + initialPos = pos + 1; + + pos = msgStr.find(" ", initialPos); + } + args.push_back(msgStr.substr(initialPos, std::min(pos, msgStr.size()) - initialPos + 1)); + + std::string cmd = args[0]; + std::transform(cmd.begin(), cmd.end(), cmd.begin(), ::tolower); + + for (auto it = this->commandList.begin(); it != this->commandList.end(); ++it) { + IMCCommand* c = *it; + auto* aliases = c->getAliasList(); + for (auto it = aliases->begin(); it != aliases->end(); ++it) { + if (*it == cmd) { + try { + if (!c->execute(&args)) + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%s%sUsage: %s%c%s %s", RED, BOLD, RESET, cmdMgr->prefix, c->getCommand(), c->getUsage(cmd.c_str())); + } catch (...) { + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%s%sUsage: %s%c%s %s", RED, BOLD, RESET, cmdMgr->prefix, c->getCommand(), c->getUsage(cmd.c_str())); + } + return; + } + } + } + + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("[%sHorion%s] %sCommand '%s' could not be found!", GOLD, WHITE, RED, cmd.c_str()); + } +} + +CommandMgr* cmdMgr = new CommandMgr(&g_Data); diff --git a/Horion/Command/CommandMgr.h b/Horion/Command/CommandMgr.h new file mode 100644 index 0000000..cb16b2f --- /dev/null +++ b/Horion/Command/CommandMgr.h @@ -0,0 +1,66 @@ +#pragma once + +#include "../../Memory/GameData.h" +#include "Commands/BindCommand.h" +#include "Commands/BruhCommand.h" +#include "Commands/CoordsCommand.h" +#include "Commands/DamageCommand.h" +#include "Commands/DupeCommand.h" +#include "Commands/EjectCommand.h" +#include "Commands/EnchantCommand.h" +#include "Commands/FriendListCommand.h" +#include "Commands/GameModeCommand.h" +#include "Commands/GiveCommand.h" +#include "Commands/HelpCommand.h" +#include "Commands/HideCommand.h" +#include "Commands/ICommand.h" +#include "Commands/ModulesCommand.h" +#include "Commands/PanicCommand.h" +#include "Commands/PlayerTeleportCommand.h" +#include "Commands/RelativeTeleportCommand.h" +#include "Commands/SayCommand.h" +#include "Commands/ServerCommand.h" +#include "Commands/SpammerCommand.h" +#include "Commands/TeleportCommand.h" +#include "Commands/ToggleCommand.h" +#include "Commands/TopCommand.h" +#include "Commands/UnbindCommand.h" +#include "Commands/setoffhandCommand.h" +#include "Commands/CommandBlockExploitCommand.h" +#include "Commands/ConfigCommand.h" +#include "Commands/NameSpoofCommand.h" +#include "Commands/SetPrefixCommand.h" +#include "Commands/NbtCommand.h" +#include "Commands/ExecuteCommand.h" +#include "Commands/WaypointCommand.h" +#include"Commands/XpCommand.h" +#include "Commands/ScriptCommand.h" +#include "Commands/PathCommand.h" + +#ifdef _DEBUG +#include "Commands/TestCommand.h" +#endif + +#include +#include +#include + +class CommandMgr { +private: + GameData* gameData; + std::vector commandList; + +public: + CommandMgr(GameData* gm); + ~CommandMgr(); + + char prefix = '.'; + + void initCommands(); + void disable(); + std::vector* getCommandList(); + + void execute(char* message); +}; + +extern CommandMgr* cmdMgr; diff --git a/Horion/Command/Commands/BindCommand.cpp b/Horion/Command/Commands/BindCommand.cpp new file mode 100644 index 0000000..520dc65 --- /dev/null +++ b/Horion/Command/Commands/BindCommand.cpp @@ -0,0 +1,79 @@ +#include "BindCommand.h" + +#include "../../Module/ModuleManager.h" + +BindCommand::BindCommand() : IMCCommand("bind", "Binds modules to specific keys", " ") { + registerAlias("b"); +} + +BindCommand::~BindCommand() { +} + +bool BindCommand::execute(std::vector* args) { + assertTrue(args->size() >= 2); + std::string moduleName = args->at(1); + assertTrue(moduleName.size() > 0); + + auto modOpt = moduleMgr->getModuleByName(moduleName); + if (!modOpt.has_value()) { + clientMessageF("%sCould not find module with name: %s", RED, moduleName.c_str()); + return true; + } + auto mod = modOpt.value(); + + if (args->size() >= 3) { + std::string key = args->at(2); + + assertTrue(key.size() > 0); + + if (key.size() > 1) { + std::transform(key.begin(), key.end(), key.begin(), ::tolower); + const char* needle = key.c_str(); + + if (key == "none") { + mod->setKeybind(0x0); + clientMessageF("%sSuccessfully unbound %s!", GREEN, mod->getModuleName()); + return true; + } + + for (int i = 0; i < 190; i++) { + const char* haystack = KeyNames[i]; + size_t len = strlen(needle) + 1; + char* haystackLowercase = new char[len]; + for (int i = 0; i < len; i++) + haystackLowercase[i] = tolower(haystack[i]); + + if (strcmp(needle, haystackLowercase) == 0) { + mod->setKeybind(i); + clientMessageF("%sThe keybind of %s is now '%s'", GREEN, mod->getModuleName(), haystack); + delete[] haystackLowercase; + return true; + } + delete[] haystackLowercase; + } + clientMessageF("%sInvalid key!", RED); + return true; + } + + int keyCode = (int)key.at(0); + if (keyCode >= 0x61 && keyCode <= 0x7A) // Convert key to lower case + keyCode -= 0x20; + + if (keyCode >= 0x30 && keyCode <= 0x5A) { + auto modOpt = moduleMgr->getModuleByName(moduleName); + if (!modOpt.has_value()) { + clientMessageF("%sCould not find module with name: %s", RED, moduleName.c_str()); + } else { + modOpt.value()->setKeybind(keyCode); + clientMessageF("%sThe Keybind of %s is now '%c'", GREEN, mod->getModuleName(), keyCode); + } + } else { + clientMessageF("%sInvalid Key! Outside of ascii range: %X", RED, keyCode); + } + return true; + } else { + clientMessageF("%s%s is currently bound to %s", RED, mod->getModuleName(), Utils::getKeybindName(mod->getKeybind())); + return true; + } + +} diff --git a/Horion/Command/Commands/BindCommand.h b/Horion/Command/Commands/BindCommand.h new file mode 100644 index 0000000..ac18730 --- /dev/null +++ b/Horion/Command/Commands/BindCommand.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#include "ICommand.h" + +class BindCommand : public IMCCommand { +public: + BindCommand(); + ~BindCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/BruhCommand.cpp b/Horion/Command/Commands/BruhCommand.cpp new file mode 100644 index 0000000..d9ab9ee --- /dev/null +++ b/Horion/Command/Commands/BruhCommand.cpp @@ -0,0 +1,14 @@ +#include "BruhCommand.h" + +BruhCommand::BruhCommand() : IMCCommand("bruh", "bruh moment", "bruh") { +} + +BruhCommand::~BruhCommand() { +} + +bool BruhCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + + clientMessageF("bruh moment"); + return true; +} diff --git a/Horion/Command/Commands/BruhCommand.h b/Horion/Command/Commands/BruhCommand.h new file mode 100644 index 0000000..16608cc --- /dev/null +++ b/Horion/Command/Commands/BruhCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class BruhCommand : public IMCCommand { +public: + BruhCommand(); + ~BruhCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/CommandBlockExploitCommand.cpp b/Horion/Command/Commands/CommandBlockExploitCommand.cpp new file mode 100644 index 0000000..68703a3 --- /dev/null +++ b/Horion/Command/Commands/CommandBlockExploitCommand.cpp @@ -0,0 +1,66 @@ +#include "CommandBlockExploitCommand.h" + +#include "../../../SDK/Tag.h" +#include "../../Module/ModuleManager.h" + +CommandBlockExploitCommand::CommandBlockExploitCommand() : IMCCommand("commandblockexploit", "Workaround for executing commands without op", " ") { + registerAlias("cbe"); +} + +CommandBlockExploitCommand::~CommandBlockExploitCommand() { +} + +bool CommandBlockExploitCommand::execute(std::vector* args) { + assertTrue(args->size() > 2); + + std::ostringstream os; + for (int i = 2; i < args->size(); i++) { + if (i > 2) + os << " "; + os << args->at(i); + } + std::string cmd = os.str(); + + std::string type = args->at(1); + std::transform(type.begin(), type.end(), type.begin(), tolower); + + C_ItemStack* item; + + if (type == "beehive" || type == "bh") { + item = new C_ItemStack(***ItemRegistry::lookUpByName(std::make_unique().get(), std::make_unique().get(), TextHolder("beehive")), 1, 0); + std::string tag = R"({Count:1b,Damage:0s,Name:"minecraft:beehive",tag:{Occupants:[{ActorIdentifier:"minecraft:command_block_minecart<>",SaveData:{Command:")" + cmd + R"(",Persistent:1b,Ticking:1b,TicksLeftToStay:0}}],ench:[{id:28s,lvl:1s}],display:{Lore:[")" + cmd + R"("],Name:"§g§lBeehive Command"}})"; + item->fromTag(*Mojangson::parseTag(tag)); + } + + else if (type == "beenest" || type == "bn") { + item = new C_ItemStack(***ItemRegistry::lookUpByName(std::make_unique().get(), std::make_unique().get(), TextHolder("movingblock")), 1, 0); + std::string tag = R"({Count:1b,Damage:0s,Name:"minecraft:bee_nest",tag:{Occupants:[{ActorIdentifier:"minecraft:command_block_minecart<>",SaveData:{Command:")" + cmd + R"(",Persistent:1b,Ticking:1b,TicksLeftToStay:0}}],ench:[{id:28s,lvl:1s}],display:{Lore:[")" + cmd + R"("],Name:"§g§lBeeNest Command"}})"; + item->fromTag(*Mojangson::parseTag(tag)); + } + + else if (type == "movingblock" || type == "mb") { + item = new C_ItemStack(***ItemRegistry::lookUpByName(std::make_unique().get(), std::make_unique().get(), TextHolder("beehive")), 1, 0); + std::string tag = R"({Count:1b,Damage:0s,Name:"minecraft:movingblock",tag:{movingEntity:{id:"Beehive",Occupants:[{ActorIdentifier:"minecraft:command_block_minecart<>",SaveData:{Command:")" + cmd + R"(",Persistent:1b,Ticking:1b,TicksLeftToStay:0}}]},pistonPosX:0,movingBlock:{name:"minecraft:bee_nest"},pistonPosY:0,pistonPosZ:0,ench:[{id:28s,lvl:1s}],display:{Name:"§g§lMovingBlock BeeNest Command",Lore:[")" + cmd + R"("]}}})"; + item->fromTag(*Mojangson::parseTag(tag)); + } + + else if (type == "spoof" || type == "sp") { + item = new C_ItemStack(***ItemRegistry::lookUpByName(std::make_unique().get(), std::make_unique().get(), TextHolder("movingblock")), 1, 0); + std::string tag = R"({Count:1b,Damage:0s,Name:"minecraft:movingblock",tag:{movingEntity:{id:"Beehive",Occupants:[{ActorIdentifier:"minecraft:command_block_minecart<>",SaveData:{Command:")" + cmd + R"(",definitions:["+minecraft:bee"],identifier:"minecraft:command_block_minecart",Persistent:1b,Ticking:1b,TicksLeftToStay:1}}]},pistonPosX:0,movingBlock:{name:"minecraft:bee_nest"},pistonPosY:0,pistonPosZ:0,ench:[{id:28s,lvl:1s}],display:{Name:"§g§lSpoofed BeeNest Command",Lore:[")" + cmd + R"("]}}})"; + item->fromTag(*Mojangson::parseTag(tag)); + } + + else if (type == "invisible" || type == "invis") { + item = new C_ItemStack(***ItemRegistry::lookUpByName(std::make_unique().get(), std::make_unique().get(), TextHolder("movingblock")), 1, 0); + std::string tag = R"({Count:1b,Damage:0s,Name:"minecraft:movingblock",tag:{movingEntity:{id:"Beehive",Occupants:[{ActorIdentifier:"minecraft:command_block_minecart<>",SaveData:{Command:")" + cmd + R"(",definitions:["+minecraft:moving_block"],identifier:"minecraft:command_block_minecart",Persistent:1b,Ticking:1b,TicksLeftToStay:1}}]},pistonPosX:0,movingBlock:{name:"minecraft:air"},pistonPosY:0,pistonPosZ:0,ench:[{id:28s,lvl:1s}],display:{Name:"§g§lInvisible Beehive Command",Lore:[")" + cmd + R"("]}}})"; + item->fromTag(*Mojangson::parseTag(tag)); + } + + else return false; + + g_Data.getLocalPlayer()->getTransactionManager()->addInventoryAction(C_InventoryAction(0, nullptr, nullptr, item, nullptr, 1, 507, 99999)); + g_Data.getLocalPlayer()->getSupplies()->inventory->addItemToFirstEmptySlot(item); + + clientMessageF("%sPlace the item down to execute the command!", GREEN); + return true; +} diff --git a/Horion/Command/Commands/CommandBlockExploitCommand.h b/Horion/Command/Commands/CommandBlockExploitCommand.h new file mode 100644 index 0000000..0b3e0d9 --- /dev/null +++ b/Horion/Command/Commands/CommandBlockExploitCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "ICommand.h" + +class CommandBlockExploitCommand : public IMCCommand { +public: + CommandBlockExploitCommand(); + ~CommandBlockExploitCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ConfigCommand.cpp b/Horion/Command/Commands/ConfigCommand.cpp new file mode 100644 index 0000000..31e09c3 --- /dev/null +++ b/Horion/Command/Commands/ConfigCommand.cpp @@ -0,0 +1,24 @@ +#include "ConfigCommand.h" + +ConfigCommand::ConfigCommand() : IMCCommand("config", "Load/save configs", " ") { +} + +ConfigCommand::~ConfigCommand() { +} + +bool ConfigCommand::execute(std::vector* args) { + if (args->at(1) == "load") { + std::string name = args->at(2); + configMgr->loadConfig(name, false); + return true; + } else if (args->at(1) == "new") { + std::string name = args->at(2); + configMgr->loadConfig(name, true); + return true; + } else if (args->at(1) == "save") { + configMgr->saveConfig(); + clientMessageF("[%sHorion%s] %sSuccessfully saved config %s%s%s!", GOLD, WHITE, GREEN, GRAY, configMgr->currentConfig.c_str(), GREEN); + return true; + } + return false; +} \ No newline at end of file diff --git a/Horion/Command/Commands/ConfigCommand.h b/Horion/Command/Commands/ConfigCommand.h new file mode 100644 index 0000000..b9de736 --- /dev/null +++ b/Horion/Command/Commands/ConfigCommand.h @@ -0,0 +1,12 @@ +#pragma once +#include "ICommand.h" +#include "..\..\Config\ConfigManager.h" + +class ConfigCommand : public IMCCommand { +public: + ConfigCommand(); + ~ConfigCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; \ No newline at end of file diff --git a/Horion/Command/Commands/CoordsCommand.cpp b/Horion/Command/Commands/CoordsCommand.cpp new file mode 100644 index 0000000..2bd86fb --- /dev/null +++ b/Horion/Command/Commands/CoordsCommand.cpp @@ -0,0 +1,15 @@ +#include "CoordsCommand.h" + +CoordsCommand::CoordsCommand() : IMCCommand("coords", "Prints your coordinates", "") { + registerAlias("pos"); +} + +CoordsCommand::~CoordsCommand() { +} + +bool CoordsCommand::execute(std::vector* args) { + vec3_t* pos = g_Data.getLocalPlayer()->getPos(); + float yPos = pos->y - 1.62f; + clientMessageF("[%sHorion%s] %sX: %.2f Y: %.2f Z: %.2f", GOLD, WHITE, GREEN, pos->x, yPos /* eye height */, pos->z); + return true; +} diff --git a/Horion/Command/Commands/CoordsCommand.h b/Horion/Command/Commands/CoordsCommand.h new file mode 100644 index 0000000..4004c7a --- /dev/null +++ b/Horion/Command/Commands/CoordsCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class CoordsCommand : public IMCCommand { +public: + CoordsCommand(); + ~CoordsCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/DamageCommand.cpp b/Horion/Command/Commands/DamageCommand.cpp new file mode 100644 index 0000000..2b54067 --- /dev/null +++ b/Horion/Command/Commands/DamageCommand.cpp @@ -0,0 +1,29 @@ +#include "DamageCommand.h" + +#include "../../Module/ModuleManager.h" + +DamageCommand::DamageCommand() : IMCCommand("damage", "Damage yourself (relies on falldamage)", "") { + registerAlias("dmg"); +} + +DamageCommand::~DamageCommand() { +} + +bool DamageCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + float amount = assertFloat(args->at(1)); + if (amount < 1.f) { + clientMessageF("%sPlease put a number bigger than 0", RED); + return true; + } + auto noFallMod = moduleMgr->getModule(); + + if (noFallMod->isEnabled()) { + noFallMod->setEnabled(false); + g_Data.getLocalPlayer()->causeFallDamage(amount + 3.f); + noFallMod->setEnabled(true); + } else { + g_Data.getLocalPlayer()->causeFallDamage(amount + 3.f); + } + return true; +} diff --git a/Horion/Command/Commands/DamageCommand.h b/Horion/Command/Commands/DamageCommand.h new file mode 100644 index 0000000..f7ef086 --- /dev/null +++ b/Horion/Command/Commands/DamageCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class DamageCommand : public IMCCommand { +public: + DamageCommand(); + ~DamageCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/DupeCommand.cpp b/Horion/Command/Commands/DupeCommand.cpp new file mode 100644 index 0000000..9e04045 --- /dev/null +++ b/Horion/Command/Commands/DupeCommand.cpp @@ -0,0 +1,38 @@ +#include "DupeCommand.h" + +DupeCommand::DupeCommand() : IMCCommand("dupe", "Duplicates the item in hand", " ") { + registerAlias("d"); +} + +DupeCommand::~DupeCommand() { +} + +bool DupeCommand::execute(std::vector* args) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + auto transactionManager = g_Data.getLocalPlayer()->getTransactionManager(); + C_Inventory* inv = supplies->inventory; + int selectedSlot = supplies->selectedHotbarSlot; + C_ItemStack* item = inv->getItemStack(selectedSlot); + int count = item->count; + bool isGive = true; + if (args->size() > 1) + item->count = assertInt(args->at(1)); + if (args->size() > 2) + isGive = static_cast(assertInt(args->at(2))); + if (isGive) { + C_InventoryAction* firstAction = nullptr; + C_InventoryAction* secondAction = nullptr; + firstAction = new C_InventoryAction(0, item, nullptr, 507, 99999); + transactionManager->addInventoryAction(*firstAction); + inv->addItemToFirstEmptySlot(item); + } else { + C_InventoryAction* pp = nullptr; + pp = new C_InventoryAction(0, item, nullptr, 507, 99999); + transactionManager->addInventoryAction(*pp); + g_Data.getLocalPlayer()->setOffhandSlot(item); + } + if (args->size() > 1) + item->count = count; + clientMessageF("%sSuccessfully duplicated the item!", GREEN); + return true; +} diff --git a/Horion/Command/Commands/DupeCommand.h b/Horion/Command/Commands/DupeCommand.h new file mode 100644 index 0000000..0ca72f5 --- /dev/null +++ b/Horion/Command/Commands/DupeCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "ICommand.h" + +class DupeCommand : public IMCCommand { +public: + DupeCommand(); + ~DupeCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/EjectCommand.cpp b/Horion/Command/Commands/EjectCommand.cpp new file mode 100644 index 0000000..18a280b --- /dev/null +++ b/Horion/Command/Commands/EjectCommand.cpp @@ -0,0 +1,13 @@ +#include "EjectCommand.h" + +EjectCommand::EjectCommand() : IMCCommand("eject", "Removes the cheat from the game.", "") { + registerAlias("uninject"); +} + +EjectCommand::~EjectCommand() { +} + +bool EjectCommand::execute(std::vector* args) { + GameData::terminate(); + return true; +} diff --git a/Horion/Command/Commands/EjectCommand.h b/Horion/Command/Commands/EjectCommand.h new file mode 100644 index 0000000..2a44ab2 --- /dev/null +++ b/Horion/Command/Commands/EjectCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class EjectCommand : public IMCCommand { +public: + EjectCommand(); + ~EjectCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/EnchantCommand.cpp b/Horion/Command/Commands/EnchantCommand.cpp new file mode 100644 index 0000000..2af59c4 --- /dev/null +++ b/Horion/Command/Commands/EnchantCommand.cpp @@ -0,0 +1,176 @@ +#include "EnchantCommand.h" +#include "../../../Utils/Utils.h" + +EnchantCommand::EnchantCommand() : IMCCommand("enchant", "Enchants items", " [level] ") { + enchantMap["protection"] = 0; + enchantMap["fire_protection"] = 1; + enchantMap["feather_falling"] = 2; + enchantMap["blast_protection"] = 3; + enchantMap["projectile_protection"] = 4; + enchantMap["thorns"] = 5; + enchantMap["respiration"] = 6; + enchantMap["depth_strider"] = 7; + enchantMap["aqua_affinity"] = 8; + enchantMap["frost_walker"] = 25; + enchantMap["sharpness"] = 9; + enchantMap["smite"] = 10; + enchantMap["bane_of_arthropods"] = 11; + enchantMap["knockback"] = 12; + enchantMap["fire_aspect"] = 13; + enchantMap["looting"] = 14; + enchantMap["channeling"] = 32; + enchantMap["impaling"] = 29; + enchantMap["loyalty"] = 31; + enchantMap["riptide"] = 30; + enchantMap["silktouch"] = 16; + enchantMap["fortune"] = 18; + enchantMap["unbreaking"] = 17; + enchantMap["efficiency"] = 15; + enchantMap["mending"] = 26; + enchantMap["power"] = 19; + enchantMap["punch"] = 20; + enchantMap["flame"] = 21; + enchantMap["infinity"] = 22; + enchantMap["multishot"] = 33; + enchantMap["quick_charge"] = 35; + enchantMap["piercing"] = 34; + enchantMap["luck_of_sea"] = 23; + enchantMap["lure"] = 24; + enchantMap["soul_speed"] = 36; +} + +EnchantCommand::~EnchantCommand() { +} + +bool EnchantCommand::execute(std::vector* args) { + assertTrue(args->size() > 1); + + int enchantId = 0; + int enchantLevel = 32767; + bool isAuto = true; + + if (args->at(1) != "all") { + try { + // convert string to back to lower case + std::string data = args->at(1); + std::transform(data.begin(), data.end(), data.begin(), ::tolower); + + auto convertedString = enchantMap.find(data); + if (convertedString != enchantMap.end()) + enchantId = convertedString->second; + else + enchantId = assertInt(args->at(1)); + } catch (int) { + clientMessageF("exception while trying to get enchant string"); + enchantId = assertInt(args->at(1)); + } + } + + if (args->size() > 2) + enchantLevel = assertInt(args->at(2)); + if (args->size() > 3) + isAuto = static_cast(assertInt(args->at(3))); + + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + + int selectedSlot = supplies->selectedHotbarSlot; + C_ItemStack* item = inv->getItemStack(selectedSlot); + + C_InventoryAction* firstAction = nullptr; + C_InventoryAction* secondAction = nullptr; + + ItemDescriptor* desc = nullptr; + desc = new ItemDescriptor((*item->item)->itemId, 0); + + if (isAuto) { + { + firstAction = new C_InventoryAction(supplies->selectedHotbarSlot, desc, nullptr, item, nullptr, item->count); + if (strcmp(g_Data.getRakNetInstance()->serverIp.getText(), "mco.mineplex.com") == 0) + secondAction = new C_InventoryAction(0, nullptr, desc, nullptr, item, item->count, 32766, 100); + else + secondAction = new C_InventoryAction(0, nullptr, desc, nullptr, item, item->count, 507, 99999); + manager->addInventoryAction(*firstAction); + manager->addInventoryAction(*secondAction); + delete firstAction; + delete secondAction; + } + } + + using getEnchantsFromUserData_t = void(__fastcall*)(C_ItemStack*, void*); + using addEnchant_t = bool(__fastcall*)(void*, __int64); + using saveEnchantsToUserData_t = void(__fastcall*)(C_ItemStack*, void*); + + static getEnchantsFromUserData_t getEnchantsFromUserData = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 48 81 EC ? ? ? ? 48 8B F2 48 8B D9 48 89 54 24 ? 33 FF 89 7C 24 ? E8 ? ? ? ? 84 C0")); + static addEnchant_t addEnchant = reinterpret_cast(FindSignature("48 89 5C 24 ?? 48 89 54 24 ?? 57 48 83 EC ?? 45 0F")); + + static saveEnchantsToUserData_t saveEnchantsToUserData = 0x0; + if (!saveEnchantsToUserData) { + saveEnchantsToUserData = reinterpret_cast(FindSignature("48 89 5C 24 ? 56 57 41 56 48 81 EC ? ? ? ? 0F 29 B4 24 ? ? ? ? 48 8B FA 4C 8B C1 48 8B 41 08 48 85 C0")); + } + + if (strcmp(args->at(1).c_str(), "all") == 0) { + for (int i = 0; i < 38; i++) { + void* EnchantData = malloc(0x60); + if (EnchantData != nullptr) + memset(EnchantData, 0x0, 0x60); + + getEnchantsFromUserData(item, EnchantData); + + __int64 enchantPair = ((__int64)enchantLevel << 32) | i; + + if (addEnchant(EnchantData, enchantPair)) { // Upper 4 bytes = level, lower 4 bytes = enchant type + saveEnchantsToUserData(item, EnchantData); + __int64 proxy = reinterpret_cast<__int64>(g_Data.getLocalPlayer()->getSupplies()); + if (!*(uint8_t*)(proxy + 168)) + (*(void(__fastcall**)(unsigned long long, unsigned long long, C_ItemStack*))(**(unsigned long long**)(proxy + 176) + 72i64))( + *(unsigned long long*)(proxy + 176), + *(unsigned int*)(proxy + 16), + item); // Player::selectItem + + //g_Data.getLocalPlayer()->sendInventory(); + } + free(EnchantData); + } + clientMessageF("%sEnchant successful!", GREEN); + } else { + void* EnchantData = malloc(0x60); + if (EnchantData != nullptr) + memset(EnchantData, 0x0, 0x60); + + getEnchantsFromUserData(item, EnchantData); + + __int64 enchantPair = ((__int64)enchantLevel << 32) | enchantId; + + if (addEnchant(EnchantData, enchantPair)) { // Upper 4 bytes = level, lower 4 bytes = enchant type + saveEnchantsToUserData(item, EnchantData); + __int64 proxy = reinterpret_cast<__int64>(g_Data.getLocalPlayer()->getSupplies()); + if (!*(uint8_t*)(proxy + 168)) + (*(void(__fastcall**)(unsigned long long, unsigned long long, C_ItemStack*))(**(unsigned long long**)(proxy + 176) + 72i64))( + *(unsigned long long*)(proxy + 176), + *(unsigned int*)(proxy + 16), + item); // Player::selectItem + + //g_Data.getLocalPlayer()->sendInventory(); + clientMessageF("%sEnchant successful!", GREEN); + } else + clientMessageF("%sEnchant failed, try using a lower enchant-level", RED); + + free(EnchantData); + } + + if (isAuto) { + if (strcmp(g_Data.getRakNetInstance()->serverIp.getText(), "mco.mineplex.com") == 0) + firstAction = new C_InventoryAction(0, desc, nullptr, item, nullptr, item->count, 32766, 100); + else + firstAction = new C_InventoryAction(0, desc, nullptr, item, nullptr, item->count, 507, 99999); + secondAction = new C_InventoryAction(supplies->selectedHotbarSlot, nullptr, desc, nullptr, item, item->count); + manager->addInventoryAction(*firstAction); + manager->addInventoryAction(*secondAction); + delete firstAction; + delete secondAction; + } + + return true; +} diff --git a/Horion/Command/Commands/EnchantCommand.h b/Horion/Command/Commands/EnchantCommand.h new file mode 100644 index 0000000..f5ef815 --- /dev/null +++ b/Horion/Command/Commands/EnchantCommand.h @@ -0,0 +1,13 @@ +#pragma once +#include "ICommand.h" +class EnchantCommand : public IMCCommand { +private: + std::map enchantMap; + +public: + EnchantCommand(); + ~EnchantCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ExecuteCommand.cpp b/Horion/Command/Commands/ExecuteCommand.cpp new file mode 100644 index 0000000..cd5763d --- /dev/null +++ b/Horion/Command/Commands/ExecuteCommand.cpp @@ -0,0 +1,23 @@ +#include "ExecuteCommand.h" + +ExecuteCommand::ExecuteCommand() : IMCCommand("execute", "Executes javascript code", "") { + registerAlias("exec"); +} + +ExecuteCommand::~ExecuteCommand() { +} + +bool ExecuteCommand::execute(std::vector* args) { + assertTrue(args->size() > 1); + std::ostringstream os; + for (int i = 1; i < args->size(); i++) { + if (i > 1) + os << " "; + os << args->at(i); + } + auto str = os.str(); + + auto wstr = Utils::stringToWstring(str); + clientMessageF("%sScript returned: %s%S", GOLD, WHITE, scriptMgr.runScript(wstr).c_str()); + return true; +} diff --git a/Horion/Command/Commands/ExecuteCommand.h b/Horion/Command/Commands/ExecuteCommand.h new file mode 100644 index 0000000..077b236 --- /dev/null +++ b/Horion/Command/Commands/ExecuteCommand.h @@ -0,0 +1,14 @@ +#pragma once + +#include "ICommand.h" + +#include "../../Scripting/ScriptManager.h" + +class ExecuteCommand : public IMCCommand { +public: + ExecuteCommand(); + ~ExecuteCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/FriendListCommand.cpp b/Horion/Command/Commands/FriendListCommand.cpp new file mode 100644 index 0000000..1a29ae3 --- /dev/null +++ b/Horion/Command/Commands/FriendListCommand.cpp @@ -0,0 +1,64 @@ +#include "FriendListCommand.h" + +FriendListCommand::FriendListCommand() : IMCCommand("friend", "Add/Remove friendly players", "") { + registerAlias("friendlist"); +} + +FriendListCommand::~FriendListCommand() { +} + +bool FriendListCommand::execute(std::vector* args) { + assertTrue(args->size() >= 3); + std::string subcommand = args->at(1); + std::transform(subcommand.begin(), subcommand.end(), subcommand.begin(), ::tolower); + std::string searchedName = args->at(2); // Friend to add/remove + std::transform(searchedName.begin(), searchedName.end(), searchedName.begin(), ::tolower); // tolower + + C_EntityList* entList = g_Data.getEntityList(); + size_t listSize = entList->getListSize(); + + if (listSize > 10000) { + return true; + } + + std::string playerName; + //Loop through all our players and retrieve their information + for (size_t i = 0; i < listSize; i++) { + C_Entity* currentEntity = entList->get(i); + + std::string currentEntityName(currentEntity->getNameTag()->getText()); + + std::transform(currentEntityName.begin(), currentEntityName.end(), currentEntityName.begin(), ::tolower); // tolower + + if (currentEntity == 0) + break; + + if (currentEntity == g_Data.getLocalPlayer()) // Skip Local player + continue; + + if (currentEntityName.find(searchedName) == std::string::npos) // Continue if name not found + continue; + + playerName = currentEntity->getNameTag()->getText(); + break; + } + if (playerName.size() <= 1) { + clientMessageF("[%sHorion%s] %sCouldn't find player: %s!", GOLD, WHITE, RED, searchedName.c_str()); + return true; + } + if (subcommand == "add") { + FriendList::addPlayerToList(playerName); + clientMessageF("[%sHorion%s] %s%s is now your friend!", GOLD, WHITE, GREEN, playerName.c_str()); + return true; + + } else if (subcommand == "remove") { + if (FriendList::removePlayer(searchedName)) { + clientMessageF("[%sHorion%s] %s%s has been removed from your friendlist!", GOLD, WHITE, GREEN, searchedName.c_str()); + return true; + } else { + clientMessageF("[%sHorion%s] %s%s was not in your friendlist!", GOLD, WHITE, GREEN, searchedName.c_str()); + return true; + } + } + return true; +} diff --git a/Horion/Command/Commands/FriendListCommand.h b/Horion/Command/Commands/FriendListCommand.h new file mode 100644 index 0000000..e50bbcb --- /dev/null +++ b/Horion/Command/Commands/FriendListCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class FriendListCommand : public IMCCommand { +public: + FriendListCommand(); + ~FriendListCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/GameModeCommand.cpp b/Horion/Command/Commands/GameModeCommand.cpp new file mode 100644 index 0000000..dd47839 --- /dev/null +++ b/Horion/Command/Commands/GameModeCommand.cpp @@ -0,0 +1,22 @@ +#include "GameModeCommand.h" + +GameModeCommand::GameModeCommand() : IMCCommand("gamemode", "Changes the local player's gamemode", "") { + registerAlias("gm"); +} + +GameModeCommand::~GameModeCommand() { +} + +bool GameModeCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + assertTrue(args->size() > 1); + int gamemode = assertInt(args->at(1)); + if (gamemode >= 0 && gamemode <= 2) { + g_Data.getLocalPlayer()->setGameModeType(gamemode); + clientMessageF("[%sHorion%s] %sGameMode changed!", GOLD, WHITE, GREEN); + return true; + } + + clientMessageF("[%sHorion%s] %sInvalid GameMode!", GOLD, WHITE, RED); + return true; +} diff --git a/Horion/Command/Commands/GameModeCommand.h b/Horion/Command/Commands/GameModeCommand.h new file mode 100644 index 0000000..4f812f0 --- /dev/null +++ b/Horion/Command/Commands/GameModeCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class GameModeCommand : public IMCCommand { +public: + GameModeCommand(); + ~GameModeCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/GiveCommand.cpp b/Horion/Command/Commands/GiveCommand.cpp new file mode 100644 index 0000000..cbeae78 --- /dev/null +++ b/Horion/Command/Commands/GiveCommand.cpp @@ -0,0 +1,191 @@ +#include "GiveCommand.h" + +#include "../../../SDK/Tag.h" +#include "../../../Utils/Utils.h" + +GiveCommand::GiveCommand() : IMCCommand("give", "spawn items", " [itemData] [NBT]") { +} + +GiveCommand::~GiveCommand() { +} + +bool GiveCommand::execute(std::vector *args) { + assertTrue(args->size() > 2); + + int itemId = 0; + uint32_t fullCount = static_cast(assertInt(args->at(2))); + unsigned int stackCount = fullCount / 64; // Get the amount of stacks we have. + char count = fullCount % 64; // Get the amount we have left. + char itemData = 0; + if (args->size() > 3) { + itemData = static_cast(assertInt(args->at(3))); + } + + try { + itemId = std::stoi(args->at(1)); + } catch (const std::invalid_argument &) { + } + + //clientMessageF("%sDEBUG:%s Will give %d stacks!", RED, GREEN, stackCount); + //clientMessageF("%sDEBUG:%s Will give %d as a remainder!", RED, GREEN, count); + + // Give us all the stacks of the items we want. + for (unsigned int i = 0; i < stackCount; i++) { + //clientMessageF("%sDEBUG:%s Giving stack %d of items!", RED, GREEN, i + 1); + std::string tag; + bool success = false; + + if (args->size() > 4) { + std::string tag = Utils::getClipboardText(); + } + if (itemId == 0) { + TextHolder tempText(args->at(1)); + success = giveItem(64, tempText, itemData, tag); + } else { + success = giveItem(64, itemId, itemData, tag); + } + // If one of these fail. Then something went wrong. + // Return to prevent a possible spam of error messages. + if (!success) return true; + } + + // Now give us our remainder. + if (count >= 1) { + //clientMessageF("%sDEBUG:%s Giving remaining %d items!", RED, GREEN, count); + std::string tag; + bool success = false; + + if (args->size() > 4) { + std::string tag = Utils::getClipboardText(); + } + if (itemId == 0) { + TextHolder tempText(args->at(1)); + success = giveItem(count, tempText, itemData, tag); + } else { + success = giveItem(count, itemId, itemData, tag); + } + if (!success) return true; + } + C_Inventory *inv = g_Data.getLocalPlayer()->getSupplies()->inventory; + C_ItemStack *item = g_Data.getLocalPlayer()->getSelectedItem(); + if (args->size() > 4) { + std::string tag; + tag = Utils::getClipboardText(); + if (args->size() > 4) { + g_Data.getLocalPlayer()->getTransactionManager()->addInventoryAction(C_InventoryAction(0, nullptr, nullptr, item, nullptr, 1, 507, 99999)); + } + + if (tag.size() > 1 && tag.front() == MojangsonToken::COMPOUND_START.getSymbol() && tag.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + if (args->size() > 4) { + item->setUserData(std::move(Mojangson::parseTag(tag))); + } + } else { + clientMessageF("%sInvalid NBT tag!", RED); + return true; + } + + if (args->size() > 4) { + g_Data.getLocalPlayer()->getTransactionManager()->addInventoryAction(C_InventoryAction(0, nullptr, nullptr, item, nullptr, 1, 507, 99999)); + } + clientMessageF("%s%s", GREEN, "Successfully loaded mojangson !"); + } + if (args->size() > 4) { + C_InventoryAction *firstAction = nullptr; + auto transactionMan = g_Data.getLocalPlayer()->getTransactionManager(); + firstAction = new C_InventoryAction(0, item, nullptr, 507, 99999); + transactionMan->addInventoryAction(*firstAction); + inv->addItemToFirstEmptySlot(item); + } + + clientMessageF("%sSuccessfully gave items!", GREEN); + return true; +} + +bool GiveCommand::giveItem(uint8_t count, int itemId, uint8_t itemData, std::string &tag) { + C_Inventory *inv = g_Data.getLocalPlayer()->getSupplies()->inventory; + C_ItemStack *itemStack = nullptr; + auto transactionManager = g_Data.getLocalPlayer()->getTransactionManager(); + + std::unique_ptr ItemPtr = std::make_unique(); + C_Item ***cStack = ItemRegistry::getItemFromId(ItemPtr.get(), itemId); + if (cStack == nullptr || *cStack == nullptr || **cStack == nullptr) { + clientMessageF("%sInvalid item ID!", RED); + return false; + } + itemStack = new C_ItemStack(***cStack, count, itemData); + + if (itemStack != nullptr) { + itemStack->count = count; + } + + int slot = inv->getFirstEmptySlot(); + + if (tag.size() > 1 && tag.front() == MojangsonToken::COMPOUND_START.getSymbol() && tag.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + //itemStack->setUserData(std::move(Mojangson::parseTag(tag))); + itemStack->fromTag(*Mojangson::parseTag(tag)); + } + + ItemDescriptor *desc = new ItemDescriptor((*itemStack->item)->itemId, itemData); + + // If we add the second action, Only one stack will come through for some reason. + // Otherwise all stacks will come through but will be buggy till dropped or + // till the world is saved then reloaded. + + C_InventoryAction *firstAction = new C_InventoryAction(slot, desc, nullptr, itemStack, nullptr, count, 507, 99999); + //C_InventoryAction *secondAction = new C_InventoryAction(slot, nullptr, desc, nullptr, itemStack, count); + + transactionManager->addInventoryAction(*firstAction); + //transactionManager->addInventoryAction(*secondAction); + + delete firstAction; + //delete secondAction; + delete desc; + + inv->addItemToFirstEmptySlot(itemStack); + return true; +} + +bool GiveCommand::giveItem(uint8_t count, TextHolder &text, uint8_t itemData, std::string &tag) { + C_Inventory *inv = g_Data.getLocalPlayer()->getSupplies()->inventory; + C_ItemStack *itemStack = nullptr; + auto transactionManager = g_Data.getLocalPlayer()->getTransactionManager(); + + std::unique_ptr ItemPtr = std::make_unique(); + std::unique_ptr buffer = std::make_unique(); + C_Item ***cStack = ItemRegistry::lookUpByName(ItemPtr.get(), buffer.get(), text); + if (*cStack == nullptr) { + clientMessageF("%sInvalid item name!", RED); + return false; + } + itemStack = new C_ItemStack(***cStack, count, itemData); + + if (itemStack != nullptr) { + itemStack->count = count; + } + + int slot = inv->getFirstEmptySlot(); + + if (tag.size() > 1 && tag.front() == MojangsonToken::COMPOUND_START.getSymbol() && tag.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + //itemStack->setUserData(std::move(Mojangson::parseTag(tag))); + itemStack->fromTag(*Mojangson::parseTag(tag)); + } + + ItemDescriptor *desc = new ItemDescriptor((*itemStack->item)->itemId, itemData); + + // If we add the second action, Only one stack will come through for some reason. + // Otherwise all stacks will come through but will be buggy till dropped or + // till the world is saved then reloaded. + + C_InventoryAction *firstAction = new C_InventoryAction(slot, desc, nullptr, itemStack, nullptr, count, 507, 99999); + //C_InventoryAction *secondAction = new C_InventoryAction(slot, nullptr, desc, nullptr, itemStack, count); + + transactionManager->addInventoryAction(*firstAction); + //transactionManager->addInventoryAction(*secondAction); + + delete firstAction; + //delete secondAction; + delete desc; + + inv->addItemToFirstEmptySlot(itemStack); + return true; +} diff --git a/Horion/Command/Commands/GiveCommand.h b/Horion/Command/Commands/GiveCommand.h new file mode 100644 index 0000000..b0caf84 --- /dev/null +++ b/Horion/Command/Commands/GiveCommand.h @@ -0,0 +1,14 @@ +#pragma once +#include "ICommand.h" +class GiveCommand : public IMCCommand { +public: + GiveCommand(); + ~GiveCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector *args) override; + +private: + bool giveItem(uint8_t count, int itemId, uint8_t itemData, std::string &tag); + bool giveItem(uint8_t count, TextHolder &text, uint8_t itemData, std::string &tag); +}; diff --git a/Horion/Command/Commands/HelpCommand.cpp b/Horion/Command/Commands/HelpCommand.cpp new file mode 100644 index 0000000..3d3652f --- /dev/null +++ b/Horion/Command/Commands/HelpCommand.cpp @@ -0,0 +1,20 @@ +#include "HelpCommand.h" + +#include "../CommandMgr.h" + +HelpCommand::HelpCommand() : IMCCommand("help", "Lists all commands", "") { + registerAlias("h"); +} + +HelpCommand::~HelpCommand() { +} + +bool HelpCommand::execute(std::vector* args) { + clientMessageF("=========="); + std::vector* commandList = cmdMgr->getCommandList(); + for (auto it = commandList->begin(); it != commandList->end(); ++it) { + IMCCommand* plump = *it; + clientMessageF("%s%s - %s%s", plump->getCommand(), GRAY, ITALIC, plump->getDescription()); + } + return true; +} diff --git a/Horion/Command/Commands/HelpCommand.h b/Horion/Command/Commands/HelpCommand.h new file mode 100644 index 0000000..cc9b934 --- /dev/null +++ b/Horion/Command/Commands/HelpCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class HelpCommand : public IMCCommand { +public: + HelpCommand(); + ~HelpCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/HideCommand.cpp b/Horion/Command/Commands/HideCommand.cpp new file mode 100644 index 0000000..ed09ea1 --- /dev/null +++ b/Horion/Command/Commands/HideCommand.cpp @@ -0,0 +1,17 @@ +#include "HideCommand.h" + +HideCommand::HideCommand() : IMCCommand("hide", "hide the mod", "") { +} + +HideCommand::~HideCommand() { +} + +bool HideCommand::execute(std::vector* args) { + GameData::hide(); + if (GameData::shouldHide()) { + clientMessageF("[%sHorion%s] %sHidden.", GOLD, WHITE, GREEN); + } else { + clientMessageF("[%sHorion%s] %sMod is now visible.", GOLD, WHITE, GREEN); + } + return true; +} diff --git a/Horion/Command/Commands/HideCommand.h b/Horion/Command/Commands/HideCommand.h new file mode 100644 index 0000000..c08503b --- /dev/null +++ b/Horion/Command/Commands/HideCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class HideCommand : public IMCCommand { +public: + HideCommand(); + ~HideCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ICommand.cpp b/Horion/Command/Commands/ICommand.cpp new file mode 100644 index 0000000..eb70ea6 --- /dev/null +++ b/Horion/Command/Commands/ICommand.cpp @@ -0,0 +1,25 @@ +#include "ICommand.h" +#include +#include +#include + +IMCCommand::IMCCommand(const char* command, const char* description, const char* usage) { + this->_command = command; + this->_description = description; + this->_usage = usage; + registerAlias(command); +} + +IMCCommand::~IMCCommand() { +} +void IMCCommand::clientMessageF(const char* fmt, ...) { + va_list arg; + va_start(arg, fmt); + g_Data.getGuiData()->displayClientMessageVA(fmt, arg); + va_end(arg); +} +void IMCCommand::registerAlias(const char* str) { + std::string ss = str; + std::transform(ss.begin(), ss.end(), ss.begin(), ::tolower); + aliasList.push_back(ss); +} diff --git a/Horion/Command/Commands/ICommand.h b/Horion/Command/Commands/ICommand.h new file mode 100644 index 0000000..92b3da1 --- /dev/null +++ b/Horion/Command/Commands/ICommand.h @@ -0,0 +1,40 @@ +#pragma once + +#include "../../../Memory/GameData.h" +#include "../../FriendList/FriendList.h" + +#ifndef ASSERT_T +#define ASSERT_T(x) \ + if (!(x)) return false; +#endif + +class IMCCommand { +private: + const char* _command; + const char* _description; + const char* _usage; + std::vector aliasList; + +protected: + inline void assertTrue(bool condition) { + if (!condition) { + throw std::exception(); + } + }; + inline float assertFloat(std::string string) { return std::stof(string); }; + inline int assertInt(std::string string) { return std::stoi(string); }; + + void registerAlias(const char* str); + + void clientMessageF(const char* fmt, ...); + +public: + IMCCommand(const char* command, const char* description, const char* usage); + virtual ~IMCCommand(); + + virtual const char* getCommand() { return _command; }; + virtual std::vector* getAliasList() { return &aliasList; }; + virtual const char* getDescription() { return _description; }; + virtual const char* getUsage(const char* alias) { return _usage; }; + virtual bool execute(std::vector* args) = 0; +}; diff --git a/Horion/Command/Commands/ModulesCommand.cpp b/Horion/Command/Commands/ModulesCommand.cpp new file mode 100644 index 0000000..b97b940 --- /dev/null +++ b/Horion/Command/Commands/ModulesCommand.cpp @@ -0,0 +1,24 @@ +#include "ModulesCommand.h" + +#include +#include "../../Module/ModuleManager.h" + +ModulesCommand::ModulesCommand() : IMCCommand("modules", "Lists all modules", "") { + registerAlias("mods"); +} + +ModulesCommand::~ModulesCommand() { +} + +bool ModulesCommand::execute(std::vector* args) { + auto lock = moduleMgr->lockModuleList(); + std::vector>* modules = moduleMgr->getModuleList(); + clientMessageF("=========="); + clientMessageF("Modules (%i):", modules->size()); + for (auto it = modules->begin(); it != modules->end(); ++it) { + auto mod = *it; + clientMessageF("%s %s- %s%s", mod->getModuleName(), GRAY, ITALIC, mod->getTooltip()); + } + + return true; +} diff --git a/Horion/Command/Commands/ModulesCommand.h b/Horion/Command/Commands/ModulesCommand.h new file mode 100644 index 0000000..b532c28 --- /dev/null +++ b/Horion/Command/Commands/ModulesCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class ModulesCommand : public IMCCommand { +public: + ModulesCommand(); + ~ModulesCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/NameSpoofCommand.cpp b/Horion/Command/Commands/NameSpoofCommand.cpp new file mode 100644 index 0000000..df7cf9d --- /dev/null +++ b/Horion/Command/Commands/NameSpoofCommand.cpp @@ -0,0 +1,30 @@ +#include "NameSpoofCommand.h" + +NameSpoofCommand::NameSpoofCommand() : IMCCommand("namespoof", "Spoof your name on realms/bds", " ") { + registerAlias("ns"); + registerAlias("fakename"); + registerAlias("fn"); +} + +NameSpoofCommand::~NameSpoofCommand() { +} + +bool NameSpoofCommand::execute(std::vector* args) { + if (args->at(1) == "name" && args->size() > 2) { + std::ostringstream os; + for (int i = 2; i < args->size(); i++) { + if (i > 2) + os << " "; + os << args->at(i); + } + TextHolder* name = new TextHolder(os.str()); + g_Data.setFakeName(name); + clientMessageF("[%sHorion%s] %sSet fakename to %s%s%s, please reconnect!", GOLD, WHITE, GREEN, GRAY, name->getText(), GREEN); + return true; + } else if (args->at(1) == "reset") { + g_Data.setFakeName(NULL); + clientMessageF("[%sHorion%s] %sReset fakename!", GOLD, WHITE, GREEN); + return true; + } + return false; +} diff --git a/Horion/Command/Commands/NameSpoofCommand.h b/Horion/Command/Commands/NameSpoofCommand.h new file mode 100644 index 0000000..14de813 --- /dev/null +++ b/Horion/Command/Commands/NameSpoofCommand.h @@ -0,0 +1,12 @@ +#pragma once +#include "ICommand.h" +#include + +class NameSpoofCommand : public IMCCommand { +public: + NameSpoofCommand(); + ~NameSpoofCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/NbtCommand.cpp b/Horion/Command/Commands/NbtCommand.cpp new file mode 100644 index 0000000..058cb11 --- /dev/null +++ b/Horion/Command/Commands/NbtCommand.cpp @@ -0,0 +1,110 @@ +#include "NbtCommand.h" +#include "../../../Utils/Utils.h" +#include "../../../Utils/Logger.h" +#include "../../../SDK/Tag.h" + +NbtCommand::NbtCommand() : IMCCommand("nbt", "read and write NBT tags to/from your clipboard (You have to point at an entity/block entity)", "") { + registerAlias("nbtraw"); +} + +NbtCommand::~NbtCommand() { +} + +bool NbtCommand::execute(std::vector* args) { + assertTrue(args->size() > 1); + bool isRaw = args->at(0) == "nbtraw"; + if(isRaw){ + assertTrue(args->at(1) == "write"); + assertTrue(args->size() > 2); + } + + PointingStruct* pointingStruct = g_Data.getClientInstance()->getPointerStruct(); + C_BlockActor* blockActor = g_Data.getLocalPlayer()->region->getBlockEntity(pointingStruct->block); + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + C_ItemStack* item = g_Data.getLocalPlayer()->getSelectedItem(); + + if (args->at(1) == "read" || args->at(1) == "save") { + std::unique_ptr tag = std::make_unique(); + std::stringstream build; + + if (args->at(1) == "save" && item != nullptr) { + auto* boy = new CompoundTag(); + item->save(&boy); + boy->write(build); + delete boy; + } else { + if (pointingStruct->getEntity() != nullptr) { + if (g_Data.getRakNetInstance()->serverIp.getTextLength() >= 1) { + clientMessageF("%sNBT tags for mobs only works in local world!", RED); + return true; + } + pointingStruct->getEntity()->save(tag.get()); + tag->write(build); + } else if (blockActor != nullptr) { + blockActor->save(tag.get()); + tag->write(build); + } else if (item != nullptr && item->tag != nullptr) { + item->tag->write(build); + } else { + clientMessageF("%sCouldn't find NBT tags!", RED); + return true; + } + } + + auto builtStr = build.str(); + Utils::setClipboardText(builtStr); + clientMessageF("%s%s", GREEN, "CompoundTag copied:"); + clientMessageF(builtStr.c_str()); + } else if ((args->at(1) == "write" || args->at(1) == "load") && item) { + std::string tag; + if(isRaw){ + std::ostringstream os; + for (int i = 2; i < args->size(); i++) { + if (i > 2) + os << " "; + os << args->at(i); + } + + tag = os.str(); + }else{ + tag = Utils::getClipboardText(); + } + + { + manager->addInventoryAction(C_InventoryAction(supplies->selectedHotbarSlot, item, nullptr)); + manager->addInventoryAction(C_InventoryAction(0, nullptr, item, 507, 99999)); + } + + if (tag.size() > 1 && tag.front() == MojangsonToken::COMPOUND_START.getSymbol() && tag.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + if (args->at(1) == "write") + item->setUserData(std::move(Mojangson::parseTag(tag))); + else if (args->at(1) == "load") { + item->fromTag(*Mojangson::parseTag(tag)); + item->count = 64; + } + } else { + clientMessageF("%sInvalid NBT tag!", RED); + return true; + } + + { + manager->addInventoryAction(C_InventoryAction(0, item, nullptr, 507, 99999)); + manager->addInventoryAction(C_InventoryAction(supplies->selectedHotbarSlot, nullptr, item)); + } + + clientMessageF("%s%s", GREEN, "Successfully loaded mojangson !"); + } else { + clientMessageF("%s%s", RED, "Couldn't execute command correctly"); + } + + return true; +} +const char* NbtCommand::getUsage(const char* alias) { + if(strcmp(alias, "nbtraw") == 0){ + return "write "; + } + + return IMCCommand::getUsage(alias); +} diff --git a/Horion/Command/Commands/NbtCommand.h b/Horion/Command/Commands/NbtCommand.h new file mode 100644 index 0000000..04cef73 --- /dev/null +++ b/Horion/Command/Commands/NbtCommand.h @@ -0,0 +1,12 @@ +#pragma once +#include "ICommand.h" + +class NbtCommand : public IMCCommand { +public: + NbtCommand(); + ~NbtCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; + const char* getUsage(const char* alias) override; +}; diff --git a/Horion/Command/Commands/PanicCommand.cpp b/Horion/Command/Commands/PanicCommand.cpp new file mode 100644 index 0000000..f27abdc --- /dev/null +++ b/Horion/Command/Commands/PanicCommand.cpp @@ -0,0 +1,21 @@ +#include "PanicCommand.h" + +#include "../../Module/ModuleManager.h" + +PanicCommand::PanicCommand() : IMCCommand("panic", "Disables all Modules", "") { +} + +PanicCommand::~PanicCommand() { +} + +bool PanicCommand::execute(std::vector* args) { + auto lock = moduleMgr->lockModuleList(); + std::vector> * modules = moduleMgr->getModuleList(); + + for (auto it = modules->begin(); it != modules->end(); ++it) { + auto mod = *it; + mod->setEnabled(false); + } + clientMessageF("%sDisabled all Modules!", YELLOW); + return true; +} diff --git a/Horion/Command/Commands/PanicCommand.h b/Horion/Command/Commands/PanicCommand.h new file mode 100644 index 0000000..7ca7578 --- /dev/null +++ b/Horion/Command/Commands/PanicCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class PanicCommand : public IMCCommand { +public: + PanicCommand(); + ~PanicCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/PathCommand.cpp b/Horion/Command/Commands/PathCommand.cpp new file mode 100644 index 0000000..993b6de --- /dev/null +++ b/Horion/Command/Commands/PathCommand.cpp @@ -0,0 +1,92 @@ +#include "PathCommand.h" + +#include "../../Module/ModuleManager.h" +#include "../../path/goals/JoeGoalY.h" +#include "../../path/goals/JoeGoalXZ.h" +#include "../../path/goals/JoeGoalXYZ.h" + +PathCommand::PathCommand() : IMCCommand("path", "Joe path", " [args]"){ + this->registerAlias("joe"); +} +PathCommand::~PathCommand() { +} +bool PathCommand::execute(std::vector *args) { + assertTrue(args->size() > 1); + static auto mod = moduleMgr->getModule(); + if(mod->isEnabled()){ + clientMessageF("Joe is already enabled, disable joe to use this command"); + return true; + } + + auto cmd = args->at(1); + if(cmd == "y"){ + assertTrue(args->size() > 2); + int yLevel = assertInt(args->at(2)); + assertTrue(yLevel > 0 && yLevel < 256); + + mod->goal = std::make_unique((float)yLevel); + mod->setEnabled(true); + + clientMessageF("Starting search..."); + return true; + } + if(cmd == "xz"){ + assertTrue(args->size() > 3); + int x = assertInt(args->at(2)); + int z = assertInt(args->at(3)); + + mod->goal = std::make_unique(vec3_ti(x, 0, z)); + mod->setEnabled(true); + + clientMessageF("Starting search..."); + return true; + } + if(cmd == "xyz"){ + assertTrue(args->size() > 4); + int x = assertInt(args->at(2)); + int y = assertInt(args->at(3)); + int z = assertInt(args->at(4)); + + mod->goal = std::make_unique(vec3_ti(x, y, z)); + mod->setEnabled(true); + + clientMessageF("Starting search..."); + return true; + } + if(cmd == "p" || cmd == "player"){ + std::string nameOfPlayer = args->at(2); + assertTrue(!nameOfPlayer.empty()); + std::string nameOfPlayerLower = std::string(nameOfPlayer); + std::transform(nameOfPlayerLower.begin(), nameOfPlayerLower.end(), nameOfPlayerLower.begin(), ::tolower); + nameOfPlayerLower = Utils::sanitize(nameOfPlayerLower); + + vec3_t pos{}; + auto playerFinder = [&](C_Entity* e, bool isNewList){ + if(e == g_Data.getLocalPlayer()) + return; + std::string name(e->getNameTag()->getText()); + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + + if (name.find(nameOfPlayerLower) == std::string::npos) + return; + + pos = e->eyePos0; + }; + g_Data.forEachEntity(playerFinder); + + if(pos.iszero()){ + clientMessageF("%s Player \"%s\" could not be found!", GOLD, nameOfPlayer.c_str()); + return true; + } + + vec3_ti endNode((int)floorf(pos.x), (int)roundf(pos.y - 1.62f), (int)floorf(pos.z)); + mod->goal = std::make_unique(endNode); + mod->setEnabled(true); + clientMessageF("Starting search..."); + + return true; + } + + + return false; +} diff --git a/Horion/Command/Commands/PathCommand.h b/Horion/Command/Commands/PathCommand.h new file mode 100644 index 0000000..9a28dab --- /dev/null +++ b/Horion/Command/Commands/PathCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" + +class PathCommand : public IMCCommand{ +public: + PathCommand(); + ~PathCommand(); + + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/PlayerTeleportCommand.cpp b/Horion/Command/Commands/PlayerTeleportCommand.cpp new file mode 100644 index 0000000..c276fc4 --- /dev/null +++ b/Horion/Command/Commands/PlayerTeleportCommand.cpp @@ -0,0 +1,55 @@ +#include "PlayerTeleportCommand.h" +#include "../../../Utils/Utils.h" + +PlayerTeleportCommand::PlayerTeleportCommand() : IMCCommand("playertp", "Teleports to players coordinates", "") { +} + +PlayerTeleportCommand::~PlayerTeleportCommand() { +} + +bool PlayerTeleportCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + assertTrue(args->size() > 1); // .playertp + std::string nameOfPlayer = args->at(1); + assertTrue(!nameOfPlayer.empty()); + std::string nameOfPlayerLower = std::string(nameOfPlayer); + std::transform(nameOfPlayerLower.begin(), nameOfPlayerLower.end(), nameOfPlayerLower.begin(), ::tolower); + nameOfPlayerLower = Utils::sanitize(nameOfPlayerLower); + + C_EntityList* entList = g_Data.getEntityList(); + size_t listSize = entList->getListSize(); + vec3_t pos; + + if (listSize > 5000) { + return true; + } + std::string playerName; + //Loop through all our players and retrieve their information + for (size_t i = 0; i < listSize; i++) { + C_Entity* currentEntity = entList->get(i); + + std::string name(currentEntity->getNameTag()->getText()); + + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + + if (currentEntity == 0) + break; + + if (currentEntity == g_Data.getLocalPlayer()) // Skip Local player + continue; + + if (name.find(nameOfPlayerLower) == std::string::npos) + continue; + + pos = *currentEntity->getPos(); + playerName = currentEntity->getNameTag()->getText(); + break; + } + if (pos.iszero()) { + clientMessageF("[%sHorion%s] %sCouldn't find player: %s!", GOLD, WHITE, RED, nameOfPlayer.c_str()); + return true; + } + g_Data.getLocalPlayer()->setPos(pos); + clientMessageF("[%sHorion%s] %sTeleported to %s", GOLD, WHITE, GREEN, playerName.c_str()); + return true; +} diff --git a/Horion/Command/Commands/PlayerTeleportCommand.h b/Horion/Command/Commands/PlayerTeleportCommand.h new file mode 100644 index 0000000..731da6e --- /dev/null +++ b/Horion/Command/Commands/PlayerTeleportCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class PlayerTeleportCommand : public IMCCommand { +public: + PlayerTeleportCommand(); + ~PlayerTeleportCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/RelativeTeleportCommand.cpp b/Horion/Command/Commands/RelativeTeleportCommand.cpp new file mode 100644 index 0000000..84a547b --- /dev/null +++ b/Horion/Command/Commands/RelativeTeleportCommand.cpp @@ -0,0 +1,26 @@ +#include "RelativeTeleportCommand.h" + +RelativeTeleportCommand::RelativeTeleportCommand() : IMCCommand("relativeteleport", "Teleports to coordinates relative to the Player", " ") { + registerAlias("reltp"); + registerAlias("rtp"); + registerAlias("vclip"); +} + +RelativeTeleportCommand::~RelativeTeleportCommand() { +} + +bool RelativeTeleportCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + assertTrue(args->size() >= 4); + + vec3_t pPos = g_Data.getLocalPlayer()->eyePos0; + + vec3_t pos; + pos.x = assertFloat(args->at(1)) + pPos.x; + pos.y = assertFloat(args->at(2)) + pPos.y; + pos.z = assertFloat(args->at(3)) + pPos.z; + + g_Data.getLocalPlayer()->setPos(pos); + clientMessageF("%sTeleported!", GREEN); + return true; +} diff --git a/Horion/Command/Commands/RelativeTeleportCommand.h b/Horion/Command/Commands/RelativeTeleportCommand.h new file mode 100644 index 0000000..8591511 --- /dev/null +++ b/Horion/Command/Commands/RelativeTeleportCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class RelativeTeleportCommand : public IMCCommand { +public: + RelativeTeleportCommand(); + ~RelativeTeleportCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/SayCommand.cpp b/Horion/Command/Commands/SayCommand.cpp new file mode 100644 index 0000000..ae66240 --- /dev/null +++ b/Horion/Command/Commands/SayCommand.cpp @@ -0,0 +1,51 @@ +#include "SayCommand.h" + +SayCommand::SayCommand() : IMCCommand("say", "Sends a chat message", "") { +} + +SayCommand::~SayCommand() { +} + +std::string string_replace(const std::string& s, const std::string& findS, const std::string& replaceS) { + std::string result = s; + auto pos = s.find(findS); + if (pos == std::string::npos) { + return result; + } + result.replace(pos, findS.length(), replaceS); + return string_replace(result, findS, replaceS); +} + +std::string parse(const std::string& s) { + static std::vector > patterns = { + {"\\\\", "\\"}, + {"\\n", "\n"}, + {"\\r", "\r"}, + {"\\t", "\t"}, + {"\\f", "\f"}, + {"\\\"", "\""}}; + std::string result = s; + for (const auto& p : patterns) { + result = string_replace(result, p.first, p.second); + } + return result; +} + +bool SayCommand::execute(std::vector* args) { + assertTrue(args->size() > 1); + + std::ostringstream os; + for (int i = 1; i < args->size(); i++) { + if (i > 1) + os << " "; + os << args->at(i); + } + C_TextPacket textPacket; + textPacket.message.setText(parse(os.str())); + textPacket.sourceName.setText(g_Data.getLocalPlayer()->getNameTag()->getText()); + textPacket.xboxUserId = std::to_string(g_Data.getLocalPlayer()->getUserId()); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&textPacket); + + clientMessageF("[%sHorion%s] %sSent Message", GOLD, WHITE, GREEN); + return true; +} diff --git a/Horion/Command/Commands/SayCommand.h b/Horion/Command/Commands/SayCommand.h new file mode 100644 index 0000000..a95756d --- /dev/null +++ b/Horion/Command/Commands/SayCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "ICommand.h" +#include +class SayCommand : public IMCCommand { +public: + SayCommand(); + ~SayCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ScriptCommand.cpp b/Horion/Command/Commands/ScriptCommand.cpp new file mode 100644 index 0000000..e53cdee --- /dev/null +++ b/Horion/Command/Commands/ScriptCommand.cpp @@ -0,0 +1,55 @@ +#include "ScriptCommand.h" + +ScriptCommand::ScriptCommand() : IMCCommand("script", "Manage scripts", "") { +} + +ScriptCommand::~ScriptCommand() { +} + +bool ScriptCommand::execute(std::vector* args) { + assertTrue(args->size() >= 2); + std::string action = args->at(1); + if (action == "load") { + HorionDataPacket packet; + packet.cmd = CMD_FOLDERCHOOSER; + auto temp = std::shared_ptr(new unsigned char[300]); + packet.data.swap(temp); + memset(packet.data.get(), 0, 300); + strcpy_s((char*)packet.data.get(), 200, "{\"title\": \"Select a Script Folder\", \"filter\":\".js\"}"); + packet.dataArraySize = (int)strlen((char*)packet.data.get()); + packet.params[0] = g_Data.addInjectorResponseCallback([](std::shared_ptr pk) { + if (pk->params[0] != 1) { // Dialog Canceled, reset geo + auto box = g_Data.addInfoBox("Scripting", "Invalid Folder"); + box->closeTimer = 1; + return; + } + + wchar_t* jsonData = reinterpret_cast(pk->data.get()); + std::wstring jsonDataStr(jsonData); + + json parsed = json::parse(jsonDataStr); + if (parsed["path"].is_string()) { + auto box = g_Data.addInfoBox("Importing Script", "Please wait..."); + std::thread gamer([parsed, box]() { + auto result = scriptMgr.importScriptFolder(parsed["path"].get()); + if (result) + box->fadeTarget = 0; + else { + box->message = "Script import error, \ncheck the console"; + box->closeTimer = 2; + } + }); + gamer.detach(); + } + }); + + g_Data.sendPacketToInjector(packet); + return true; + } else if (action == "unloadall") { + scriptMgr.unloadAllScripts(); + return true; + } + + + return false; +} diff --git a/Horion/Command/Commands/ScriptCommand.h b/Horion/Command/Commands/ScriptCommand.h new file mode 100644 index 0000000..a15745f --- /dev/null +++ b/Horion/Command/Commands/ScriptCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "../../Scripting/ScriptManager.h" +#include "ICommand.h" + +class ScriptCommand : public IMCCommand { +public: + ScriptCommand(); + ~ScriptCommand(); + + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ServerCommand.cpp b/Horion/Command/Commands/ServerCommand.cpp new file mode 100644 index 0000000..94d4ca7 --- /dev/null +++ b/Horion/Command/Commands/ServerCommand.cpp @@ -0,0 +1,18 @@ +#include "ServerCommand.h" + +ServerCommand::ServerCommand() : IMCCommand("server", "Show information about the server you're playing on", "") { + registerAlias("ip"); +} + +ServerCommand::~ServerCommand() { +} + +bool ServerCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + + if (g_Data.getRakNetInstance()->isonaServer()) + clientMessageF("You're currently playing on:\nIP: %s\nPort: %s", g_Data.getRakNetInstance()->serverIp.getText(), std::to_string(g_Data.getRakNetInstance()->serverPort).c_str()); + else + clientMessageF("%sYou're not playing on a server.", RED); + return true; +} diff --git a/Horion/Command/Commands/ServerCommand.h b/Horion/Command/Commands/ServerCommand.h new file mode 100644 index 0000000..22700c0 --- /dev/null +++ b/Horion/Command/Commands/ServerCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "ICommand.h" + +class ServerCommand : public IMCCommand { +public: + ServerCommand(); + ~ServerCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/SetOffhandCommand.cpp b/Horion/Command/Commands/SetOffhandCommand.cpp new file mode 100644 index 0000000..87a0cb8 --- /dev/null +++ b/Horion/Command/Commands/SetOffhandCommand.cpp @@ -0,0 +1,77 @@ +#include "SetOffhandCommand.h" + +#include "../../../SDK/Tag.h" +#include "../../../Utils/Utils.h" + +SetOffhandCommand::SetOffhandCommand() : IMCCommand("setoffhand", "Spawn items in ur offhand", " ") { + registerAlias("soh"); +} + +SetOffhandCommand::~SetOffhandCommand() { +} + +bool SetOffhandCommand::execute(std::vector* args) { + assertTrue(args->size() > 2); + + int itemId = 0; + char count = static_cast(assertInt(args->at(2))); + char itemData = 0; + if (args->size() > 3) + itemData = static_cast(assertInt(args->at(3))); + + try { + itemId = std::stoi(args->at(1)); + } catch (const std::invalid_argument&) { + } + + C_Inventory* inv = g_Data.getLocalPlayer()->getSupplies()->inventory; + C_ItemStack* yot = nullptr; + auto transactionManager = g_Data.getLocalPlayer()->getTransactionManager(); + + if (itemId == 0) { + TextHolder tempText(args->at(1)); + std::unique_ptr ItemPtr = std::make_unique(); + std::unique_ptr buffer = std::make_unique(); + C_Item*** cStack = ItemRegistry::lookUpByName(ItemPtr.get(), buffer.get(), tempText); + if (*cStack == nullptr) { + clientMessageF("%sInvalid item name!", RED); + return true; + } + yot = new C_ItemStack(***cStack, count, itemData); + } else { + std::unique_ptr ItemPtr = std::make_unique(); + C_Item*** cStack = ItemRegistry::getItemFromId(ItemPtr.get(), itemId); + if (cStack == nullptr || *cStack == nullptr || **cStack == nullptr) { + clientMessageF("%sInvalid item ID!", RED); + return true; + } + yot = new C_ItemStack(***cStack, count, itemData); + } + + if (yot != nullptr) + yot->count = count; + + if (args->size() > 4) { + std::string tag = Utils::getClipboardText(); + if (tag.size() > 1 && tag.front() == MojangsonToken::COMPOUND_START.getSymbol() && tag.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + yot->setUserData(std::move(Mojangson::parseTag(tag))); + } + } + + ItemDescriptor* desc = nullptr; + desc = new ItemDescriptor((*yot->item)->itemId, itemData); + + C_InventoryAction* firstAction = nullptr; + C_InventoryAction* secondAction = nullptr; + + firstAction = new C_InventoryAction(0, desc, nullptr, yot, nullptr, count, 507, 99999); + + transactionManager->addInventoryAction(*firstAction); + + delete firstAction; + delete desc; + g_Data.getLocalPlayer()->setOffhandSlot(yot); + + clientMessageF("%sSuccessfully set item to offhand!", GREEN); + return true; +} diff --git a/Horion/Command/Commands/SetOffhandCommand.h b/Horion/Command/Commands/SetOffhandCommand.h new file mode 100644 index 0000000..c46ac80 --- /dev/null +++ b/Horion/Command/Commands/SetOffhandCommand.h @@ -0,0 +1,14 @@ +#pragma once + +#include + +#include "ICommand.h" + +class SetOffhandCommand : public IMCCommand { +public: + SetOffhandCommand(); + ~SetOffhandCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/SetPrefixCommand.cpp b/Horion/Command/Commands/SetPrefixCommand.cpp new file mode 100644 index 0000000..b7292a0 --- /dev/null +++ b/Horion/Command/Commands/SetPrefixCommand.cpp @@ -0,0 +1,17 @@ +#include "SetPrefixCommand.h" + +SetPrefixCommand::SetPrefixCommand() : IMCCommand("setprefix", "Set the prefix for horion commands", "") { + registerAlias("prefix"); +} + +SetPrefixCommand::~SetPrefixCommand() { +} + +bool SetPrefixCommand::execute(std::vector* args) { + assertTrue(args->size() > 1); + assertTrue(args->at(1).length() == 1); + char prefix = args->at(1).at(0); + cmdMgr->prefix = prefix; + clientMessageF("[%sHorion%s] %sSet prefix to %s%c", GOLD, WHITE, GREEN, GRAY, prefix); + return true; +} diff --git a/Horion/Command/Commands/SetPrefixCommand.h b/Horion/Command/Commands/SetPrefixCommand.h new file mode 100644 index 0000000..87cc9d6 --- /dev/null +++ b/Horion/Command/Commands/SetPrefixCommand.h @@ -0,0 +1,12 @@ +#pragma once +#include "../CommandMgr.h" + +#include "ICommand.h" +class SetPrefixCommand : public IMCCommand { +public: + SetPrefixCommand(); + ~SetPrefixCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; \ No newline at end of file diff --git a/Horion/Command/Commands/SpammerCommand.cpp b/Horion/Command/Commands/SpammerCommand.cpp new file mode 100644 index 0000000..1724a48 --- /dev/null +++ b/Horion/Command/Commands/SpammerCommand.cpp @@ -0,0 +1,74 @@ +#include "SpammerCommand.h" + +#include "../../Module/ModuleManager.h" + +SpammerCommand::SpammerCommand() : IMCCommand("spammer", "Edit spammer delay/text", " ") { + registerAlias("spam"); +} + +SpammerCommand::~SpammerCommand() { +} + +bool SpammerCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + std::string option = args->at(1); + std::transform(option.begin(), option.end(), option.begin(), ::tolower); + + auto spamMod = moduleMgr->getModule(); + + if (option == "message") { + std::ostringstream os; + for (int i = 2; i < args->size(); i++) { + if (i > 1) + os << " "; + os << args->at(i); + } + std::string text = os.str().substr(1); + spamMod->getMessage() = text; + clientMessageF("%sSpammer message set to %s%s%s!", GREEN, GRAY, text.c_str(), GREEN); + return true; + } else if (option == "delay") { + int delay = assertInt(args->at(2)); + if (delay < 1) { + clientMessageF("%sDelay needs to be 1 or more!", RED); + return true; + } else { + spamMod->getDelay() = delay; + return true; + } + } else if (option == "bypass") { + std::string data = args->at(2); + std::transform(data.begin(), data.end(), data.begin(), ::tolower); + bool state = (data == "true") ? true : false; + spamMod->getBypass() = state; + clientMessageF("%sBypass set to %s%s%s!", GREEN, GRAY, state ? "true" : "false", GREEN); + return true; + } else if (option == "length") { + int length = assertInt(args->at(2)); + if (length < 1) { + clientMessageF("%sLength needs to be 1 or more!", RED); + return true; + } else { + spamMod->getLength() = length; + return true; + } + } else if (option == "manual") { + int times = assertInt(args->at(2)); + std::ostringstream os; + for (int i = 3; i < args->size(); i++) { + if (i > 1) + os << " "; + os << args->at(i); + } + std::string text = os.str().substr(1); + for (int i = 0; i < times; i++) { + C_TextPacket textPacket; + textPacket.message.setText(text + (spamMod->getBypass() ? (" | " + Utils::randomString(spamMod->getLength())) : "")); + textPacket.sourceName = *g_Data.getLocalPlayer()->getNameTag(); + textPacket.xboxUserId = TextHolder(std::to_string(g_Data.getLocalPlayer()->getUserId())); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&textPacket); + } + return true; + } + return false; +} diff --git a/Horion/Command/Commands/SpammerCommand.h b/Horion/Command/Commands/SpammerCommand.h new file mode 100644 index 0000000..3b033b4 --- /dev/null +++ b/Horion/Command/Commands/SpammerCommand.h @@ -0,0 +1,12 @@ +#pragma once +#include "ICommand.h" +#include + +class SpammerCommand : public IMCCommand { +public: + SpammerCommand(); + ~SpammerCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/TeleportCommand.cpp b/Horion/Command/Commands/TeleportCommand.cpp new file mode 100644 index 0000000..443ac49 --- /dev/null +++ b/Horion/Command/Commands/TeleportCommand.cpp @@ -0,0 +1,23 @@ +#include "TeleportCommand.h" + +TeleportCommand::TeleportCommand() : IMCCommand("tp", "Teleports to coordinates", " ") { + registerAlias("teleport"); + registerAlias("setpos"); +} + +TeleportCommand::~TeleportCommand() { +} + +bool TeleportCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + assertTrue(args->size() >= 4); + + vec3_t pos; + pos.x = assertFloat(args->at(1)); + pos.y = assertFloat(args->at(2)) + 1; + pos.z = assertFloat(args->at(3)); + + g_Data.getLocalPlayer()->setPos(pos); + clientMessageF("%sTeleported!", GREEN); + return true; +} diff --git a/Horion/Command/Commands/TeleportCommand.h b/Horion/Command/Commands/TeleportCommand.h new file mode 100644 index 0000000..951cce3 --- /dev/null +++ b/Horion/Command/Commands/TeleportCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class TeleportCommand : public IMCCommand { +public: + TeleportCommand(); + ~TeleportCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/TestCommand.cpp b/Horion/Command/Commands/TestCommand.cpp new file mode 100644 index 0000000..88b5491 --- /dev/null +++ b/Horion/Command/Commands/TestCommand.cpp @@ -0,0 +1,42 @@ +#include "TestCommand.h" +#include "../../../Utils/Logger.h" +#include "../../../Utils/Utils.h" +#include +#include "../../../SDK/Tag.h" + +TestCommand::TestCommand() : IMCCommand("test", "Test for Debugging purposes", "") { +} + +TestCommand::~TestCommand() { +} + +void listEnts(C_Entity* ent, bool isValid) { + int id = ent->getEntityTypeId(); + char* name = ent->getNameTag()->getText(); + logF("---------------"); + logF("Entity Name: %s", name); + logF("Entity ID: %d", id); + logF("---------------"); +} + +void showAimedBlockInfo() { + PointingStruct* pointingStruct = g_Data.getClientInstance()->getPointerStruct(); + C_Block* block = g_Data.getLocalPlayer()->region->getBlock(pointingStruct->block); + auto id = block->toLegacy()->blockId; + char* name = block->toLegacy()->name.getText(); + logF("---------------"); + logF("Block Name: %s", name); + logF("Block ID: %lld", id); + logF("---------------"); +} + +bool TestCommand::execute(std::vector* args) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + + auto inv = player->getSupplies()->inventory; + logF("%i %i", inv->getFirstEmptySlot(), inv->getEmptySlotsCount()); + + inv->swapSlots(1, 2); + + return true; +} diff --git a/Horion/Command/Commands/TestCommand.h b/Horion/Command/Commands/TestCommand.h new file mode 100644 index 0000000..a7f5b1f --- /dev/null +++ b/Horion/Command/Commands/TestCommand.h @@ -0,0 +1,11 @@ +#pragma once +#include "ICommand.h" + +class TestCommand : public IMCCommand { +public: + TestCommand(); + ~TestCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/ToggleCommand.cpp b/Horion/Command/Commands/ToggleCommand.cpp new file mode 100644 index 0000000..97c1093 --- /dev/null +++ b/Horion/Command/Commands/ToggleCommand.cpp @@ -0,0 +1,33 @@ +#include "ToggleCommand.h" + +#include "../../Module/ModuleManager.h" + +ToggleCommand::ToggleCommand() : IMCCommand("toggle", "Toggles a module", "") { + registerAlias("t"); +} + +ToggleCommand::~ToggleCommand() { +} + +bool ToggleCommand::execute(std::vector* args) { + assertTrue(args->size() >= 2); + std::string moduleName = args->at(1); + + assertTrue(moduleName.size() > 0); + + auto modOpt = moduleMgr->getModuleByName(moduleName); + if (!modOpt.has_value()) { + clientMessageF("%sCould not find Module with name: %s", RED, moduleName.c_str()); + return true; + } + + auto mod = modOpt.value(); + if (mod->isFlashMode()) + clientMessageF("%sModule cannot be toggled!", RED); + else { + mod->toggle(); + clientMessageF("%s%s is now %s", GREEN, mod->getModuleName(), mod->isEnabled() ? "enabled" : "disabled"); + } + + return true; +} diff --git a/Horion/Command/Commands/ToggleCommand.h b/Horion/Command/Commands/ToggleCommand.h new file mode 100644 index 0000000..6e6e344 --- /dev/null +++ b/Horion/Command/Commands/ToggleCommand.h @@ -0,0 +1,10 @@ +#pragma once +#include "ICommand.h" +class ToggleCommand : public IMCCommand { +public: + ToggleCommand(); + ~ToggleCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/TopCommand.cpp b/Horion/Command/Commands/TopCommand.cpp new file mode 100644 index 0000000..464073b --- /dev/null +++ b/Horion/Command/Commands/TopCommand.cpp @@ -0,0 +1,39 @@ +#include "TopCommand.h" + +TopCommand::TopCommand() : IMCCommand("top", "Teleports to the nearest pocket of air above you - highly recommend against using this inside the Nether.", "") { +} + +TopCommand::~TopCommand() { +} + +bool TopCommand::execute(std::vector* args) { + assertTrue(g_Data.getLocalPlayer() != nullptr); + + C_LocalPlayer* player = g_Data.getLocalPlayer(); + vec3_t playerPos = player->eyePos0; + bool groundAbove = false; //Checking if ground above us. + vec3_t blockPos; + + for (int y(0); y < 256 - playerPos.y; ++y) { + if (player->region->getBlock(vec3_t{playerPos.x, playerPos.y + y, playerPos.z})->toLegacy()->blockId != 0) { + groundAbove = true; + blockPos = vec3_t{playerPos.x, playerPos.y + y, playerPos.z}; + break; + } + } + + if (groundAbove) { + for (int y(0); y < 256 - blockPos.y; ++y) { //This time we're going through loop again, but continuing where we left off to find open air pocket. + if ((player->region->getBlock(vec3_t{blockPos.x, blockPos.y + y, blockPos.z})->toLegacy()->blockId == 0) && (player->region->getBlock(vec3_t{blockPos.x, blockPos.y + y + 1, blockPos.z})->toLegacy()->blockId == 0)) { + player->setPos(vec3_t{blockPos.x, blockPos.y + y + 1, blockPos.z}); + clientMessageF("Whoosh!"); + return true; + } + } + clientMessageF("There is no open space above you!"); + return true; + } else { + clientMessageF("There are no blocks above you!"); + return true; + } +} \ No newline at end of file diff --git a/Horion/Command/Commands/TopCommand.h b/Horion/Command/Commands/TopCommand.h new file mode 100644 index 0000000..7735d1d --- /dev/null +++ b/Horion/Command/Commands/TopCommand.h @@ -0,0 +1,9 @@ +#pragma once +#include "ICommand.h" +class TopCommand : public IMCCommand { +public: + TopCommand(); + ~TopCommand(); + + virtual bool execute(std::vector* args) override; +}; \ No newline at end of file diff --git a/Horion/Command/Commands/UnbindCommand.cpp b/Horion/Command/Commands/UnbindCommand.cpp new file mode 100644 index 0000000..828ac29 --- /dev/null +++ b/Horion/Command/Commands/UnbindCommand.cpp @@ -0,0 +1,43 @@ +#include "UnbindCommand.h" + +#include "../../Module/ModuleManager.h" + +UnbindCommand::UnbindCommand() : IMCCommand("unbind", "unbind modules", "") { +} + +UnbindCommand::~UnbindCommand() { +} + +bool UnbindCommand::execute(std::vector* args) { + assertTrue(args->size() >= 2); + std::string moduleName = args->at(1); + + assertTrue(moduleName.size() > 0); + + if (moduleName == "all") { + if (args->size() >= 3 && args->at(2) == "force") { + auto lock = moduleMgr->lockModuleList(); + std::vector>* modules = moduleMgr->getModuleList(); + for (auto it = modules->begin(); it != modules->end(); ++it) { + auto mod = *it; + mod->setKeybind(0x0); + } + clientMessageF("%sUnbound all modules!", YELLOW); + } else { + clientMessageF("%sAre you sure? This will unbind %sALL%s%s modules!", RED, BOLD, RESET, RED); + clientMessageF("%sUse %s.unbind all force%s to unbind all modules", RED, WHITE, RED); + } + return true; + } + + auto modOpt = moduleMgr->getModuleByName(moduleName); + if (!modOpt.has_value()) { + clientMessageF("%sCould not find module with name: %s", RED, moduleName.c_str()); + return true; + } + + auto mod = modOpt.value(); + mod->setKeybind(0x0); + clientMessageF("%sSuccessfully unbound %s!", GREEN, mod->getModuleName()); + return true; +} diff --git a/Horion/Command/Commands/UnbindCommand.h b/Horion/Command/Commands/UnbindCommand.h new file mode 100644 index 0000000..f0517a4 --- /dev/null +++ b/Horion/Command/Commands/UnbindCommand.h @@ -0,0 +1,13 @@ +#pragma once +#include + +#include "ICommand.h" + +class UnbindCommand : public IMCCommand { +public: + UnbindCommand(); + ~UnbindCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/WaypointCommand.cpp b/Horion/Command/Commands/WaypointCommand.cpp new file mode 100644 index 0000000..24aceff --- /dev/null +++ b/Horion/Command/Commands/WaypointCommand.cpp @@ -0,0 +1,74 @@ +#include "WaypointCommand.h" + +WaypointCommand::WaypointCommand() : IMCCommand("waypoint", "Manage Waypoints", " [x y z]") { + registerAlias("wp"); +} + +WaypointCommand::~WaypointCommand() { +} + +bool WaypointCommand::execute(std::vector* args) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + assertTrue(player != nullptr); + assertTrue(args->size() >= 2); + + static auto mod = moduleMgr->getModule(); + + std::string opt = args->at(1); + + if (opt == "removeall") { + auto num = mod->getWaypoints()->size(); + mod->getWaypoints()->clear(); + clientMessageF("%sRemoved %i waypoints!", YELLOW, num); + return true; + } + + assertTrue(args->size() > 2); + + std::string name = args->at(2); + name = Utils::sanitize(name); + if (name.size() <= 1 || name.size() > 30) { + clientMessageF("%sInvalid name! Must be less than 30 characters!", RED); + return true; + } + + if (opt == "add") { + vec3_t pos = player->currentPos.floor().add(0.5, 0, 0.5); + if (args->size() == 6) { + pos.x = assertFloat(args->at(3)); + pos.y = assertFloat(args->at(4)); + assertTrue(pos.y >= 0); + pos.z = assertFloat(args->at(5)); + } else if (args->size() != 3) { + return false; + } + int dimension; + player->getDimensionId(&dimension); + if (mod->add(name, pos, dimension)) { + clientMessageF("%sSuccessfully added waypoint \"%s\"", GREEN, name.c_str()); + if (!mod->isEnabled()) + clientMessageF("%sEnable the waypoints module to see it ingame!", YELLOW); + } else { + clientMessageF("%sWaypoint \"%s\" already exists", RED, name.c_str()); + } + } else if (opt == "remove") { + if (mod->remove(name)) { + clientMessageF("%sRemoved waypoint \"%s\"", YELLOW, name.c_str()); + } else { + clientMessageF("%sUnknown waypoint \"%s\"", RED, name.c_str()); + } + }else if (opt == "tp" || opt == "teleport") { + if (auto wp = mod->getWaypoint(name)) { + auto wpV = wp.value(); + auto pos = wpV.pos; + player->setPos(pos); + clientMessageF("%sTeleported to waypoint \"%s\" (%.02f, %.02f, %.02f)", GREEN, name.c_str(), pos.x, pos.y, pos.z); + } else { + clientMessageF("%sUnknown waypoint \"%s\"", RED, name.c_str()); + } + } else { + return false; + } + + return true; +} diff --git a/Horion/Command/Commands/WaypointCommand.h b/Horion/Command/Commands/WaypointCommand.h new file mode 100644 index 0000000..b1c5075 --- /dev/null +++ b/Horion/Command/Commands/WaypointCommand.h @@ -0,0 +1,14 @@ +#pragma once + +#include "ICommand.h" +#include "../../Module/ModuleManager.h" +#include "../../Module/Modules/Waypoints.h" + +class WaypointCommand : public IMCCommand { +public: + WaypointCommand(); + ~WaypointCommand(); + + // Inherited via IMCCommand + virtual bool execute(std::vector* args) override; +}; diff --git a/Horion/Command/Commands/XpCommand.cpp b/Horion/Command/Commands/XpCommand.cpp new file mode 100644 index 0000000..bc73f83 --- /dev/null +++ b/Horion/Command/Commands/XpCommand.cpp @@ -0,0 +1,28 @@ +#include "XpCommand.h" + +XpCommand::XpCommand() : IMCCommand("xp", "Add experience to your player", "xp L") { +} + +XpCommand::~XpCommand() { +} + +bool XpCommand::execute(std::vector* args) { + auto player = g_Data.getLocalPlayer(); + if (!player) return false; + + std::string amount = args->at(1); + std::transform(amount.begin(), amount.end(), amount.begin(), tolower); + const bool levels = amount.substr(amount.length() - 1) == "l"; + if (levels) amount = amount.substr(0, amount.length() - 1); + try { + int xp = std::stoi(amount); + if (levels) + player->addLevels(xp); + else + player->addExperience(xp); + clientMessageF("%sAdded %i experience %s", GREEN, xp, levels ? "levels" : "points"); + } catch (std::invalid_argument&) { + clientMessageF("%sInvalid amount of experience!", RED); + } + return true; +} diff --git a/Horion/Command/Commands/XpCommand.h b/Horion/Command/Commands/XpCommand.h new file mode 100644 index 0000000..cfdf7ae --- /dev/null +++ b/Horion/Command/Commands/XpCommand.h @@ -0,0 +1,11 @@ +#pragma once + +#include "ICommand.h" + +class XpCommand : public IMCCommand { +public: + XpCommand(); + ~XpCommand(); + + bool execute(std::vector* args) override; +}; diff --git a/Horion/Config/AccountInformation.cpp b/Horion/Config/AccountInformation.cpp new file mode 100644 index 0000000..f395e22 --- /dev/null +++ b/Horion/Config/AccountInformation.cpp @@ -0,0 +1,71 @@ +#include "AccountInformation.h" + +#include "../../Utils/Json.hpp" +#include "../../include/WinHttpClient.h" +#include "../../Memory/GameData.h" +#include "../../Utils/Logger.h" + +AccountInformation::AccountInformation(std::string authTok, unsigned int serial) : isGuest(false), authToken(authTok), serialNum(serial){}; +AccountInformation::AccountInformation() : isGuest(true), authToken("none"){}; + +bool AccountInformation::verify() { + if (isGuest) + return true; + if (authToken.size() < 10) + return false; + if (didVerify) + return isValid; + didVerify = true; + + wchar_t formatString[130]; // Little hack for xor'd url + swprintf_s(formatString, 130, L"%S", XorString("http://www.horionbeta.club/api/beta/check?client=%S&serial=%u&edition=%S&compile=%S&stamp=%u")); + + wchar_t fullUrl[250]; + +#ifdef _DEBUG + const char* edition = "dev"; +#elif defined(_BETA) + const char* edition = "beta"; +#else + const char* edition = "public"; +#endif + + swprintf_s(fullUrl, 250, formatString, authToken.c_str(), serialNum, edition, XorString(__TIME__), g_Data.networkedData.xorKey); + WinHttpClient client(fullUrl); + client.SetTimeouts(1500, 3000, 2000, 3000); + bool boi = client.SendHttpRequest(); + if (!boi) { + logF("Account verification failed, %d", client.GetLastError()); + return false; + } + + // The response header. + std::wstring status = client.GetResponseStatusCode(); + if (status == L"200") { + std::wstring content = client.GetResponseContent(); + nlohmann::json data = nlohmann::json::parse(content); + + if (data.contains("status") && data["status"].is_string() && data["status"].get() == "success") { + logF("Account verified"); + + // evade and deceive + g_Data.networkedData.localPlayerOffset = data["serverTime"].get(); + g_Data.networkedData.dataSet = true; + + isValid = true; + return true; + } else + logF("Account is a guest account"); + } + + return false; +}; + +AccountInformation AccountInformation::fromToken(std::string authToken, unsigned int serial) { + auto acc = AccountInformation(authToken, serial); + return acc; +} + +AccountInformation AccountInformation::asGuest() { + return AccountInformation(); +} diff --git a/Horion/Config/AccountInformation.h b/Horion/Config/AccountInformation.h new file mode 100644 index 0000000..fd90d3b --- /dev/null +++ b/Horion/Config/AccountInformation.h @@ -0,0 +1,23 @@ +#pragma once + + +#include + +class AccountInformation { +private: + bool isGuest; + bool didVerify = false; // Did check if its verified? + bool isValid = false; // Is it a verified account + std::string name; + std::string authToken; + unsigned int serialNum = 0; + + AccountInformation(std::string, unsigned int); + AccountInformation(); + +public: + bool verify(); + + static AccountInformation fromToken(std::string authToken, unsigned int serial); + static AccountInformation asGuest(); +}; diff --git a/Horion/Config/ConfigManager.cpp b/Horion/Config/ConfigManager.cpp new file mode 100644 index 0000000..686ef43 --- /dev/null +++ b/Horion/Config/ConfigManager.cpp @@ -0,0 +1,119 @@ +#include "ConfigManager.h" + +#include +#include + +using namespace ABI::Windows::Storage; +using namespace Microsoft::WRL; +using namespace Microsoft::WRL::Wrappers; + +std::wstring ConfigManager::GetRoamingFolderPath() { + ComPtr appDataStatics; + auto hr = RoGetActivationFactory(HStringReference(L"Windows.Storage.ApplicationData").Get(), __uuidof(appDataStatics), &appDataStatics); + if (FAILED(hr)) throw std::runtime_error("Failed to retrieve application data statics"); + + ComPtr appData; + hr = appDataStatics->get_Current(&appData); + if (FAILED(hr)) throw std::runtime_error("Failed to retrieve current application data"); + + ComPtr roamingFolder; + hr = appData->get_RoamingFolder(&roamingFolder); + if (FAILED(hr)) throw std::runtime_error("Failed to retrieve roaming folder"); + + ComPtr folderItem; + hr = roamingFolder.As(&folderItem); + if (FAILED(hr)) throw std::runtime_error("Failed to cast roaming folder to IStorageItem"); + + HString roamingPathHString; + hr = folderItem->get_Path(roamingPathHString.GetAddressOf()); + if (FAILED(hr)) throw std::runtime_error("Failed to retrieve roaming folder path"); + + uint32_t pathLength; + auto roamingPathCStr = roamingPathHString.GetRawBuffer(&pathLength); + return std::wstring(roamingPathCStr, pathLength); +} + +ConfigManager::ConfigManager() { + this->roamingFolder = GetRoamingFolderPath(); +} + +ConfigManager::~ConfigManager() { +} + +void ConfigManager::loadConfig(std::string name, bool create) { + + size_t allocSize = name.size() + roamingFolder.size() + 20; // std::wstring::size() can be wierd so lets make sure this actually fits + char* fullPath = new char[allocSize]; + sprintf_s(fullPath, allocSize, "%S\\%s.h", roamingFolder.c_str(), name.c_str()); + + const bool configExists = std::filesystem::exists(fullPath); + if (configExists || create) { + if (name != currentConfig) + saveConfig(); // Save old config + + currentConfig = name; + if (configExists) { + std::ifstream confFile(fullPath, std::ifstream::binary); + json conf; + try { + currentConfigObj.clear(); + confFile >> currentConfigObj; + } catch (json::parse_error& e) { + logF("Config Load Exception!: %s", e.what()); + } + currentConfigObj["from"] = "Horion"; + } + + if (configExists) { + moduleMgr->onLoadConfig(¤tConfigObj); + if (currentConfigObj.contains("prefix")) { + std::string prefix = currentConfigObj["prefix"]; + cmdMgr->prefix = prefix.at(0); + } + } + + if (create) + saveConfig(); + + if (g_Data.getLocalPlayer() != nullptr) { + static bool helpedUser = false; + g_Data.getGuiData()->displayClientMessageF("[%sHorion%s] %sSuccessfully %s config %s%s%s!", GOLD, WHITE, GREEN, !configExists ? "created" : "loaded", GRAY, name.c_str(), GREEN); + if (!helpedUser && name != "default") { + helpedUser = true; + g_Data.getGuiData()->displayClientMessageF("[%sHorion%s] %sEnter \"%s%cconfig load default%s\" to load your old config!", GOLD, WHITE, YELLOW, WHITE, cmdMgr->prefix, YELLOW); + } + } + } else { + if (g_Data.getLocalPlayer() != nullptr) + g_Data.getGuiData()->displayClientMessageF("[%sHorion%s] %sCould not load config %s%s%s!", GOLD, WHITE, RED, GRAY, name.c_str(), RED); + } + + delete[] fullPath; +} + +void ConfigManager::saveConfig() { + logF("Saving config %s", currentConfig.c_str()); + size_t allocSize = currentConfig.size() + roamingFolder.size() + 20; // std::wstring::size() can be wierd so lets make sure this actually fits + char* fullPath = new char[allocSize]; + sprintf_s(fullPath, allocSize, "%S\\%s.h", roamingFolder.c_str(), currentConfig.c_str()); + + moduleMgr->onSaveConfig(¤tConfigObj); + + std::string prefix; + prefix.push_back(cmdMgr->prefix); + currentConfigObj["prefix"] = prefix; + + std::ofstream o(fullPath, std::ifstream::binary); + o << std::setw(4) << currentConfigObj << std::endl; + o.flush(); + o.close(); + + delete[] fullPath; +} + +void ConfigManager::init() { + logF("Initializing config"); + loadConfig(currentConfig, true); +} + +ConfigManager* configMgr = new ConfigManager(); diff --git a/Horion/Config/ConfigManager.h b/Horion/Config/ConfigManager.h new file mode 100644 index 0000000..498a072 --- /dev/null +++ b/Horion/Config/ConfigManager.h @@ -0,0 +1,36 @@ +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include +#pragma comment(lib, "runtimeobject") + +#include "../../Utils/Json.hpp" +#include "../Command/CommandMgr.h" +#include "../Module/ModuleManager.h" + +using json = nlohmann::json; + +class ConfigManager { +private: + std::wstring roamingFolder; + static std::wstring GetRoamingFolderPath(); + json currentConfigObj; + +public: + ConfigManager(); + ~ConfigManager(); + + std::string currentConfig = "default"; + + void loadConfig(std::string name, bool create); + void saveConfig(); + void init(); +}; + +extern ConfigManager* configMgr; diff --git a/Horion/DrawUtils.cpp b/Horion/DrawUtils.cpp new file mode 100644 index 0000000..d7b0af0 --- /dev/null +++ b/Horion/DrawUtils.cpp @@ -0,0 +1,607 @@ +#include "DrawUtils.h" + +#include "Module/ModuleManager.h" +#include +#include "../Utils/Logger.h" + +struct MaterialPtr { + char padding[0x138]; +}; + +using tess_vertex_t = void(__fastcall*)(Tessellator* _this, float v1, float v2, float v3); +using meshHelper_renderImm_t = void(__fastcall*)(__int64, Tessellator* tesselator, MaterialPtr*); + +C_MinecraftUIRenderContext* renderCtx; +C_GuiData* guiData; +__int64 screenContext2d; +__int64 game3dContext; +Tessellator* tesselator; +float* colorHolder; +std::shared_ptr refdef; +vec2_t fov; +vec2_t screenSize; +vec3_t origin; +float lerpT; +C_TexturePtr* texturePtr = nullptr; + +static MaterialPtr* uiMaterial = nullptr; +static MaterialPtr* entityFlatStaticMaterial = nullptr; + +tess_vertex_t tess_vertex; +meshHelper_renderImm_t meshHelper_renderImm; +//mce__VertexFormat__disableHalfFloats_t mce__VertexFormat__disableHalfFloats; +//Tessellator__initializeFormat_t Tessellator__initializeFormat; + +bool hasInitializedSigs = false; +void initializeSigs() { + + tess_vertex = reinterpret_cast(FindSignature("40 57 48 83 EC ? 0F 29 74 24 ? 0F 29 7C 24")); + meshHelper_renderImm = reinterpret_cast(FindSignature("40 53 56 57 48 81 EC ?? ?? ?? ?? 49 8B F0 48 8B DA")); + //mce__VertexFormat__disableHalfFloats = reinterpret_cast(FindSignature("40 53 48 83 EC ?? 48 8B D9 C7 81 ?? ?? ?? ?? 00 00 00 00 C6 81 ?? ?? ?? ?? 00")); + //Tessellator__initializeFormat = reinterpret_cast(FindSignature("48 89 74 24 ?? 57 48 83 EC 20 4C 8B 41 ?? 48 8B FA 4C 2B 41 ?? 48 8B F1 48 83 C1 08 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 49 F7 E8 48 D1 FA 48 8B C2 48 C1 E8 3F 48 03 D0 48 3B FA")); + hasInitializedSigs = true; +} + +void DrawUtils::setCtx(C_MinecraftUIRenderContext* ctx, C_GuiData* gui) { + if (!hasInitializedSigs) + initializeSigs(); + LARGE_INTEGER EndingTime, ElapsedMicroseconds; + LARGE_INTEGER Frequency; + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&EndingTime); + ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - g_Data.getLastUpdateTime(); + + ElapsedMicroseconds.QuadPart *= 1000000; + int ticksPerSecond = 20; + if(g_Data.getClientInstance()->minecraft) + if (g_Data.getClientInstance()->minecraft->timer != nullptr) + ticksPerSecond = (int)*g_Data.getClientInstance()->minecraft->timer; + if(ticksPerSecond < 1) + ticksPerSecond = 1; + ElapsedMicroseconds.QuadPart /= Frequency.QuadPart / ticksPerSecond; + lerpT = (ElapsedMicroseconds.QuadPart / 1000000.f); + if (lerpT > 1) + lerpT = 1; + else if (lerpT < 0) + lerpT = 0; + + guiData = gui; + renderCtx = ctx; + screenContext2d = reinterpret_cast<__int64*>(renderCtx)[2]; + + tesselator = *reinterpret_cast(screenContext2d + 0xB0); + colorHolder = *reinterpret_cast(screenContext2d + 0x30); + + glmatrixf* badrefdef = g_Data.getClientInstance()->getRefDef(); + + refdef = std::shared_ptr(badrefdef->correct()); + fov = g_Data.getClientInstance()->getFov(); + screenSize.x = gui->widthGame; + screenSize.y = gui->heightGame; + if (g_Data.getClientInstance()->levelRenderer != nullptr) + origin = g_Data.getClientInstance()->levelRenderer->origin; + + if (uiMaterial == nullptr) { + // 2 Sigs, wanted one comes first + uintptr_t sigOffset = FindSignature("4C 8D 05 ?? ?? ?? ?? 48 8B D3 48 8B CF 48 8B 5C 24 ?? 0F 28 7C 24 ?? 44 0F 28 44 24 ?? 48"); + int offset = *reinterpret_cast(sigOffset + 3); + uiMaterial = reinterpret_cast(sigOffset + offset + 7); + } + if(entityFlatStaticMaterial == nullptr && g_Data.isInGame()){ + entityFlatStaticMaterial = reinterpret_cast(g_Data.getClientInstance()->itemInHandRenderer->entityLineMaterial.materialPtr); + } +} + +void DrawUtils::setColor(float r, float g, float b, float a) { + colorHolder[0] = r; + colorHolder[1] = g; + colorHolder[2] = b; + colorHolder[3] = a; + *reinterpret_cast(colorHolder + 4) = 1; +} + +C_Font* DrawUtils::getFont(Fonts font) { + + if (true) + return g_Data.getClientInstance()->minecraftGame->getOldFont(); + switch (font) { + case Fonts::SMOOTH: + return g_Data.getClientInstance()->minecraftGame->getTheGoodFontThankYou(); + break; + case Fonts::UNICOD: + return g_Data.getClientInstance()->minecraftGame->getTheBetterFontYes(); + break; + case Fonts::RUNE: + return g_Data.getClientInstance()->_getRuneFont(); + break; + default: + return g_Data.getClientInstance()->_getFont(); + break; + } +} + +Tessellator* DrawUtils::get3dTessellator() { + auto myTess = *reinterpret_cast(game3dContext + 0xB0); + return myTess; +} + +__int64 DrawUtils::getScreenContext() { + return game3dContext == 0 ? screenContext2d : game3dContext; +} + +MatrixStack* DrawUtils::getMatrixStack() { + return reinterpret_cast(*reinterpret_cast<__int64*>(DrawUtils::getScreenContext() + 0x18i64) + 0x30i64); +} + +float DrawUtils::getTextWidth(std::string* textStr, float textSize, Fonts font) { + TextHolder text(*textStr); + + C_Font* fontPtr = getFont(font); + + float ret = renderCtx->getLineLength(fontPtr, &text, textSize, false); + + return ret; +} + +float DrawUtils::getFontHeight(float textSize, Fonts font) { + C_Font* fontPtr = getFont(font); + + float ret = fontPtr->getLineHeight() * textSize; + + return ret; +} + +void DrawUtils::flush() { + renderCtx->flushText(0); +} + +void DrawUtils::drawTriangle(const vec2_t& p1, const vec2_t& p2, const vec2_t& p3) { + + DrawUtils::tess__begin(tesselator, 3, 3); + + tess_vertex(tesselator, p1.x, p1.y, 0); + tess_vertex(tesselator, p2.x, p2.y, 0); + tess_vertex(tesselator, p3.x, p3.y, 0); + + meshHelper_renderImm(screenContext2d, tesselator, uiMaterial); +} + + +void DrawUtils::drawQuad(const vec2_t& p1, const vec2_t& p2, const vec2_t& p3, const vec2_t& p4) { + DrawUtils::tess__begin(tesselator, 1, 4); + + tess_vertex(tesselator, p1.x, p1.y, 0); + tess_vertex(tesselator, p2.x, p2.y, 0); + tess_vertex(tesselator, p3.x, p3.y, 0); + tess_vertex(tesselator, p4.x, p4.y, 0); + + meshHelper_renderImm(screenContext2d, tesselator, uiMaterial); +} + +void DrawUtils::drawLine(const vec2_t& start, const vec2_t& end, float lineWidth) { + float modX = 0 - (start.y - end.y); + float modY = start.x - end.x; + + float len = sqrtf(modX * modX + modY * modY); + + modX /= len; + modY /= len; + modX *= lineWidth; + modY *= lineWidth; + + DrawUtils::tess__begin(tesselator, 3, 6); + + tess_vertex(tesselator, start.x + modX, start.y + modY, 0); + tess_vertex(tesselator, start.x - modX, start.y - modY, 0); + tess_vertex(tesselator, end.x - modX, end.y - modY, 0); + + tess_vertex(tesselator, start.x + modX, start.y + modY, 0); + tess_vertex(tesselator, end.x + modX, end.y + modY, 0); + tess_vertex(tesselator, end.x - modX, end.y - modY, 0); + + meshHelper_renderImm(screenContext2d, tesselator, uiMaterial); +} + +void DrawUtils::drawText(const vec2_t& pos, std::string* textStr, const MC_Color& color, float textSize, float alpha, Fonts font) { + TextHolder text(*textStr); + C_Font* fontPtr = getFont(font); + static uintptr_t caretMeasureData = 0xFFFFFFFF; + + + float posF[4]; // vec4_t(startX, startY, endX, endY); + posF[0] = pos.x; + posF[1] = pos.x + 1000; + posF[2] = pos.y - 1; + posF[3] = pos.y + 1000; + + TextMeasureData textMeasure{}; + memset(&textMeasure, 0, sizeof(TextMeasureData)); + textMeasure.textSize = textSize; + + renderCtx->drawText(fontPtr, posF, &text, color.arr, alpha, 0, &textMeasure, &caretMeasureData); +} + +void DrawUtils::drawBox(const vec3_t& lower, const vec3_t& upper, float lineWidth, bool outline) { + + vec3_t diff; + diff.x = upper.x - lower.x; + diff.y = upper.y - lower.y; + diff.z = upper.z - lower.z; + + vec3_t vertices[8]; + vertices[0] = vec3_t(lower.x, lower.y, lower.z); + vertices[1] = vec3_t(lower.x + diff.x, lower.y, lower.z); + vertices[2] = vec3_t(lower.x, lower.y + diff.y, lower.z); + vertices[3] = vec3_t(lower.x + diff.x, lower.y + diff.y, lower.z); + vertices[4] = vec3_t(lower.x, lower.y, lower.z + diff.z); + vertices[5] = vec3_t(lower.x + diff.x, lower.y, lower.z + diff.z); + vertices[6] = vec3_t(lower.x, lower.y + diff.y, lower.z + diff.z); + vertices[7] = vec3_t(lower.x + diff.x, lower.y + diff.y, lower.z + diff.z); + + // Convert to screen coord + std::vector> screenCords; + for (int i = 0; i < 8; i++) { + vec2_t screen; + if (refdef->OWorldToScreen(origin, vertices[i], screen, fov, screenSize)) { + screenCords.emplace_back(outline ? (int) screenCords.size() : i, screen); + } + } + if (screenCords.size() < 2) + return; // No lines possible + + if (!outline) { + for (auto it = screenCords.begin(); it != screenCords.end(); it++) { + auto from = *it; + auto fromOrig = vertices[std::get<0>(from)]; + + for (auto to : screenCords) { + auto toOrig = vertices[std::get<0>(to)]; + + bool shouldDraw = false; + // X direction + shouldDraw |= fromOrig.y == toOrig.y && fromOrig.z == toOrig.z && fromOrig.x < toOrig.x; + // Y direction + shouldDraw |= fromOrig.x == toOrig.x && fromOrig.z == toOrig.z && fromOrig.y < toOrig.y; + // Z direction + shouldDraw |= fromOrig.x == toOrig.x && fromOrig.y == toOrig.y && fromOrig.z < toOrig.z; + + if (shouldDraw) + drawLine(std::get<1>(from), std::get<1>(to), lineWidth); + } + } + + return; + } + // Find start vertex + auto it = screenCords.begin(); + std::tuple start = *it; + it++; + for (; it != screenCords.end(); it++) { + auto cur = *it; + if (std::get<1>(cur).x < std::get<1>(start).x) { + start = cur; + } + } + + // Follow outer line + std::vector indices; + + auto current = start; + indices.push_back(std::get<0>(current)); + vec2_t lastDir(0, -1); + do { + float smallestAngle = PI * 2; + vec2_t smallestDir; + std::tuple smallestE; + auto lastDirAtan2 = atan2(lastDir.y, lastDir.x); + for (auto cur : screenCords) { + if (std::get<0>(current) == std::get<0>(cur)) + continue; + + // angle between vecs + vec2_t dir = vec2_t(std::get<1>(cur)).sub(std::get<1>(current)); + float angle = atan2(dir.y, dir.x) - lastDirAtan2; + if (angle > PI) { + angle -= 2 * PI; + } else if (angle <= -PI) { + angle += 2 * PI; + } + if (angle >= 0 && angle < smallestAngle) { + smallestAngle = angle; + smallestDir = dir; + smallestE = cur; + } + } + indices.push_back(std::get<0>(smallestE)); + lastDir = smallestDir; + current = smallestE; + } while (std::get<0>(current) != std::get<0>(start) && indices.size() < 8); + + // draw + + vec2_t lastVertex; + bool hasLastVertex = false; + for (auto& indice : indices) { + vec2_t curVertex = std::get<1>(screenCords[indice]); + if (!hasLastVertex) { + hasLastVertex = true; + lastVertex = curVertex; + continue; + } + + drawLine(lastVertex, curVertex, lineWidth); + lastVertex = curVertex; + } +} + +void DrawUtils::drawImage(std::string FilePath, vec2_t& imagePos, vec2_t& ImageDimension, vec2_t& idk) { + if (texturePtr == nullptr) { + texturePtr = new C_TexturePtr(); + C_FilePath file(FilePath); + renderCtx->getTexture(texturePtr, file); + } + + __int64 yot = 0; + static unsigned __int64 hashedString = 0xA99285D21E94FC80; + static uintptr_t flushImageAddr = FindSignature("48 8B C4 55 56 57 41 54 41 55 41 56 41 57 ?? ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? ?? 48 89 58 ?? 0F 29 70 ?? 0F 29 78 ?? 44 0F 29 40 ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 ?? ?? ?? ?? ?? ?? ?? 4D 8B E1 44 0F 28 C2 4C 8B F2 4C 8B F9"); + + if (texturePtr != nullptr) { + renderCtx->drawImage(texturePtr, imagePos, ImageDimension, yot, idk); + MC_Color col(1.f, 1.f, 1.f); + renderCtx->flushImages(col, flushImageAddr, (__int64)&hashedString); + } +} + +void DrawUtils::drawNameTags(C_Entity* ent, float textSize, bool drawHealth, bool useUnicodeFont) { + vec2_t textPos; + vec4_t rectPos; + std::string text = ent->getNameTag()->getText(); + text = Utils::sanitize(text); + + float textWidth = getTextWidth(&text, textSize); + float textHeight = DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() * textSize; + + if (refdef->OWorldToScreen(origin, ent->eyePos0.add(0, 0.5f, 0), textPos, fov, screenSize)) { + textPos.y -= textHeight; + textPos.x -= textWidth / 2.f; + rectPos.x = textPos.x - 1.f * textSize; + rectPos.y = textPos.y - 1.f * textSize; + rectPos.z = textPos.x + textWidth + 1.f * textSize; + rectPos.w = textPos.y + textHeight + 2.f * textSize; + vec4_t subRectPos = rectPos; + subRectPos.y = subRectPos.w - 1.f * textSize; + static auto nametagsMod = moduleMgr->getModule(); + fillRectangle(rectPos, MC_Color(12, 12, 12), nametagsMod->opacity); + if (nametagsMod->underline) { + fillRectangle(subRectPos, MC_Color(85, 85, 85), 0.9f); + } + drawText(textPos, &text, MC_Color(255, 255, 255), textSize); + + static auto nameTagsMod = moduleMgr->getModule(); + + if (ent->getEntityTypeId() == 63 && nameTagsMod->displayArmor) { // is player, show armor + auto* player = reinterpret_cast(ent); + float scale = textSize * 0.6f; + float spacing = scale + 15.f; + float x = rectPos.x + 1.f * textSize; + float y = rectPos.y - 20.f * scale; + // armor + for (int i = 0; i < 4; i++) { + C_ItemStack* stack = player->getArmor(i); + if (stack->item != nullptr) { + DrawUtils::drawItem(stack, vec2_t(x, y), 1.f, scale, stack->isEnchanted()); + x += scale * spacing; + } + } + // item + { + C_ItemStack* stack = player->getSelectedItem(); + if (stack->item != nullptr) { + DrawUtils::drawItem(stack, vec2_t(rectPos.z - 1.f - 15.f * scale, y), 1.f, scale, stack->isEnchanted()); + } + } + } + } +} + +void DrawUtils::drawEntityBox(C_Entity* ent, float lineWidth) { + vec3_t* start = ent->getPosOld(); + vec3_t* end = ent->getPos(); + + vec3_t lerped = start->lerp(end, lerpT); + + AABB render(lerped, ent->width, ent->height, end->y - ent->aabb.lower.y); + render.upper.y += 0.1f; + + drawBox(render.lower, render.upper, lineWidth, true); +} + +void DrawUtils::draw2D(C_Entity* ent, float lineWidth) { + vec3_t base = vec3_t(ent->eyePos0.x, ent->eyePos0.y + 0.15f, ent->eyePos0.z); + float ofs = (g_Data.getLocalPlayer()->yaw + 90.f) * (PI / 180); + + vec3_t corners[4]; + vec2_t corners2d[4]; + + corners[0] = vec3_t(base.x - ent->width / 1.5f * -sin(ofs), ent->aabb.upper.y + (float)0.1, base.z - ent->width / 1.5f * cos(ofs)); + corners[1] = vec3_t(base.x + ent->width / 1.5f * -sin(ofs), ent->aabb.upper.y + (float)0.1, base.z + ent->width / 1.5f * cos(ofs)); + corners[2] = vec3_t(base.x - ent->width / 1.5f * -sin(ofs), ent->aabb.lower.y, base.z - ent->width / 1.5f * cos(ofs)); + corners[3] = vec3_t(base.x + ent->width / 1.5f * -sin(ofs), ent->aabb.lower.y, base.z + ent->width / 1.5f * cos(ofs)); + + if (refdef->OWorldToScreen(origin, corners[0], corners2d[0], fov, screenSize) && + refdef->OWorldToScreen(origin, corners[1], corners2d[1], fov, screenSize) && + refdef->OWorldToScreen(origin, corners[2], corners2d[2], fov, screenSize) && + refdef->OWorldToScreen(origin, corners[3], corners2d[3], fov, screenSize)) { + float length = (corners2d[1].x - corners2d[0].x) / 4.f; + + drawLine(corners2d[0], vec2_t(corners2d[0].x + length, corners2d[0].y), lineWidth); + drawLine(corners2d[0], vec2_t(corners2d[0].x, corners2d[0].y + length), lineWidth); + + drawLine(vec2_t(corners2d[1].x - length, corners2d[1].y), corners2d[1], lineWidth); + drawLine(corners2d[1], vec2_t(corners2d[1].x, corners2d[1].y + length), lineWidth); + + drawLine(vec2_t(corners2d[2].x, corners2d[2].y - length), corners2d[2], lineWidth); + drawLine(corners2d[2], vec2_t(corners2d[2].x + length, corners2d[2].y), lineWidth); + + drawLine(vec2_t(corners2d[3].x, corners2d[3].y - length), corners2d[3], lineWidth); + drawLine(vec2_t(corners2d[3].x - length, corners2d[3].y), corners2d[3], lineWidth); + + /*drawLine(corners2d[0], corners2d[1], lineWidth); + drawLine(corners2d[0], corners2d[2], lineWidth); + drawLine(corners2d[3], corners2d[1], lineWidth); + drawLine(corners2d[3], corners2d[2], lineWidth);*/ + } +} + +void DrawUtils::drawItem(C_ItemStack* item, const vec2_t& itemPos, float opacity, float scale, bool isEnchanted) { + __int64 scnCtx = reinterpret_cast<__int64*>(renderCtx)[2]; + auto* screenCtx = reinterpret_cast(scnCtx); + C_BaseActorRenderContext baseActorRenderCtx(screenCtx, g_Data.getClientInstance(), g_Data.getClientInstance()->minecraftGame); + C_ItemRenderer* renderer = baseActorRenderCtx.renderer; + renderer->renderGuiItemNew(&baseActorRenderCtx, item, g_Data.getClientInstance()->minecraftGame, itemPos.x, itemPos.y, opacity, scale, isEnchanted); + +} + +vec2_t DrawUtils::worldToScreen(const vec3_t& world) { + vec2_t ret{-1, -1}; + refdef->OWorldToScreen(origin, world, ret, fov, screenSize); + return ret; +} +void DrawUtils::drawLine3d(const vec3_t& start, const vec3_t& end) { + if(game3dContext == 0 || entityFlatStaticMaterial == 0) + return; + + auto myTess = DrawUtils::get3dTessellator(); + + DrawUtils::tess__begin(myTess, 4, 2); + + auto start1 = start.sub(origin); + auto end1 = end.sub(origin); + + tess_vertex(myTess, start1.x, start1.y, start1.z); + tess_vertex(myTess, end1.x, end1.y, end1.z); + + meshHelper_renderImm(game3dContext, myTess, entityFlatStaticMaterial); +} +void DrawUtils::drawBox3d(const vec3_t& lower, const vec3_t& upper) { + if (game3dContext == 0 || entityFlatStaticMaterial == 0) + return; + + auto myTess = DrawUtils::get3dTessellator(); + + DrawUtils::tess__begin(myTess, 4, 12); + + vec3_t diff; + diff.x = upper.x - lower.x; + diff.y = upper.y - lower.y; + diff.z = upper.z - lower.z; + + auto newLower = lower.sub(origin); + + vec3_t vertices[8]; + vertices[0] = vec3_t(newLower.x, newLower.y, newLower.z); + vertices[1] = vec3_t(newLower.x + diff.x, newLower.y, newLower.z); + vertices[2] = vec3_t(newLower.x, newLower.y, newLower.z + diff.z); + vertices[3] = vec3_t(newLower.x + diff.x, newLower.y, newLower.z + diff.z); + + vertices[4] = vec3_t(newLower.x, newLower.y + diff.y, newLower.z); + vertices[5] = vec3_t(newLower.x + diff.x, newLower.y + diff.y, newLower.z); + vertices[6] = vec3_t(newLower.x, newLower.y + diff.y, newLower.z + diff.z); + vertices[7] = vec3_t(newLower.x + diff.x, newLower.y + diff.y, newLower.z + diff.z); + + #define line(m, n) tess_vertex(myTess, m.x, m.y, m.z); \ + tess_vertex(myTess, n.x, n.y, n.z); + + #define li(m, n) line(vertices[m], vertices[n]); + + li(0, 1); + li(1, 3); + li(3, 2); + li(2, 0); + + li(4, 5); + li(5, 7); + li(7, 6); + li(6, 4); + + li(0, 4); + li(1, 5); + li(2, 6); + li(3, 7); + + #undef li + #undef line + + meshHelper_renderImm(game3dContext, myTess, entityFlatStaticMaterial); +} +void DrawUtils::fillRectangle(const vec4_t& pos, const MC_Color& col, float alpha) { + DrawUtils::setColor(col.r, col.g, col.b, alpha); + DrawUtils::drawQuad({pos.x, pos.w}, {pos.z, pos.w}, {pos.z, pos.y}, {pos.x, pos.y}); +} +inline void DrawUtils::tess__begin(Tessellator* tess, int vertexFormat, int numVerticesReserved) { + __int64 tesselator = reinterpret_cast<__int64>(tess); + + using tess_begin_t = void(__fastcall*)(Tessellator*, int, int); + static tess_begin_t tess_begin = reinterpret_cast(FindSignature("48 89 5C 24 ?? 55 48 83 EC ?? 80 B9 ?? ?? ?? ?? 00 45")); + tess_begin(tess, vertexFormat, numVerticesReserved); +} +void DrawUtils::setGameRenderContext(__int64 ctx) { + game3dContext = ctx; + if (g_Data.getClientInstance()->levelRenderer != nullptr) + origin = g_Data.getClientInstance()->levelRenderer->origin; + + if(ctx){ + LARGE_INTEGER EndingTime, ElapsedMicroseconds; + LARGE_INTEGER Frequency; + QueryPerformanceFrequency(&Frequency); + QueryPerformanceCounter(&EndingTime); + ElapsedMicroseconds.QuadPart = EndingTime.QuadPart - g_Data.getLastUpdateTime(); + + ElapsedMicroseconds.QuadPart *= 1000000; + int ticksPerSecond = 20; + if(g_Data.getClientInstance()->minecraft) + ticksPerSecond = (int)*g_Data.getClientInstance()->minecraft->timer; + if(ticksPerSecond < 1) + ticksPerSecond = 1; + ElapsedMicroseconds.QuadPart /= Frequency.QuadPart / ticksPerSecond; + lerpT = (ElapsedMicroseconds.QuadPart / 1000000.f); + if (lerpT > 1) + lerpT = 1; + else if (lerpT < 0) + lerpT = 0; + } +} +float DrawUtils::getLerpTime() { + return lerpT; +} +vec3_t DrawUtils::getOrigin() { + return origin; +} +void DrawUtils::drawLinestrip3d(const std::vector& points) { + if(game3dContext == 0 || entityFlatStaticMaterial == 0) + return; + + auto myTess = DrawUtils::get3dTessellator(); + + DrawUtils::tess__begin(myTess, 5, (int)points.size()); + + /* + * 1: quads + * 2: triangle list + * 3: trianglestrip (6) + * 4: line list + * 5: line strip (7) + */ + + for(const auto& p : points){ + auto pD = p.sub(origin); + tess_vertex(myTess, pD.x, pD.y, pD.z); + } + + + meshHelper_renderImm(game3dContext, myTess, entityFlatStaticMaterial); +} + +MC_Color MC_Color::lerp(const MC_Color& o, float t) const { + return MC_Color(Utils::lerp(r, o.r, t), Utils::lerp(g, o.g, t), Utils::lerp(b, o.b, t), Utils::lerp(a, o.a, t)); +} diff --git a/Horion/DrawUtils.h b/Horion/DrawUtils.h new file mode 100644 index 0000000..7b6d206 --- /dev/null +++ b/Horion/DrawUtils.h @@ -0,0 +1,136 @@ +#pragma once + +#include "../Memory/GameData.h" +#include "../SDK/CClientInstance.h" +#include "../SDK/CMinecraftUIRenderContext.h" +#include "../SDK/Tessellator.h" +#include "../Utils/HMath.h" +#include "../Utils/Target.h" +#include "../Utils/Utils.h" + +enum class Fonts { DEFAULT, + UNICOD, + SMOOTH, + RUNE }; + +using mce__VertexFormat__disableHalfFloats_t = void(__fastcall*)(__int64, int, int); +using Tessellator__initializeFormat_t = void(__fastcall*)(__int64, __int64); + +extern C_MinecraftUIRenderContext* renderCtx; +extern mce__VertexFormat__disableHalfFloats_t mce__VertexFormat__disableHalfFloats; +extern Tessellator__initializeFormat_t Tessellator__initializeFormat; + +struct MC_Color { + union { + struct { + float r, g, b, a; + }; + float arr[4]; + }; + bool shouldDelete = true; + + MC_Color() { + this->r = 1; + this->g = 1; + this->b = 1; + this->a = 1; + }; + + MC_Color(const MC_Color& other) { + this->r = other.r; + this->g = other.g; + this->b = other.b; + this->a = other.a; + this->shouldDelete = other.shouldDelete; + } + + MC_Color(const float* arr) { + this->arr[0] = arr[0]; + this->arr[1] = arr[1]; + this->arr[2] = arr[2]; + this->arr[3] = arr[3]; + }; + + MC_Color(const float r, const float g, const float b, const float a = 1) { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + }; + + MC_Color(const int r, const int g, const int b, const int a = 255) { + this->r = r / 255.0f; + this->g = g / 255.0f; + this->b = b / 255.0f; + this->a = a / 255.0f; + }; + + MC_Color(const float r, const float g, const float b, const float a, const bool shouldDelete) { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + this->shouldDelete = shouldDelete; + }; + + MC_Color lerp(const MC_Color& o, float t) const; +}; + +enum VertexFormat { + +}; + +class MatrixStack; + +class DrawUtils { +public: + static void setCtx(C_MinecraftUIRenderContext* ctx, C_GuiData* guiData); + static void setGameRenderContext(__int64 ctx); + static void flush(); + static void setColor(float r, float g, float b, float a); // rgba, values from 0 to 1 + static inline void tess__begin(Tessellator* tesselator, int vertexFormat = 3, int numVerticesReserved = 0); + static C_Font* getFont(Fonts font); + static Tessellator* get3dTessellator(); + static __int64 getScreenContext(); + static MatrixStack* getMatrixStack(); + static float getTextWidth(std::string* textStr, float textSize = 1, Fonts font = Fonts::SMOOTH); + static float getFontHeight(float textSize = 1, Fonts font = Fonts::SMOOTH); + + static void drawTriangle(const vec2_t& p1, const vec2_t& p2, const vec2_t& p3); + static void drawQuad(const vec2_t& p1, const vec2_t& p2, const vec2_t& p3, const vec2_t& p4); + static void drawLine(const vec2_t& start, const vec2_t& end, float lineWidth); // rgba + static void drawLinestrip3d(const std::vector& points); + static void drawLine3d(const vec3_t& start, const vec3_t& end); + static void drawBox3d(const vec3_t& lower, const vec3_t& upper); + static void fillRectangle(const vec4_t& pos, const MC_Color& col, float alpha); + static inline void fillRectangle(const vec2_t& start, const vec2_t& end) { + DrawUtils::drawQuad({start.x, end.y}, {end.x, end.y}, {end.x, start.y}, {start.x, start.y}); + } + static inline void drawRectangle(const vec2_t& start, const vec2_t& end, float lineWidth = 1.0f) { + lineWidth /= 2; + fillRectangle({start.x - lineWidth, start.y - lineWidth}, {end.x + lineWidth, start.y + lineWidth}); // TOP + fillRectangle({start.x - lineWidth, start.y}, {start.x + lineWidth, end.y}); // LEFT + fillRectangle({end.x - lineWidth, start.y}, {end.x + lineWidth, end.y}); // + fillRectangle({start.x - lineWidth, end.y - lineWidth}, {end.x + lineWidth, end.y + lineWidth}); + } + static inline void drawRectangle(const vec4_t& pos, const MC_Color& col, float alpha, float lineWidth = 1.0f) { + lineWidth /= 2; + fillRectangle(vec4_t(pos.x - lineWidth, pos.y - lineWidth, pos.z + lineWidth, pos.y + lineWidth), col, alpha); // TOP + fillRectangle(vec4_t(pos.x - lineWidth, pos.y, pos.x + lineWidth, pos.w), col, alpha); // LEFT + fillRectangle(vec4_t(pos.z - lineWidth, pos.y, pos.z + lineWidth, pos.w), col, alpha); // + fillRectangle(vec4_t(pos.x - lineWidth, pos.w - lineWidth, pos.z + lineWidth, pos.w + lineWidth), col, alpha); + } + static void drawImage(std::string filePath, vec2_t& ImagePos, vec2_t& ImageDimension, vec2_t& idk); + + static void drawText(const vec2_t& pos, std::string* text, const MC_Color& color, float textSize = 1, float alpha = 1, Fonts font = Fonts::SMOOTH); + static void drawBox(const vec3_t& lower, const vec3_t& upper, float lineWidth, bool outline = false); + static void drawEntityBox(C_Entity* ent, float lineWidth); + static void draw2D(C_Entity* ent, float lineWidth); + static void drawNameTags(C_Entity* ent, float textSize, bool drawHealth = false, bool useUnicodeFont = false); + static void drawItem(C_ItemStack* item, const vec2_t& ItemPos, float opacity, float scale, bool isEnchanted); + static float getLerpTime(); + static vec3_t getOrigin(); + + static vec2_t worldToScreen(const vec3_t& world); +}; + diff --git a/Horion/FriendList/FriendList.cpp b/Horion/FriendList/FriendList.cpp new file mode 100644 index 0000000..3ea3289 --- /dev/null +++ b/Horion/FriendList/FriendList.cpp @@ -0,0 +1,38 @@ +#include "FriendList.h" + +FriendList g_friend; + +FriendList::FriendList() { +} + +FriendList::~FriendList() { +} + +void FriendList::addPlayerToList(const std::string& name) { + g_friend.List.push_back(name); +} + +std::vector FriendList::getList() { + return g_friend.List; +} + +bool FriendList::findPlayer(const std::string& name) { + for (std::vector::iterator it = g_friend.List.begin(); it != g_friend.List.end(); ++it) { + if (it->find(name) != std::string::npos) { + return true; + } + } + return false; +} + +bool FriendList::removePlayer(const std::string& g) { + for (std::vector::iterator it = g_friend.List.begin(); it != g_friend.List.end(); ++it) { + std::string copy = *it; + std::transform(copy.begin(), copy.end(), copy.begin(), ::tolower); + if (copy.find(g) != std::string::npos) { + g_friend.List.erase(it); + return true; + } + } + return false; +} diff --git a/Horion/FriendList/FriendList.h b/Horion/FriendList/FriendList.h new file mode 100644 index 0000000..8d7710f --- /dev/null +++ b/Horion/FriendList/FriendList.h @@ -0,0 +1,29 @@ +#pragma once + +#include +#include +#include +#include + +#include "../../Memory/GameData.h" + +class FriendList { +private: + //GameData* gameData; + std::vector List; + +public: + FriendList(); + ~FriendList(); + + static std::vector getList(); + static bool findPlayer(const std::string& name); + static bool findPlayer(const char* name) { + std::string local(name); + return findPlayer(local); + } + static void addPlayerToList(const std::string& name); + static bool removePlayer(const std::string& g); +}; + +extern FriendList g_friend; diff --git a/Horion/GuiUtils.cpp b/Horion/GuiUtils.cpp new file mode 100644 index 0000000..05bb065 --- /dev/null +++ b/Horion/GuiUtils.cpp @@ -0,0 +1,11 @@ +#include "GuiUtils.h" + +void GuiUtils::drawCrossLine(vec2_t pos, MC_Color col, float lineWidth, float crossSize, bool secondCross) { + crossSize /= 2; + DrawUtils::setColor(col.r, col.g, col.b, col.a); + //float MidX = (pos.z + pos.x) / 2; + //float MidY = (pos.y + pos.w) / 2; + DrawUtils::drawLine(vec2_t(pos.x - crossSize, pos.y), vec2_t(pos.x + crossSize, pos.y), lineWidth); + if (secondCross) + DrawUtils::drawLine(vec2_t(pos.x, pos.y - crossSize), vec2_t(pos.x, pos.y + crossSize), lineWidth); +} diff --git a/Horion/GuiUtils.h b/Horion/GuiUtils.h new file mode 100644 index 0000000..238fb79 --- /dev/null +++ b/Horion/GuiUtils.h @@ -0,0 +1,7 @@ +#pragma once +#include "DrawUtils.h" + +class GuiUtils { +public: + static void drawCrossLine(vec2_t pos, MC_Color col, float lineWidth, float crossSize, bool secondCross); +}; diff --git a/Horion/ImmediateGui.cpp b/Horion/ImmediateGui.cpp new file mode 100644 index 0000000..c0192b5 --- /dev/null +++ b/Horion/ImmediateGui.cpp @@ -0,0 +1,104 @@ +#include "ImmediateGui.h" + +ImmediateGui HImGui; + +ComponentInfo::ComponentInfo(int id) : id(id) { +} + +ButtonInfo::ButtonInfo(int id, vec2_t pos, bool centered) : ComponentInfo(id), pos(pos), centered(centered) { +} + +void ButtonInfo::calculateSize(const char* txt) { + std::string str(txt); + this->size = {DrawUtils::getTextWidth(&str), DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight()}; +} + +bool ButtonInfo::isInSelectableSurface(vec2_t mouse) { + vec4_t surface = getSelectableSurface(); + return surface.contains(&mouse); +} + +vec4_t ButtonInfo::getSelectableSurface() { + if (centered) { + return {this->pos.x - padding - this->size.x / 2, + this->pos.y - padding - this->size.y / 2, + this->pos.x + padding + this->size.x / 2, + this->pos.y + padding + this->size.y / 2}; + } else { + return {this->pos.x - padding, + this->pos.y - padding, + this->pos.x + padding + this->size.x, + this->pos.y + padding + this->size.y}; + } +} + +void ButtonInfo::draw(vec2_t mousePos, const char* label) { + calculateSize(label); + auto surface = getSelectableSurface(); + vec2_t textPos = pos; + std::string str(label); + if (centered) { + textPos.x -= DrawUtils::getTextWidth(&str) / 2; + textPos.y -= DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2; + } + + DrawUtils::drawText(textPos, &str, MC_Color()); + if (isInSelectableSurface(mousePos)) { // Mouse hovering over us + DrawUtils::fillRectangle(surface, MC_Color(85, 85, 85), 1); + this->canClickB = true; + } else { + DrawUtils::fillRectangle(surface, MC_Color(12, 12, 12), 1); + this->canClickB = false; + } +} + +void ImmediateGui::onMouseClickUpdate(int key, bool isDown) { + switch (key) { + case 1: // Left Click + this->leftMb.nextIsDown = true; + break; + case 2: // Right Click + this->rightMb.nextIsDown = true; + break; + } +} + +void ImmediateGui::startFrame() { + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + vec2_t windowSizeReal = g_Data.getClientInstance()->getGuiData()->windowSizeReal; + this->mousePos = *g_Data.getClientInstance()->getMousePos(); + this->mousePos = this->mousePos.div(windowSizeReal); + this->mousePos = this->mousePos.mul(windowSize); + + this->leftMb.update(); + this->rightMb.update(); + + if (g_Data.getClientInstance()->getMouseGrabbed()) { + this->leftMb.isClicked = false; + this->rightMb.isClicked = false; + + this->mousePos = {-1000, 1000}; + } +} + +void ImmediateGui::endFrame() { + this->leftMb.isClicked = false; + this->rightMb.isClicked = false; +} + +bool ImmediateGui::Button(const char* label, vec2_t pos, bool centered) { + auto id = Utils::getCrcHash(label); + if (this->components.find(id) == this->components.end()) { // Create new button + this->components[id] = std::make_shared(id, pos, centered); + } + auto comp = this->components[id]; + auto button = dynamic_cast(comp.get()); + + button->updatePos(pos); + button->draw(this->mousePos, label); + if (button->canClick() && this->leftMb.trySteal()) { // Click + return true; + } + + return false; +} diff --git a/Horion/ImmediateGui.h b/Horion/ImmediateGui.h new file mode 100644 index 0000000..7535c9c --- /dev/null +++ b/Horion/ImmediateGui.h @@ -0,0 +1,74 @@ +#pragma once + +#include + +#include "../Utils/HMath.h" +#include "../Utils/Utils.h" +#include "DrawUtils.h" + +class ComponentInfo { +public: + ComponentInfo(int id); + virtual ~ComponentInfo(){}; + +protected: + unsigned int id; +}; + +class ButtonInfo : public ComponentInfo { +private: + vec2_t pos; + vec2_t size; + bool centered; + float padding = 3.f; + bool canClickB = false; + +public: + ButtonInfo(int id, vec2_t pos, bool centered = false); + virtual ~ButtonInfo(){}; + + void calculateSize(const char*); + bool isInSelectableSurface(vec2_t mouse); + vec4_t getSelectableSurface(); + void draw(vec2_t mousePos, const char* label); + bool canClick() { return canClickB; }; + void updatePos(vec2_t pos) { this->pos = pos; } + +}; + + +struct KeyInfo { + bool isDown; // Held down right now + bool isClicked; // Did it go down this frame + bool nextIsDown; + + void update() { + if (!isDown && nextIsDown) + isClicked = true; + isDown = nextIsDown; + } + + bool trySteal() { + if (isClicked) { + isClicked = false; + return true; + } + return false; + } +}; + +class ImmediateGui { +private: + vec2_t mousePos; + KeyInfo leftMb; + KeyInfo rightMb; + std::map> components; + +public: + void onMouseClickUpdate(int key, bool isDown); + void startFrame(); + void endFrame(); + bool Button(const char* label, vec2_t pos, bool centered = false); +}; + +extern ImmediateGui HImGui; \ No newline at end of file diff --git a/Horion/Loader.cpp b/Horion/Loader.cpp new file mode 100644 index 0000000..f913646 --- /dev/null +++ b/Horion/Loader.cpp @@ -0,0 +1,407 @@ +#include "Loader.h" + +SlimUtils::SlimMem mem; +const SlimUtils::SlimModule* gameModule; +bool isRunning = true; + +#if defined _M_X64 +#pragma comment(lib, "MinHook.x64.lib") +#elif defined _M_IX86 +#pragma comment(lib, "MinHook.x86.lib") +#endif + +DWORD WINAPI keyThread(LPVOID lpParam) { + logF("Key thread started"); + + bool* keyMap = static_cast(malloc(0xFF * 4 + 0x4)); + if (keyMap == nullptr) + throw std::exception("Keymap not allocated"); + + auto clickMap = reinterpret_cast(malloc(5)); + if (clickMap == 0) + throw std::exception("Clickmap not allocated"); + + bool* keyMapAddr = nullptr; + uintptr_t sigOffset = FindSignature("48 8D 0D ?? ?? ?? ?? 89 1C B9"); + if (sigOffset != 0x0) { + int offset = *reinterpret_cast((sigOffset + 3)); // Get Offset from code + keyMapAddr = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); // Offset is relative + } else { + logF("!!!KeyMap not located!!!"); + throw std::exception("Keymap not located"); + } + + C_HIDController** hidController = g_Data.getHIDController(); + + while (isRunning) { + if ((GameData::isKeyDown('L') && GameData::isKeyDown(VK_CONTROL)) || GameData::shouldTerminate()) { // Press L to uninject + isRunning = false; + break; + } + + for (uintptr_t i = 0; i < 0xFF; i++) { + bool* newKey = keyMapAddr + (4 * i); + bool newKeyPressed = (*newKey) && GameData::canUseMoveKeys(); // Disable Keybinds when in chat or inventory + bool* oldKey = keyMap + (4 * i); + if (newKeyPressed != *oldKey) { + moduleMgr->onKeyUpdate((int)i, newKeyPressed); + } + if (*newKey != *oldKey) { // Skip Chat or inventory checks + TabGui::onKeyUpdate((int)i, *newKey); + ClickGui::onKeyUpdate((int)i, *newKey); + } + } + + memcpy_s(keyMap, 0xFF * 4, keyMapAddr, 0xFF * 4); + + Sleep(2); + } + logF("Stopping Threads..."); + GameData::terminate(); + Sleep(200); // Give the threads a bit of time to exit + + FreeLibraryAndExitThread(static_cast(lpParam), 1); // Uninject +} + +DWORD WINAPI injectorConnectionThread(LPVOID lpParam) { + logF("Injector Connection Thread started"); + + struct MemoryBoi { + short protocolVersion; + bool isPresent; + bool isUnread; + int clientVersion; + DATAPACKET_CMD cmd; + int params[5]; + int dataSize; + unsigned char data[3000]; + unsigned char zeroByte = 0; + }; + + unsigned char magicValues[16] = {0x00, 0x4F, 0x52, 0x00, 0x49, 0x4F, 0x4E, 0x23, 0x9C, 0x47, 0xFB, 0xFF, 0x7D, 0x9C, 0x42, 0x57}; + char* magicArray = new char[sizeof(magicValues) + sizeof(uintptr_t) * 2]; + memcpy(magicArray, magicValues, sizeof(magicValues)); + + logF("Magic array at %llX", magicArray); + + auto** horionToInjectorPtr = reinterpret_cast(magicArray + sizeof(magicValues)); + auto** injectorToHorionPtr = reinterpret_cast(magicArray + sizeof(magicValues) + sizeof(uintptr_t)); + + *horionToInjectorPtr = new MemoryBoi(); + MemoryBoi* horionToInjector = *horionToInjectorPtr; + horionToInjector->isPresent = true; + horionToInjector->protocolVersion = 1; + + *injectorToHorionPtr = new MemoryBoi(); + MemoryBoi* injectorToHorion = *injectorToHorionPtr; + + magicArray[0] = 0x48; //Only find this allocated one, not the one in the thread stack + + logF("horionToInjectorPtr at %llX", horionToInjector); + logF("injectorToHorionPtr at %llX", injectorToHorion); + + LARGE_INTEGER frequency, timeSinceLastMessage, timeSinceLastPing; + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&timeSinceLastMessage); + QueryPerformanceCounter(&timeSinceLastPing); + + bool loggedIn = false; + + while (isRunning) { + Sleep(2); + LARGE_INTEGER endTime; + QueryPerformanceCounter(&endTime); + bool isConnected = horionToInjector->isPresent && injectorToHorion->isPresent && horionToInjector->protocolVersion >= injectorToHorion->protocolVersion; + + if (isConnected && !injectorToHorion->isUnread) { + __int64 elapsed = endTime.QuadPart - timeSinceLastMessage.QuadPart; + float realElapsed = (float)elapsed / frequency.QuadPart; + if (realElapsed > 4.f) { + isConnected = false; + logF("Disconnected from injector due to timeout"); + injectorToHorion->isPresent = false; + QueryPerformanceCounter(&timeSinceLastMessage); + } + } + g_Data.setInjectorConnectionActive(isConnected); + + if (isConnected) { + // Send Ping every 2 seconds to keep connection alive + { + __int64 elapsedPing = endTime.QuadPart - timeSinceLastPing.QuadPart; + float realPing = (float)elapsedPing / frequency.QuadPart; + if (realPing > 1) { + HorionDataPacket pingPacket; + pingPacket.cmd = CMD_PING; + pingPacket.params[0] = 0x1333337; + g_Data.sendPacketToInjector(pingPacket); + QueryPerformanceCounter(&timeSinceLastPing); + } + } + + if (injectorToHorion->isUnread) { // They sent us a message + QueryPerformanceCounter(&timeSinceLastMessage); + switch (injectorToHorion->cmd) { + case CMD_INIT: { + logF("Got CMD_INIT from injector"); + loggedIn = true; + int flags = injectorToHorion->params[0]; + if (flags & (1 << 0) && injectorToHorion->dataSize > 0 && injectorToHorion->dataSize < sizeof(injectorToHorion->data)) { // Has Json data + injectorToHorion->data[sizeof(injectorToHorion->data) - 1] = '\0'; + json data = json::parse(reinterpret_cast(injectorToHorion->data)); + if (data.at("discordAuth").is_string() && data.at("serial").is_number_integer()) { + logF("Got api token from injector"); + auto serialNum = data.at("serial").get(); + if (serialNum == 0) { + logF("Serial is null!"); + GameData::terminate(); + } + + auto roamingFolder = Logger::GetRoamingFolderPath(); + if (roamingFolder.substr(0, 2) == L"C:") { // Make sure we're getting a handle to the C volume + + HANDLE file = CreateFileW(roamingFolder.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, 0); + if (file != INVALID_HANDLE_VALUE) { + unsigned long serial = 0; + unsigned long maxNameLen = 0, flags2 = 0; + bool succ = GetVolumeInformationByHandleW(file, 0, 0, &serial, &maxNameLen, &flags2, nullptr, 0); + if (succ) { + /*if (serial != serialNum) { // Dont print the raw values here, don't leak serials + logF("Serial doesn't match! (Diff: %lli)", (long long) serial - (long long)serialNum); + g_Data.terminate(); + } + serialNum = serial;*/ + } + CloseHandle(file); + } + } + g_Data.setAccountInformation(AccountInformation::fromToken(data.at("discordAuth").get(), serialNum)); + } + } + if (flags & (1 << 2)) // WIP Features + g_Data.setAllowWIPFeatures(true); + + break; + } + case CMD_PING: { + HorionDataPacket pongPacket; + pongPacket.cmd = CMD_PONG; + pongPacket.params[0] = injectorToHorion->params[0]; + g_Data.sendPacketToInjector(pongPacket); + break; + } + case CMD_PONG: { + break; + } + case CMD_RESPONSE: { + int id = injectorToHorion->params[1]; + + auto pk = std::make_shared(); + pk->cmd = (DATAPACKET_CMD)injectorToHorion->params[0]; + memcpy(pk->params, &injectorToHorion->params[2], sizeof(injectorToHorion->params) - sizeof(int) * 2); + + if (injectorToHorion->dataSize > 0 && injectorToHorion->dataSize < 3000) { + pk->dataArraySize = injectorToHorion->dataSize; + + auto dataTemp = new unsigned char[injectorToHorion->dataSize + 2]; + memset(dataTemp + injectorToHorion->dataSize, 0, 2); // If we don't zero the last 2 bytes, printing as unicode string won't work + memcpy(dataTemp, injectorToHorion->data, injectorToHorion->dataSize); + auto tmp = std::shared_ptr(dataTemp); + pk->data.swap(tmp); + } + + g_Data.callInjectorResponseCallback(id, pk); + break; + } + case CMD_LOG: { + if(injectorToHorion->dataSize > 4 && injectorToHorion->dataSize < 2999){ + injectorToHorion->data[injectorToHorion->dataSize] = 0; // null terminator + + char* command = reinterpret_cast(&injectorToHorion->data[3]); + if(command[1] == cmdMgr->prefix) + command++; + + cmdMgr->execute(command); + } + break; + } + default: + break; + } + + injectorToHorion->isUnread = false; + } + + // Send log messages + { + auto vecLock = Logger::GetTextToInjectorLock();; + + if (loggedIn && g_Data.isPacketToInjectorQueueEmpty()) { + auto* stringPrintVector = Logger::GetTextToSend(); +#if defined(_DEBUG) or defined(_BETA) + if (stringPrintVector->size() > 0 && g_Data.isPacketToInjectorQueueEmpty()) { + auto str = *stringPrintVector->begin(); + stringPrintVector->erase(stringPrintVector->begin()); + + auto wstr = Utils::stringToWstring(str->text); + + const wchar_t* ident = L"log "; + size_t identLength = wcslen(ident); + size_t textLength = wcslen(wstr.c_str()) + identLength; + + if(textLength < 2990){ + HorionDataPacket packet; + packet.cmd = CMD_LOG; + auto tmp = std::shared_ptr(new unsigned char[(textLength + 1) * sizeof(wchar_t)]); + packet.data.swap(tmp); + size_t leng = (textLength + 1) * sizeof(wchar_t); + wcscpy_s((wchar_t*)packet.data.get(), textLength, ident); + wcscpy_s((wchar_t*)(packet.data.get() + identLength * sizeof(wchar_t)), textLength - identLength + 1, wstr.c_str()); + packet.dataArraySize = (int)wcslen((wchar_t*)packet.data.get()) * sizeof(wchar_t); + + if(packet.dataArraySize < 2999) + g_Data.sendPacketToInjector(packet); + } + } +#else + stringPrintVector->clear(); +#endif + } + } + + if (!horionToInjector->isUnread && !g_Data.isPacketToInjectorQueueEmpty()) { + QueryPerformanceCounter(&timeSinceLastMessage); + // They read the message, lets send the next one + HorionDataPacket nextDataPack = g_Data.getPacketToInjector(); + if (nextDataPack.dataArraySize >= 3000) { + throw std::exception("Horion Data packet too big to send"); + } + + horionToInjector->cmd = nextDataPack.cmd; + memcpy(horionToInjector->params, nextDataPack.params, sizeof(int) * 5); + if (nextDataPack.dataArraySize > 0) { + memcpy(horionToInjector->data, nextDataPack.data.get(), nextDataPack.dataArraySize); + } + + horionToInjector->dataSize = nextDataPack.dataArraySize; + + horionToInjector->isUnread = true; + } + } else + Sleep(30); + } + logF("Quitting connection thread"); + horionToInjector->isPresent = false; + memset(magicValues, 0, sizeof(magicValues)); + memset(magicArray, 0, sizeof(magicValues) + sizeof(uintptr_t) * 2); + Sleep(150); + delete *horionToInjectorPtr; + delete *injectorToHorionPtr; + delete[] magicArray; + + ExitThread(0); +} + +#ifndef _MSC_VER +#define _MSC_VER "unk" +#endif + +DWORD WINAPI start(LPVOID lpParam) { + logF("Starting up..."); + logF("MSC v%i at %s", _MSC_VER, __TIMESTAMP__); + + DWORD conThread; + CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)injectorConnectionThread, lpParam, NULL, &conThread); + logF("InjCon: %i", conThread); + init(); + + DWORD procId = GetCurrentProcessId(); + if (!mem.Open(procId, SlimUtils::ProcessAccess::Full)) { + logF("Failed to open process, error-code: %i", GetLastError()); + return 1; + } + gameModule = mem.GetModule(L"Minecraft.Windows.exe"); // Get Module for Base Address + + MH_Initialize(); + GameData::initGameData(gameModule, &mem, (HMODULE)lpParam); + Target::init(g_Data.getPtrLocalPlayer()); + + Hooks::Init(); + + DWORD keyThreadId; + CreateThread(nullptr, NULL, (LPTHREAD_START_ROUTINE)keyThread, lpParam, NULL, &keyThreadId); // Checking Keypresses + logF("KeyT: %i", keyThreadId); + + /*logF("Waiting for injector"); + while (!g_Data.isInjectorConnectionActive()) { + Sleep(10); + if (!isRunning) + ExitThread(0); + } + logF("Injector found");*/ + + cmdMgr->initCommands(); + logF("Initialized command manager (1/3)"); + moduleMgr->initModules(); + logF("Initialized module manager (2/3)"); + configMgr->init(); + logF("Initialized config manager (3/3)"); + + Hooks::Enable(); + TabGui::init(); + ClickGui::init(); + + logF("Hooks enabled"); + + std::thread countThread([] { + while (isRunning) { + Sleep(1000); + g_Data.fps = g_Data.frameCount; + g_Data.frameCount = 0; + g_Data.cpsLeft = g_Data.leftclickCount; + g_Data.leftclickCount = 0; + g_Data.cpsRight = g_Data.rightclickCount; + g_Data.rightclickCount = 0; + } + }); + countThread.detach(); + + logF("Count thread started"); + + ExitThread(0); +} + +BOOL __stdcall DllMain(HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: { + CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)start, hModule, NULL, NULL); + DisableThreadLibraryCalls(hModule); + } break; + case DLL_PROCESS_DETACH: + isRunning = false; + + scriptMgr.unloadAllScripts(); + configMgr->saveConfig(); + moduleMgr->disable(); + cmdMgr->disable(); + Hooks::Restore(); + //GameWnd.OnDeactivated(); + + logF("Removing logger"); + Logger::Disable(); + + MH_Uninitialize(); + delete moduleMgr; + delete cmdMgr; + delete configMgr; + if (g_Data.getLocalPlayer() != nullptr) { + C_GuiData* guiData = g_Data.getClientInstance()->getGuiData(); + if (guiData != nullptr && !GameData::shouldHide()) + guiData->displayClientMessageF("%sEjected!", RED); + } + break; + } + return TRUE; +} diff --git a/Horion/Loader.h b/Horion/Loader.h new file mode 100644 index 0000000..5ba89ae --- /dev/null +++ b/Horion/Loader.h @@ -0,0 +1,33 @@ +#pragma once + +#include "../Utils/Logger.h" + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +#include +#include +#include + +#include "../Memory/GameData.h" +#include "../Memory/Hooks.h" +#include "../Memory/MinHook.h" +#include "../SDK/CChestBlockActor.h" +#include "../SDK/CClientInstance.h" +#include "../SDK/CClientInstanceScreenModel.h" +#include "../SDK/CEntity.h" +#include "../SDK/CGameMode.h" +#include "../SDK/CPacket.h" +#include "../Utils/HMath.h" +#include "../Utils/Target.h" +#include "../Utils/TextFormat.h" +#include "../Utils/Utils.h" +#include "../include/WinHttpClient.h" +#include "Command/CommandMgr.h" +#include "Config/ConfigManager.h" +#include "Menu/ClickGui.h" +#include "Menu/TabGui.h" +#include "Module/ModuleManager.h" +#include "ImmediateGui.h" diff --git a/Horion/Menu/ClickGui.cpp b/Horion/Menu/ClickGui.cpp new file mode 100644 index 0000000..0b6ff98 --- /dev/null +++ b/Horion/Menu/ClickGui.cpp @@ -0,0 +1,917 @@ +#include "ClickGui.h" + +#include "../Scripting/ScriptManager.h" +#include "../../Utils/Logger.h" +#include + +#include "../../Utils/Json.hpp" + +bool isLeftClickDown = false; +bool isRightClickDown = false; +bool shouldToggleLeftClick = false; // If true, toggle the focused module +bool shouldToggleRightClick = false; +bool resetStartPos = true; +bool initialised = false; +int scrollingDirection = 0; + +struct SavedWindowSettings { + vec2_t pos = {-1, -1}; + bool isExtended = true; + const char* name = ""; +}; + +std::map> windowMap; +std::map savedWindowSettings; + +bool isDragging = false; +unsigned int draggedWindow = -1; +vec2_t dragStart = vec2_t(); + +unsigned int focusedElement = -1; +bool isFocused = false; + +static constexpr float textPaddingX = 2.0f; +static constexpr float textPaddingY = 1.0f; +static constexpr float textSize = 1.0f; +static constexpr float textHeight = textSize * 10.0f; +static constexpr float categoryMargin = 0.5f; +static constexpr float paddingRight = 13.5f; +static constexpr float crossSize = textHeight / 2.f; +static constexpr float crossWidth = 0.2f; +static constexpr float backgroundAlpha = 1; + +static const MC_Color whiteColor = MC_Color(1.f, 1.f, 1.f, 1.f); +static const MC_Color moduleColor = MC_Color(0x12, 0x12, 0x12); // background +static const MC_Color selectedModuleColor = moduleColor.lerp(whiteColor, 0.08f); // 30, 110, 200 +static const MC_Color enabledModuleColor = moduleColor.lerp(whiteColor, 0.04f); +static const MC_Color brightModuleBlendColor = moduleColor.lerp(whiteColor, 0.2f); // tooltip border & category divider +static const MC_Color selectedSettingColor1 = MC_Color(85, 85, 85); +static const MC_Color selectedSettingColor2 = MC_Color(85, 85, 85); +static const MC_Color SettingColor1 = MC_Color(12, 12, 12); +static const MC_Color SettingColor2 = MC_Color(12, 12, 12); + +float currentYOffset = 0; +float currentXOffset = 0; + +int timesRendered = 0; + +void ClickGui::getModuleListByCategory(Category category, std::vector>* modList) { + auto lock = moduleMgr->lockModuleList(); + std::vector>* moduleList = moduleMgr->getModuleList(); + + for (auto& it : *moduleList) { + if (it->getCategory() == category) + modList->push_back(it); + } +} + +std::shared_ptr ClickGui::getWindow(const char* name) { + unsigned int id = Utils::getCrcHash(name); + + auto search = windowMap.find(id); + if (search != windowMap.end()) { // Window exists already + return search->second; + } else { // Create window + // TODO: restore settings for position etc + std::shared_ptr newWindow = std::make_shared(); + newWindow->name = name; + + auto savedSearch = savedWindowSettings.find(id); + if(savedSearch != savedWindowSettings.end()){ // Use values from config + newWindow->isExtended = savedSearch->second.isExtended; + if(savedSearch->second.pos.x > 0) + newWindow->pos = savedSearch->second.pos; + } + + windowMap.insert(std::make_pair(id, newWindow)); + return newWindow; + } +} + +std::shared_ptr ClickGui::getClickModule(std::shared_ptr window, const char* name) { + unsigned int id = Utils::getCrcHash(name); + + auto search = window->moduleMap.find(id); + if (search != window->moduleMap.end()) { // Window exists already + return search->second; + } else { // Create window + // TODO: restore settings for position etc + std::shared_ptr newModule = std::make_shared(); + + window->moduleMap.insert(std::make_pair(id, newModule)); + return newModule; + } +} + +void ClickGui::renderLabel(const char* text) { +} + +void ClickGui::renderTooltip(std::string* text) { + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + vec2_t currentTooltipPos = vec2_t(5.f, windowSize.y - 15.f); + float textWidth = DrawUtils::getTextWidth(text, textSize); + vec2_t textPos = vec2_t( + currentTooltipPos.x + textPaddingX, + currentTooltipPos.y); + vec4_t rectPos = vec4_t( + currentTooltipPos.x - 2.f, + currentTooltipPos.y - 2.f, + currentTooltipPos.x + (textPaddingX * 2) + textWidth + 2.f, + currentTooltipPos.y + textHeight + 2.f); + DrawUtils::fillRectangle(rectPos, moduleColor, 1.0f); + DrawUtils::drawRectangle(rectPos, brightModuleBlendColor, 1.f, 0.5f); + DrawUtils::drawText(textPos, text, whiteColor, textSize); +} + +void ClickGui::renderCategory(Category category) { + const char* categoryName = ClickGui::catToName(category); + + const std::shared_ptr ourWindow = getWindow(categoryName); + + // Reset Windows to pre-set positions to avoid confusion + if (resetStartPos && ourWindow->pos.x <= 0) { + float yot = g_Data.getGuiData()->windowSize.x; + ourWindow->pos.y = 4; + switch (category) { + case Category::COMBAT: + ourWindow->pos.x = 10.f; + break; + case Category::VISUAL: + ourWindow->pos.x = yot / 7.f; + break; + case Category::MOVEMENT: + ourWindow->pos.x = yot / 7.f * 2.f; + break; + case Category::PLAYER: + ourWindow->pos.x = yot / 7.f * 3.f; + break; + case Category::WORLD: + ourWindow->pos.x = yot / 7.f * 4.f; + break; + case Category::MISC: + ourWindow->pos.x = yot / 7.f * 5.f; + break; + case Category::CUSTOM: + ourWindow->pos.x = yot / 7.f * 6.f; + break; + } + } + + const float xOffset = ourWindow->pos.x; + const float yOffset = ourWindow->pos.y; + vec2_t* windowSize = &ourWindow->size; + currentXOffset = xOffset; + currentYOffset = yOffset; + + // Get All Modules in our category + std::vector> moduleList; + getModuleListByCategory(category, &moduleList); + + // Get max width of all text + { + for (auto& it : moduleList) { + std::string label = it->getModuleName(); + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&label, textSize, Fonts::SMOOTH)); + } + } + + const float xEnd = currentXOffset + windowSize->x + paddingRight; + + vec2_t mousePos = *g_Data.getClientInstance()->getMousePos(); + + // Convert mousePos to visual Pos + { + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + vec2_t windowSizeReal = g_Data.getClientInstance()->getGuiData()->windowSizeReal; + + mousePos = mousePos.div(windowSizeReal); + mousePos = mousePos.mul(windowSize); + } + + float categoryHeaderYOffset = currentYOffset; + + if (ourWindow->isInAnimation) { + if (ourWindow->isExtended) { + ourWindow->animation *= 0.85f; + if (ourWindow->animation < 0.001f) { + ourWindow->yOffset = 0; // reset scroll + ourWindow->isInAnimation = false; + } + + } else { + ourWindow->animation = 1 - ((1 - ourWindow->animation) * 0.85f); + if (1 - ourWindow->animation < 0.001f) + ourWindow->isInAnimation = false; + } + } + + currentYOffset += textHeight + (textPaddingY * 2); + // Loop through Modules to display em + if (ourWindow->isExtended || ourWindow->isInAnimation) { + if (ourWindow->isInAnimation) { + currentYOffset -= ourWindow->animation * moduleList.size() * (textHeight + (textPaddingY * 2)); + } + + bool overflowing = false; + const float cutoffHeight = roundf(g_Data.getGuiData()->heightGame * 0.75f) + 0.5f /*fix flickering related to rounding errors*/; + int moduleIndex = 0; + for (auto& mod : moduleList) { + moduleIndex++; + if (moduleIndex < ourWindow->yOffset) + continue; + float probableYOffset = (moduleIndex - ourWindow->yOffset) * (textHeight + (textPaddingY * 2)); + + if (ourWindow->isInAnimation) { // Estimate, we don't know about module settings yet + if (probableYOffset > cutoffHeight) { + overflowing = true; + break; + } + }else if ((currentYOffset - ourWindow->pos.y) > cutoffHeight || currentYOffset > g_Data.getGuiData()->heightGame - 5) { + overflowing = true; + break; + } + + std::string textStr = mod->getModuleName(); + + vec2_t textPos = vec2_t( + currentXOffset + textPaddingX, + currentYOffset + textPaddingY); + vec4_t rectPos = vec4_t( + currentXOffset, + currentYOffset, + xEnd, + currentYOffset + textHeight + (textPaddingY * 2)); + + bool allowRender = currentYOffset >= categoryHeaderYOffset; + + // Background + if (allowRender) { + if (!ourWindow->isInAnimation && !isDragging && rectPos.contains(&mousePos)) { // Is the Mouse hovering above us? + DrawUtils::fillRectangle(rectPos, selectedModuleColor, backgroundAlpha); + std::string tooltip = mod->getTooltip(); + static auto clickGuiMod = moduleMgr->getModule(); + if (clickGuiMod->showTooltips && !tooltip.empty()) + renderTooltip(&tooltip); + if (shouldToggleLeftClick && !ourWindow->isInAnimation) { // Are we being clicked? + mod->toggle(); + shouldToggleLeftClick = false; + } + } else { + DrawUtils::fillRectangle(rectPos, mod->isEnabled() ? enabledModuleColor : moduleColor, backgroundAlpha); + } + } + + // Text + if (allowRender) + DrawUtils::drawText(textPos, &textStr, mod->isEnabled() ? whiteColor : MC_Color(200, 200, 200), textSize); + + // Settings + { + std::vector* settings = mod->getSettings(); + if (settings->size() > 2 && allowRender) { + std::shared_ptr clickMod = getClickModule(ourWindow, mod->getRawModuleName()); + if (rectPos.contains(&mousePos) && shouldToggleRightClick && !ourWindow->isInAnimation) { + shouldToggleRightClick = false; + clickMod->isExtended = !clickMod->isExtended; + } + + GuiUtils::drawCrossLine(vec2_t( + currentXOffset + windowSize->x + paddingRight - (crossSize / 2) - 1.f, + currentYOffset + textPaddingY + (textHeight / 2)), + whiteColor, crossWidth, crossSize, !clickMod->isExtended); + + currentYOffset += textHeight + (textPaddingY * 2); + + if (clickMod->isExtended) { + float startYOffset = currentYOffset; + for (auto setting : *settings) { + if (strcmp(setting->name, "enabled") == 0 || strcmp(setting->name, "keybind") == 0) + continue; + + vec2_t textPos = vec2_t( + currentXOffset + textPaddingX + 5, + currentYOffset + textPaddingY); + + // Incomplete, because we dont know the endY yet + vec4_t rectPos = vec4_t( + currentXOffset, + currentYOffset, + xEnd, + 0); + + if ((currentYOffset - ourWindow->pos.y) > cutoffHeight) { + overflowing = true; + break; + } + + switch (setting->valueType) { + case ValueType::BOOL_T: { + rectPos.w = currentYOffset + textHeight + (textPaddingY * 2); + // Background of bool setting + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); + vec4_t selectableSurface = vec4_t( + textPos.x + textPaddingX, + textPos.y + textPaddingY, + xEnd - textPaddingX, + textPos.y + textHeight - textPaddingY); + + bool isFocused = selectableSurface.contains(&mousePos); + // Logic + { + if (isFocused && shouldToggleLeftClick && !ourWindow->isInAnimation) { + shouldToggleLeftClick = false; + setting->value->_bool = !setting->value->_bool; + } + } + // Checkbox + { + float boxHeight = textHeight - textPaddingY * 2; + vec4_t boxPos = vec4_t( + textPos.x + textPaddingX, + textPos.y + textPaddingY, + textPos.x + textPaddingX + boxHeight, + textPos.y + textPaddingY + boxHeight); + + DrawUtils::drawRectangle(boxPos, whiteColor, isFocused ? 1 : 0.8f, 0.5f); + + if (setting->value->_bool) { + DrawUtils::setColor(85, 85, 85, 1); + boxPos.x += 1; + boxPos.y += 1; + boxPos.z -= 1; + boxPos.w -= 1; + DrawUtils::drawLine(vec2_t(boxPos.x, boxPos.y), vec2_t(boxPos.z, boxPos.w), 0.5f); + DrawUtils::drawLine(vec2_t(boxPos.z, boxPos.y), vec2_t(boxPos.x, boxPos.w), 0.5f); + } + } + textPos.x += textHeight + (textPaddingX * 2); + // Text + { + // Convert first letter to uppercase for more friendlieness + char name[0x21]; + sprintf_s(name, 0x21, "%s", setting->name); + if (name[0] != 0) + name[0] = toupper(name[0]); + + std::string elTexto = name; + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&elTexto, textSize) + 10 /* because we add 10 to text padding + checkbox*/); + DrawUtils::drawText(textPos, &elTexto, isFocused ? whiteColor : MC_Color(0.8f, 0.8f, 0.8f), textSize); + currentYOffset += textHeight + (textPaddingY * 2); + } + break; + } + case ValueType::ENUM_T: { + // Text and background + { + char name[0x22]; + sprintf_s(name, "%s:", setting->name); + // Convert first letter to uppercase for more friendlieness + if (name[0] != 0) + name[0] = toupper(name[0]); + + std::string elTexto = name; + rectPos.w = currentYOffset + textHeight + (textPaddingY * 2); + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&elTexto, textSize) + 5 /* because we add 5 to text padding*/ + crossSize); + // Background of enum setting + + if (rectPos.contains(&mousePos)) { + DrawUtils::fillRectangle(rectPos, selectedModuleColor, backgroundAlpha); + if (shouldToggleRightClick && !ourWindow->isInAnimation) { + shouldToggleRightClick = false; + setting->minValue->_bool = !setting->minValue->_bool; + } + }else + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); + + DrawUtils::drawText(textPos, &elTexto, whiteColor, textSize); + GuiUtils::drawCrossLine(vec2_t( + currentXOffset + windowSize->x + paddingRight - (crossSize / 2) - 1.f, + currentYOffset + textPaddingY + (textHeight / 2)), + whiteColor, crossWidth, crossSize, !setting->minValue->_bool); + + currentYOffset += textHeight + (textPaddingY * 2); + } + if (setting->minValue->_bool) { + int e = 0; + auto enumData = reinterpret_cast(setting->extraData); + for (auto it = enumData->Entrys.begin(); + it != enumData->Entrys.end(); it++, e++) { + if ((currentYOffset - ourWindow->pos.y) > cutoffHeight) { + overflowing = true; + break; + } + bool isEven = e % 2 == 0; + rectPos.y = currentYOffset; + rectPos.w = currentYOffset + textHeight + (textPaddingY * 2); + EnumEntry i = *it._Ptr; + char name[0x21]; + sprintf_s(name, 0x21, " %s", i.GetName().c_str()); + // Convert first letter to uppercase for more friendlieness + if (name[0] != 0) + name[0] = toupper(name[0]); + std::string elTexto = name; + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth( + &elTexto, textSize) + + 5); //because we add 5 to text padding + textPos.y = currentYOffset + textPaddingY; + vec4_t selectableSurface = vec4_t( + textPos.x, + rectPos.y, + xEnd, + rectPos.w); + MC_Color col; + if (setting->value->_int == e || (selectableSurface.contains(&mousePos) && !ourWindow->isInAnimation)) { + if (isEven) + col = selectedSettingColor1; + else + col = selectedSettingColor2; + } else { + if (isEven) + col = SettingColor1; + else + col = SettingColor2; + } + // Background of individual enum + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); + DrawUtils::fillRectangle(selectableSurface, col, backgroundAlpha); + DrawUtils::drawText(textPos, &elTexto, whiteColor); + // logic + if (selectableSurface.contains(&mousePos) && + shouldToggleLeftClick && !ourWindow->isInAnimation) { + shouldToggleLeftClick = false; + setting->value->_int = e; + } + currentYOffset += textHeight + (textPaddingY * 2); + } + } + break; + } + case ValueType::FLOAT_T: { + // Text and background + { + // Convert first letter to uppercase for more friendlieness + char name[0x22]; + sprintf_s(name, "%s:", setting->name); + if (name[0] != 0) + name[0] = toupper(name[0]); + + std::string elTexto = name; + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&elTexto, textSize) + 5 /* because we add 5 to text padding*/); + DrawUtils::drawText(textPos, &elTexto, whiteColor, textSize); + currentYOffset += textPaddingY + textHeight; + rectPos.w = currentYOffset; + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); + } + + if ((currentYOffset - ourWindow->pos.y) > cutoffHeight) { + overflowing = true; + break; + } + // Slider + { + vec4_t rect = vec4_t( + currentXOffset + textPaddingX + 5, + currentYOffset + textPaddingY, + xEnd - textPaddingX, + currentYOffset - textPaddingY + textHeight); + + // Visuals & Logic + { + rectPos.y = currentYOffset; + rectPos.w += textHeight + (textPaddingY * 2); + // Background + const bool areWeFocused = rect.contains(&mousePos); + + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); // Background + DrawUtils::drawRectangle(rect, whiteColor, 1.f, backgroundAlpha); // Slider background + + const float minValue = setting->minValue->_float; + const float maxValue = setting->maxValue->_float - minValue; + float value = (float) fmax(0, setting->value->_float - minValue); // Value is now always > 0 && < maxValue + if (value > maxValue) + value = maxValue; + value /= maxValue; // Value is now in range 0 - 1 + const float endXlol = (xEnd - textPaddingX) - (currentXOffset + textPaddingX + 5); + value *= endXlol; // Value is now pixel diff between start of bar and end of progress + + // Draw Int + { + vec2_t mid = vec2_t( + rect.x + ((rect.z - rect.x) / 2), + rect.y - 0.2f + ); + char str[10]; + sprintf_s(str, 10, "%.2f", setting->value->_float); + std::string text = str; + mid.x -= DrawUtils::getTextWidth(&text, textSize) / 2; + + DrawUtils::drawText(mid, &text, whiteColor, textSize); + } + + // Draw Progress + { + rect.z = rect.x + value; + DrawUtils::fillRectangle(rect, MC_Color(85, 85, 85), (areWeFocused || setting->isDragging) ? 1.f : 0.8f); + } + + // Drag Logic + { + if (setting->isDragging) { + if (isLeftClickDown && !isRightClickDown) + value = mousePos.x - rect.x; + else + setting->isDragging = false; + } else if (areWeFocused && shouldToggleLeftClick && !ourWindow->isInAnimation) { + shouldToggleLeftClick = false; + setting->isDragging = true; + } + } + + // Save Value + { + value /= endXlol; // Now in range 0 - 1 + value *= maxValue; + value += minValue; + + setting->value->_float = value; + setting->makeSureTheValueIsAGoodBoiAndTheUserHasntScrewedWithIt(); + } + } + currentYOffset += textHeight + (textPaddingY * 2); + } + } break; + case ValueType::INT_T: { + + + // Text and background + { + // Convert first letter to uppercase for more friendlieness + char name[0x22]; + sprintf_s(name, "%s:", setting->name); + if (name[0] != 0) + name[0] = toupper(name[0]); + + std::string elTexto = name; + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&elTexto, textSize) + 5 /* because we add 5 to text padding*/); + DrawUtils::drawText(textPos, &elTexto, whiteColor, textSize); + currentYOffset += textPaddingY + textHeight; + rectPos.w = currentYOffset; + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); + } + if ((currentYOffset - ourWindow->pos.y) > (g_Data.getGuiData()->heightGame * 0.75)) { + overflowing = true; + break; + } + // Slider + { + vec4_t rect = vec4_t( + currentXOffset + textPaddingX + 5, + currentYOffset + textPaddingY, + xEnd - textPaddingX, + currentYOffset - textPaddingY + textHeight); + + // Visuals & Logic + { + rectPos.y = currentYOffset; + rectPos.w += textHeight + (textPaddingY * 2); + // Background + const bool areWeFocused = rect.contains(&mousePos); + + DrawUtils::fillRectangle(rectPos, moduleColor, backgroundAlpha); // Background + DrawUtils::drawRectangle(rect, whiteColor, 1.f, backgroundAlpha); // Slider background + + const float minValue = (float)setting->minValue->_int; + const float maxValue = (float)setting->maxValue->_int - minValue; + float value = (float)fmax(0, setting->value->_int - minValue); // Value is now always > 0 && < maxValue + if (value > maxValue) + value = maxValue; + value /= maxValue; // Value is now in range 0 - 1 + const float endXlol = (xEnd - textPaddingX) - (currentXOffset + textPaddingX + 5); + value *= endXlol; // Value is now pixel diff between start of bar and end of progress + + // Draw Int + { + vec2_t mid = vec2_t( + rect.x + ((rect.z - rect.x) / 2), + rect.y - 0.2f // Hardcoded ghetto + ); + char str[10]; + sprintf_s(str, 10, "%i", setting->value->_int); + std::string text = str; + mid.x -= DrawUtils::getTextWidth(&text, textSize) / 2; + + DrawUtils::drawText(mid, &text, whiteColor, textSize); + } + + // Draw Progress + { + rect.z = rect.x + value; + DrawUtils::fillRectangle(rect, MC_Color(85, 85, 85), (areWeFocused || setting->isDragging) ? 1.f : 0.8f); + } + + // Drag Logic + { + if (setting->isDragging) { + if (isLeftClickDown && !isRightClickDown) + value = mousePos.x - rect.x; + else + setting->isDragging = false; + } else if (areWeFocused && shouldToggleLeftClick && !ourWindow->isInAnimation) { + shouldToggleLeftClick = false; + setting->isDragging = true; + } + } + + // Save Value + { + value /= endXlol; // Now in range 0 - 1 + value *= maxValue; + value += minValue; + + setting->value->_int = (int)roundf(value); + setting->makeSureTheValueIsAGoodBoiAndTheUserHasntScrewedWithIt(); + } + } + currentYOffset += textHeight + (textPaddingY * 2); + } + } break; + default: { + char alc[100]; + sprintf_s(alc, 100, "Not implemented (%s)", setting->name); + std::string elTexto = alc; + // Adjust window size if our text is too t h i c c + windowSize->x = fmax(windowSize->x, DrawUtils::getTextWidth(&elTexto, textSize) + 5 /* because we add 5 to text padding*/); + + DrawUtils::drawText(textPos, &elTexto, whiteColor, textSize); + currentYOffset += textHeight + (textPaddingY * 2); + } break; + } + } + float endYOffset = currentYOffset; + if (endYOffset - startYOffset > textHeight + 1 || overflowing) { + startYOffset += textPaddingY; + endYOffset -= textPaddingY; + DrawUtils::setColor(1, 1, 1, 1); + DrawUtils::drawLine(vec2_t(currentXOffset + 2, startYOffset), vec2_t(currentXOffset + 2, endYOffset), 0.5f); + } + } + } else + currentYOffset += textHeight + (textPaddingY * 2); + } + } + + vec4_t winRectPos = vec4_t( + xOffset, + yOffset, + xEnd, + currentYOffset); + + if (winRectPos.contains(&mousePos)) { + if (scrollingDirection > 0 && overflowing) { + ourWindow->yOffset += scrollingDirection; + } else if (scrollingDirection < 0) { + ourWindow->yOffset += scrollingDirection; + } + scrollingDirection = 0; + if (ourWindow->yOffset < 0) { + ourWindow->yOffset = 0; + } + } + } + DrawUtils::flush(); + // Draw Category Header + { + vec2_t textPos = vec2_t( + currentXOffset + textPaddingX, + categoryHeaderYOffset + textPaddingY); + vec4_t rectPos = vec4_t( + currentXOffset - categoryMargin, + categoryHeaderYOffset - categoryMargin, + currentXOffset + windowSize->x + paddingRight + categoryMargin, + categoryHeaderYOffset + textHeight + (textPaddingY * 2)); + + // Extend Logic + { + if (rectPos.contains(&mousePos) && shouldToggleRightClick && !isDragging) { + shouldToggleRightClick = false; + ourWindow->isExtended = !ourWindow->isExtended; + if (ourWindow->isExtended && ourWindow->animation == 0) + ourWindow->animation = 0.2f; + else if (!ourWindow->isExtended && ourWindow->animation == 1) + ourWindow->animation = 0; + ourWindow->isInAnimation = true; + + for (auto& mod : moduleList) { + std::shared_ptr clickMod = getClickModule(ourWindow, mod->getRawModuleName()); + clickMod->isExtended = false; + } + } + } + + // Dragging Logic + { + if (isDragging && Utils::getCrcHash(categoryName) == draggedWindow) { // WE are being dragged + if (isLeftClickDown) { // Still dragging + vec2_t diff = vec2_t(mousePos).sub(dragStart); + ourWindow->pos = ourWindow->pos.add(diff); + dragStart = mousePos; + } else { // Stopped dragging + isDragging = false; + } + } else if (rectPos.contains(&mousePos) && shouldToggleLeftClick) { + isDragging = true; + draggedWindow = Utils::getCrcHash(categoryName); + shouldToggleLeftClick = false; + dragStart = mousePos; + } + } + + // Draw category component + { + // Draw Text + std::string textStr = categoryName; + DrawUtils::drawText(textPos, &textStr, whiteColor, textSize); + DrawUtils::fillRectangle(rectPos, moduleColor, 1.f); + + DrawUtils::fillRectangle(vec4_t(rectPos.x, rectPos.w - 1, rectPos.z, rectPos.w), brightModuleBlendColor, 1 - ourWindow->animation); + // Draw Dash + GuiUtils::drawCrossLine(vec2_t( + currentXOffset + windowSize->x + paddingRight - (crossSize / 2) - 1.f, + categoryHeaderYOffset + textPaddingY + (textHeight / 2)), + whiteColor, crossWidth, crossSize, !ourWindow->isExtended); + } + } + + // anti idiot + { + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + + if (ourWindow->pos.x + ourWindow->size.x > windowSize.x) { + ourWindow->pos.x = windowSize.x - ourWindow->size.x; + } + + if (ourWindow->pos.y + ourWindow->size.y > windowSize.y) { + ourWindow->pos.y = windowSize.y - ourWindow->size.y; + } + + ourWindow->pos.x = (float)fmax(0, ourWindow->pos.x); + ourWindow->pos.y = (float)fmax(0, ourWindow->pos.y); + } + + moduleList.clear(); + DrawUtils::flush(); +} + +void ClickGui::render() { + if (!moduleMgr->isInitialized()) + return; + + if (timesRendered < 10) + timesRendered++; + + // Fill Background + { + DrawUtils::fillRectangle(vec4_t( + 0, + 0, + g_Data.getClientInstance()->getGuiData()->widthGame, + g_Data.getClientInstance()->getGuiData()->heightGame), + MC_Color(12, 12, 12), 0.2f); + } + + // Render all categorys + renderCategory(Category::COMBAT); + renderCategory(Category::VISUAL); + renderCategory(Category::MOVEMENT); + renderCategory(Category::PLAYER); + renderCategory(Category::WORLD); + renderCategory(Category::MISC); + + if (scriptMgr.getNumEnabledScripts() > 0) + renderCategory(Category::CUSTOM); + + shouldToggleLeftClick = false; + shouldToggleRightClick = false; + resetStartPos = false; + + DrawUtils::flush(); +} + +void ClickGui::init() { initialised = true; } + +void ClickGui::onMouseClickUpdate(int key, bool isDown) { + static auto clickGuiMod = moduleMgr->getModule(); + if (clickGuiMod->isEnabled() && g_Data.isInGame()) + switch (key) { + case 1: // Left Click + isLeftClickDown = isDown; + if (isDown) + shouldToggleLeftClick = true; + break; + case 2: // Right Click + isRightClickDown = isDown; + if (isDown) + shouldToggleRightClick = true; + break; + } +} + +void ClickGui::onWheelScroll(bool direction) { + if (!direction) + scrollingDirection++; + else + scrollingDirection--; +} + +void ClickGui::onKeyUpdate(int key, bool isDown) { + if (!initialised) + return; + static auto clickGuiMod = moduleMgr->getModule(); + + if (!isDown) + return; + + if (!clickGuiMod->isEnabled()) { + timesRendered = 0; + return; + } + + if (timesRendered < 10) + return; + timesRendered = 0; + + switch (key) { + case VK_ESCAPE: + clickGuiMod->setEnabled(false); + return; + default: + if (key == clickGuiMod->getKeybind()) + clickGuiMod->setEnabled(false); + } + +} +using json = nlohmann::json; +void ClickGui::onLoadConfig(void* confVoid) { + savedWindowSettings.clear(); + windowMap.clear(); + json* conf = reinterpret_cast(confVoid); + if (conf->contains("ClickGui")) { + auto obj = conf->at("ClickGui"); + if (obj.is_null()) + return; + for (int i = 0; i <= (int)Category::CUSTOM /*last category*/; i++) { + auto catName = ClickGui::catToName((Category)i); + if (obj.contains(catName)) { + auto value = obj.at(catName); + if (value.is_null()) + continue; + try { + SavedWindowSettings windowSettings = {}; + windowSettings.name = catName; + if(value.contains("pos")){ + auto posVal = value.at("pos"); + if(!posVal.is_null() && posVal.contains("x") && posVal["x"].is_number_float() && posVal.contains("y") && posVal["y"].is_number_float()){ + try{ + windowSettings.pos = {posVal["x"].get(), posVal["y"].get()}; + } catch (std::exception e) {} + } + } + if(value.contains("isExtended")){ + auto isExtVal = value.at("isExtended"); + if(!isExtVal.is_null() && isExtVal.is_boolean()){ + try{ + windowSettings.isExtended = isExtVal.get(); + } catch (std::exception e) {} + } + } + savedWindowSettings[Utils::getCrcHash(catName)] = windowSettings; + } catch (std::exception e) { + logF("Config Load Error (ClickGuiMenu): %s", e.what()); + } + } + } + } +} +void ClickGui::onSaveConfig(void* confVoid) { + json* conf = reinterpret_cast(confVoid); + // First update our map + for(const auto& wind : windowMap){ + savedWindowSettings[wind.first] = {wind.second->pos, wind.second->isExtended, wind.second->name}; + } + + // Save to json + if (conf->contains("ClickGui")) + conf->erase("ClickGui"); + + json obj = {}; + + for(const auto& wind : savedWindowSettings){ + json subObj = {}; + subObj["pos"]["x"] = wind.second.pos.x; + subObj["pos"]["y"] = wind.second.pos.y; + subObj["isExtended"] = wind.second.isExtended; + obj[wind.second.name] = subObj; + } + + conf->emplace("ClickGui", obj); +} diff --git a/Horion/Menu/ClickGui.h b/Horion/Menu/ClickGui.h new file mode 100644 index 0000000..268fe32 --- /dev/null +++ b/Horion/Menu/ClickGui.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include + +#include "../../Memory/GameData.h" +#include "../DrawUtils.h" +#include "../GuiUtils.h" +#include "../Module/ModuleManager.h" + +struct ClickModule { + bool isExtended = false; +}; + +struct ClickWindow { + ClickWindow() { + pos.x = 0; + pos.y = 0; + + size.x = 30; + size.y = 30; + } + vec2_t pos; + vec2_t size; + bool isExtended = true; + bool isInAnimation = false; + float animation = 0; + const char* name; + std::map> moduleMap; + + int yOffset = 0; +}; + +class ClickGui { +private: + + inline static std::shared_ptr getWindow(const char* id); + inline static std::shared_ptr getClickModule(std::shared_ptr window, const char* id); + + static void renderLabel(const char* text); + static void renderTooltip(std::string* text); + + static void renderCategory(Category category); + inline static void getModuleListByCategory(Category category, std::vector>* modList); + + inline static const char* catToName(Category cat){ + const char* categoryName; + + // Get Category Name + { + switch (cat) { + case Category::COMBAT: + categoryName = "Combat"; + break; + case Category::VISUAL: + categoryName = "Visual"; + break; + case Category::MOVEMENT: + categoryName = "Movement"; + break; + case Category::PLAYER: + categoryName = "Player"; + break; + case Category::WORLD: + categoryName = "World"; + break; + case Category::MISC: + categoryName = "Misc"; + break; + case Category::CUSTOM: + categoryName = "Scripts"; + break; + } + } + return categoryName; + } + +public: + static void init(); + static void render(); + static void onKeyUpdate(int key, bool isDown); + static void onMouseClickUpdate(int key, bool isDown); + static void onWheelScroll(bool direction); // true = up, false = down + static void onLoadConfig(void* confVoid); + static void onSaveConfig(void* confVoid); +}; diff --git a/Horion/Menu/TabGui.cpp b/Horion/Menu/TabGui.cpp new file mode 100644 index 0000000..3f0d878 --- /dev/null +++ b/Horion/Menu/TabGui.cpp @@ -0,0 +1,245 @@ +#include "TabGui.h" + +#include +#include "../Scripting/ScriptManager.h" + +struct SelectedItemInformation { + int selectedItemId = 0; + float currentSelectedItemInterpol = 0; + float rollbackVal = 1; + + void setSelectedItemForce(int item) { + selectedItemId = item; + currentSelectedItemInterpol = (float)item; + } + + void interp() { + currentSelectedItemInterpol += (selectedItemId - currentSelectedItemInterpol) * 0.2f; + } + + void rollback() { + rollbackVal *= 0.7f; + } + void rollin() { + rollbackVal = 1 - ((1 - rollbackVal) * 0.7f); + } +}; + +// State +int level; +SelectedItemInformation selected[4]; +bool toggleCurrentSelection = false; + +// Render +static float yOffset; +static float xOffset; +int renderedLevel; + +struct LabelContainer { + const char* text = 0; + bool enabled = false; + std::shared_ptr mod = 0; +}; + +std::vector labelList; + +void TabGui::renderLabel(const char* text, std::shared_ptr mod) { + //size_t strlength = strlen(text) + 1; + //char* alloc = new char[strlength]; + //strcpy_s(alloc, strlength, text); + LabelContainer yikes; + yikes.text = text; + if (mod != 0) { + yikes.enabled = mod->isEnabled(); + yikes.mod = mod; + } + + labelList.push_back(yikes); +} + +void TabGui::renderLevel() { + auto hudModule = moduleMgr->getModule(); + + // Parameters + float textSize = hudModule->scale; + float textHeight = 10.f * textSize; + float alphaVal = 1.0f; + + // First loop: Get the maximum text length + float maxLength = 0.f; + int labelListLength = 0; + for (auto it = labelList.begin(); it != labelList.end(); ++it) { + labelListLength++; + std::string label = it->text; + maxLength = fmax(maxLength, DrawUtils::getTextWidth(&label, textSize)); + } + + if (selected[renderedLevel].selectedItemId < 0) + selected[renderedLevel].selectedItemId += labelListLength; + if (selected[renderedLevel].selectedItemId >= labelListLength) + selected[renderedLevel].selectedItemId -= labelListLength; + + selected[renderedLevel].interp(); // Converge to selected item + if (renderedLevel < level) + selected[renderedLevel].rollbackVal = 1; // Speed up animation when we are in the next menu already + + // Second loop: Render everything + int i = 0; + float selectedYOffset = yOffset; + float startYOffset = yOffset; + for (auto it = labelList.begin(); it != labelList.end(); ++it, i++) { + auto label = *it; + vec4_t rectPos = vec4_t( + xOffset - 0.5f, // Off screen / Left border not visible + yOffset, + xOffset + maxLength + 4.5f, + yOffset + textHeight); + + MC_Color color = MC_Color(200, 200, 200); + + if (selected[renderedLevel].selectedItemId == i && level >= renderedLevel) { // We are selected + if (renderedLevel == level) { // Are we actually in the menu we are drawing right now? + // We are selected in the current menu + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + static bool lastVal = toggleCurrentSelection; + + if (toggleCurrentSelection) { + if (label.mod->isFlashMode()) { + label.mod->setEnabled(true); + } else { + toggleCurrentSelection = false; + label.mod->toggle(); + } + } else if (toggleCurrentSelection != lastVal && label.mod->isFlashMode()) + label.mod->setEnabled(false); + lastVal = toggleCurrentSelection; + } else { // selected, but not what the user is interacting with + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + } + //selectedYOffset = yOffset; + } else { // We are not selected + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + } + + std::string tempLabel(label.text); + DrawUtils::drawText(vec2_t(xOffset + 1.5f, yOffset + 0.5f), &tempLabel, label.enabled ? MC_Color() : color, textSize); + + yOffset += textHeight; + } + + // Draw selected item + { + selectedYOffset = startYOffset + textHeight * selected[renderedLevel].currentSelectedItemInterpol; + vec4_t selectedPos = vec4_t( + xOffset - 0.5f, // Off screen / Left border not visible + selectedYOffset, + xOffset + maxLength + 4.5f, + selectedYOffset + textHeight); + + float diff = selectedPos.z - selectedPos.x; + selectedPos.z = selectedPos.x + diff * selected[renderedLevel].rollbackVal; + + if (renderedLevel > level) { + selected[renderedLevel].rollback(); + } else + selected[renderedLevel].rollin(); + DrawUtils::fillRectangle(selectedPos, MC_Color(85, 85, 85), alphaVal); + } + + // Cleanup + DrawUtils::flush(); + labelList.clear(); + xOffset += maxLength + 4.5f; + yOffset = selectedYOffset; + renderedLevel++; +} + +void TabGui::render() { + if (!moduleMgr->isInitialized()) + return; + if (!GameData::canUseMoveKeys()) + level = -1; + renderedLevel = 0; + yOffset = 4; + xOffset = 3; + + // Render all categorys + renderLabel("Combat"); + renderLabel("Visual"); + renderLabel("Movement"); + renderLabel("Player"); + renderLabel("World"); + renderLabel("Misc"); + if(scriptMgr.getNumEnabledScripts() > 0) + renderLabel("Scripts"); + renderLevel(); + + // Render all modules + if (level >= 0) { + auto lock = moduleMgr->lockModuleList(); + + std::vector>* modules = moduleMgr->getModuleList(); + for (std::vector>::iterator it = modules->begin(); it != modules->end(); ++it) { + auto mod = *it; + if (selected[0].selectedItemId == static_cast(mod->getCategory())) { + auto name = mod->getModuleName(); + renderLabel(name, mod); + } + } + + renderLevel(); + } +} + +void TabGui::init() { + level = 0; + xOffset = 0; + yOffset = 0; + renderedLevel = 0; +} + +void TabGui::onKeyUpdate(int key, bool isDown) { + if (!GameData::canUseMoveKeys()) { + level = -1; + return; + } + + if (!isDown) { + if (key == VK_RIGHT) + toggleCurrentSelection = false; + return; + } + + switch (key) { + case VK_LEFT: // Leave menus + if (level > -1) { + level--; + } + if (level == -1) + selected[1].rollbackVal = 0; + return; + case VK_RIGHT: + if (level < 1) { + level++; + selected[level].setSelectedItemForce(0); + selected[level].rollbackVal = 0; + } else + toggleCurrentSelection = true; + return; + case VK_UP: + if (level >= 0) + selected[level].selectedItemId--; + else + level = 0; + break; + case VK_DOWN: + if (level >= 0) + selected[level].selectedItemId++; + else + level = 0; + break; + }; + + if (level < 3) + selected[level + 1].setSelectedItemForce(0); +} diff --git a/Horion/Menu/TabGui.h b/Horion/Menu/TabGui.h new file mode 100644 index 0000000..9e34a8c --- /dev/null +++ b/Horion/Menu/TabGui.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "../DrawUtils.h" +#include "../Module/ModuleManager.h" + +class TabGui { +private: + static void renderLabel(const char* text, std::shared_ptr mod = 0); + static void renderLevel(); + +public: + static void init(); + static void render(); + static void onKeyUpdate(int key, bool isDown); +}; diff --git a/Horion/Module/ModuleManager.cpp b/Horion/Module/ModuleManager.cpp new file mode 100644 index 0000000..4d845e1 --- /dev/null +++ b/Horion/Module/ModuleManager.cpp @@ -0,0 +1,257 @@ +#include "ModuleManager.h" +#include "../../Utils/Logger.h" +#include "../../Utils/Json.hpp" + +using json = nlohmann::json; + +ModuleManager::ModuleManager(GameData* gameData) { + this->gameData = gameData; +} + +ModuleManager::~ModuleManager() { + initialized = false; + auto lock = this->lockModuleListExclusive(); + this->moduleList.clear(); +} + +void ModuleManager::initModules() { + logF("Initializing modules"); + { + auto lock = this->lockModuleListExclusive(); + + this->moduleList.push_back(std::shared_ptr(new HudModule())); + this->moduleList.push_back(std::shared_ptr(new Killaura())); + this->moduleList.push_back(std::shared_ptr(new ESP())); + this->moduleList.push_back(std::shared_ptr(new Jetpack())); + this->moduleList.push_back(std::shared_ptr(new Aimbot())); + this->moduleList.push_back(std::shared_ptr(new TriggerBot())); + this->moduleList.push_back(std::shared_ptr(new StorageESP())); + this->moduleList.push_back(std::shared_ptr(new Velocity())); + this->moduleList.push_back(std::shared_ptr(new RainbowSky())); + this->moduleList.push_back(std::shared_ptr(new AirJump())); + this->moduleList.push_back(std::shared_ptr(new Step())); + this->moduleList.push_back(std::shared_ptr(new Glide())); + this->moduleList.push_back(std::shared_ptr(new EditionFaker())); + this->moduleList.push_back(std::shared_ptr(new Phase())); + this->moduleList.push_back(std::shared_ptr(new Freecam())); + this->moduleList.push_back(std::shared_ptr(new AutoSprint())); + this->moduleList.push_back(std::shared_ptr(new Tracer())); + this->moduleList.push_back(std::shared_ptr(new BowAimbot())); + this->moduleList.push_back(std::shared_ptr(new Scaffold())); + this->moduleList.push_back(std::shared_ptr(new NoFall())); + this->moduleList.push_back(std::shared_ptr(new Blink())); + this->moduleList.push_back(std::shared_ptr(new Nuker())); + this->moduleList.push_back(std::shared_ptr(new InstaBreak())); + this->moduleList.push_back(std::shared_ptr(new NoPacket())); + this->moduleList.push_back(std::shared_ptr(new Speed())); + this->moduleList.push_back(std::shared_ptr(new Xray())); + this->moduleList.push_back(std::shared_ptr(new Fucker())); + this->moduleList.push_back(std::shared_ptr(new NoSlowDown())); + this->moduleList.push_back(std::shared_ptr(new AutoTotem())); + this->moduleList.push_back(std::shared_ptr(new InfiniteAura())); + this->moduleList.push_back(std::shared_ptr(new ClickGuiMod())); + this->moduleList.push_back(std::shared_ptr(new ChestStealer())); + this->moduleList.push_back(std::shared_ptr(new Fly())); + this->moduleList.push_back(std::shared_ptr(new Hitbox())); + this->moduleList.push_back(std::shared_ptr(new Reach())); + this->moduleList.push_back(std::shared_ptr(new FullBright())); + this->moduleList.push_back(std::shared_ptr(new AirSwim())); + this->moduleList.push_back(std::shared_ptr(new InventoryMove())); + this->moduleList.push_back(std::shared_ptr(new HighJump())); + this->moduleList.push_back(std::shared_ptr(new NoWeb())); + this->moduleList.push_back(std::shared_ptr(new FastLadder())); + this->moduleList.push_back(std::shared_ptr(new StackableItem())); + this->moduleList.push_back(std::shared_ptr(new FastEat())); + this->moduleList.push_back(std::shared_ptr(new Jesus())); + this->moduleList.push_back(std::shared_ptr(new AutoArmor())); + this->moduleList.push_back(std::shared_ptr(new ExtendedBlockReach())); + this->moduleList.push_back(std::shared_ptr(new AutoClicker())); + this->moduleList.push_back(std::shared_ptr(new NameTags())); + this->moduleList.push_back(std::shared_ptr(new Criticals())); + this->moduleList.push_back(std::shared_ptr(new Bhop())); + this->moduleList.push_back(std::shared_ptr(new Tower())); + this->moduleList.push_back(std::shared_ptr(new AntiVoid())); + this->moduleList.push_back(std::shared_ptr(new MidClick())); + this->moduleList.push_back(std::shared_ptr(new Teleport())); + this->moduleList.push_back(std::shared_ptr(new NoFriends())); + this->moduleList.push_back(std::shared_ptr(new Spammer())); + this->moduleList.push_back(std::shared_ptr(new ChestAura())); + this->moduleList.push_back(std::shared_ptr(new AntiBot())); + this->moduleList.push_back(std::shared_ptr(new InventoryCleaner())); + this->moduleList.push_back(std::shared_ptr(new Derp())); + this->moduleList.push_back(std::shared_ptr(new Crasher())); + this->moduleList.push_back(std::shared_ptr(new CrystalAura())); + this->moduleList.push_back(std::shared_ptr(new Timer())); + this->moduleList.push_back(std::shared_ptr(new NightMode())); + this->moduleList.push_back(std::shared_ptr(new NoSwing())); + //this->moduleList.push_back(std::shared_ptr(new CubeGlide())); + this->moduleList.push_back(std::shared_ptr(new AirStuck())); + this->moduleList.push_back(std::shared_ptr(new Zoom())); + this->moduleList.push_back(std::shared_ptr(new Teams())); + this->moduleList.push_back(std::shared_ptr(new Nbt())); + //this->moduleList.push_back(std::shared_ptr(new Godmode())); + this->moduleList.push_back(std::shared_ptr(new Freelook())); + this->moduleList.push_back(std::shared_ptr(new AutoSneak())); + this->moduleList.push_back(std::shared_ptr(new NoHurtcam())); + this->moduleList.push_back(std::shared_ptr(new AntiImmobile())); + this->moduleList.push_back(std::shared_ptr(new NoPaintingCrash())); + this->moduleList.push_back(std::shared_ptr(new Waypoints())); + this->moduleList.push_back(std::shared_ptr(new TimeChanger())); + this->moduleList.push_back(std::shared_ptr(new Spider())); + this->moduleList.push_back(std::shared_ptr(new Compass())); + this->moduleList.push_back(std::shared_ptr(new Radar())); + this->moduleList.push_back(std::shared_ptr(new VanillaPlus())); + this->moduleList.push_back(std::shared_ptr(new ViewModel())); + this->moduleList.push_back(std::shared_ptr(new Twerk())); + this->moduleList.push_back(std::shared_ptr(new FollowPathModule())); + +#ifdef _DEBUG + this->moduleList.push_back(std::shared_ptr(new PacketLogger())); + this->moduleList.push_back(std::shared_ptr(new TestModule())); +#endif + + // Sort modules alphabetically + std::sort(moduleList.begin(), moduleList.end(), [](auto lhs, auto rhs) { + auto current = lhs; + auto other = rhs; + return std::string{*current->getModuleName()} < std::string{*other->getModuleName()}; + }); + + initialized = true; + } + + this->getModule()->setEnabled(true); + this->getModule()->setEnabled(false); + this->getModule()->setEnabled(true); +} + +void ModuleManager::disable() { + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + if (mod->isEnabled()) + mod->setEnabled(false); + } +} + +void ModuleManager::onLoadConfig(void* confVoid) { + auto conf = reinterpret_cast(confVoid); + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + mod->onLoadConfig(conf); + } + + this->getModule()->setEnabled(true); + this->getModule()->setEnabled(false); + this->getModule()->setEnabled(true); +} + +void ModuleManager::onSaveConfig(void* confVoid) { + auto conf = reinterpret_cast(confVoid); + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + mod->onSaveConfig(conf); + } +} + +void ModuleManager::onTick(C_GameMode* gameMode) { + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + if (mod->isEnabled() || mod->callWhenDisabled()) + mod->onTick(gameMode); + } +} + +void ModuleManager::onAttack(C_Entity* attackEnt) { + if (!isInitialized()) + return; + + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + if (mod->isEnabled() || mod->callWhenDisabled()) + mod->onAttack(attackEnt); + } +} + +void ModuleManager::onKeyUpdate(int key, bool isDown) { + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& mod : this->moduleList) { + mod->onKeyUpdate(key, isDown); + } +} + +void ModuleManager::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + if (!isInitialized()) + return; + auto mutex = this->lockModuleList(); + + for (auto& mod : this->moduleList) { + if (mod->isEnabled() || mod->callWhenDisabled()) + mod->onPreRender(renderCtx); + } +} + +void ModuleManager::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + if (!isInitialized()) + return; + auto mutex = this->lockModuleList(); + + for (auto& mod : this->moduleList) { + if (mod->isEnabled() || mod->callWhenDisabled()) + mod->onPostRender(renderCtx); + } +} + +void ModuleManager::onSendPacket(C_Packet* packet) { + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& it : moduleList) { + if (it->isEnabled() || it->callWhenDisabled()) + it->onSendPacket(packet); + } +} + +std::vector>* ModuleManager::getModuleList() { + return &this->moduleList; +} + +int ModuleManager::getModuleCount() { + return (int)moduleList.size(); +} + +int ModuleManager::getEnabledModuleCount() { + int i = 0; + auto lock = this->lockModuleList(); + for (auto& it : moduleList) { + if (it->isEnabled()) i++; + } + return i; +} +void ModuleManager::onMove(C_MoveInputHandler* hand) { + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& it : moduleList) { + if (it->isEnabled() || it->callWhenDisabled()) + it->onMove(hand); + } +} +void ModuleManager::onLevelRender() { + if (!isInitialized()) + return; + auto lock = this->lockModuleList(); + for (auto& it : moduleList) { + if (it->isEnabled() || it->callWhenDisabled()) + it->onLevelRender(); + } +} + +ModuleManager* moduleMgr = new ModuleManager(&g_Data); diff --git a/Horion/Module/ModuleManager.h b/Horion/Module/ModuleManager.h new file mode 100644 index 0000000..5c8310a --- /dev/null +++ b/Horion/Module/ModuleManager.h @@ -0,0 +1,179 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "../../Memory/GameData.h" + +#include "Modules/Aimbot.h" +#include "Modules/AirJump.h" +#include "Modules/AirSwim.h" +#include "Modules/AntiBot.h" +#include "Modules/AutoArmor.h" +#include "Modules/AutoClicker.h" +#include "Modules/AutoGapple.h" +#include "Modules/AutoSneak.h" +#include "Modules/AutoSprint.h" +#include "Modules/AutoTotem.h" +#include "Modules/Fucker.h" +#include "Modules/Bhop.h" +#include "Modules/Blink.h" +#include "Modules/BowAimbot.h" +#include "Modules/AntiVoid.h" +#include "Modules/ChestAura.h" +#include "Modules/StorageESP.h" +#include "Modules/ChestStealer.h" +#include "Modules/ClickGuiMod.h" +#include "Modules/Teleport.h" +#include "Modules/Crasher.h" +#include "Modules/Criticals.h" +#include "Modules/CrystalAura.h" +#include "Modules/Derp.h" +#include "Modules/ESP.h" +#include "Modules/EditionFaker.h" +#include "Modules/FastEat.h" +#include "Modules/FastLadder.h" +#include "Modules/Fly.h" +#include "Modules/Freecam.h" +#include "Modules/FullBright.h" +#include "Modules/Glide.h" +#include "Modules/HighJump.h" +#include "Modules/Hitbox.h" +#include "Modules/HudModule.h" +#include "Modules/ExtendedBlockReach.h" +#include "Modules/InfiniteAura.h" +#include "Modules/InstaBreak.h" +#include "Modules/InventoryCleaner.h" +#include "Modules/InventoryMove.h" +#include "Modules/Jesus.h" +#include "Modules/Jetpack.h" +#include "Modules/Killaura.h" +#include "Modules/MidClick.h" +#include "Modules/Module.h" +#include "Modules/NameTags.h" +#include "Modules/NoFall.h" +#include "Modules/NoFriends.h" +#include "Modules/Velocity.h" +#include "Modules/NoPacket.h" +#include "Modules/NoSlowDown.h" +#include "Modules/NoWeb.h" +#include "Modules/Nuker.h" +#include "Modules/Phase.h" +#include "Modules/RainbowSky.h" +#include "Modules/Reach.h" +#include "Modules/Scaffold.h" +#include "Modules/Spammer.h" +#include "Modules/Speed.h" +#include "Modules/StackableItem.h" +#include "Modules/Step.h" +#include "Modules/TimeChanger.h" +#include "Modules/Timer.h" +#include "Modules/Tower.h" +#include "Modules/Tracer.h" +#include "Modules/TriggerBot.h" +#include "Modules/Xray.h" +#include "Modules/NightMode.h" +#include "Modules/NoSwing.h" +#include "Modules/CubeGlide.h" +#include "Modules/AirStuck.h" +#include "Modules/Zoom.h" +#include "Modules/Teams.h" +#include "Modules/Nbt.h" +#include "Modules/Godmode.h" +#include "Modules/Freelook.h" +#include "Modules/NoHurtcam.h" +#include "Modules/AntiImmobile.h" +#include "Modules/FollowPathModule.h" +#include "Modules/NoPaintingCrash.h" +#include "Modules/Waypoints.h" +#include "Modules/Spider.h" +#include "Modules/Compass.h" +#include "Modules/Radar.h" +#include "Modules/VanillaPlus.h" +#include "Modules/ViewModel.h" +#include "Modules/Twerk.h" + +#ifdef _DEBUG +#include "Modules/PacketLogger.h" +#include "Modules/TestModule.h" +#endif + + +class ModuleManager { +private: + GameData* gameData; + std::vector> moduleList; + bool initialized = false; + std::shared_mutex moduleListMutex; + +public: + ~ModuleManager(); + ModuleManager(GameData* gameData); + void initModules(); + void disable(); + void onLoadConfig(void* conf); + void onSaveConfig(void* conf); + void onTick(C_GameMode* gameMode); + void onAttack(C_Entity* attackedEnt); + + void onKeyUpdate(int key, bool isDown); + void onPreRender(C_MinecraftUIRenderContext* renderCtx); + void onPostRender(C_MinecraftUIRenderContext* renderCtx); + void onLevelRender(); + void onMove(C_MoveInputHandler* handler); + void onSendPacket(C_Packet*); + + std::shared_lock lockModuleList() { return std::shared_lock(this->moduleListMutex); } + std::unique_lock lockModuleListExclusive() { return std::unique_lock(this->moduleListMutex); } + + std::shared_mutex* getModuleListLock() { return &this->moduleListMutex; } + + bool isInitialized() { return initialized; }; + std::vector>* getModuleList(); + + int getModuleCount(); + int getEnabledModuleCount(); + + /* + * Use as follows: + * IModule* mod = moduleMgr.getModule(); + * Check for nullptr directly after that call, as Hooks::init is called before ModuleManager::initModules ! + */ + template + TRet* getModule() { + if (!isInitialized()) + return nullptr; + auto lock = this->lockModuleList(); + for (auto pMod : moduleList) { + if (auto pRet = dynamic_cast::type*>(pMod.get())){ + + return pRet; + } + } + return nullptr; + }; + + // Dont Use this functions unless you absolutely need to. The function above this one works in 99% of cases + std::optional> getModuleByName(const std::string name) { + if (!isInitialized()) + return nullptr; + std::string nameCopy = name; + std::transform(nameCopy.begin(), nameCopy.end(), nameCopy.begin(), ::tolower); + + auto lock = this->lockModuleList(); + for (std::vector>::iterator it = this->moduleList.begin(); it != this->moduleList.end(); ++it) { + std::shared_ptr mod = *it; + std::string modNameCopy = mod->getRawModuleName(); + std::transform(modNameCopy.begin(), modNameCopy.end(), modNameCopy.begin(), ::tolower); + if (modNameCopy == nameCopy) + return std::optional>(mod); + } + return std::optional>(); + } +}; + +extern ModuleManager* moduleMgr; diff --git a/Horion/Module/Modules/Aimbot.cpp b/Horion/Module/Modules/Aimbot.cpp new file mode 100644 index 0000000..7d6f505 --- /dev/null +++ b/Horion/Module/Modules/Aimbot.cpp @@ -0,0 +1,84 @@ +#include "Aimbot.h" + +Aimbot::Aimbot() : IModule(0, Category::COMBAT, "Automatically aims at the nearest entity") { + this->registerFloatSetting("range", &this->range, this->range, 3.f, 8.f); + this->registerBoolSetting("Require click", &this->click, this->click); + this->registerBoolSetting("only swords/axes", &this->sword, this->sword); + this->registerBoolSetting("vertical", &this->vertical, this->vertical); + this->registerFloatSetting("horizontal speed", &this->horizontalspeed, this->horizontalspeed, 10.f, 90.f); + this->registerFloatSetting("vertical speed", &this->verticalspeed, this->verticalspeed, 10.f, 90.f); + this->registerFloatSetting("horizontal range", &this->horizontalrange, this->horizontalrange, 20.f, 180.f); + this->registerFloatSetting("vertical range", &this->verticalrange, this->verticalrange, 20.f, 180.f); + this->registerBoolSetting("aimlock", &this->lock, this->lock); +} + +Aimbot::~Aimbot() { +} + +const char* Aimbot::getModuleName() { + return ("Aimbot"); +} + +struct CompareTargetEnArray { + bool operator()(C_Entity* lhs, C_Entity* rhs) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + return (*lhs->getPos()).dist(*localPlayer->getPos()) < (*rhs->getPos()).dist(*localPlayer->getPos()); + } +}; + +void Aimbot::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + if (localPlayer == nullptr) + return; + C_EntityList* entList = g_Data.getEntityList(); + if (entList == nullptr) + return; + size_t listSize = entList->getListSize(); + + if (listSize > 1000) { + return; + } + + vec3_t origin = g_Data.getClientInstance()->levelRenderer->origin; + + //Loop through all our players and retrieve their information + static std::vector targetList; + targetList.clear(); + for (size_t i = 0; i < listSize; i++) { + C_Entity* currentEntity = entList->get(i); + + if (!Target::isValidTarget(currentEntity)) + continue; + + float dist = (*currentEntity->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + + if (dist < range) + targetList.push_back(currentEntity); + } + + if (targetList.size() > 0) { + std::sort(targetList.begin(), targetList.end(), CompareTargetEnArray()); + vec2_t angle = origin.CalcAngle(*targetList[0]->getPos()); + vec2_t appl = angle.sub(localPlayer->viewAngles).normAngles(); + appl.x = -appl.x; + if ((appl.x < verticalrange && appl.x > -verticalrange) && (appl.y < horizontalrange && appl.y > -horizontalrange) && GameData::canUseMoveKeys()) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_ItemStack* item = supplies->inventory->getItemStack(supplies->selectedHotbarSlot); + if (sword && !(item->getItem()->isWeapon())) + return; + + if (click && !g_Data.isLeftClickDown()) + return; + + if (!this->lock) { + appl.x /= (100.f - verticalspeed); + appl.y /= (100.f - horizontalspeed); + if (appl.x >= 1 || appl.x <= -1) appl.div(abs(appl.x)); + if (appl.y >= 1 || appl.y <= -1) appl.div(abs(appl.y)); + } + if (!vertical) + appl.x = 0; + localPlayer->applyTurnDelta(&appl); + } + } +} diff --git a/Horion/Module/Modules/Aimbot.h b/Horion/Module/Modules/Aimbot.h new file mode 100644 index 0000000..11e0e7f --- /dev/null +++ b/Horion/Module/Modules/Aimbot.h @@ -0,0 +1,24 @@ +#pragma once +#include "../ModuleManager.h" +#include "Module.h" + +class Aimbot : public IModule { +private: + float range = 4.f; + bool vertical = true; + bool sword = false; + bool click = false; + float horizontalspeed = 50.f; + float verticalspeed = 50.f; + float verticalrange = 40.f; + float horizontalrange = 60.f; + bool lock = false; + +public: + Aimbot(); + ~Aimbot(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/AirJump.cpp b/Horion/Module/Modules/AirJump.cpp new file mode 100644 index 0000000..49adde1 --- /dev/null +++ b/Horion/Module/Modules/AirJump.cpp @@ -0,0 +1,30 @@ +#include "AirJump.h" + +AirJump::AirJump() : IModule('G', Category::MOVEMENT, "Jump even you're not on the ground") { + registerBoolSetting("Legacy", &legacyMode, legacyMode); +} + +AirJump::~AirJump() { +} + +const char* AirJump::getModuleName() { + return ("AirJump"); +} + +void AirJump::onTick(C_GameMode* gm) { + if (legacyMode) { + gm->player->onGround = true; + return; + } + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + + if (input == nullptr) + return; + + if (GameData::isKeyDown(*input->spaceBarKey) && hasJumped == 0) { + gm->player->onGround = true; + hasJumped = 1; + } else if (!GameData::isKeyDown(*input->spaceBarKey)) { + hasJumped = 0; + } +} diff --git a/Horion/Module/Modules/AirJump.h b/Horion/Module/Modules/AirJump.h new file mode 100644 index 0000000..3d704ca --- /dev/null +++ b/Horion/Module/Modules/AirJump.h @@ -0,0 +1,15 @@ +#pragma once +#include "../ModuleManager.h" +#include "Module.h" +class AirJump : public IModule { +private: + int hasJumped = 0; + bool legacyMode = false; + +public: + AirJump(); + ~AirJump(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/AirStuck.cpp b/Horion/Module/Modules/AirStuck.cpp new file mode 100644 index 0000000..f6d1cc9 --- /dev/null +++ b/Horion/Module/Modules/AirStuck.cpp @@ -0,0 +1,15 @@ +#include "AirStuck.h" + +AirStuck::AirStuck() : IModule(0, Category::MOVEMENT, "Become stuck.") { +} + +AirStuck::~AirStuck() { +} + +const char* AirStuck::getModuleName() { + return ("AirStuck"); +} + +void AirStuck::onTick(C_GameMode* gm) { + gm->player->velocity = vec3_t(0, 0, 0); +} \ No newline at end of file diff --git a/Horion/Module/Modules/AirStuck.h b/Horion/Module/Modules/AirStuck.h new file mode 100644 index 0000000..27ea2e8 --- /dev/null +++ b/Horion/Module/Modules/AirStuck.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" + +class AirStuck : public IModule { +public: + AirStuck(); + ~AirStuck(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/AirSwim.cpp b/Horion/Module/Modules/AirSwim.cpp new file mode 100644 index 0000000..ef06ea8 --- /dev/null +++ b/Horion/Module/Modules/AirSwim.cpp @@ -0,0 +1,31 @@ +#include "AirSwim.h" + +AirSwim::AirSwim() : IModule(0, Category::MOVEMENT, "Swim even though your in air") { +} + +AirSwim::~AirSwim() { +} + +const char* AirSwim::getModuleName() { + return ("AirSwim"); +} + +void AirSwim::onEnable() { + if (g_Data.getLocalPlayer() == nullptr) + return; + g_Data.getLocalPlayer()->didEnterWaterBool = true; + g_Data.getLocalPlayer()->startSwimming(); +} + +void AirSwim::onTick(C_GameMode* gm) { + g_Data.getLocalPlayer()->didEnterWaterBool = true; + g_Data.getLocalPlayer()->doWaterSplashEffect(); + g_Data.getLocalPlayer()->startSwimming(); +} + +void AirSwim::onDisable() { + if (g_Data.getLocalPlayer() == nullptr) + return; + g_Data.getLocalPlayer()->didEnterWaterBool = false; + g_Data.getLocalPlayer()->stopSwimming(); +} \ No newline at end of file diff --git a/Horion/Module/Modules/AirSwim.h b/Horion/Module/Modules/AirSwim.h new file mode 100644 index 0000000..8cd4530 --- /dev/null +++ b/Horion/Module/Modules/AirSwim.h @@ -0,0 +1,14 @@ +#pragma once +#include "Module.h" + +class AirSwim : public IModule { +public: + AirSwim(); + ~AirSwim(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onEnable() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; \ No newline at end of file diff --git a/Horion/Module/Modules/AntiBot.cpp b/Horion/Module/Modules/AntiBot.cpp new file mode 100644 index 0000000..146692b --- /dev/null +++ b/Horion/Module/Modules/AntiBot.cpp @@ -0,0 +1,17 @@ +#include "AntiBot.h" + +AntiBot::AntiBot() : IModule(0, Category::PLAYER, "Enable this module to filter bots!") { + registerBoolSetting("Hitbox Check", &this->hitboxCheck, this->hitboxCheck); + //registerBoolSetting("Name Check", &this->nameCheck, this->nameCheck); + registerBoolSetting("Invisible Check", &this->invisibleCheck, this->invisibleCheck); + registerBoolSetting("EntityID Check", &this->entityIdCheck, this->entityIdCheck); + registerBoolSetting("Other Check", &this->otherCheck, this->otherCheck); + registerBoolSetting("Extra Check", &this->extraCheck, this->extraCheck); +} + +AntiBot::~AntiBot() { +} + +const char* AntiBot::getModuleName() { + return ("AntiBot"); +} diff --git a/Horion/Module/Modules/AntiBot.h b/Horion/Module/Modules/AntiBot.h new file mode 100644 index 0000000..ec4c4ec --- /dev/null +++ b/Horion/Module/Modules/AntiBot.h @@ -0,0 +1,37 @@ +#pragma once +#include "Module.h" +class AntiBot : public IModule { +private: + bool hitboxCheck = true; + bool nameCheck = false; + bool invisibleCheck = true; + bool entityIdCheck = true; + bool otherCheck = true; + bool extraCheck = false; + +public: + AntiBot(); + ~AntiBot(); + + inline bool isHitboxCheckEnabled() { + return hitboxCheck && this->isEnabled(); + } + inline bool isNameCheckEnabled() { + return false && this->isEnabled(); + } + inline bool isInvisibleCheckEnabled() { + return invisibleCheck && this->isEnabled(); + } + inline bool isEntityIdCheckEnabled() { + return entityIdCheck && this->isEnabled(); + } + inline bool isOtherCheckEnabled() { + return otherCheck && this->isEnabled(); + } + inline bool isExtraCheckEnabled() { + return this->extraCheck && this->isEnabled(); + } + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/AntiImmobile.cpp b/Horion/Module/Modules/AntiImmobile.cpp new file mode 100644 index 0000000..c5344d7 --- /dev/null +++ b/Horion/Module/Modules/AntiImmobile.cpp @@ -0,0 +1,10 @@ +#include "AntiImmobile.h" + +AntiImmobile::AntiImmobile() : IModule(0, Category::MISC, "Disables immobile flag set by some servers to prevent you from moving") { +} +AntiImmobile::~AntiImmobile() { +} + +const char* AntiImmobile::getModuleName() { + return "AntiImmobile"; +} \ No newline at end of file diff --git a/Horion/Module/Modules/AntiImmobile.h b/Horion/Module/Modules/AntiImmobile.h new file mode 100644 index 0000000..a660c87 --- /dev/null +++ b/Horion/Module/Modules/AntiImmobile.h @@ -0,0 +1,10 @@ +#pragma once +#include "Module.h" + +class AntiImmobile : public IModule { +public: + AntiImmobile(); + ~AntiImmobile(); + + const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/AntiVoid.cpp b/Horion/Module/Modules/AntiVoid.cpp new file mode 100644 index 0000000..7e0691b --- /dev/null +++ b/Horion/Module/Modules/AntiVoid.cpp @@ -0,0 +1,29 @@ +#include "AntiVoid.h" + +AntiVoid::AntiVoid() : IModule(0, Category::MOVEMENT, "Automatically teleports you back up if you fall down more than X blocks") { + registerIntSetting("distance", &this->distance, this->distance, 1, 20); +} + +AntiVoid::~AntiVoid() { +} + +const char* AntiVoid::getModuleName() { + return ("AntiVoid"); +} + +void AntiVoid::onTick(C_GameMode* gm) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + vec3_t blockBelow = player->eyePos0; + blockBelow.y -= player->height; + blockBelow.y -= 0.5f; + + if (((player->region->getBlock(blockBelow)->blockLegacy))->blockId != 0 && ((player->region->getBlock(blockBelow)->blockLegacy))->material->isSolid) { + savepos = blockBelow; + savepos.y += player->height; + savepos.y += 0.5f; + } + + if (player->fallDistance >= distance) { + player->setPos(savepos); + } +} diff --git a/Horion/Module/Modules/AntiVoid.h b/Horion/Module/Modules/AntiVoid.h new file mode 100644 index 0000000..ee51954 --- /dev/null +++ b/Horion/Module/Modules/AntiVoid.h @@ -0,0 +1,18 @@ +#pragma once +#include "..\ModuleManager.h" +#include "Module.h" + +class AntiVoid : public IModule { +private: + int distance = 5; + vec3_t savepos; + +public: + C_MoveInputHandler* inputHandler = nullptr; + AntiVoid(); + ~AntiVoid(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/AutoArmor.cpp b/Horion/Module/Modules/AutoArmor.cpp new file mode 100644 index 0000000..feb4749 --- /dev/null +++ b/Horion/Module/Modules/AutoArmor.cpp @@ -0,0 +1,120 @@ +#include "AutoArmor.h" +#include "../../../Utils/Utils.h" +#include "../../../Utils/Logger.h" + +class ArmorStruct { +public: + ArmorStruct(C_ItemStack* item, C_ArmorItem* yot, int slot) { + armor = yot; + m_slot = slot; + m_item = item; + } + bool isEqual(ArmorStruct& src) { + if (this->m_item->getArmorValueWithEnchants() == src.m_item->getArmorValueWithEnchants()) + return true; + else + return false; + } + + bool operator()(ArmorStruct lhs, ArmorStruct rhs) { + return (lhs.m_item->getArmorValueWithEnchants() > rhs.m_item->getArmorValueWithEnchants()); + } + C_ArmorItem* armor = nullptr; + C_ItemStack* m_item = nullptr; + int m_slot = 0; +}; + +AutoArmor::AutoArmor() : IModule(0, Category::PLAYER, "Automatically equips the best armor") { +} + +AutoArmor::~AutoArmor() { +} + +const char* AutoArmor::getModuleName() { + return ("AutoArmor"); +} + +void AutoArmor::onTick(C_GameMode* gm) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + + C_InventoryAction* first = nullptr; + C_InventoryAction* second = nullptr; + static C_ItemStack* emptyItemStack = nullptr; + + if (emptyItemStack == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 3D ? ? ? ? 80 B8 ? ? ? ? ? 75 19 48 8B 88 ? ? ? ? 48 8B 11 4C 8B 42 28 8B 50 10"); + int offset = *reinterpret_cast(sigOffset + 3); + emptyItemStack = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + } + + std::vector armorList; + + struct CompareArmorStruct { + bool operator()(ArmorStruct lhs, ArmorStruct rhs) { + return (lhs.m_item->getArmorValueWithEnchants() > rhs.m_item->getArmorValueWithEnchants()); + } + }; + + for (int i = 0; i < 4; i++) { + for (int n = 0; n < 36; n++) { + C_ItemStack* stack = inv->getItemStack(n); + if (stack->item != NULL && (*stack->item)->isArmor() && reinterpret_cast(*stack->item)->ArmorSlot == i) { + armorList.push_back(ArmorStruct(stack, reinterpret_cast(*stack->item), n)); + } + } + + if (gm->player->getArmor(i)->item != nullptr) + armorList.push_back(ArmorStruct(gm->player->getArmor(i), reinterpret_cast(*gm->player->getArmor(i)->item), i)); + + if (armorList.size() > 0) { + std::sort(armorList.begin(), armorList.end(), CompareArmorStruct()); + C_ItemStack* armorItem = gm->player->getArmor(i); + + if (armorItem->item != nullptr && (ArmorStruct(armorItem, reinterpret_cast(*armorItem->item), 0).isEqual(armorList[0])) == false) { + int slot = inv->getFirstEmptySlot(); + + first = new C_InventoryAction(i, armorItem, nullptr, 632); + second = new C_InventoryAction(slot, nullptr, armorItem); + + *g_Data.getLocalPlayer()->getArmor(i) = *emptyItemStack; + *inv->getItemStack(slot) = *armorItem; + + manager->addInventoryAction(*first); + manager->addInventoryAction(*second); + + delete first; + delete second; + + first = new C_InventoryAction(armorList[0].m_slot, armorList[0].m_item, nullptr); + second = new C_InventoryAction(i, nullptr, armorList[0].m_item, 632); + + *g_Data.getLocalPlayer()->getArmor(i) = *inv->getItemStack(armorList[0].m_slot); + *inv->getItemStack(armorList[0].m_slot) = *emptyItemStack; + + manager->addInventoryAction(*first); + manager->addInventoryAction(*second); + + delete first; + delete second; + } + if (armorItem->item == nullptr) { + *g_Data.getLocalPlayer()->getArmor(i) = *inv->getItemStack(armorList[0].m_slot); + + first = new C_InventoryAction(armorList[0].m_slot, armorList[0].m_item, nullptr); + second = new C_InventoryAction(i, nullptr, armorList[0].m_item, 632); + + *inv->getItemStack(armorList[0].m_slot) = *emptyItemStack; + + manager->addInventoryAction(*first); + manager->addInventoryAction(*second); + + delete first; + delete second; + } + } + armorList.clear(); + } + armorList.clear(); +} diff --git a/Horion/Module/Modules/AutoArmor.h b/Horion/Module/Modules/AutoArmor.h new file mode 100644 index 0000000..2a9d288 --- /dev/null +++ b/Horion/Module/Modules/AutoArmor.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class AutoArmor : public IModule { +public: + C_CraftingScreenController* inventoryScreen = nullptr; + AutoArmor(); + ~AutoArmor(); + + virtual void onTick(C_GameMode* gm) override; + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/AutoClicker.cpp b/Horion/Module/Modules/AutoClicker.cpp new file mode 100644 index 0000000..e57d4be --- /dev/null +++ b/Horion/Module/Modules/AutoClicker.cpp @@ -0,0 +1,57 @@ +#include "AutoClicker.h" + +AutoClicker::AutoClicker() : IModule(0, Category::COMBAT, "A simple autoclicker, automatically clicks for you.") { + this->registerBoolSetting("rightclick", &this->rightclick, rightclick); + this->registerBoolSetting("only weapons", &this->weapons, this->weapons); + this->registerBoolSetting("break blocks", &this->breakBlocks, this->breakBlocks); + this->registerIntSetting("delay", &this->delay, this->delay, 0, 20); + this->registerBoolSetting("hold", &this->hold, this->hold); +} + +AutoClicker::~AutoClicker() { +} + +const char* AutoClicker::getModuleName() { + return ("AutoClicker"); +} + +void AutoClicker::onTick(C_GameMode* gm) { + if ((GameData::isLeftClickDown() || !hold) && GameData::canUseMoveKeys()) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + PointingStruct* pointing = g_Data.getClientInstance()->getPointerStruct(); + Odelay++; + + if (Odelay >= delay) { + auto selectedItem = localPlayer->getSelectedItem(); + if (weapons && selectedItem->getAttackingDamageWithEnchants() < 1) + return; + + g_Data.leftclickCount++; + + localPlayer->swingArm(); + + if (pointing->hasEntity() != 0) + gm->attack(pointing->getEntity()); + else if (breakBlocks) { + bool isDestroyed = false; + gm->startDestroyBlock(pointing->block, pointing->blockSide, isDestroyed); + gm->stopDestroyBlock(pointing->block); + if (isDestroyed && localPlayer->region->getBlock(pointing->block)->blockLegacy->blockId != 0) + gm->destroyBlock(&pointing->block, 0); + } + Odelay = 0; + } + } + + if (rightclick) { + if ((GameData::isRightClickDown() || !hold) && GameData::canUseMoveKeys()) { + PointingStruct* pstruct = g_Data.getClientInstance()->getPointerStruct(); + Odelay++; + if (Odelay >= delay) { + g_Data.rightclickCount++; + gm->buildBlock(new vec3_ti(pstruct->block), pstruct->blockSide); + Odelay = 0; + } + } + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/AutoClicker.h b/Horion/Module/Modules/AutoClicker.h new file mode 100644 index 0000000..0864102 --- /dev/null +++ b/Horion/Module/Modules/AutoClicker.h @@ -0,0 +1,21 @@ +#pragma once +#include "Module.h" +#include "../ModuleManager.h" + +class AutoClicker : public IModule { +private: + int delay = 0; + int Odelay = 0; + bool weapons = true; + bool breakBlocks = true; + bool rightclick = false; + bool hold = false; + +public: + AutoClicker(); + ~AutoClicker(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/AutoGapple.cpp b/Horion/Module/Modules/AutoGapple.cpp new file mode 100644 index 0000000..e775f4f --- /dev/null +++ b/Horion/Module/Modules/AutoGapple.cpp @@ -0,0 +1,16 @@ +#include "AutoGapple.h" + +AutoGapple::AutoGapple() : IModule(0, Category::MOVEMENT, "Auto eat gapples if you're low health") { + registerIntSetting("health", &this->health, 10, 1, 20); +} + +AutoGapple::~AutoGapple() { +} + +const char* AutoGapple::getModuleName() { + return ("AutoGapple"); +} + +void AutoGapple::onTick(C_GameMode* gm) { + +} diff --git a/Horion/Module/Modules/AutoGapple.h b/Horion/Module/Modules/AutoGapple.h new file mode 100644 index 0000000..47be13f --- /dev/null +++ b/Horion/Module/Modules/AutoGapple.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" + +class AutoGapple : public IModule { +private: + int health; + +public: + C_MoveInputHandler* inputHandler = nullptr; + AutoGapple(); + ~AutoGapple(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/AutoSneak.cpp b/Horion/Module/Modules/AutoSneak.cpp new file mode 100644 index 0000000..c711b52 --- /dev/null +++ b/Horion/Module/Modules/AutoSneak.cpp @@ -0,0 +1,45 @@ +#include "AutoSneak.h" + +AutoSneak::AutoSneak() : IModule(0, Category::MOVEMENT, "Automatically sneak without holding the key") { + this->registerBoolSetting("silent", &this->doSilent, doSilent); +} + +AutoSneak::~AutoSneak() { +} + +const char* AutoSneak::getModuleName() { + return ("AutoSneak"); +} + +void AutoSneak::onTick(C_GameMode* gm) { + + if (!doSilent) + g_Data.getClientInstance()->getMoveTurnInput()->isSneakDown = true; +} + +void AutoSneak::onDisable() { + if (g_Data.getLocalPlayer() == nullptr) + return; + + if (!doSilent) { + g_Data.getClientInstance()->getMoveTurnInput()->isSneakDown = false; + return; + } + + C_PlayerActionPacket p; + p.action = 12; //stop crouch packet + p.entityRuntimeId = g_Data.getLocalPlayer()->entityRuntimeId; + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); +} + +void AutoSneak::onEnable() { + if (g_Data.getLocalPlayer() == nullptr) + return; //fixed crash + + if (doSilent) { + C_PlayerActionPacket p; + p.action = 11; //start crouch packet + p.entityRuntimeId = g_Data.getLocalPlayer()->entityRuntimeId; + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); + } +} diff --git a/Horion/Module/Modules/AutoSneak.h b/Horion/Module/Modules/AutoSneak.h new file mode 100644 index 0000000..bccd153 --- /dev/null +++ b/Horion/Module/Modules/AutoSneak.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class AutoSneak : public IModule { +private: + + +public: + bool doSilent = false; + AutoSneak(); + ~AutoSneak(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; + virtual void onEnable() override; +}; diff --git a/Horion/Module/Modules/AutoSprint.cpp b/Horion/Module/Modules/AutoSprint.cpp new file mode 100644 index 0000000..ca1d518 --- /dev/null +++ b/Horion/Module/Modules/AutoSprint.cpp @@ -0,0 +1,20 @@ +#include "AutoSprint.h" + +AutoSprint::AutoSprint() : IModule(0, Category::MOVEMENT, "Automatically sprint without holding the key") { + registerBoolSetting("all directions", &this->alldirections, this->alldirections); +} + +AutoSprint::~AutoSprint() { +} + +const char* AutoSprint::getModuleName() { + return ("AutoSprint"); +} + +void AutoSprint::onTick(C_GameMode* gm) { + if (!gm->player->isSprinting() && gm->player->velocity.magnitudexz() > 0.01f) { + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + if (alldirections || GameData::isKeyDown(*input->forwardKey)) + gm->player->setSprinting(true); + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/AutoSprint.h b/Horion/Module/Modules/AutoSprint.h new file mode 100644 index 0000000..3e36ef4 --- /dev/null +++ b/Horion/Module/Modules/AutoSprint.h @@ -0,0 +1,13 @@ +#pragma once +#include "Module.h" +class AutoSprint : public IModule { +private: + bool alldirections = true; + +public: + AutoSprint(); + ~AutoSprint(); + + virtual void onTick(C_GameMode* gm) override; + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/AutoTotem.cpp b/Horion/Module/Modules/AutoTotem.cpp new file mode 100644 index 0000000..9f97414 --- /dev/null +++ b/Horion/Module/Modules/AutoTotem.cpp @@ -0,0 +1,32 @@ +#include "AutoTotem.h" + +AutoTotem::AutoTotem() : IModule(0, Category::PLAYER, "Automatically puts totems into your offhand") { +} + +AutoTotem::~AutoTotem() { +} + +const char* AutoTotem::getModuleName() { + return ("AutoTotem"); +} + +void AutoTotem::onTick(C_GameMode* gm) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + C_ItemStack* current = g_Data.getLocalPlayer()->getEquippedTotem(); + if (current->item == NULL) { + for (int i = 0; i < 36; i++) { + C_ItemStack* totem = inv->getItemStack(i); + if (totem->item != NULL && (*totem->item)->itemId == 568) { + ItemDescriptor* desc = nullptr; + desc = new ItemDescriptor((*totem->item)->itemId, 0); + C_InventoryAction first(i, desc, nullptr, totem, nullptr, 1); + C_InventoryAction second(37, nullptr, desc, nullptr, totem, 1); + g_Data.getLocalPlayer()->setOffhandSlot(totem); + manager->addInventoryAction(first); + manager->addInventoryAction(second); + } + } + } +} diff --git a/Horion/Module/Modules/AutoTotem.h b/Horion/Module/Modules/AutoTotem.h new file mode 100644 index 0000000..042d826 --- /dev/null +++ b/Horion/Module/Modules/AutoTotem.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" + +class AutoTotem : public IModule { +public: + AutoTotem(); + ~AutoTotem(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Bhop.cpp b/Horion/Module/Modules/Bhop.cpp new file mode 100644 index 0000000..78293b5 --- /dev/null +++ b/Horion/Module/Modules/Bhop.cpp @@ -0,0 +1,39 @@ +#include "Bhop.h" + +Bhop::Bhop() : IModule(0, Category::MOVEMENT, "Hop around like a bunny!") { + registerFloatSetting("Speed", &this->speed, this->speed, 0.1f, 0.8f); +} + +Bhop::~Bhop() { +} + +const char* Bhop::getModuleName() { + return ("Bhop"); +} + +void Bhop::onMove(C_MoveInputHandler* input) { + auto player = g_Data.getLocalPlayer(); + if (player == nullptr) return; + + if (player->isInLava() == 1 || player->isInWater() == 1) + return; + + if (player->isSneaking()) + return; + + vec2_t moveVec2d = {input->forwardMovement, -input->sideMovement}; + bool pressed = moveVec2d.magnitude() > 0.01f; + + if (player->onGround && pressed) + player->jumpFromGround(); + + float calcYaw = (player->yaw + 90) * (PI / 180); + vec3_t moveVec; + float c = cos(calcYaw); + float s = sin(calcYaw); + moveVec2d = {moveVec2d.x * c - moveVec2d.y * s, moveVec2d.x * s + moveVec2d.y * c}; + moveVec.x = moveVec2d.x * speed; + moveVec.y = player->velocity.y; + moveVec.z = moveVec2d.y * speed; + if(pressed) player->lerpMotion(moveVec); +} diff --git a/Horion/Module/Modules/Bhop.h b/Horion/Module/Modules/Bhop.h new file mode 100644 index 0000000..811dd27 --- /dev/null +++ b/Horion/Module/Modules/Bhop.h @@ -0,0 +1,16 @@ +#pragma once +#include "..\ModuleManager.h" +#include "Module.h" + +class Bhop : public IModule { +private: + float speed = 0.325f; + +public: + Bhop(); + ~Bhop(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onMove(C_MoveInputHandler* input) override; +}; diff --git a/Horion/Module/Modules/Blink.cpp b/Horion/Module/Modules/Blink.cpp new file mode 100644 index 0000000..e758ba7 --- /dev/null +++ b/Horion/Module/Modules/Blink.cpp @@ -0,0 +1,17 @@ +#include "Blink.h" + +Blink::Blink() : IModule(0, Category::MISC, "Stops you from sending packets and then sends them in a bunch") { +} + +Blink::~Blink() { + this->getMovePlayerPacketHolder()->clear(); + this->getPlayerAuthInputPacketHolder()->clear(); +} + +const char* Blink::getModuleName() { + return ("Blink"); +} + +void Blink::onTick(C_GameMode* gm) { + gm->player->fallDistance = 0.f; +} diff --git a/Horion/Module/Modules/Blink.h b/Horion/Module/Modules/Blink.h new file mode 100644 index 0000000..d95d534 --- /dev/null +++ b/Horion/Module/Modules/Blink.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +class Blink : public IModule { +private: + std::vector MovePlayerPacketHolder; + std::vector PlayerAuthInputPacketHolder; + +public: + Blink(); + ~Blink(); + + // Inherited via IModule + virtual void onTick(C_GameMode* gm) override; + virtual const char* getModuleName() override; + + inline std::vector* getMovePlayerPacketHolder() { return &MovePlayerPacketHolder; }; + inline std::vector* getPlayerAuthInputPacketHolder() { return &PlayerAuthInputPacketHolder; }; +}; diff --git a/Horion/Module/Modules/BowAimbot.cpp b/Horion/Module/Modules/BowAimbot.cpp new file mode 100644 index 0000000..f94d76e --- /dev/null +++ b/Horion/Module/Modules/BowAimbot.cpp @@ -0,0 +1,104 @@ +#include "BowAimbot.h" + +#include "../../../Utils/Target.h" +#include "../../DrawUtils.h" + +std::vector targetList; + +BowAimbot::BowAimbot() : IModule(0, Category::COMBAT, "Aimbot, but for bows") { + registerBoolSetting("silent", &this->silent, this->silent); + registerBoolSetting("predict", &this->predict, this->predict); + registerBoolSetting("visualize", &this->visualize, this->visualize); +} + +BowAimbot::~BowAimbot() { +} + +struct CompareTargetEnArray { + bool operator()(C_Entity* lhs, C_Entity* rhs) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + return (*lhs->getPos()).dist(*localPlayer->getPos()) < (*rhs->getPos()).dist(*localPlayer->getPos()); + } +}; + +const char* BowAimbot::getModuleName() { + return ("BowAimbot"); +} + +void findTargets(C_Entity* currentEntity, bool isRegularEntitie) { + if (!Target::isValidTarget(currentEntity)) + return; + + float dist = (*currentEntity->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + + if (dist < 130) { + targetList.push_back(currentEntity); + } +} + +void BowAimbot::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + targetList.clear(); + + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + if (localPlayer == nullptr) + return; + + if (localPlayer->getSelectedItemId() != 300) // Bow in hand? + return; + + if (!(GameData::isRightClickDown() && GameData::canUseMoveKeys())) // is aiming? + return; + + g_Data.forEachEntity(findTargets); + + if (!targetList.empty()) { + std::sort(targetList.begin(), targetList.end(), CompareTargetEnArray()); + vec3_t origin = g_Data.getLocalPlayer()->eyePos0; // TODO: sort list + C_Entity* entity = targetList[0]; + vec3_t pos = entity->aabb.centerPoint(); + if (predict) { + vec3_t velocity = entity->getPos()->sub(*entity->getPosOld()); + velocity.x *= origin.dist(pos) / 2.f; + velocity.z *= origin.dist(pos) / 2.f; + pos = pos.add(velocity); + } + if(visualize) + DrawUtils::drawBox(pos.sub(0.5), pos.add(0.5), 0.3f, true); + pos = pos.sub(origin); + float yaw = (atan2f(pos.z, pos.x) * DEG_RAD) - 90; + float len = pos.magnitudexz(); + constexpr float g = 0.002f; // nukkit = 0.012, some servers need different values + float tmp = 1 - g * (g * (len * len) + 2 * pos.y); + float pitch = DEG_RAD * -atanf((1 - sqrtf(tmp)) / (g * len)); + + if (this->silent) { + this->angle = vec2_t(pitch, yaw); + C_MovePlayerPacket p(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + p.pitch = angle.x; + p.yaw = angle.y; + p.headYaw = angle.y; + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); + } else { + if (pitch < 89 && pitch > -89) { + vec2_t angles = vec2_t(pitch, yaw); + + vec2_t appl = angles.sub(localPlayer->viewAngles).normAngles(); + appl.x = -appl.x; + appl = appl.div(7); // Smooth dat boi + + localPlayer->applyTurnDelta(&appl); + } + } + } +} + +void BowAimbot::onSendPacket(C_Packet* packet) { + if (packet->isInstanceOf() && silent) { + if (!targetList.empty()) { + auto* movePacket = reinterpret_cast(packet); + movePacket->pitch = this->angle.x; + movePacket->headYaw = this->angle.y; + movePacket->yaw = this->angle.y; + } + } +} diff --git a/Horion/Module/Modules/BowAimbot.h b/Horion/Module/Modules/BowAimbot.h new file mode 100644 index 0000000..378ce3e --- /dev/null +++ b/Horion/Module/Modules/BowAimbot.h @@ -0,0 +1,17 @@ +#pragma once +#include "Module.h" +class BowAimbot : public IModule { +private: + bool silent = true; + bool predict = false; + bool visualize = false; + vec2_t angle; + +public: + BowAimbot(); + ~BowAimbot(); + + virtual const char* getModuleName() override; + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onSendPacket(C_Packet* packet) override; +}; diff --git a/Horion/Module/Modules/ChestAura.cpp b/Horion/Module/Modules/ChestAura.cpp new file mode 100644 index 0000000..5b35678 --- /dev/null +++ b/Horion/Module/Modules/ChestAura.cpp @@ -0,0 +1,44 @@ +#include "ChestAura.h" + +ChestAura::ChestAura() : IModule(0, Category::PLAYER, "Aura for opening chests") { + registerIntSetting("Range", &this->range, this->range, 1, 10); + registerBoolSetting("EnderChests", &this->enderchests, this->enderchests); +} + +ChestAura::~ChestAura() { +} + +const char* ChestAura::getModuleName() { + return ("ChestAura"); +} + +void ChestAura::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer()->getSupplies()->inventory->isFull()) + return; + + vec3_t* pos = gm->player->getPos(); + for (int x = (int)pos->x - range; x < pos->x + range; x++) { + for (int z = (int)pos->z - range; z < pos->z + range; z++) { + for (int y = (int)pos->y - range; y < pos->y + range; y++) { + vec3_ti pos = vec3_ti(x, y, z); + C_Block* block = gm->player->region->getBlock(pos); + if (block != nullptr && g_Data.canUseMoveKeys()) { + auto id = gm->player->region->getBlock(pos)->toLegacy()->blockId; + bool open = false; + if (id == 54) open = true; // Chests + if (id == 130 && enderchests) open = true; // EnderCheats + if (open) + if (!(std::find(chestlist.begin(), chestlist.end(), pos) != chestlist.end())) { + gm->buildBlock(&pos, 0); + chestlist.push_back(pos); + return; + } + } + } + } + } +} + +void ChestAura::onDisable() { + this->chestlist.clear(); // this code should be changed later, the chestlist has to be cleared when loading into a new world +} diff --git a/Horion/Module/Modules/ChestAura.h b/Horion/Module/Modules/ChestAura.h new file mode 100644 index 0000000..2ec53f6 --- /dev/null +++ b/Horion/Module/Modules/ChestAura.h @@ -0,0 +1,21 @@ +#pragma once +#include "..\ModuleManager.h" +#include "Module.h" + +class ChestAura : public IModule { +private: + int range = 3; + bool enderchests = false; + +public: + C_MoveInputHandler* inputHandler = nullptr; + ChestAura(); + ~ChestAura(); + + std::vector chestlist; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/ChestStealer.cpp b/Horion/Module/Modules/ChestStealer.cpp new file mode 100644 index 0000000..d00282b --- /dev/null +++ b/Horion/Module/Modules/ChestStealer.cpp @@ -0,0 +1,38 @@ +#include "ChestStealer.h" +#include "../ModuleManager.h" + +ChestStealer::ChestStealer() : IModule(0, Category::PLAYER, "Automatically takes all items out of a chest") { + registerIntSetting("Close Delay", &this->setDelay, this->setDelay, 0, 20); + registerBoolSetting("enhanced", &this->enhanced, this->enhanced); +} + +ChestStealer::~ChestStealer() { +} + +const char* ChestStealer::getModuleName() { + return ("ChestStealer"); +} + +void ChestStealer::chestScreenController_tick(C_ChestScreenController* c) { + if (c != nullptr && !g_Data.getLocalPlayer()->canOpenContainerScreen()) { + std::vector items = {}; + auto invcleanerMod = moduleMgr->getModule(); + for (int i = 0; i < 54; i++) { + C_ItemStack* stack = c->_getItemStack(TextHolder("container_items"), i); + if (stack != nullptr && stack->item != NULL) + if (!this->enhanced || invcleanerMod->stackIsUseful(stack)) + items.push_back(i); + } + if (!items.empty()) { + for (int i : items) { + c->handleAutoPlace(0x7FFFFFFF, "container_items", i); + } + } else { + delay++; + if (delay > setDelay) { + c->tryExit(); + delay = 0; + } + } + } +} diff --git a/Horion/Module/Modules/ChestStealer.h b/Horion/Module/Modules/ChestStealer.h new file mode 100644 index 0000000..0793493 --- /dev/null +++ b/Horion/Module/Modules/ChestStealer.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class ChestStealer : public IModule { +private: + int delay = 0; + int setDelay = 7; + bool enhanced = true; + +public: + ChestStealer(); + ~ChestStealer(); + + // Inherited via IModule + virtual void chestScreenController_tick(C_ChestScreenController* c); + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/ClickGuiMod.cpp b/Horion/Module/Modules/ClickGuiMod.cpp new file mode 100644 index 0000000..0ca5041 --- /dev/null +++ b/Horion/Module/Modules/ClickGuiMod.cpp @@ -0,0 +1,38 @@ +#include "ClickGuiMod.h" +#include "../../Menu/ClickGui.h" + +ClickGuiMod::ClickGuiMod() : IModule(VK_INSERT, Category::VISUAL, "The clickgui - toggle everything by just clicking on it!") { + registerBoolSetting("Show Tooltips", &this->showTooltips, this->showTooltips); +} + +ClickGuiMod::~ClickGuiMod() { +} + +const char* ClickGuiMod::getModuleName() { + return ("ClickGui"); +} + +void ClickGuiMod::onEnable() { + g_Data.getClientInstance()->releaseMouse(); +} + +bool ClickGuiMod::allowAutoStart() { + return false; +} + +void ClickGuiMod::onDisable() { + g_Data.getClientInstance()->grabMouse(); +} + +void ClickGuiMod::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + if (GameData::canUseMoveKeys()) + g_Data.getClientInstance()->releaseMouse(); +} +void ClickGuiMod::onLoadConfig(void* conf) { + IModule::onLoadConfig(conf); + ClickGui::onLoadConfig(conf); +} +void ClickGuiMod::onSaveConfig(void* conf) { + IModule::onSaveConfig(conf); + ClickGui::onSaveConfig(conf); +} diff --git a/Horion/Module/Modules/ClickGuiMod.h b/Horion/Module/Modules/ClickGuiMod.h new file mode 100644 index 0000000..46263fc --- /dev/null +++ b/Horion/Module/Modules/ClickGuiMod.h @@ -0,0 +1,19 @@ +#pragma once +#include "Module.h" + +class ClickGuiMod : public IModule { +public: + ClickGuiMod(); + ~ClickGuiMod(); + + bool showTooltips = true; + + // Inherited via IModule + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual const char* getModuleName() override; + virtual void onDisable() override; + virtual void onEnable() override; + virtual bool allowAutoStart() override; + virtual void onLoadConfig(void* conf) override; + virtual void onSaveConfig(void* conf) override; +}; diff --git a/Horion/Module/Modules/Compass.cpp b/Horion/Module/Modules/Compass.cpp new file mode 100644 index 0000000..7c704c3 --- /dev/null +++ b/Horion/Module/Modules/Compass.cpp @@ -0,0 +1,138 @@ +#include "Compass.h" + +#include "../ModuleManager.h" + +Compass::Compass() : IModule(0, Category::VISUAL, "Compass") { + registerFloatSetting("Opacity", &opacity, opacity, 0.1f, 1); + registerIntSetting("Range", &range, range, 45, 180); + registerBoolSetting("Show Waypoints", &showWaypoints, showWaypoints); +} + +Compass::~Compass() { +} + +const char* Compass::getModuleName() { + return "Compass"; +} + +void Compass::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + + if (player == nullptr || !GameData::canUseMoveKeys()) return; + + static auto wpMod = moduleMgr->getModule(); + + auto extraPoints = std::multimap{}; + + if (showWaypoints) { + auto waypoints = wpMod->getWaypoints(); + int curDim = 0; + player->getDimensionId(&curDim); + auto playerInterpPos = player->getPosOld()->lerp(player->getPos(), DrawUtils::getLerpTime()); + for (auto it = waypoints->begin(); it != waypoints->end(); it++) { + if (it->second.dimension != curDim) + continue; + int angle = (int)round(playerInterpPos.CalcAngle(it->second.pos).y + 180.0f) % 360; + if (angle < 0) angle += 360; + + extraPoints.insert(std::make_pair(angle, it->first)); + } + } + + std::vector stacking{}; + + const int deg = (int)(player->yaw + 180); + const float degSubOffset = 0; // -fmodf(player->yaw, 1) + const float sCenter = g_Data.getGuiData()->widthGame / 2; + + for (int off = -range; off <= range; off++) { + int oDeg = (deg + off) % 360; + if (oDeg < 0) oDeg += 360; + + const float xOff = sCenter + off + degSubOffset; + constexpr float fadeOutPos = 0.25f; + constexpr float centerCutoff = 5, centerFadeout = 10; + float majorOpacity = this->opacity; // big compass text + float minorOpacity = majorOpacity; // minor features, degree numbers + + // Fading logic + { + if ((range - abs(off)) < range * fadeOutPos) // Far from center + minorOpacity = majorOpacity = lerp(0, opacity, (range - abs(off)) / (range * fadeOutPos)); + else if (abs(off) < centerFadeout) // Close to center + minorOpacity = lerp(0, opacity, (abs(off) - centerCutoff) / (centerFadeout - centerCutoff)); + } + + switch (oDeg) { + case 0: + drawCenteredText(vec2_t(xOff, 30.f), "N", 1, majorOpacity); + break; + case 45: + drawCenteredText(vec2_t(xOff, 30.f), "NE", 1, majorOpacity); + break; + case 90: + drawCenteredText(vec2_t(xOff, 30.f), "E", 1, majorOpacity); + break; + case 135: + drawCenteredText(vec2_t(xOff, 30.f), "SE", 1, majorOpacity); + break; + case 180: + drawCenteredText(vec2_t(xOff, 30.f), "S", 1, majorOpacity); + break; + case 225: + drawCenteredText(vec2_t(xOff, 30.f), "SW", 1, majorOpacity); + break; + case 270: + drawCenteredText(vec2_t(xOff, 30.f), "W", 1, majorOpacity); + break; + case 315: + drawCenteredText(vec2_t(xOff, 30.f), "NW", 1, majorOpacity); + break; + } + auto result = extraPoints.equal_range(oDeg); + for (auto it = result.first; it != result.second; it++) { + std::string pName = it->second; + std::transform(pName.begin(), pName.end(), pName.begin(), ::toupper); + + vec2_t pos = vec2_t(xOff, 31.f); + + int overlapping = 0; + const float tSize = 0.75f; + const float tWidth = DrawUtils::getTextWidth(&pName, tSize); + pos.x -= tWidth / 2; + const vec2_t myTextRange = vec2_t(pos.x, pos.x + tWidth); + for (const vec2_t otherTextRange : stacking) { + // Check if other text overlaps us + if (myTextRange.x < otherTextRange.y && otherTextRange.x < myTextRange.y) { + overlapping++; + } + } + stacking.push_back(myTextRange); + pos.y += 5 * (overlapping + 1); + DrawUtils::drawText(pos, &pName, MC_Color(255, 255, 255), tSize, majorOpacity); + } + + if (off != 0 && minorOpacity > 0) { + if ((oDeg % 15) != 0) { + if ((oDeg % 5) == 0) { + DrawUtils::fillRectangle(vec4_t(xOff - 0.25f, 16, xOff + 0.25f, 19), MC_Color(255, 255, 255), minorOpacity); + } + continue; + } + + // Bigger line with degree displayed + DrawUtils::fillRectangle(vec4_t(xOff - 0.5f, 15, xOff + 0.5f, 20), MC_Color(255, 255, 255), minorOpacity); + drawCenteredText(vec2_t(xOff, 20.f), std::to_string(oDeg), 0.75f, minorOpacity); + } + } + + // Center line + DrawUtils::fillRectangle(vec4_t(sCenter - 0.5f, 15, sCenter + 0.5f, 25), MC_Color(255, 255, 255), opacity); + drawCenteredText(vec2_t(sCenter, 25.f), std::to_string(deg), 0.75f, opacity); + DrawUtils::flush(); +} + +void Compass::drawCenteredText(vec2_t pos, std::string text, float size, float textOpacity) { + pos.x -= DrawUtils::getTextWidth(&text, size) / 2; + DrawUtils::drawText(pos, &text, MC_Color(255, 255, 255), size, textOpacity); +} diff --git a/Horion/Module/Modules/Compass.h b/Horion/Module/Modules/Compass.h new file mode 100644 index 0000000..0c54cf3 --- /dev/null +++ b/Horion/Module/Modules/Compass.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +#include "../../DrawUtils.h" +class Compass : public IModule { +private: + float opacity = 0.5; + int range = 90; + bool showWaypoints = true; + void drawCenteredText(vec2_t pos, std::string text, float size, float textOpacity = 1); + +public: + Compass(); + ~Compass(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/Crasher.cpp b/Horion/Module/Modules/Crasher.cpp new file mode 100644 index 0000000..1871b09 --- /dev/null +++ b/Horion/Module/Modules/Crasher.cpp @@ -0,0 +1,35 @@ +#include "Crasher.h" + +Crasher::Crasher() : IModule(0, Category::MISC, "Crash Realms Servers") { +} + +Crasher::~Crasher() { +} + +const char* Crasher::getModuleName() { + return ("Crasher"); +} + +void Crasher::onEnable() { + if (g_Data.getLocalPlayer() == nullptr) + this->setEnabled(false); +} + +void Crasher::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer() == nullptr) + this->setEnabled(false); +} + +void Crasher::onSendPacket(C_Packet* packet) { + if (packet->isInstanceOf()) { + PlayerAuthInputPacket* InputPacket = reinterpret_cast(packet); + InputPacket->pos.x = static_cast(0xFFFFFFFF); + InputPacket->pos.y = static_cast(0xFFFFFFFF); + InputPacket->pos.z = static_cast(0xFFFFFFFF); + } else if (packet->isInstanceOf()) { + C_MovePlayerPacket* movePacket = reinterpret_cast(packet); + movePacket->Position.x = static_cast(0xFFFFFFFF); + movePacket->Position.y = static_cast(0xFFFFFFFF); + movePacket->Position.z = static_cast(0xFFFFFFFF); + } +} diff --git a/Horion/Module/Modules/Crasher.h b/Horion/Module/Modules/Crasher.h new file mode 100644 index 0000000..7533798 --- /dev/null +++ b/Horion/Module/Modules/Crasher.h @@ -0,0 +1,13 @@ +#pragma once +#include "Module.h" +class Crasher : public IModule { +public: + Crasher(); + ~Crasher(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onSendPacket(C_Packet* packet) override; + virtual void onEnable() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Criticals.cpp b/Horion/Module/Modules/Criticals.cpp new file mode 100644 index 0000000..39f8f10 --- /dev/null +++ b/Horion/Module/Modules/Criticals.cpp @@ -0,0 +1,18 @@ +#include "Criticals.h" + +Criticals::Criticals() : IModule(0, Category::COMBAT, "Each hit is a critical hit") { +} + +Criticals::~Criticals() { +} + +const char* Criticals::getModuleName() { + return ("Criticals"); +} + +void Criticals::onSendPacket(C_Packet* packet) { + if (packet->isInstanceOf() && g_Data.getLocalPlayer() != nullptr) { + C_MovePlayerPacket* movePacket = reinterpret_cast(packet); + movePacket->onGround = false; + } +} diff --git a/Horion/Module/Modules/Criticals.h b/Horion/Module/Modules/Criticals.h new file mode 100644 index 0000000..2079397 --- /dev/null +++ b/Horion/Module/Modules/Criticals.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class Criticals : public IModule { +public: + Criticals(); + ~Criticals(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onSendPacket(C_Packet* packet) override; +}; diff --git a/Horion/Module/Modules/CrystalAura.cpp b/Horion/Module/Modules/CrystalAura.cpp new file mode 100644 index 0000000..067a840 --- /dev/null +++ b/Horion/Module/Modules/CrystalAura.cpp @@ -0,0 +1,204 @@ +#include "CrystalAura.h" + +CrystalAura::CrystalAura() : IModule(VK_NUMPAD0, Category::COMBAT, "Destroys nearby Crystals") { + registerIntSetting("Range", &this->range, this->range, 1, 10); + registerIntSetting("Crystal range", &this->cRange, this->cRange, 1, 15); + registerIntSetting("Place range", &this->eRange, this->eRange, 1, 5); + registerIntSetting("Player range", &this->pRange, this->pRange, 1, 10); + registerBoolSetting("Auto select", &this->AutoSelect, this->AutoSelect); + registerBoolSetting("Autoplace", &this->autoplace, this->autoplace); + registerBoolSetting("Enhance place", &this->pEnhanced, this->pEnhanced); + registerBoolSetting("Enhance destroy", &this->dEnhanced, this->dEnhanced); + registerBoolSetting("preview", &this->Preview, this->Preview); + delay = 0; +} +CrystalAura::~CrystalAura() { +} +const char* CrystalAura::getModuleName() { + return ("CrystalAura"); +} + +static std::vector targetList; + +void CrystalAura::onEnable() { + targetList.clear(); + this->delay = 0; +} + +bool CfindEntity(C_Entity* curEnt, bool isRegularEntity) { + if (curEnt == nullptr) return false; + if (curEnt == g_Data.getLocalPlayer()) return false; // Skip Local player + if (!curEnt->isAlive()) return false; + if (!g_Data.getLocalPlayer()->isAlive()) return false; + if (curEnt->getEntityTypeId() == 71) return false; // endcrystal + if (curEnt->getEntityTypeId() == 66) return false; // falling block + if (curEnt->getEntityTypeId() == 64) return false; // item + if (curEnt->getEntityTypeId() == 69) return false; // xp orb + if (!Target::isValidTarget(curEnt)) return false; + + float dist = (*curEnt->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + if (dist <= moduleMgr->getModule()->pRange) { + targetList.push_back(curEnt); + return true; + } + return false; +} + +bool space = true; +vec3_t _pos; +bool CanPlaceC(vec3_ti* pos) { + space = true; + _pos = pos->toVec3t(); + g_Data.forEachEntity([](C_Entity* ent, bool b) { + if (!space) + return; + if (ent->aabb.intersects(AABB(_pos, _pos.add(1.f)))) + space = false; + }); + return space; +} + +void CrystalAura::CPlace(C_GameMode* gm, vec3_t* pos) { + if (!pEnhanced) { +#pragma warning(push) +#pragma warning(disable : 4244) + vec3_ti blockPos = vec3_ti(pos->x, pos->y, pos->z); + vec3_ti upperBlockPos = vec3_ti(pos->x, pos->y + 1, pos->z); +#pragma warning(pop) + C_Block* block = gm->player->region->getBlock(blockPos); + C_Block* upperBlock = gm->player->region->getBlock(upperBlockPos); + gm->buildBlock(&blockPos, g_Data.getClientInstance()->getPointerStruct()->blockSide); + return; + } + vec3_ti bestPos; + bool ValidPos = false; + for (int x = (int)pos->x - eRange; x < pos->x + eRange; x++) { + for (int z = (int)pos->z - eRange; z < pos->z + eRange; z++) { + for (int y = (int)pos->y - eRange; y < pos->y + eRange; y++) { + vec3_ti blockPos = vec3_ti(x, y, z); + vec3_ti upperBlockPos = vec3_ti(x, y + 1, z); + C_Block* block = gm->player->region->getBlock(blockPos); + C_Block* upperBlock = gm->player->region->getBlock(upperBlockPos); + if (block != nullptr) { + auto blockId = block->toLegacy()->blockId; + auto upperBlockId = upperBlock->toLegacy()->blockId; + if ((blockId == 49 || blockId == 7) && upperBlockId == 0 && CanPlaceC(&blockPos)) { //Check for awailable block + if (!ValidPos) { + ValidPos = true; + bestPos = blockPos; + } else if (blockPos.toVec3t().dist(*pos) < bestPos.toVec3t().dist(*pos)) { + bestPos = blockPos; + } + } + } + } + } + } + if (ValidPos) + gm->buildBlock(&bestPos, 0); +} + +void CrystalAura::DestroyC(C_Entity* ent, int range) { + if (g_Data.getLocalPlayer()->getPos()->dist(*ent->getPos()) < range && !dEnhanced) { + g_Data.getCGameMode()->attack(ent); + g_Data.getLocalPlayer()->swingArm(); + } else if (dEnhanced) { + for (auto& i : targetList) + if (ent->getPos()->dist(*i->getPos()) < range) { + g_Data.getCGameMode()->attack(ent); + g_Data.getLocalPlayer()->swingArm(); + return; + } + } +} + +bool shouldChange = false; +void CrystalAura::onTick(C_GameMode* gm) { + if (shouldChange) { + shouldChange = false; + } + this->delay++; + if (supplies == nullptr) + supplies = g_Data.getLocalPlayer()->getSupplies(); + if (inv == nullptr) + inv = supplies->inventory; + targetList.clear(); + g_Data.forEachEntity(CfindEntity); + if (this->delay == 0) { + // place block around players? + return; + } + + if (this->delay == 1 && AutoSelect) { + prevSlot = supplies->selectedHotbarSlot; + FinishSelect = true; + for (int n = 0; n < 9; n++) { + C_ItemStack* stack = inv->getItemStack(n); + if (stack->item != nullptr) { + if (stack->getItem()->itemId == 629) { + if (prevSlot != n) + supplies->selectedHotbarSlot = n; + return; + } + } + } + return; + } + if (this->delay == 2) { + if (autoplace && g_Data.getLocalPlayer()->getSelectedItemId() == 629) { //endcrystal + if (pEnhanced) + for (auto& i : targetList) + CPlace(gm, i->getPos()); + else { + auto ptr = g_Data.getClientInstance()->getPointerStruct(); + if (ptr->getEntity() == nullptr && ptr->rayHitType == 0) + CPlace(gm, &ptr->block.toFloatVector()); + } + } + return; + } + if (this->delay == 3 && FinishSelect) { + supplies->selectedHotbarSlot = prevSlot; + FinishSelect = false; + return; + } + if (this->delay == 4) { + g_Data.forEachEntity([](C_Entity* ent, bool b) { + if (ent->getEntityTypeId() != 71) + return; + int range; + if (moduleMgr->getModule()->dEnhanced) + range = moduleMgr->getModule()->cRange; + else + range = moduleMgr->getModule()->range; + moduleMgr->getModule()->DestroyC(ent, range); + }); + return; + } + if (this->delay >= 5) { + this->delay = 0; + return; + } +} + +void CrystalAura::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + if (!Preview || (!pEnhanced && autoplace) || + g_Data.getClientInstance() == nullptr || + g_Data.getPtrLocalPlayer() == nullptr || + g_Data.getLocalPlayer() == nullptr) + return; + + auto ptr = g_Data.getClientInstance()->getPointerStruct(); + if (ptr != nullptr) + if (ptr->getEntity() == nullptr && ptr->rayHitType == 0) + if (g_Data.getLocalPlayer()->region->getBlock(ptr->block)->toLegacy()->blockId == 49 || + g_Data.getLocalPlayer()->region->getBlock(ptr->block)->toLegacy()->blockId == 7) { + DrawUtils::setColor(.75f, .25f, .5f, 1.f); + DrawUtils::drawBox(ptr->block.toVec3t().add(0.f, 1.5f, 0.f), + ptr->block.add(1).toVec3t().add(0.f, 1.5f, 0.f), .3f); + } +} + +void CrystalAura::onDisable() { + this->delay = 0; +} \ No newline at end of file diff --git a/Horion/Module/Modules/CrystalAura.h b/Horion/Module/Modules/CrystalAura.h new file mode 100644 index 0000000..ca49607 --- /dev/null +++ b/Horion/Module/Modules/CrystalAura.h @@ -0,0 +1,37 @@ +#pragma once +#include "../../../Utils/Target.h" +#include "../ModuleManager.h" +#include "Module.h" + +class CrystalAura : public IModule { +private: + int prevSlot; + int delay = 0; + int eRange = 3; + bool autoplace = true; + bool pEnhanced = true; + bool dEnhanced = true; + bool Preview = true; + bool AutoSelect = true; + bool FinishSelect = false; + C_PlayerInventoryProxy* supplies = nullptr; + C_Inventory* inv = nullptr; + +public: + CrystalAura(); + ~CrystalAura(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onEnable() override; + virtual void onDisable() override; + + int cRange = 10; + int pRange = 5; + int range = 10; + + void CPlace(C_GameMode* gm, vec3_t* pos); + void DestroyC(C_Entity* ent, int range); +}; \ No newline at end of file diff --git a/Horion/Module/Modules/CubeGlide.cpp b/Horion/Module/Modules/CubeGlide.cpp new file mode 100644 index 0000000..b80fba8 --- /dev/null +++ b/Horion/Module/Modules/CubeGlide.cpp @@ -0,0 +1,55 @@ +#include "CubeGlide.h" + +CubeGlide::CubeGlide() : IModule(0, Category::MOVEMENT, "Glide on Cubecraft") { + registerFloatSetting("Speed", &this->speed, this->speed, 1.f, 3.f); +} + +CubeGlide::~CubeGlide() { +} + +const char* CubeGlide::getModuleName() { + return "CubeGlide"; +} + +bool CubeGlide::isFlashMode() { + return true; +} + +void CubeGlide::onEnable() { + g_Data.getLocalPlayer()->setPos((*g_Data.getLocalPlayer()->getPos()).add(vec3_t(0, 1, 0))); +} + +void CubeGlide::onTick(C_GameMode* gm) { + float calcYaw = (gm->player->yaw + 90) * (PI / 180); + + gameTick++; + + vec3_t pos = *g_Data.getLocalPlayer()->getPos(); + pos.y += 1.3f; + C_MovePlayerPacket a(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + pos.y -= 1.3f; + C_MovePlayerPacket a2(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a2); + + vec3_t moveVec; + moveVec.x = cos(calcYaw) * speed; + moveVec.z = sin(calcYaw) * speed; + + gm->player->lerpMotion(moveVec); + + if (gameTick >= 5) { + gameTick = 0; + float yaw = gm->player->yaw * (PI / 180); + float length = 4.f; + + float x = -sin(yaw) * length; + float z = cos(yaw) * length; + + gm->player->setPos(pos.add(vec3_t(x, 0.5f, z))); + } +} + +void CubeGlide::onDisable() { + g_Data.getLocalPlayer()->velocity = vec3_t(0, 0, 0); +} diff --git a/Horion/Module/Modules/CubeGlide.h b/Horion/Module/Modules/CubeGlide.h new file mode 100644 index 0000000..3515b3c --- /dev/null +++ b/Horion/Module/Modules/CubeGlide.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +class CubeGlide : public IModule { +private: + float speed = 1.5f; + int gameTick = 0; + +public: + CubeGlide(); + ~CubeGlide(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual bool isFlashMode() override; + virtual void onEnable() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Derp.cpp b/Horion/Module/Modules/Derp.cpp new file mode 100644 index 0000000..f671c8b --- /dev/null +++ b/Horion/Module/Modules/Derp.cpp @@ -0,0 +1,40 @@ +#include "Derp.h" + +Derp::Derp() : IModule(0, Category::MISC, "lol you stupid") { + this->registerBoolSetting("ihaveastroke", &this->epicStroke, this->epicStroke); + this->registerBoolSetting("packet mode", &this->packetMode, this->packetMode); +} + +Derp::~Derp() { +} + +const char* Derp::getModuleName() { + return "Derp"; +} + +void Derp::onTick(C_GameMode* gm) { + if (packetMode) { + C_MovePlayerPacket p(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + if (epicStroke) { + p.pitch = (float)(rand() % 360); + p.yaw = (float)(rand() % 360); + } else { + p.pitch = (float)(counter % 360); + p.yaw = (float)(counter % 360); + } + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); + } else { + if (epicStroke) { + gm->player->pitch = (float)(rand() % 360); + gm->player->bodyYaw = (float)(rand() % 360); + } else { + gm->player->pitch = (float)(counter % 360); + gm->player->bodyYaw = (float)(counter % 360); + } + } + + if (counter < 360) + counter++; + else + counter = 0; +} diff --git a/Horion/Module/Modules/Derp.h b/Horion/Module/Modules/Derp.h new file mode 100644 index 0000000..f84386b --- /dev/null +++ b/Horion/Module/Modules/Derp.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class Derp : public IModule { +private: + int counter = 0; + bool epicStroke = false; + bool packetMode = false; + +public: + Derp(); + ~Derp(); + + // Inherited via IModule + virtual void onTick(C_GameMode* gm) override; + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/ESP.cpp b/Horion/Module/Modules/ESP.cpp new file mode 100644 index 0000000..e5ad7dd --- /dev/null +++ b/Horion/Module/Modules/ESP.cpp @@ -0,0 +1,77 @@ +#include "ESP.h" + +#include "../../../Utils/Target.h" + +ESP::ESP() : IModule('O', Category::VISUAL, "Makes it easier to find entities around you") { + this->registerBoolSetting("rainbow", &this->doRainbow, this->doRainbow); + this->registerBoolSetting("MobEsp", &this->isMobEsp, this->isMobEsp); + this->registerBoolSetting("2d", &this->is2d, this->is2d); +} + +ESP::~ESP() { +} + +const char* ESP::getModuleName() { + return ("ESP"); +} + +static float rcolors[4]; + +void doRenderStuff(C_Entity* ent, bool isRegularEntitie) { + static auto espMod = moduleMgr->getModule(); + + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + if (ent == localPlayer) + return; + if (ent->timeSinceDeath > 0) + return; + static auto noFriendsModule = moduleMgr->getModule(); + if (!noFriendsModule->isEnabled() && FriendList::findPlayer(ent->getNameTag()->getText())) { + DrawUtils::setColor(0.1f, 0.9f, 0.1f, (float)fmax(0.1f, (float)fmin(1.f, 15 / (ent->damageTime + 1)))); + } else if (Target::isValidTarget(ent)) { + if (espMod->doRainbow) + DrawUtils::setColor(rcolors[0], rcolors[1], rcolors[2], (float)fmax(0.1f, (float)fmin(1.f, 15 / (ent->damageTime + 1)))); + else + DrawUtils::setColor(0.9f, 0.9f, 0.9f, (float)fmax(0.1f, (float)fmin(1.f, 15 / (ent->damageTime + 1)))); + } else if (espMod->isMobEsp) { + if (ent->getNameTag()->getTextLength() <= 1 && ent->getEntityTypeId() == 63) + return; + + if (ent->isInvisible()) + return; + + if (!localPlayer->canAttack(ent, false)) + return; + if (espMod->doRainbow) + DrawUtils::setColor(rcolors[0], rcolors[1], rcolors[2], (float)fmax(0.1f, (float)fmin(1.f, 15 / (ent->damageTime + 1)))); + else + DrawUtils::setColor(0.9f, 0.9f, 0.9f, (float)fmax(0.1f, (float)fmin(1.f, 15 / (ent->damageTime + 1)))); + } else + return; + if (espMod->is2d) + DrawUtils::draw2D(ent, (float)fmax(0.4f, 1 / (float)fmax(1, localPlayer->getPos()->dist(*ent->getPos()) * 3.f))); + else + DrawUtils::drawEntityBox(ent, (float)fmax(0.2f, 1 / (float)fmax(1, localPlayer->getPos()->dist(*ent->getPos())))); + + +} + +void ESP::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + + if (localPlayer != nullptr && GameData::canUseMoveKeys()) { + // Rainbow colors + { + if (rcolors[3] < 1) { + rcolors[0] = 0.2f; + rcolors[1] = 0.2f; + rcolors[2] = 1.f; + rcolors[3] = 1; + } + + Utils::ApplyRainbow(rcolors, 0.0015f); + } + + g_Data.forEachEntity(doRenderStuff); + } +} diff --git a/Horion/Module/Modules/ESP.h b/Horion/Module/Modules/ESP.h new file mode 100644 index 0000000..7aede33 --- /dev/null +++ b/Horion/Module/Modules/ESP.h @@ -0,0 +1,17 @@ +#pragma once + +#include "Module.h" +#include "../ModuleManager.h" + +class ESP : public IModule { +public: + bool isMobEsp = false; + bool doRainbow = true; + bool is2d = false; + ESP(); + ~ESP(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/EditionFaker.cpp b/Horion/Module/Modules/EditionFaker.cpp new file mode 100644 index 0000000..3698821 --- /dev/null +++ b/Horion/Module/Modules/EditionFaker.cpp @@ -0,0 +1,17 @@ +#include "EditionFaker.h" + +EditionFaker::EditionFaker() : IModule(0, Category::MISC, "Fakes your device to android") { +} + +EditionFaker::~EditionFaker() { +} + +int EditionFaker::getFakedEditon() { + // static const char* gameEditons[] = { "Unknown", "Android", "iOS", "macOS", "FireOS", "GearVR", "HoloLens", "Windows 10 (PC)", "Windows", "Dedicated", "Orbis", "NX" }; + + return 1; // Android +} + +const char* EditionFaker::getModuleName() { + return ("EditionFaker"); +} diff --git a/Horion/Module/Modules/EditionFaker.h b/Horion/Module/Modules/EditionFaker.h new file mode 100644 index 0000000..d4930b0 --- /dev/null +++ b/Horion/Module/Modules/EditionFaker.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" +class EditionFaker : public IModule { +public: + EditionFaker(); + ~EditionFaker(); + + int getFakedEditon(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/ExtendedBlockReach.cpp b/Horion/Module/Modules/ExtendedBlockReach.cpp new file mode 100644 index 0000000..20985e7 --- /dev/null +++ b/Horion/Module/Modules/ExtendedBlockReach.cpp @@ -0,0 +1,12 @@ +#include "ExtendedBlockReach.h" + +ExtendedBlockReach::ExtendedBlockReach() : IModule(0, Category::PLAYER, "Exteneded reach for placing/breaking blocks") { + this->registerFloatSetting(std::string("reach"), &this->blockReach, this->blockReach, 7, 20); +} + +ExtendedBlockReach::~ExtendedBlockReach() { +} + +const char* ExtendedBlockReach::getModuleName() { + return ("ExtendedBlockReach"); +} diff --git a/Horion/Module/Modules/ExtendedBlockReach.h b/Horion/Module/Modules/ExtendedBlockReach.h new file mode 100644 index 0000000..6d308c6 --- /dev/null +++ b/Horion/Module/Modules/ExtendedBlockReach.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" + +class ExtendedBlockReach : public IModule { +private: + float blockReach = 7.f; + +public: + ExtendedBlockReach(); + ~ExtendedBlockReach(); + + inline float getBlockReach() { return blockReach; }; + inline void setBlockReach(float reach) { blockReach = reach; }; + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/FastEast.cpp b/Horion/Module/Modules/FastEast.cpp new file mode 100644 index 0000000..28638ec --- /dev/null +++ b/Horion/Module/Modules/FastEast.cpp @@ -0,0 +1,35 @@ +#include "FastEat.h" + +FastEat::FastEat() : IModule(0, Category::PLAYER, "Eat food almost instant") { +} + +FastEat::~FastEat() { +} + +const char* FastEat::getModuleName() { + return ("FastEat"); +} + +void FastEat::onTick(C_GameMode* gm) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + for (int i = 0; i < 36; i++) { + C_ItemStack* stack = inv->getItemStack(i); + if (stack->item != NULL && (*stack->item)->itemId != 261 && (*stack->item)->duration == 32) { + (*stack->item)->setMaxUseDuration(5); + } + } +} + +void FastEat::onDisable() { + if (g_Data.getLocalPlayer() == nullptr) + return; + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + for (int i = 0; i < 36; i++) { + C_ItemStack* stack = inv->getItemStack(i); + if (stack->item != NULL && (*stack->item)->itemId != 261 && (*stack->item)->duration == 5) { + (*stack->item)->setMaxUseDuration(32); + } + } +} diff --git a/Horion/Module/Modules/FastEat.h b/Horion/Module/Modules/FastEat.h new file mode 100644 index 0000000..7759209 --- /dev/null +++ b/Horion/Module/Modules/FastEat.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" +class FastEat : public IModule { +public: + FastEat(); + ~FastEat(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/FastLadder.cpp b/Horion/Module/Modules/FastLadder.cpp new file mode 100644 index 0000000..ee85078 --- /dev/null +++ b/Horion/Module/Modules/FastLadder.cpp @@ -0,0 +1,12 @@ +#include "FastLadder.h" + +FastLadder::FastLadder() : IModule(0, Category::MOVEMENT, "Climb up ladders faster") { + registerFloatSetting("Speed", &this->speed, this->speed, 0.1f, 1.0f); +} + +FastLadder::~FastLadder() { +} + +const char* FastLadder::getModuleName() { + return ("FastLadder"); +} diff --git a/Horion/Module/Modules/FastLadder.h b/Horion/Module/Modules/FastLadder.h new file mode 100644 index 0000000..3d2849e --- /dev/null +++ b/Horion/Module/Modules/FastLadder.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" +class FastLadder : public IModule { +public: + float speed = 0.6f; + + FastLadder(); + ~FastLadder(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Fly.cpp b/Horion/Module/Modules/Fly.cpp new file mode 100644 index 0000000..3edec2a --- /dev/null +++ b/Horion/Module/Modules/Fly.cpp @@ -0,0 +1,88 @@ +#include "Fly.h" + +Fly::Fly() : IModule(0, Category::MOVEMENT, "Enables fly like in creative mode") { + mode = (*new SettingEnum(this)).addEntry(EnumEntry("Fly", 1)).addEntry(EnumEntry("CubeGlide", 2)); + registerEnumSetting("Mode", &mode, 0); + registerFloatSetting("CubeGlide Speed", &this->speed, this->speed, 1.f, 3.f); +} + +Fly::~Fly() { +} + + + +const char* Fly::getModuleName() { + return ("Fly"); +} + +bool Fly::isFlashMode() { + switch (mode.selected) { + case 0: + return false; + break; + case 1: + return true; + break; + } + return false; +} + +void Fly::onEnable() { + if (mode.selected == 1) { + g_Data.getLocalPlayer()->setPos((*g_Data.getLocalPlayer()->getPos()).add(vec3_t(0, 1, 0))); + } +} + + +void Fly::onTick(C_GameMode* gm) { + gm->player->canFly = true; + + switch (mode.selected) { + case 0: + gm->player->canFly = true; + break; + case 1: + float calcYaw = (gm->player->yaw + 90) * (PI / 180); + + gameTick++; + + vec3_t pos = *g_Data.getLocalPlayer()->getPos(); + pos.y += 1.3f; + C_MovePlayerPacket a(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + pos.y -= 1.3f; + C_MovePlayerPacket a2(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a2); + + vec3_t moveVec; + moveVec.x = cos(calcYaw) * speed; + moveVec.z = sin(calcYaw) * speed; + + gm->player->lerpMotion(moveVec); + + if (gameTick >= 5) { + gameTick = 0; + float yaw = gm->player->yaw * (PI / 180); + float length = 4.f; + + float x = -sin(yaw) * length; + float z = cos(yaw) * length; + + gm->player->setPos(pos.add(vec3_t(x, 0.5f, z))); + } + break; + } + +} + +void Fly::onDisable() { + switch (mode.selected) { + case 0: + if (g_Data.getLocalPlayer() != nullptr) + if (g_Data.getLocalPlayer()->gamemode != 1) + g_Data.getLocalPlayer()->canFly = false; + break; + case 1: + g_Data.getLocalPlayer()->velocity = vec3_t(0, 0, 0); + } +} diff --git a/Horion/Module/Modules/Fly.h b/Horion/Module/Modules/Fly.h new file mode 100644 index 0000000..f27fad6 --- /dev/null +++ b/Horion/Module/Modules/Fly.h @@ -0,0 +1,20 @@ +#pragma once +#include "Module.h" +class Fly : public IModule { +private: + float speed = 1.5f; + int gameTick = 0; + +public: + Fly(); + ~Fly(); + + SettingEnum mode; + + // Inherited via IModule + virtual bool isFlashMode() override; + virtual void onEnable() override; + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/FollowPathModule.cpp b/Horion/Module/Modules/FollowPathModule.cpp new file mode 100644 index 0000000..44a52b1 --- /dev/null +++ b/Horion/Module/Modules/FollowPathModule.cpp @@ -0,0 +1,171 @@ +#include "FollowPathModule.h" + +#include "../../../Utils/Logger.h" + +FollowPathModule::FollowPathModule() : IModule(0, Category::MOVEMENT, "Follows joe paths") {} + +const char *FollowPathModule::getModuleName() { + return "FollowPath"; +} + +void FollowPathModule::startSearch(vec3_ti startNode, C_BlockSource* region, float searchTimeout, std::function callback){ + if(this->pathFinder){ + logF("Already searching!"); + return; + } + this->pathFinder = std::make_shared(startNode, region, this->goal); + this->pathFinder->pathSearchTimeout = searchTimeout; + //std::thread([this, callback](){ + auto ref = this->pathFinder; // so it won't get deleted when followpathmodule is disabled + auto tempPath = this->pathFinder->findPath(); + this->pathFinder.reset(); + if(tempPath.getNumSegments() == 0 || !this->isEnabled()){ + callback(false, tempPath); + return; + } + callback(true, tempPath); + //}).detach(); +} + + +bool shouldStartSearch = false; +void FollowPathModule::onEnable() { + if(!g_Data.isInGame() || !g_Data.getLocalPlayer()->isAlive()){ + setEnabled(false); + return; + } + + if(!this->goal){ + logF("goal not set"); + setEnabled(false); + return; + } + shouldStartSearch = true; +} + +void FollowPathModule::onDisable() { + shouldStartSearch = false; + if(this->pathFinder) + this->pathFinder->terminateSearch = true; + this->engageDelay = -1; + + this->pathFinder.reset(); + this->path.reset(); + this->nextPath.reset(); + this->movementController.reset(); + this->goal.reset(); +} + +void FollowPathModule::onTick(C_GameMode *mode) { + if (!shouldStartSearch) + return; + shouldStartSearch = false; + + auto player = g_Data.getLocalPlayer(); + auto pPos = player->eyePos0; + vec3_ti startNode((int)floorf(pPos.x), (int)roundf(pPos.y - 1.62f), (int)floorf(pPos.z)); + + this->startSearch(startNode, player->region, 0.5f, [&](bool succeeded, JoePath tempPath) { + if (!succeeded) { + this->clientMessageF("%sCould not find a path!", RED); + this->path.reset(); + this->movementController.reset(); + this->setEnabled(false); + this->engageDelay = -1; + return; + } + + this->clientMessageF("%sFound %s path!", tempPath.isIncomplete1() ? YELLOW : GREEN, tempPath.isIncomplete1() ? "incomplete" : "complete"); + + if (tempPath.isIncomplete1()) { + tempPath.cutoff(0.9f); + } + this->engageDelay = 10; + + this->path = std::make_shared(tempPath.getAllSegments(), tempPath.isIncomplete1()); + this->movementController = std::make_unique(path); + }); +} + +void FollowPathModule::onMove(C_MoveInputHandler *handler) { + if(this->movementController){ + this->movementController->step(g_Data.getLocalPlayer(), g_Data.getClientInstance()->getMoveTurnInput()); + if(this->engageDelay > 0) + this->engageDelay--; + + if(this->movementController->isDone()){ + if(this->movementController->getCurrentPath()->isIncomplete1()){ + // Replace with next path if it exists + if(this->nextPath && !pathFinder){ + this->clientMessageF("%sContinuing on next path...", GREEN); + + this->path = this->nextPath; + this->nextPath.reset(); + this->movementController = std::make_unique(path); + }else if(!pathFinder){ + this->setEnabled(false); + }else if(g_Data.getLocalPlayer()->isInWater()){ + handler->isJumping = true; + } + }else{ + this->clientMessageF("%sDone!", GREEN); + this->setEnabled(false); + return; + } + }else if(!this->pathFinder && this->engageDelay == 0 && this->path && this->path->isIncomplete1() && !this->nextPath){ + this->engageDelay = 10; + + // Estimate time to completion + auto curPath = this->movementController->getCurrentPath(); + float timeSpent = 0; + if(curPath->getNumSegments() == 0){ + this->setEnabled(false); + return; + } + for(size_t i = curPath->getNumSegments() - 1; i > this->movementController->getCurrentPathSegment(); i--){ + auto cur = curPath->getSegment(i); + timeSpent += cur.getCost(); + if(timeSpent > 11) + break; + } + + if(timeSpent > 11) + return; + + this->clientMessageF("%sCalculating next path...", YELLOW); + + float timeForSearch = std::clamp(timeSpent - 0.5f, 1.f, 3.f); + auto lastSeg = curPath->getSegment(curPath->getNumSegments() - 1); + this->nextPath.reset(); + this->startSearch(lastSeg.getEnd(), g_Data.getLocalPlayer()->region, timeForSearch, [&](bool succeeded, JoePath tempPath){ + if(!succeeded){ + this->clientMessageF("%sCould not find subsequent path!", RED); + + this->engageDelay = -1; + return; + } + + this->clientMessageF("%sFound subsequent %s path!", tempPath.isIncomplete1() ? YELLOW : GREEN, tempPath.isIncomplete1() ? "incomplete" : "complete"); + + if(tempPath.isIncomplete1()){ + tempPath.cutoff(0.9f); + } + + this->nextPath = std::make_shared(tempPath.getAllSegments(), tempPath.isIncomplete1()); + }); + } + } +} +void FollowPathModule::onLevelRender() { + if(!g_Data.isInGame()){ + this->setEnabled(false); + return; + } + + if(this->movementController && this->path){ + this->path->draw(this->movementController->getCurrentPathSegment()); + } /* else if (this->pathFinder) { + JoePath localPath = this->pathFinder->getCurrentPath(); + localPath.draw(-1); // copy so we avoid drawing while its being updated by the pathfinder + }*/ +} diff --git a/Horion/Module/Modules/FollowPathModule.h b/Horion/Module/Modules/FollowPathModule.h new file mode 100644 index 0000000..072d5e9 --- /dev/null +++ b/Horion/Module/Modules/FollowPathModule.h @@ -0,0 +1,28 @@ +#pragma once + +#include "Module.h" +#include "../../path/JoePathFinder.h" +#include "../../path/JoeMovementController.h" +#include "../../path/goals/JoeGoal.h" +#include + +class FollowPathModule : public IModule { +private: + std::shared_ptr pathFinder; + std::unique_ptr movementController; + std::shared_ptr path; + std::shared_ptr nextPath; + int engageDelay = -1; +public: + std::shared_ptr goal; + + FollowPathModule(); + + const char *getModuleName() override; + void startSearch(vec3_ti startNode, C_BlockSource* region, float searchTimeout, std::function callback); + void onTick(C_GameMode *mode) override; + void onEnable() override; + void onDisable() override; + void onLevelRender() override; + void onMove(C_MoveInputHandler *handler) override; +}; diff --git a/Horion/Module/Modules/Freecam.cpp b/Horion/Module/Modules/Freecam.cpp new file mode 100644 index 0000000..3df1083 --- /dev/null +++ b/Horion/Module/Modules/Freecam.cpp @@ -0,0 +1,59 @@ +#include "Freecam.h" + +Freecam::Freecam() : IModule('V', Category::MISC, "Move your cam without moving the player") { + registerFloatSetting("Speed", &this->speed, this->speed, 0.50f, 1.25f); +} + +Freecam::~Freecam() { +} + +const char* Freecam::getModuleName() { + return ("Freecam"); +} + +void Freecam::onTick(C_GameMode* gm) { + gm->player->fallDistance = 0.f; + gm->player->velocity = vec3_t(0, 0, 0); + gm->player->aabb.upper = gm->player->aabb.lower; +} + +void Freecam::onEnable() { + if (g_Data.getLocalPlayer() != nullptr) { + oldPos = *g_Data.getLocalPlayer()->getPos(); + oldOffset = g_Data.getLocalPlayer()->aabb.upper.sub(g_Data.getLocalPlayer()->aabb.lower); + } +} + +void Freecam::onMove(C_MoveInputHandler* input) { + auto player = g_Data.getLocalPlayer(); + if (player == nullptr) return; + + vec2_t moveVec2d = {input->forwardMovement, -input->sideMovement}; + bool pressed = moveVec2d.magnitude() > 0.01f; + + float calcYaw = (player->yaw + 90) * (PI / 180); + vec3_t moveVec; + float c = cos(calcYaw); + float s = sin(calcYaw); + moveVec2d = {moveVec2d.x * c - moveVec2d.y * s, moveVec2d.x * s + moveVec2d.y * c}; + moveVec.x = moveVec2d.x * speed; + moveVec.y = player->velocity.y; + moveVec.z = moveVec2d.y * speed; + if (pressed) player->lerpMotion(moveVec); + C_MovePlayerPacket p(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + if (input->isJumping) { + player->velocity.y += 0.50f; + } + if (input->isSneakDown) { + player->velocity.y -= 0.50f; + } +} + +void Freecam::onDisable() { + auto plr = g_Data.getLocalPlayer(); + if (plr) { + plr->setPos(oldPos); + *g_Data.getClientInstance()->minecraft->timer = 20.f; + plr->aabb.upper = plr->aabb.lower.add(oldOffset); + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/Freecam.h b/Horion/Module/Modules/Freecam.h new file mode 100644 index 0000000..1c0ba02 --- /dev/null +++ b/Horion/Module/Modules/Freecam.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +class Freecam : public IModule { +private: + vec3_t oldPos; + vec3_t oldOffset = {}; + float speed = 0.325f; +public: + Freecam(); + ~Freecam(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onMove(C_MoveInputHandler* input) override; + virtual void onEnable() override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Freelook.cpp b/Horion/Module/Modules/Freelook.cpp new file mode 100644 index 0000000..01550d4 --- /dev/null +++ b/Horion/Module/Modules/Freelook.cpp @@ -0,0 +1,86 @@ +#include "Freelook.h" + +#include "../../../Utils/Logger.h" + +Freelook::Freelook(): IModule(0, Category::VISUAL, "Move straight while moving your camera around") { +} +Freelook::~Freelook() { +} +const char* Freelook::getModuleName() { + return "Freelook"; +} +vec2_t mouseEnd = {0, 0}; +void Freelook::onEnable() { + if(!g_Data.isInGame() || this->resetViewTick > -1){ + this->setEnabled(false); + return; + } + + this->redirectMouse = true; + this->resetViewTick = -1; + this->initialViewAngles = g_Data.getLocalPlayer()->viewAngles; + this->lastCameraAngle = {0, 0}; +} +void Freelook::onDisable() { + if(g_Data.isInGame() && this->resetViewTick == -1 && this->redirectMouse){ + + this->resetViewTick = this->isThirdPerson ? 0 : 100; // give it time + if(this->cameraFacesFront){ + lastCameraAngle.y += 180; + lastCameraAngle = lastCameraAngle.normAngles(); + mouseEnd = this->lastCameraAngle; + + initialViewAngles.y += 180; + initialViewAngles = initialViewAngles.normAngles(); + } else { + mouseEnd = this->lastCameraAngle; + mouseEnd.y += 180; + } + }else if(!g_Data.isInGame()){ + this->resetViewTick = -1; + this->redirectMouse = false; + } +} +void Freelook::onPostRender(C_MinecraftUIRenderContext* mode) { + if(!this->redirectMouse) + return; + if(!g_Data.isInGame()){ + this->setEnabled(false); + return; + } + + if(this->resetViewTick > 0){ + this->resetViewTick--; + + if(this->cameraFacesFront){ + this->lastCameraAngle.x *= -1; + } + vec2_t appl = this->initialViewAngles; + appl = appl.sub(this->lastCameraAngle).normAngles(); + appl.x = this->initialViewAngles.x - this->lastCameraAngle.x; // dont norm this angle + if(appl.magnitude() < 0.1f) + this->resetViewTick = 0; + + appl = appl.div(fmaxf(1, appl.magnitude() / 15)); + + this->lastCameraAngle = this->lastCameraAngle.add(appl); + if(this->cameraFacesFront){ + this->lastCameraAngle.x *= -1; + } + } +} +void Freelook::onTick(C_GameMode* mode) { + if(this->resetViewTick == 0){ + this->redirectMouse = false; + this->resetViewTick = -1; + auto loc = g_Data.getLocalPlayer(); + vec2_t l = initialViewAngles; + l = l.sub(mouseEnd).normAngles(); + l.x = this->initialViewAngles.x - mouseEnd.x; // dont norm this angle + + l.x *= -1; + loc->applyTurnDelta(&l); + + this->lastCameraAngle = {0, 0}; + } +} diff --git a/Horion/Module/Modules/Freelook.h b/Horion/Module/Modules/Freelook.h new file mode 100644 index 0000000..faed410 --- /dev/null +++ b/Horion/Module/Modules/Freelook.h @@ -0,0 +1,28 @@ +#pragma once +#include "Module.h" + +class Freelook : public IModule { +private: + vec2_t initialViewAngles = {}; +public: + int resetViewTick = -1; + vec2_t lastCameraAngle = {0, 0}; + bool redirectMouse = false; + bool isThirdPerson = false; + bool cameraFacesFront = false; + + Freelook(); + ~Freelook(); + + virtual const char* getModuleName() override; + bool isFlashMode() override { + return true; + } + void onTick(C_GameMode* mode) override; + void onEnable() override; + void onDisable() override; + void onPostRender(C_MinecraftUIRenderContext* ctx) override; + bool callWhenDisabled() override { + return true; + } +}; diff --git a/Horion/Module/Modules/Fucker.cpp b/Horion/Module/Modules/Fucker.cpp new file mode 100644 index 0000000..8435a01 --- /dev/null +++ b/Horion/Module/Modules/Fucker.cpp @@ -0,0 +1,61 @@ +#include "Fucker.h" + +Fucker::Fucker() : IModule(VK_NUMPAD9, Category::MISC, "Destroys certain blocks around you") { + registerIntSetting("Range", &this->range, this->range, 1, 10); + registerBoolSetting("Beds", &this->beds, this->beds); + registerBoolSetting("Eggs", &this->eggs, this->eggs); + registerBoolSetting("Cakes", &this->cakes, this->cakes); + registerBoolSetting("Treasures", &this->treasures, this->treasures); + registerBoolSetting("Chests", &this->chests, this->chests); + registerBoolSetting("Barrels", &this->barrels, this->barrels); +} + +Fucker::~Fucker() { +} + +const char* Fucker::getModuleName() { + return ("Fucker"); +} + +void Fucker::onTick(C_GameMode* gm) { + vec3_t* pos = gm->player->getPos(); + for (int x = (int)pos->x - range; x < pos->x + range; x++) { + for (int z = (int)pos->z - range; z < pos->z + range; z++) { + for (int y = (int)pos->y - range; y < pos->y + range; y++) { + vec3_ti blockPos = vec3_ti(x, y, z); + bool destroy = false; + bool eat = false; + auto id = gm->player->region->getBlock(blockPos)->toLegacy()->blockId; + + if (id == 26 && this->beds) destroy = true; // Beds + if (id == 122 && this->eggs) destroy = true; // Dragon Eggs + if (id == 92 && this->cakes) eat = true; // Cakes + if (id == 54 && this->chests) destroy = true; // Chests + if (id == 458 && this->barrels) destroy = true; // Barrels + + if (destroy) { + gm->destroyBlock(&blockPos, 0); + g_Data.getLocalPlayer()->swingArm(); + return; + } + + if (eat) { + gm->buildBlock(&blockPos, 0); + g_Data.getLocalPlayer()->swingArm(); + return; + } + } + } + } + + if (this->treasures) { + g_Data.forEachEntity([](C_Entity* ent, bool b) { + std::string name = ent->getNameTag()->getText(); + int id = ent->getEntityTypeId(); + if (name.find("Treasure") != std::string::npos && g_Data.getLocalPlayer()->getPos()->dist(*ent->getPos()) <= 5) { + g_Data.getLocalPlayer()->swingArm(); + g_Data.getCGameMode()->attack(ent); + } + }); + } +} diff --git a/Horion/Module/Modules/Fucker.h b/Horion/Module/Modules/Fucker.h new file mode 100644 index 0000000..5585a9d --- /dev/null +++ b/Horion/Module/Modules/Fucker.h @@ -0,0 +1,22 @@ +#pragma once +#include "Module.h" +#include "../ModuleManager.h" + +class Fucker : public IModule { +private: + int range = 5; + bool beds = true; + bool eggs = true; + bool cakes = true; + bool treasures = true; + bool chests = false; + bool barrels = false; + +public: + Fucker(); + ~Fucker(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/FullBright.cpp b/Horion/Module/Modules/FullBright.cpp new file mode 100644 index 0000000..bc6a0f8 --- /dev/null +++ b/Horion/Module/Modules/FullBright.cpp @@ -0,0 +1,36 @@ +#include "FullBright.h" + +FullBright::FullBright() : IModule(0, Category::VISUAL, "Puts your gamma to max") { + registerFloatSetting("Intensity", &this->intensity, this->intensity, -25.f, 25.f); +} + +FullBright::~FullBright() { +} + +float originalGamma = -1; + +const char* FullBright::getModuleName() { + return "Fullbright"; +} + +void FullBright::onTick(C_GameMode* gm) { + if (gammaPtr != nullptr && *gammaPtr != 10) + *gammaPtr = 10; +} + +void FullBright::onEnable() { + if (gammaPtr != nullptr) { + originalGamma = *gammaPtr; + *gammaPtr = 10; + } +} + +void FullBright::onDisable() { + if (gammaPtr != nullptr) { + if (originalGamma >= 0 && originalGamma <= 1) + *gammaPtr = originalGamma; + else + *gammaPtr = 0.5f; + } + +} diff --git a/Horion/Module/Modules/FullBright.h b/Horion/Module/Modules/FullBright.h new file mode 100644 index 0000000..d3a86f7 --- /dev/null +++ b/Horion/Module/Modules/FullBright.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class FullBright : public IModule { +public: + float intensity = 25.f; + float* gammaPtr = nullptr; + FullBright(); + ~FullBright(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onEnable() override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Glide.cpp b/Horion/Module/Modules/Glide.cpp new file mode 100644 index 0000000..badcca3 --- /dev/null +++ b/Horion/Module/Modules/Glide.cpp @@ -0,0 +1,34 @@ +#include "Glide.h" + +Glide::Glide() : IModule(0, Category::MOVEMENT, "Float down") { + this->registerFloatSetting("value", &this->glideMod, this->glideMod, -2, 1); +} + +Glide::~Glide() { +} + +const char* Glide::getModuleName() { + if (isEnabled()) { + static char modName[30]; // This is kinda ghetto rn, there should be a better way to make this... + sprintf_s(modName, 30, "Glide [%.2f]", glideModEffective); + return modName; + } else + return ("Glide"); +} + +void Glide::onTick(C_GameMode* gm) { + glideModEffective = glideMod; + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + + if (g_Data.canUseMoveKeys()) { + if (GameData::isKeyDown(*input->spaceBarKey)) + glideModEffective += 0.2f; + if (GameData::isKeyDown(*input->sneakKey)) + glideModEffective -= 0.2f; + } + gm->player->velocity.y = glideModEffective; +} + +const char* Glide::getRawModuleName() { + return "Glide"; +} diff --git a/Horion/Module/Modules/Glide.h b/Horion/Module/Modules/Glide.h new file mode 100644 index 0000000..cbb7977 --- /dev/null +++ b/Horion/Module/Modules/Glide.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class Glide : public IModule { +private: + float glideMod = -0.01f; + float glideModEffective = 0; + +public: + Glide(); + ~Glide(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual const char* getRawModuleName() override; +}; diff --git a/Horion/Module/Modules/Godmode.cpp b/Horion/Module/Modules/Godmode.cpp new file mode 100644 index 0000000..c301e52 --- /dev/null +++ b/Horion/Module/Modules/Godmode.cpp @@ -0,0 +1,31 @@ +#include "Godmode.h" + +Godmode::Godmode() : IModule(0, Category::MISC, "Regen health so fast you won't die") { + registerIntSetting("regen delay", &this->regendelay, this->regendelay, 1, 20); + registerIntSetting("regen value", &this->regenvalue, this->regenvalue, 1, 20); +} + +Godmode::~Godmode() { +} + +const char* Godmode::getModuleName() { + return "Godmode"; +} + +void Godmode::onTick(C_GameMode* gm) { + delay++; + if (delay >= regendelay) { + delay = 0; + gm->player->causeFallDamage((float) regenvalue); + } +} + +void Godmode::onSendPacket(C_Packet* p) { + if (p->isInstanceOf()) { + C_MovePlayerPacket* movePacket = reinterpret_cast(p); + movePacket->onGround = true; + } /*else if (p->isInstanceOf()) { + C_ActorFallPacket* fallPacket = reinterpret_cast(p); + fallPacket->fallDistance = 0.f; + }*/ +} diff --git a/Horion/Module/Modules/Godmode.h b/Horion/Module/Modules/Godmode.h new file mode 100644 index 0000000..34979b8 --- /dev/null +++ b/Horion/Module/Modules/Godmode.h @@ -0,0 +1,17 @@ +#pragma once +#include "Module.h" +class Godmode : public IModule { +private: + int regendelay = 5; + int regenvalue = 5; + int delay = 0; + +public: + Godmode(); + ~Godmode(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onSendPacket(C_Packet* p) override; +}; diff --git a/Horion/Module/Modules/HighJump.cpp b/Horion/Module/Modules/HighJump.cpp new file mode 100644 index 0000000..9479c1e --- /dev/null +++ b/Horion/Module/Modules/HighJump.cpp @@ -0,0 +1,12 @@ +#include "HighJump.h" + +HighJump::HighJump() : IModule(0, Category::MOVEMENT, "Jump higher than ever before") { + registerFloatSetting("Jump Height", &this->jumpPower, 1, 0.5f, 5.f); +} + +HighJump::~HighJump() { +} + +const char* HighJump::getModuleName() { + return ("HighJump"); +} diff --git a/Horion/Module/Modules/HighJump.h b/Horion/Module/Modules/HighJump.h new file mode 100644 index 0000000..2c098bf --- /dev/null +++ b/Horion/Module/Modules/HighJump.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class HighJump : public IModule { +public: + float jumpPower = 1.8f; + HighJump(); + ~HighJump(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Hitbox.cpp b/Horion/Module/Modules/Hitbox.cpp new file mode 100644 index 0000000..19abfc3 --- /dev/null +++ b/Horion/Module/Modules/Hitbox.cpp @@ -0,0 +1,41 @@ +#include "Hitbox.h" + +Hitbox::Hitbox() : IModule(0, Category::COMBAT, "Increase an entitys hitbox size") { + this->registerFloatSetting("Height", &this->height, this->height, 1.8f, 10); + this->registerFloatSetting("Width", &this->width, this->width, 0.6f, 10); +} + +Hitbox::~Hitbox() { +} + +const char* Hitbox::getModuleName() { + return ("Hitbox"); +} + +void findTarget(C_Entity* currentEntity, bool isRegularEntitie) { + static auto hitboxMod = moduleMgr->getModule(); + + if (currentEntity == g_Data.getLocalPlayer()) // Skip Local player + return; + + if (currentEntity == 0) + return; + + if (currentEntity->timeSinceDeath > 0 || currentEntity->damageTime >= 7) + return; + + if (!Target::isValidTarget(currentEntity)) + return; + + float dist = (*currentEntity->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + + if (dist < hitboxMod->range) { + currentEntity->width = hitboxMod->width; + currentEntity->height = hitboxMod->height; + } + +} + +void Hitbox::onTick(C_GameMode* gm) { + g_Data.forEachEntity(findTarget); +} diff --git a/Horion/Module/Modules/Hitbox.h b/Horion/Module/Modules/Hitbox.h new file mode 100644 index 0000000..d14f9de --- /dev/null +++ b/Horion/Module/Modules/Hitbox.h @@ -0,0 +1,18 @@ +#pragma once +#include "../../../Utils/Target.h" +#include "../ModuleManager.h" +#include "Module.h" + +class Hitbox : public IModule { +public: + float height = 2; + float width = 4; + float range = 8; + + Hitbox(); + ~Hitbox(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/HudModule.cpp b/Horion/Module/Modules/HudModule.cpp new file mode 100644 index 0000000..4607419 --- /dev/null +++ b/Horion/Module/Modules/HudModule.cpp @@ -0,0 +1,184 @@ +#include "HudModule.h" +#include "../../DrawUtils.h" +#include "../../Scripting/ScriptManager.h" + +HudModule::HudModule() : IModule(0, Category::VISUAL, "Displays ArrayList/TabGUI") { + registerBoolSetting("TabGui", &this->tabgui, this->tabgui); + registerBoolSetting("ArrayList", &this->arraylist, this->arraylist); + registerBoolSetting("ClickToggle", &this->clickToggle, this->clickToggle); + registerBoolSetting("Watermark", &this->watermark, this->watermark); + registerBoolSetting("Coordinates", &this->coordinates, this->coordinates); + registerBoolSetting("Show Keybinds", &this->keybinds, this->keybinds); + registerBoolSetting("Show ArmorHUD", &this->displayArmor, this->displayArmor); + registerBoolSetting("Keystrokes", &this->keystrokes, this->keystrokes); + registerBoolSetting("Show FPS", &this->fps, this->fps); + registerBoolSetting("Show CPS", &this->cps, this->cps); + registerBoolSetting("Always show", &this->alwaysShow, this->alwaysShow); + registerFloatSetting("Scale", &this->scale, this->scale, 0.5f, 1.5f); +} + +HudModule::~HudModule() { +} + +const char* HudModule::getModuleName() { + return ("HUD"); +} + +void HudModule::drawKeystroke(char key, const vec2_t& pos) { + std::string keyString = Utils::getKeybindName(key); + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + if (key == *input->forwardKey) { + vec4_t rectPos( + pos.x, + pos.y, + pos.x + 20.f, + pos.y + 20.f); + vec2_t textPos( + (rectPos.x + (rectPos.z - rectPos.x) / 2) - (DrawUtils::getTextWidth(&keyString) / 2.f) + 0.2, + rectPos.y + 10.f - DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2.f); + + DrawUtils::fillRectangle(rectPos, GameData::isKeyDown(key) ? MC_Color(85, 85, 85) : MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &keyString, MC_Color(255, 255, 255), 1.f, 1.f); + } + if (key == *input->spaceBarKey) { + if (key == *input->spaceBarKey) keyString = "-"; + vec4_t rectPos( + pos.x, + pos.y, + pos.x + 64.f, + pos.y + 15.f); + vec2_t textPos( + (rectPos.x + (rectPos.z - rectPos.x) / 2) - (DrawUtils::getTextWidth(&keyString) / 2.f), + rectPos.y + 7.f - DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2.f); + + DrawUtils::fillRectangle(rectPos, GameData::isKeyDown(key) ? MC_Color(85, 85, 85) : MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &keyString, MC_Color(255, 255, 255), 1.f, 1.f); + } else { + vec4_t rectPos( + pos.x, + pos.y, + pos.x + ((key == *input->spaceBarKey) ? 64.f : 20.f), + pos.y + ((key == *input->spaceBarKey) ? 15.f : 20.f)); + vec2_t textPos( + (rectPos.x + (rectPos.z - rectPos.x) / 2) - (DrawUtils::getTextWidth(&keyString) / 2.f), + rectPos.y + 10.f - DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2.f); + + DrawUtils::fillRectangle(rectPos, GameData::isKeyDown(key) ? MC_Color(85, 85, 85) : MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &keyString, MC_Color(255, 255, 255), 1.f, 1.f); + } +} + +void HudModule::drawLeftMouseKeystroke(vec2_t pos) { + std::string keyString; + keyString = "LMB"; + vec4_t rectPos( + pos.x, + pos.y + 2, + pos.x + 31.f, + pos.y + 22.f); + DrawUtils::fillRectangle(rectPos, GameData::GameData::isLeftClickDown() ? MC_Color(85, 85, 85) : MC_Color(12, 12, 12), 1.f); + vec2_t textPos( + (rectPos.x + (rectPos.z - rectPos.x) / 2) - (DrawUtils::getTextWidth(&keyString) / 2.f), + rectPos.y + 10.f - DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2.f); + DrawUtils::drawText(textPos, &keyString, MC_Color(255, 255, 255), 1.f, 1.f); +} + +void HudModule::drawRightMouseKeystroke(vec2_t pos) { + std::string keyString; + keyString = "RMB"; + vec4_t rectPos( + pos.x, + pos.y + 2, + pos.x + 31.f, + pos.y + 22.f); + DrawUtils::fillRectangle(rectPos, GameData::GameData::isRightClickDown() ? MC_Color(85, 85, 85) : MC_Color(12, 12, 12), 1.f); + vec2_t textPos( + (rectPos.x + (rectPos.z - rectPos.x) / 2) - (DrawUtils::getTextWidth(&keyString) / 2.f), + rectPos.y + 10.f - DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() / 2.f); + DrawUtils::drawText(textPos, &keyString, MC_Color(255, 255, 255), 1.f, 1.f); +} + +void HudModule::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + float f = 10.f * this->scale; + std::string tempStr("Movement"); + float len = DrawUtils::getTextWidth(&tempStr, scale) + 7.f; + float startY = tabgui ? 6 * f : 0.f; + if(tabgui && scriptMgr.getNumEnabledScripts() > 0) + startY += f; + { // FPS + if (!(g_Data.getLocalPlayer() == nullptr || !this->fps)) { + std::string fpsText = "FPS: " + std::to_string(g_Data.getFPS()); + vec4_t rectPos = vec4_t(2.5f, startY + 5.f * scale, len, startY + 15.f * scale); + vec2_t textPos = vec2_t(rectPos.x + 1.5f, rectPos.y + 1.f); + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &fpsText, MC_Color(200, 200, 200), scale); + + startY += f; + } + } + { // CPS + if (!(g_Data.getLocalPlayer() == nullptr || !this->cps)) { + std::string cpsText = "CPS: " + std::to_string(g_Data.getLeftCPS()) + " - " + std::to_string(g_Data.getRightCPS()); + vec4_t rectPos = vec4_t(2.5f, startY + 5.f * scale, len, startY + 15.f * scale); + vec2_t textPos = vec2_t(rectPos.x + 1.5f, rectPos.y + 1.f); + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &cpsText, MC_Color(200, 200, 200), scale); + + startY += f; + } + } + { // Coordinates + if (!(g_Data.getLocalPlayer() == nullptr || !this->coordinates)) { + vec3_t* pos = g_Data.getLocalPlayer()->getPos(); + + std::string coordsX = "X: " + std::to_string((int)floorf(pos->x)); + std::string coordsY = "Y: " + std::to_string((int)floorf(pos->y)); + std::string coordsZ = "Z: " + std::to_string((int)floorf(pos->z)); + vec4_t rectPos = vec4_t(2.5f, startY + 5.f * scale, len, startY + 35.f * scale); + vec2_t textPos = vec2_t(rectPos.x + 1.5f, rectPos.y + 1.f); + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(textPos, &coordsX, MC_Color(200, 200, 200), scale); + textPos.y += f; + DrawUtils::drawText(textPos, &coordsY, MC_Color(200, 200, 200), scale); + textPos.y += f; + DrawUtils::drawText(textPos, &coordsZ, MC_Color(200, 200, 200), scale); + } + } + { // ArmorHUD + + if (!(g_Data.getLocalPlayer() == nullptr || !this->displayArmor || !GameData::canUseMoveKeys())) { + static float constexpr scale = 1.f; + static float constexpr opacity = 0.25f; + static float constexpr spacing = scale + 15.f; + C_LocalPlayer* player = g_Data.getLocalPlayer(); + float x = windowSize.x / 2.f + 5.f; + float y = windowSize.y - 57.5f; + for (int i = 0; i < 4; i++) { + C_ItemStack* stack = player->getArmor(i); + if (stack->isValid()) { + DrawUtils::drawItem(stack, vec2_t(x, y), opacity, scale, stack->isEnchanted()); + x += scale * spacing; + } + } + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_ItemStack* item = supplies->inventory->getItemStack(supplies->selectedHotbarSlot); + //x += scale * spacing; + if (item->isValid()) + DrawUtils::drawItem(item, vec2_t(x, y), opacity, scale, item->isEnchanted()); + } + } + { // Keystrokes + if (!(g_Data.getLocalPlayer() == nullptr || !this->keystrokes || !GameData::canUseMoveKeys())) { + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + HudModule::drawKeystroke(*input->forwardKey, vec2_t(32.f, windowSize.y - 84)); + HudModule::drawKeystroke(*input->leftKey, vec2_t(10.f, windowSize.y - 62)); + HudModule::drawKeystroke(*input->backKey, vec2_t(32.f, windowSize.y - 62)); + HudModule::drawKeystroke(*input->rightKey, vec2_t(54.f, windowSize.y - 62)); + HudModule::drawKeystroke(*input->spaceBarKey, vec2_t(10.f, windowSize.y - 40)); + HudModule::drawLeftMouseKeystroke(vec2_t(10.f, windowSize.y - 25)); + HudModule::drawRightMouseKeystroke(vec2_t(43.f, windowSize.y - 25)); + } + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/HudModule.h b/Horion/Module/Modules/HudModule.h new file mode 100644 index 0000000..a63c26e --- /dev/null +++ b/Horion/Module/Modules/HudModule.h @@ -0,0 +1,29 @@ +#pragma once +#include "Module.h" + +class HudModule : public IModule { +public: + HudModule(); + ~HudModule(); + + bool tabgui = true; + bool arraylist = true; + bool clickToggle = true; + bool watermark = true; + bool coordinates = false; + bool keybinds = true; + bool displayArmor = true; + bool keystrokes = true; + bool fps = true; + bool cps = true; + bool alwaysShow = false; + + float scale = 1.f; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; + static void drawKeystroke(char key, const vec2_t& pos); + static void drawLeftMouseKeystroke(vec2_t pos); + static void drawRightMouseKeystroke(vec2_t pos); +}; diff --git a/Horion/Module/Modules/InfiniteAura.cpp b/Horion/Module/Modules/InfiniteAura.cpp new file mode 100644 index 0000000..2a982b1 --- /dev/null +++ b/Horion/Module/Modules/InfiniteAura.cpp @@ -0,0 +1,93 @@ +#include "InfiniteAura.h" + +InfiniteAura::InfiniteAura() : IModule(0, Category::COMBAT, "Killaura with infinite reach") { + this->registerBoolSetting("multiaura", &this->isMulti, this->isMulti); + this->registerFloatSetting("range", &this->range, this->range, 15, 100); + this->registerIntSetting("delay", &this->delay, this->delay, 15, 20); +} + +InfiniteAura::~InfiniteAura() { +} + +const char* InfiniteAura::getModuleName() { + return ("InfiniteAura"); +} + +static std::vector targetList0; + +void findEntities(C_Entity* currentEntity, bool isRegularEntitie) { + static auto infiniteAuraMod = moduleMgr->getModule(); + + if (currentEntity == g_Data.getLocalPlayer()) // Skip Local player + return; + + if (currentEntity == 0) + return; + + if (currentEntity->timeSinceDeath > 0 || currentEntity->damageTime >= 7) + return; + + if (FriendList::findPlayer(currentEntity->getNameTag()->getText())) // Skip Friend + return; + + if (!Target::isValidTarget(currentEntity)) + return; + + float dist = (*currentEntity->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + + if (dist < infiniteAuraMod->range) { + targetList0.push_back(currentEntity); + } +} + +void InfiniteAura::onTick(C_GameMode* gm) { + + //Loop through all our players and retrieve their information + targetList0.clear(); + + g_Data.forEachEntity(findEntities); + Odelay++; + + if (targetList0.size() > 0 && Odelay >= delay) { + g_Data.getLocalPlayer()->swingArm(); + + float calcYaw = (gm->player->yaw + 90) * (PI / 180); + float calcPitch = (gm->player->pitch) * -(PI / 180); + + float teleportX = cos(calcYaw) * cos(calcPitch) * 3.5f; + float teleportZ = sin(calcYaw) * cos(calcPitch) * 3.5f; + C_MovePlayerPacket teleportPacket; + + if (strcmp(g_Data.getRakNetInstance()->serverIp.getText(), "mco.cubecraft.net") == 0) { + vec3_t pos = *g_Data.getLocalPlayer()->getPos(); + + C_MovePlayerPacket movePlayerPacket(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&movePlayerPacket); + + pos.y += 0.35f; + + movePlayerPacket = C_MovePlayerPacket(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&movePlayerPacket); + } + + // Attack all entitys in targetList + if (isMulti) { + for (int i = 0; i < targetList0.size(); i++) { + vec3_t pos = *targetList0[i]->getPos(); + teleportPacket = C_MovePlayerPacket(g_Data.getLocalPlayer(), vec3_t(pos.x - teleportX, pos.y, pos.z - teleportZ)); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&teleportPacket); + g_Data.getCGameMode()->attack(targetList0[i]); + teleportPacket = C_MovePlayerPacket(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&teleportPacket); + } + } else { + vec3_t pos = *targetList0[0]->getPos(); + teleportPacket = C_MovePlayerPacket(g_Data.getLocalPlayer(), vec3_t(pos.x - teleportX, pos.y, pos.z - teleportZ)); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&teleportPacket); + g_Data.getCGameMode()->attack(targetList0[0]); + teleportPacket = C_MovePlayerPacket(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&teleportPacket); + } + Odelay = 0; + } +} diff --git a/Horion/Module/Modules/InfiniteAura.h b/Horion/Module/Modules/InfiniteAura.h new file mode 100644 index 0000000..5658023 --- /dev/null +++ b/Horion/Module/Modules/InfiniteAura.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Module.h" +#include "../ModuleManager.h" + +class InfiniteAura : public IModule { +private: + int delay = 15; + int Odelay = 0; + bool isMulti = false; + +public: + float range = 15; + InfiniteAura(); + ~InfiniteAura(); + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/InstaBreak.cpp b/Horion/Module/Modules/InstaBreak.cpp new file mode 100644 index 0000000..4968c4c --- /dev/null +++ b/Horion/Module/Modules/InstaBreak.cpp @@ -0,0 +1,11 @@ +#include "InstaBreak.h" + +InstaBreak::InstaBreak() : IModule(VK_NUMPAD4, Category::WORLD, "Break any block instantly") { +} + +InstaBreak::~InstaBreak() { +} + +const char* InstaBreak::getModuleName() { + return ("InstaBreak"); +} diff --git a/Horion/Module/Modules/InstaBreak.h b/Horion/Module/Modules/InstaBreak.h new file mode 100644 index 0000000..f8d3adb --- /dev/null +++ b/Horion/Module/Modules/InstaBreak.h @@ -0,0 +1,10 @@ +#pragma once +#include "Module.h" + +class InstaBreak : public IModule { +public: + InstaBreak(); + ~InstaBreak(); + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/InventoryCleaner.cpp b/Horion/Module/Modules/InventoryCleaner.cpp new file mode 100644 index 0000000..cd3b4b5 --- /dev/null +++ b/Horion/Module/Modules/InventoryCleaner.cpp @@ -0,0 +1,254 @@ +#include "InventoryCleaner.h" + +#include "../ModuleManager.h" + +InventoryCleaner::InventoryCleaner() : IModule(0, Category::PLAYER, "Automatically throws not needed stuff out of your inventory") { + registerBoolSetting("Tools", &this->keepTools, this->keepTools); + registerBoolSetting("Armor", &this->keepArmor, this->keepArmor); + registerBoolSetting("Food", &this->keepFood, this->keepFood); + registerBoolSetting("Blocks", &this->keepBlocks, this->keepBlocks); + registerBoolSetting("OpenInv", &this->openInv, this->openInv); + registerBoolSetting("AutoSort", &this->autoSort, this->autoSort); +} + +InventoryCleaner::~InventoryCleaner() { +} + +const char* InventoryCleaner::getModuleName() { + return ("InventoryCleaner"); +} + +void InventoryCleaner::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer()->canOpenContainerScreen() && openInv) + return; + + // Drop useless items + std::vector dropSlots = findUselessItems(); + if (!dropSlots.empty()) { + for (int i : dropSlots) { + g_Data.getLocalPlayer()->getSupplies()->inventory->dropSlot(i); + } + } + + if (autoSort) { + // Put sword in first slot + { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + float damage = 0; + int item = 0; + for (int n = 0; n < 36; n++) { + C_ItemStack* stack = inv->getItemStack(n); + if (stack->item != NULL) { + float currentDamage = stack->getAttackingDamageWithEnchants(); + if (currentDamage > damage) { + damage = currentDamage; + item = n; + } + } + } + if (item != 0) inv->moveItem(item, 0); + } + } +} + +std::vector InventoryCleaner::findStackableItems() { + std::vector stackableSlot; + + for (int i = 0; i < 36; i++) { + C_ItemStack* itemStack = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i); + if (itemStack->item != nullptr) { + if ((*itemStack->item)->getMaxStackSize(0) > itemStack->count) { + for (int i2 = 0; i2 < 36; i2++) { + if (i2 == i) continue; + C_ItemStack* itemStack2 = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i2); + if ((*itemStack2->item)->getMaxStackSize(0) > itemStack->count) { + if (*itemStack->item == *itemStack2->item) { + if ((std::find(stackableSlot.begin(), stackableSlot.end(), i2) == stackableSlot.end())) stackableSlot.push_back(i2); + if ((std::find(stackableSlot.begin(), stackableSlot.end(), i) == stackableSlot.end())) stackableSlot.push_back(i); + } + } + } + } + } + } + + return stackableSlot; +} + +std::vector InventoryCleaner::findUselessItems() { + // Filter by options + + std::vector uselessItems; + std::vector items; + + { + for (int i = 0; i < 36; i++) { + C_ItemStack* itemStack = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i); + if (itemStack->item != nullptr) { + if (!stackIsUseful(itemStack)) { + if (std::find(items.begin(), items.end(), itemStack) == items.end()) + uselessItems.push_back(i); + else + items.push_back(itemStack); + } else if (std::find(items.begin(), items.end(), itemStack) == items.end()) { + if ((*itemStack->item)->itemId == 261 && !isLastItem(*itemStack->item)) + uselessItems.push_back(i); + else + items.push_back(itemStack); + } + } + } + + for (int i = 0; i < 4; i++) { + if (g_Data.getLocalPlayer()->getArmor(i)->item != nullptr) + items.push_back(g_Data.getLocalPlayer()->getArmor(i)); + } + } + // Filter weapons + if (items.size() > 0) { + // Filter by attack damage + std::sort(items.begin(), items.end(), [](const C_ItemStack* lhs, const C_ItemStack* rhs) { + C_ItemStack* current = const_cast(lhs); + C_ItemStack* other = const_cast(rhs); + return current->getAttackingDamageWithEnchants() > other->getAttackingDamageWithEnchants(); + }); + + bool hadTheBestItem = false; + C_ItemStack* bestItem = items.at(0); + + for (int i = 0; i < 36; i++) { + if (std::find(uselessItems.begin(), uselessItems.end(), i) != uselessItems.end()) + continue; + C_ItemStack* itemStack = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i); + if (itemStack->item != nullptr && itemStack->getAttackingDamageWithEnchants() > 1) { + if (itemStack->getAttackingDamageWithEnchants() < bestItem->getAttackingDamageWithEnchants()) { + uselessItems.push_back(i); + } else { + // Damage same as bestItem + if (hadTheBestItem) + uselessItems.push_back(i); + else + hadTheBestItem = true; + } + } + } + } + // Filter armor + { + std::vector helmets; + std::vector chestplates; + std::vector leggings; + std::vector boots; + + // Filter by armor value + std::sort(items.begin(), items.end(), [](const C_ItemStack* lhs, const C_ItemStack* rhs) { + C_ItemStack* current = const_cast(lhs); + C_ItemStack* other = const_cast(rhs); + return current->getArmorValueWithEnchants() > other->getArmorValueWithEnchants(); + }); + + // Put armor items in their respective vectors + for (C_ItemStack* itemsteck : items) { + C_Item* item = itemsteck->getItem(); + if (item->isArmor()) { + C_ArmorItem* armorItem = reinterpret_cast(item); + if (armorItem->isHelmet()) + helmets.push_back(itemsteck); + else if (armorItem->isChestplate()) + chestplates.push_back(itemsteck); + else if (armorItem->isLeggings()) + leggings.push_back(itemsteck); + else if (armorItem->isBoots()) + boots.push_back(itemsteck); + } + } + bool hadBest[4] = {0, 0, 0, 0}; + for (int i = 0; i < 4; i++) { + C_ItemStack* itemsteck = g_Data.getLocalPlayer()->getArmor(i); + C_Item** item = itemsteck->item; + if (item != nullptr) { + + C_ArmorItem* armor = reinterpret_cast(*item); + + float testArmorValue = 0; + switch (armor->ArmorSlot) { + case 0: + if (helmets.size() > 0) + testArmorValue = helmets.at(0)->getArmorValueWithEnchants(); + break; + case 1: + if (chestplates.size() > 0) + testArmorValue = chestplates.at(0)->getArmorValueWithEnchants(); + break; + case 2: + if (leggings.size() > 0) + testArmorValue = leggings.at(0)->getArmorValueWithEnchants(); + break; + case 3: + if (boots.size() > 0) + testArmorValue = boots.at(0)->getArmorValueWithEnchants(); + break; + } + if (itemsteck->getArmorValueWithEnchants() >= testArmorValue) + hadBest[armor->ArmorSlot] = true; + } + } + + for (int i = 0; i < 36; i++) { + if (std::find(uselessItems.begin(), uselessItems.end(), i) != uselessItems.end()) + continue; // item already useless + C_ItemStack* itemStack = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i); + if (itemStack->item != nullptr && (*itemStack->item)->isArmor()) { + C_ArmorItem* armor = reinterpret_cast(*itemStack->item); + if (armor->isHelmet()) { + if (hadBest[0] || itemStack->getArmorValueWithEnchants() < helmets.at(0)->getArmorValueWithEnchants()) { + uselessItems.push_back(i); + } else + hadBest[0] = true; + } else if (armor->isChestplate()) { + if (hadBest[1] || itemStack->getArmorValueWithEnchants() < chestplates.at(0)->getArmorValueWithEnchants()) + uselessItems.push_back(i); + else + hadBest[1] = true; + } else if (armor->isLeggings()) { + if (hadBest[2] || itemStack->getArmorValueWithEnchants() < leggings.at(0)->getArmorValueWithEnchants()) + uselessItems.push_back(i); + else + hadBest[2] = true; + } else if (armor->isBoots()) { + if (hadBest[3] || itemStack->getArmorValueWithEnchants() < boots.at(0)->getArmorValueWithEnchants()) + uselessItems.push_back(i); + else + hadBest[3] = true; + } + } + } + } + + return uselessItems; +} + +bool InventoryCleaner::stackIsUseful(C_ItemStack* itemStack) { + if (itemStack->item == nullptr) return true; + if (keepArmor && (*itemStack->item)->isArmor()) return true; // Armor + if (keepTools && (*itemStack->item)->isTool()) return true; // Tools + if (keepFood && (*itemStack->item)->isFood()) return true; // Food + if (keepBlocks && (*itemStack->item)->isBlock()) return true; // Block + if (keepTools && (*itemStack->item)->itemId == 368) return true; // Ender Pearl + return false; +} + +bool InventoryCleaner::isLastItem(C_Item* item) { + std::vector items; + for (int i = 0; i < 36; i++) { + C_ItemStack* stack = g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(i); + if (stack->item != nullptr) items.push_back((*stack->item)); + } + int count = 0; + for (C_Item* a : items) { + if (a == item) count++; + } + if (count > 1) return false; + return true; +} diff --git a/Horion/Module/Modules/InventoryCleaner.h b/Horion/Module/Modules/InventoryCleaner.h new file mode 100644 index 0000000..a79362c --- /dev/null +++ b/Horion/Module/Modules/InventoryCleaner.h @@ -0,0 +1,27 @@ +#pragma once +#include "Module.h" +class InventoryCleaner : public IModule { +private: + bool sorted = false; + + std::vector findStackableItems(); + std::vector findUselessItems(); + bool isLastItem(C_Item* item); + + bool keepTools = true; + bool keepArmor = true; + bool keepBlocks = true; + bool keepFood = true; + + bool openInv = true; + bool autoSort = false; + +public: + bool stackIsUseful(C_ItemStack* itemStack); + InventoryCleaner(); + ~InventoryCleaner(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/InventoryMove.cpp b/Horion/Module/Modules/InventoryMove.cpp new file mode 100644 index 0000000..eb0ebd1 --- /dev/null +++ b/Horion/Module/Modules/InventoryMove.cpp @@ -0,0 +1,66 @@ +#include "InventoryMove.h" + +InventoryMove::InventoryMove() : IModule(0, Category::MOVEMENT, "Move even though you have your inventory open") { +} + +InventoryMove::~InventoryMove() { +} + +const char* InventoryMove::getModuleName() { + return ("InventoryMove"); +} + +void InventoryMove::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer()->canOpenContainerScreen()) + return; + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + + if (input == nullptr) + return; + + float speed = 0.325f; + float yaw = gm->player->yaw; + + if (GameData::isKeyDown(*input->spaceBarKey) && gm->player->onGround) + gm->player->jumpFromGround(); + + if (GameData::isKeyDown(*input->forwardKey) && GameData::isKeyDown(*input->backKey)) + return; + else if (GameData::isKeyDown(*input->forwardKey) && GameData::isKeyDown(*input->rightKey) && !GameData::isKeyDown(*input->leftKey)) { + yaw += 45.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->forwardKey) && GameData::isKeyDown(*input->leftKey) && !GameData::isKeyDown(*input->rightKey)) { + yaw -= 45.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->backKey) && GameData::isKeyDown(*input->rightKey) && !GameData::isKeyDown(*input->leftKey)) { + yaw += 135.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->backKey) && GameData::isKeyDown(*input->leftKey) && !GameData::isKeyDown(*input->rightKey)) { + yaw -= 135.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->forwardKey)) { + keyPressed = true; + } else if (GameData::isKeyDown(*input->backKey)) { + yaw += 180.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->rightKey) && !GameData::isKeyDown(*input->leftKey)) { + yaw += 90.f; + keyPressed = true; + } else if (GameData::isKeyDown(*input->leftKey) && !GameData::isKeyDown(*input->rightKey)) { + yaw -= 90.f; + keyPressed = true; + } + if (yaw >= 180) + yaw -= 360.f; + + float calcYaw = (yaw + 90) * (PI / 180); + //float calcPitch = (gm->player->pitch) * -(PI / 180); + vec3_t moveVec; + moveVec.x = cos(calcYaw) * speed; + moveVec.y = gm->player->velocity.y; + moveVec.z = sin(calcYaw) * speed; + if (keyPressed) { + gm->player->lerpMotion(moveVec); + keyPressed = false; + } +} diff --git a/Horion/Module/Modules/InventoryMove.h b/Horion/Module/Modules/InventoryMove.h new file mode 100644 index 0000000..d17a745 --- /dev/null +++ b/Horion/Module/Modules/InventoryMove.h @@ -0,0 +1,14 @@ +#pragma once +#include "Module.h" +class InventoryMove : public IModule { +private: + bool keyPressed = false; + +public: + InventoryMove(); + ~InventoryMove(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/JavascriptModule.cpp b/Horion/Module/Modules/JavascriptModule.cpp new file mode 100644 index 0000000..1982753 --- /dev/null +++ b/Horion/Module/Modules/JavascriptModule.cpp @@ -0,0 +1,85 @@ +#include "JavascriptModule.h" + +JavascriptModule::JavascriptModule() : IModule(0, Category::CUSTOM, "") { +} + +JavascriptModule::~JavascriptModule() { + logF("deleted java module %s", this->getModuleName()); +} + +void JavascriptModule::setBackingScript(std::shared_ptr mod) { + this->backingScriptModule = mod; +} + +std::weak_ptr JavascriptModule::getBackingScriptModule() { + return this->backingScriptModule; +} + +const char* JavascriptModule::getModuleName() { + auto p = this->backingScriptModule.lock(); + if (p) + return p->getModuleNameCh(); + else + return "INVALID_MODULE"; +} + +void JavascriptModule::onTick(C_GameMode* gm) { + auto p = this->backingScriptModule.lock(); + if (!p) + return; + + auto lock = p->lockCallbacks(); + auto callback = p->getCallback(L"onTick"); + if (callback == JS_INVALID_REFERENCE) + return; + + p->getScriptInstance()->callCallbackImmediate(callback); +} +void JavascriptModule::onEnable() { + auto p = this->backingScriptModule.lock(); + if (!p) + return; + + auto lock = p->lockCallbacks(); + auto callback = p->getCallback(L"onEnable"); + if (callback == JS_INVALID_REFERENCE) + return; + + p->getScriptInstance()->callCallback(callback); +} +void JavascriptModule::onDisable() { + auto p = this->backingScriptModule.lock(); + if (!p) + return; + + auto lock = p->lockCallbacks(); + auto callback = p->getCallback(L"onDisable"); + if (callback == JS_INVALID_REFERENCE) + return; + + p->getScriptInstance()->callCallback(callback); +} +void JavascriptModule::onLevelRender() { + auto p = this->backingScriptModule.lock(); + if (!p) + return; + + auto lock = p->lockCallbacks(); + auto callback = p->getCallback(L"onRender"); + if (callback == JS_INVALID_REFERENCE) + return; + + p->getScriptInstance()->callCallbackImmediate(callback); +} +void JavascriptModule::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + auto p = this->backingScriptModule.lock(); + if (!p) + return; + + auto lock = p->lockCallbacks(); + auto callback = p->getCallback(L"onRender2d"); + if (callback == JS_INVALID_REFERENCE) + return; + + p->getScriptInstance()->callCallbackImmediate(callback); +} diff --git a/Horion/Module/Modules/JavascriptModule.h b/Horion/Module/Modules/JavascriptModule.h new file mode 100644 index 0000000..b84b3eb --- /dev/null +++ b/Horion/Module/Modules/JavascriptModule.h @@ -0,0 +1,26 @@ +#pragma once +#include "Module.h" +#include "../../Scripting/ScriptInstance.h" + +class JsScriptModule; + +class JavascriptModule : public IModule { +private: + std::weak_ptr backingScriptModule; + +public: + JavascriptModule(); + ~JavascriptModule(); + + void setBackingScript(std::shared_ptr); + std::weak_ptr getBackingScriptModule(); + + // Inherited via IModule + virtual void onSaveConfig(void*) override{}; // delete + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + void onEnable() override; + void onDisable() override; + void onLevelRender() override; + void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/Jesus.cpp b/Horion/Module/Modules/Jesus.cpp new file mode 100644 index 0000000..456565b --- /dev/null +++ b/Horion/Module/Modules/Jesus.cpp @@ -0,0 +1,31 @@ +#include "Jesus.h" + +Jesus::Jesus() : IModule(0, Category::MOVEMENT, "Walk over water, like Jesus") { +} + +Jesus::~Jesus() { +} + +const char* Jesus::getModuleName() { + return "Jesus"; +} + +void Jesus::onTick(C_GameMode* gm) { + if (gm->player->isSneaking()) return; + + if (gm->player->hasEnteredWater()) { + gm->player->velocity.y = 0.06f; + gm->player->onGround = true; + wasInWater = true; + } else if (gm->player->isInWater() || gm->player->isInLava()) { + gm->player->velocity.y = 0.1f; + gm->player->onGround = true; + wasInWater = true; + } else { + if (wasInWater) { + wasInWater = false; + gm->player->velocity.x *= 1.2f; + gm->player->velocity.x *= 1.2f; + } + } +} diff --git a/Horion/Module/Modules/Jesus.h b/Horion/Module/Modules/Jesus.h new file mode 100644 index 0000000..291c147 --- /dev/null +++ b/Horion/Module/Modules/Jesus.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class Jesus : + public IModule +{ +private: + bool wasInWater = false; +public: + Jesus(); + ~Jesus(); + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; + diff --git a/Horion/Module/Modules/Jetpack.cpp b/Horion/Module/Modules/Jetpack.cpp new file mode 100644 index 0000000..056d555 --- /dev/null +++ b/Horion/Module/Modules/Jetpack.cpp @@ -0,0 +1,61 @@ +#include "Jetpack.h" + +#include "../../../Utils/Logger.h" + +Jetpack::Jetpack() : IModule('F', Category::MOVEMENT, "Fly around like you had a Jetpack!") { + registerFloatSetting("speed", &this->speedMod, 1, 0.2f, 3.f); + this->registerBoolSetting("Bypass", &this->isBypass, this->isBypass); +} + +Jetpack::~Jetpack() { +} + +bool Jetpack::isFlashMode() { + return true; +} + +const char* Jetpack::getModuleName() { + return ("Jetpack"); +} + +void Jetpack::onTick(C_GameMode* gm) { + float calcYaw = (gm->player->yaw + 90) * (PI / 180); + float calcPitch = (gm->player->pitch) * -(PI / 180); + + if (!isBypass) { + vec3_t moveVec; + moveVec.x = cos(calcYaw) * cos(calcPitch) * speedMod; + moveVec.y = sin(calcPitch) * speedMod; + moveVec.z = sin(calcYaw) * cos(calcPitch) * speedMod; + + gm->player->lerpMotion(moveVec); + } else { + delay++; + + if (delay >= 5) { + vec3_t pos = *g_Data.getLocalPlayer()->getPos(); + C_MovePlayerPacket a(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + pos.y += 0.35f; + a = C_MovePlayerPacket(g_Data.getLocalPlayer(), pos); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + + gm->player->velocity.y = 0.465f; + vec3_t moveVec; + moveVec.x = cos(calcYaw) * cos(calcPitch) * speedMod; + moveVec.z = sin(calcYaw) * cos(calcPitch) * speedMod; + + gm->player->velocity.x = moveVec.x; + gm->player->velocity.z = moveVec.z; + + float teleportX = cos(calcYaw) * cos(calcPitch) * 0.00000005f; + float teleportZ = sin(calcYaw) * cos(calcPitch) * 0.00000005f; + + pos = *gm->player->getPos(); + g_Data.getLocalPlayer()->setPos(vec3_t(pos.x + teleportX, pos.y - 0.15f, pos.z + teleportZ)); + + gm->player->velocity.y -= 0.15f; + delay = 0; + } + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/Jetpack.h b/Horion/Module/Modules/Jetpack.h new file mode 100644 index 0000000..4e84e2e --- /dev/null +++ b/Horion/Module/Modules/Jetpack.h @@ -0,0 +1,20 @@ +#pragma once +#include "Module.h" + +class Jetpack : public IModule { +private: + int delay = 0; + bool isBypass = false; + float speedMod = 1; + +public: + C_MovePlayerPacket* jetpack = nullptr; + Jetpack(); + ~Jetpack(); + + virtual void onTick(C_GameMode* gm) override; + virtual bool isFlashMode() override; + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Killaura.cpp b/Horion/Module/Modules/Killaura.cpp new file mode 100644 index 0000000..3cf341d --- /dev/null +++ b/Horion/Module/Modules/Killaura.cpp @@ -0,0 +1,139 @@ +#include "Killaura.h" + +Killaura::Killaura() : IModule('P', Category::COMBAT, "Attacks entities around you automatically") { + this->registerBoolSetting("MultiAura", &this->isMulti, this->isMulti); + this->registerBoolSetting("MobAura", &this->isMobAura, this->isMobAura); + this->registerFloatSetting("range", &this->range, this->range, 2.f, 20.f); + this->registerIntSetting("delay", &this->delay, this->delay, 0, 20); + this->registerBoolSetting("hurttime", &this->hurttime, this->hurttime); + this->registerBoolSetting("AutoWeapon", &this->autoweapon, this->autoweapon); + this->registerBoolSetting("Rotations", &this->rotations, this->rotations); + this->registerBoolSetting("Silent Rotations", &this->silent, this->silent); +} + +Killaura::~Killaura() { +} + +const char* Killaura::getModuleName() { + return ("Killaura"); +} + +static std::vector targetList; + +void findEntity(C_Entity* currentEntity, bool isRegularEntity) { + static auto killauraMod = moduleMgr->getModule(); + + if (currentEntity == nullptr) + return; + + if (currentEntity == g_Data.getLocalPlayer()) // Skip Local player + return; + + if (!g_Data.getLocalPlayer()->canAttack(currentEntity, false)) + return; + + if (!g_Data.getLocalPlayer()->isAlive()) + return; + + if(!currentEntity->isAlive()) + return; + + if (currentEntity->getEntityTypeId() == 69) // XP + return; + + if (killauraMod->isMobAura) { + if (currentEntity->getNameTag()->getTextLength() <= 1 && currentEntity->getEntityTypeId() == 63) + return; + if(currentEntity->width <= 0.01f || currentEntity->height <= 0.01f) // Don't hit this pesky antibot on 2b2e.org + return; + if(currentEntity->getEntityTypeId() == 64) // item + return; + if (currentEntity->getEntityTypeId() == 80) // Arrows + return; + if (currentEntity->getEntityTypeId() == 51) // NPC + return; + } else { + if (!Target::isValidTarget(currentEntity)) + return; + } + + float dist = (*currentEntity->getPos()).dist(*g_Data.getLocalPlayer()->getPos()); + + if (dist < killauraMod->range) { + targetList.push_back(currentEntity); + } +} + +void Killaura::findWeapon() { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + float damage = 0; + int slot = supplies->selectedHotbarSlot; + for (int n = 0; n < 9; n++) { + C_ItemStack* stack = inv->getItemStack(n); + if (stack->item != nullptr) { + float currentDamage = stack->getAttackingDamageWithEnchants(); + if (currentDamage > damage) { + damage = currentDamage; + slot = n; + } + } + } + supplies->selectedHotbarSlot = slot; +} + +void Killaura::onTick(C_GameMode* gm) { + + //Loop through all our players and retrieve their information + targetList.clear(); + + g_Data.forEachEntity(findEntity); + + Odelay++; + if (!targetList.empty() && Odelay >= delay) { + + if (autoweapon) findWeapon(); + + if (g_Data.getLocalPlayer()->velocity.squaredxzlen() < 0.01) { + C_MovePlayerPacket p(g_Data.getLocalPlayer(), *g_Data.getLocalPlayer()->getPos()); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); // make sure to update rotation if player is standing still + } + + // Attack all entitys in targetList + if (isMulti) { + for (auto& i : targetList) { + if (!(i->damageTime > 1 && hurttime)) { + g_Data.getLocalPlayer()->swing(); + g_Data.getCGameMode()->attack(i); + } + } + } else { + if (!(targetList[0]->damageTime > 1 && hurttime)) { + g_Data.getLocalPlayer()->swing(); + g_Data.getCGameMode()->attack(targetList[0]); + } + } + if (rotations) { + vec2_t angle = g_Data.getLocalPlayer()->getPos()->CalcAngle(*targetList[0]->getPos()); + gm->player->setRot(angle); + } + Odelay = 0; + } +} + +void Killaura::onEnable() { + if (g_Data.getLocalPlayer() == nullptr) + this->setEnabled(false); +} + +void Killaura::onSendPacket(C_Packet* packet) { + if (packet->isInstanceOf() && g_Data.getLocalPlayer() != nullptr && silent) { + if (!targetList.empty()) { + auto* movePacket = reinterpret_cast(packet); + vec2_t angle = g_Data.getLocalPlayer()->getPos()->CalcAngle(*targetList[0]->getPos()); + movePacket->pitch = angle.x; + movePacket->headYaw = angle.y; + movePacket->yaw = angle.y; + } + } +} diff --git a/Horion/Module/Modules/Killaura.h b/Horion/Module/Modules/Killaura.h new file mode 100644 index 0000000..c4d1a39 --- /dev/null +++ b/Horion/Module/Modules/Killaura.h @@ -0,0 +1,32 @@ +#pragma once +#include "Module.h" +#include "../ModuleManager.h" +#include "../../../Utils/Target.h" + +class Killaura : public IModule +{ +private: + bool isMulti = true; + int delay = 0; + int Odelay = 0; + bool autoweapon = false; + void findWeapon(); + bool silent = true; + bool rotations = false; + +public: + bool isMobAura = false; + bool hurttime = true; + float range = 6; + + + Killaura(); + ~Killaura(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onEnable() override; + virtual void onSendPacket(C_Packet* packet) override; +}; + diff --git a/Horion/Module/Modules/MidClick.cpp b/Horion/Module/Modules/MidClick.cpp new file mode 100644 index 0000000..a6db565 --- /dev/null +++ b/Horion/Module/Modules/MidClick.cpp @@ -0,0 +1,33 @@ +#include "MidClick.h" + +MidClick::MidClick() : IModule(0, Category::PLAYER, "Click a player with your mouse wheel to add as friend") { +} + +MidClick::~MidClick() { +} + +const char* MidClick::getModuleName() { + return "MidClick"; +} + +void MidClick::onTick(C_GameMode* gm) { + C_Entity* entity = g_Data.getClientInstance()->getPointerStruct()->getEntity(); + if (entity == nullptr) + return; + + std::string name = entity->getNameTag()->getText(); + + if (GameData::isWheelDown() && !hasClicked) { + if (!FriendList::findPlayer(name)) { + FriendList::addPlayerToList(name); + g_Data.getGuiData()->displayClientMessageF("%sSuccessfully added %s %sto your friendlist.", GREEN, name.c_str(), GREEN); + } else { + std::transform(name.begin(), name.end(), name.begin(), ::tolower); + FriendList::removePlayer(name); + g_Data.getGuiData()->displayClientMessageF("%sSuccessfully removed %s %sfrom your friendlist.", GREEN, name.c_str(), GREEN); + } + hasClicked = true; + } else if (!GameData::isWheelDown()) { + hasClicked = false; + } +} diff --git a/Horion/Module/Modules/MidClick.h b/Horion/Module/Modules/MidClick.h new file mode 100644 index 0000000..d6353d2 --- /dev/null +++ b/Horion/Module/Modules/MidClick.h @@ -0,0 +1,13 @@ +#pragma once +#include "Module.h" +class MidClick : public IModule { +private: + bool hasClicked = false; + +public: + MidClick(); + ~MidClick(); + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Module.cpp b/Horion/Module/Modules/Module.cpp new file mode 100644 index 0000000..c722052 --- /dev/null +++ b/Horion/Module/Modules/Module.cpp @@ -0,0 +1,393 @@ +#include "Module.h" +#include "../../../Utils/Json.hpp" +#include "../../../Utils/Logger.h" +#include + +using json = nlohmann::json; + +#pragma region EnumEntry +EnumEntry::EnumEntry(const std::string _name, const unsigned char value) { + name = _name; + val = value; +} +std::string EnumEntry::GetName() { + return name; +} +unsigned char EnumEntry::GetValue() { + return val; +} +#pragma endregion +#pragma region SettingEnum +SettingEnum::SettingEnum(std::vector entr, IModule* mod) { + Entrys = entr; + owner = mod; + std::sort(Entrys.begin(), Entrys.end(), [](EnumEntry rhs, EnumEntry lhs) { + return rhs.GetValue() < lhs.GetValue(); + }); +} +SettingEnum::SettingEnum(IModule* mod) { + owner = mod; +} + +SettingEnum& SettingEnum::addEntry(EnumEntry entr) { + auto etr = EnumEntry(entr); + bool SameVal = false; + for (auto it = this->Entrys.begin(); it != this->Entrys.end(); it++) { + SameVal |= it->GetValue() == etr.GetValue(); + } + if (!SameVal) { + Entrys.push_back(etr); + std::sort(Entrys.begin(), Entrys.end(), [](EnumEntry rhs, EnumEntry lhs) { + return rhs.GetValue() < lhs.GetValue(); + }); + } + return *this; +} +EnumEntry& SettingEnum::GetEntry(int ind) { + return Entrys.at(ind); +} +EnumEntry& SettingEnum::GetSelectedEntry() { + return GetEntry(selected); +} +int SettingEnum::GetCount() { + return (int)Entrys.size(); +} +#pragma endregion + +IModule::IModule(int key, Category c, const char* tooltip) { + this->keybind = key; + this->category = c; + this->tooltip = tooltip; + this->registerIntSetting(std::string("keybind"), &this->keybind, this->keybind, 0, 0xFF); + this->registerBoolSetting(std::string("enabled"), &this->enabled, false); + this->ModulePos = vec2_t(0.f, 0.f); +} + +void IModule::registerFloatSetting(std::string name, float* floatPtr, float defaultValue, float minValue, float maxValue) { +#ifdef DEBUG + if (minValue > maxValue) + __debugbreak(); // Minimum value is bigger than maximum value +#endif + + SettingEntry* setting = new SettingEntry(); + setting->valueType = ValueType::FLOAT_T; + + setting->value = reinterpret_cast(floatPtr); + + // Default Value + SettingValue* defaultVal = new SettingValue(); + defaultVal->_float = defaultValue; + setting->defaultValue = defaultVal; + + // Min Value + SettingValue* minVal = new SettingValue(); + minVal->_float = minValue; + setting->minValue = minVal; + + // Max Value + SettingValue* maxVal = new SettingValue(); + maxVal->_float = maxValue; + setting->maxValue = maxVal; + + strcpy_s(setting->name, 19, name.c_str()); // Name + + settings.push_back(setting); // Add to list +} + +void IModule::registerIntSetting(std::string name, int* intPtr, int defaultValue, int minValue, int maxValue) { +#ifdef DEBUG + if (minValue > maxValue) + __debugbreak(); // Minimum value is bigger than maximum value +#endif + + SettingEntry* setting = new SettingEntry(); + setting->valueType = ValueType::INT_T; + setting->value = reinterpret_cast(intPtr); // Actual Value + + // Default Value + SettingValue* defaultVal = new SettingValue(); + defaultVal->_int = defaultValue; + setting->defaultValue = defaultVal; + + // Min Value + SettingValue* minVal = new SettingValue(); + minVal->_int = minValue; + setting->minValue = minVal; + + // Max Value + SettingValue* maxVal = new SettingValue(); + maxVal->_int = maxValue; + setting->maxValue = maxVal; + + // Name + strcpy_s(setting->name, 19, name.c_str()); + + settings.push_back(setting); // Add to list +} + +void IModule::registerEnumSetting(std::string name, SettingEnum* ptr, int defaultValue) { + SettingEntry* setting = new SettingEntry(); + setting->valueType = ValueType::ENUM_T; + if (defaultValue < 0 || defaultValue >= ptr->GetCount()) + defaultValue = 0; + + // Actual Value + setting->value = reinterpret_cast(&ptr->selected); + setting->value->_int = defaultValue; + + // Default Value + SettingValue* defaultVal = new SettingValue(); + defaultVal->_int = defaultValue; + setting->defaultValue = defaultVal; + + // Min Value (is Extended) + SettingValue* minVal = new SettingValue(); + minVal->_bool = false; + setting->minValue = minVal; + + // Enum data + setting->extraData = ptr; + + strcpy_s(setting->name, 19, name.c_str()); + settings.push_back(setting); +} + +void IModule::registerBoolSetting(std::string name, bool* boolPtr, bool defaultValue) { + SettingEntry* setting = new SettingEntry(); + setting->valueType = ValueType::BOOL_T; + + setting->value = reinterpret_cast(boolPtr); // Actual value + + SettingValue* defaultVal = new SettingValue(); // Default Value + defaultVal->_bool = defaultValue; + setting->defaultValue = defaultVal; + + strcpy_s(setting->name, 19, name.c_str()); // Name + + settings.push_back(setting); // Add to list +} + +IModule::~IModule() { + for (auto it = this->settings.begin(); it != this->settings.end(); it++) { + delete *it; + } + this->settings.clear(); +} + +const char* IModule::getModuleName() { + return "Module"; +} + +const char* IModule::getRawModuleName() { + return getModuleName(); +} + +int IModule::getKeybind() { + return this->keybind; +} + +void IModule::setKeybind(int key) { + this->keybind = key; +} + +bool IModule::allowAutoStart() { + return true; +} + +void IModule::onTick(C_GameMode*) { +} + +void IModule::onKeyUpdate(int key, bool isDown) { + if (key == getKeybind()) { + if (isFlashMode()) + setEnabled(isDown); + else if (isDown) + toggle(); + } +} + +void IModule::onEnable() { +} + +void IModule::onDisable() { +} + +void IModule::onPreRender(C_MinecraftUIRenderContext* renderCtx) { +} + +void IModule::onPostRender(C_MinecraftUIRenderContext* renderCtx) { +} + +void IModule::onSendPacket(C_Packet*) { +} + +void IModule::onLoadConfig(void* confVoid) { + json* conf = reinterpret_cast(confVoid); + if (conf->contains(this->getRawModuleName())) { + auto obj = conf->at(this->getRawModuleName()); + if (obj.is_null()) + return; + for (auto it = this->settings.begin(); it != this->settings.end(); ++it) { + SettingEntry* sett = *it; + if (obj.contains(sett->name)) { + auto value = obj.at(sett->name); + if (value.is_null()) + continue; + try { + switch (sett->valueType) { + case ValueType::FLOAT_T: + sett->value->_float = value.get(); + break; + case ValueType::DOUBLE_T: + sett->value->_double = value.get(); + break; + case ValueType::INT64_T: + sett->value->int64 = value.get<__int64>(); + break; + case ValueType::INT_T: + sett->value->_int = value.get(); + break; + case ValueType::BOOL_T: + sett->value->_bool = value.get(); + break; + case ValueType::TEXT_T: + sett->value->text = new std::string(value.get()); + break; + case ValueType::ENUM_T: + try { + sett->value->_int = value.get(); + } catch (const std::exception& e) { + logF("Config Load Error(Enum) (%s): %s ", this->getRawModuleName(), e.what()); + } + break; + } + sett->makeSureTheValueIsAGoodBoiAndTheUserHasntScrewedWithIt(); + continue; + } catch (std::exception e) { + logF("Config Load Error (%s): %s", this->getRawModuleName(), e.what()); + } + } + } + if (this->enabled) + this->onEnable(); + } +} + +#pragma warning(push) +#pragma warning(disable : 26444) +void IModule::onSaveConfig(void* confVoid) { + json* conf = reinterpret_cast(confVoid); + std::string modName = getRawModuleName(); + if (conf->contains(modName.c_str())) + conf->erase(modName.c_str()); + + json obj = {}; + //auto obj = conf->at(modName); + for (auto sett : this->settings) { + switch (sett->valueType) { + case ValueType::FLOAT_T: + obj.emplace(sett->name, sett->value->_float); + break; + case ValueType::DOUBLE_T: + obj.emplace(sett->name, sett->value->_double); + break; + case ValueType::INT64_T: + obj.emplace(sett->name, sett->value->int64); + break; + case ValueType::INT_T: + obj.emplace(sett->name, sett->value->_int); + break; + case ValueType::BOOL_T: + obj.emplace(sett->name, sett->value->_bool); + break; + case ValueType::TEXT_T: + obj.emplace(sett->name, *sett->value->text); + break; + case ValueType::ENUM_T: + obj.emplace(sett->name, sett->value->_int); + break; + } + } + + conf->emplace(modName.c_str(), obj); +} + +#pragma warning(pop) + +bool IModule::isFlashMode() { + return false; +} + +void IModule::setEnabled(bool enabled) { + if (this->enabled != enabled) { + this->enabled = enabled; +#ifndef _DEBUG + if (!isFlashMode()) // Only print jetpack stuff in debug mode +#endif + logF("%s %s", enabled ? "Enabled" : "Disabled", this->getModuleName()); + + if (enabled) + this->onEnable(); + else + this->onDisable(); + } +} + +void IModule::toggle() { + setEnabled(!this->enabled); +} + +bool IModule::isEnabled() { + return this->enabled; +} + +const char* IModule::getTooltip() { + return this->tooltip; +} +void IModule::onAttack(C_Entity*) { +} +bool IModule::callWhenDisabled() { + return false; +} +void IModule::onMove(C_MoveInputHandler*) { +} +void IModule::onLevelRender() { +} +void IModule::clientMessageF(const char* fmt, ...) { + va_list arg; + va_start(arg, fmt); + + char message[300]; + vsprintf_s(message, 300, fmt, arg); + + GameData::log("[%s]: %s", this->getModuleName(), message); + + va_end(arg); +} + +void SettingEntry::makeSureTheValueIsAGoodBoiAndTheUserHasntScrewedWithIt() { + switch (valueType) { + case ValueType::ENUM_T: + value->_int = std::max(0, std::min(reinterpret_cast(extraData)->GetCount()-1, value->_int)); + break; + case ValueType::BOOL_T: + break; + case ValueType::INT64_T: + value->int64 = std::max(minValue->int64, std::min(maxValue->int64, value->int64)); + break; + case ValueType::DOUBLE_T: + value->_double = std::max(minValue->_double, std::min(maxValue->_double, value->_double)); + break; + case ValueType::FLOAT_T: + value->_float = std::max(minValue->_float, std::min(maxValue->_float, value->_float)); + break; + case ValueType::INT_T: + value->_int = std::max(minValue->_int, std::min(maxValue->_int, value->_int)); + break; + case ValueType::TEXT_T: + //break; + default: + logF("unrecognized value %i", valueType); + break; + } +} diff --git a/Horion/Module/Modules/Module.h b/Horion/Module/Modules/Module.h new file mode 100644 index 0000000..b34b807 --- /dev/null +++ b/Horion/Module/Modules/Module.h @@ -0,0 +1,143 @@ +#pragma once +#include "../../../Memory/GameData.h" +#include "../../FriendList/FriendList.h" +#include "../../../Utils/keys.h" +//#include "../../DrawUtils.h" + +class IModule; + +enum class Category { + COMBAT = 0, + VISUAL = 1, + MOVEMENT = 2, + PLAYER = 3, + WORLD = 4, + MISC = 5, + CUSTOM = 6 +}; + +struct EnumEntry { +private: + /*const */ std::string name; + /*const */ unsigned char val; + +public: + /// Use this however you want + void* ptr = nullptr; + EnumEntry(const std::string _name, const unsigned char value); + std::string GetName(); + unsigned char GetValue(); +}; + +struct AddResult; + +class SettingEnum { +private: + IModule* owner = nullptr; + +public: + std::vector Entrys; + int selected = -1; + + SettingEnum(std::vector entr, IModule* mod = nullptr); + SettingEnum(IModule* mod = nullptr); + //SettingEnum(); + SettingEnum& addEntry(EnumEntry entr); + EnumEntry& GetEntry(int ind); + EnumEntry& GetSelectedEntry(); + int GetCount(); +}; + +enum class ValueType { + FLOAT_T, + DOUBLE_T, + INT64_T, + INT_T, + BOOL_T, + TEXT_T, + ENUM_T +}; + +struct SettingValue { + union { + float _float; + double _double; + __int64 int64; + int _int; + bool _bool; + std::string* text; + SettingEnum* Enum; + }; +}; + +struct SettingEntry { + char name[0x20] = ""; + ValueType valueType; + SettingValue* value = nullptr; + SettingValue* defaultValue = nullptr; + SettingValue* minValue = nullptr; + SettingValue* maxValue = nullptr; + void* extraData; // Only used by enum for now + + // ClickGui Data + bool isDragging = false; // This is incredibly hacky and i wanted to avoid this as much as possible but i want to get this clickgui done + + void makeSureTheValueIsAGoodBoiAndTheUserHasntScrewedWithIt(); +}; + +class IModule { +private: + bool enabled = false; + int keybind = 0x0; + bool extended = false; + vec2_t ModulePos; +private: + Category category; + const char* tooltip; + + std::vector settings; + +protected: + IModule(int key, Category c, const char* tooltip); + + void registerFloatSetting(std::string name, float* floatPtr, float defaultValue, float minValue, float maxValue); + void registerIntSetting(std::string name, int* intpTr, int defaultValue, int minValue, int maxValue); + void registerEnumSetting(std::string name, SettingEnum* intPtr, int defaultValue); + void registerBoolSetting(std::string name, bool* boolPtr, bool defaultValue); + + void clientMessageF(const char* fmt, ...); + +public: + virtual ~IModule(); + + const Category getCategory() { return category; }; + + inline vec2_t* getPos() { return &ModulePos; }; + + inline std::vector* getSettings() { return &settings; }; + + virtual const char* getModuleName() = 0; + virtual const char* getRawModuleName(); + virtual int getKeybind(); + virtual void setKeybind(int key); + virtual bool allowAutoStart(); + + virtual void onTick(C_GameMode*); + virtual void onKeyUpdate(int key, bool isDown); + virtual void onEnable(); + virtual void onDisable(); + virtual void onAttack(C_Entity*); + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx); + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx); + virtual void onLevelRender(); + virtual void onMove(C_MoveInputHandler*); + virtual void onLoadConfig(void* conf); + virtual void onSaveConfig(void* conf); + virtual bool isFlashMode(); + virtual void setEnabled(bool enabled); + virtual void toggle(); + virtual bool isEnabled(); + virtual void onSendPacket(C_Packet*); + virtual bool callWhenDisabled(); + const char* getTooltip(); +}; diff --git a/Horion/Module/Modules/NameTags.cpp b/Horion/Module/Modules/NameTags.cpp new file mode 100644 index 0000000..294e330 --- /dev/null +++ b/Horion/Module/Modules/NameTags.cpp @@ -0,0 +1,57 @@ +#include "NameTags.h" + +#include "../../../Utils/Target.h" +#include "../ModuleManager.h" + +NameTags::NameTags() : IModule(0, Category::VISUAL, "Shows betterar aways") { + this->registerBoolSetting("Underline", &this->underline, this->underline); + this->registerBoolSetting("Armor", &this->displayArmor, this->displayArmor); + this->registerFloatSetting("Opacity", &this->opacity, this->opacity, 0.f, 1.f); +} + +NameTags::~NameTags() { +} + +const char* NameTags::getModuleName() { + return ("NameTags"); +} + +void drawNameTags(C_Entity* ent, bool) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + static auto nameTagsMod = moduleMgr->getModule(); + + if (ent != localPlayer) { + if (ent->timeSinceDeath > 0) + return; + if (ent->getNameTag()->getTextLength() < 1) + return; + if (Target::isValidTarget(ent) && nameTagsMod != nullptr) { + nameTagsMod->nameTags.insert(Utils::sanitize(ent->getNameTag()->getText())); + float dist = ent->getPos()->dist(*g_Data.getLocalPlayer()->getPos()); + DrawUtils::drawNameTags(ent, fmax(0.6f, 3.f / dist)); + DrawUtils::flush(); + } + } +} + +void NameTags::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + if (localPlayer == nullptr || !GameData::canUseMoveKeys()) return; + + if (ingameNametagSetting) + if (!gotPrevSetting) { + lastSetting = *ingameNametagSetting; + gotPrevSetting = true; + *ingameNametagSetting = false; + } else + *ingameNametagSetting = false; //disable other ppl's nametags + + g_Data.forEachEntity(drawNameTags); +} + +void NameTags::onDisable() { + if (ingameNametagSetting && gotPrevSetting) { + *ingameNametagSetting = lastSetting; + gotPrevSetting = false; + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/NameTags.h b/Horion/Module/Modules/NameTags.h new file mode 100644 index 0000000..a487e88 --- /dev/null +++ b/Horion/Module/Modules/NameTags.h @@ -0,0 +1,23 @@ +#pragma once + +#include "Module.h" +#include + +class NameTags : public IModule { +public: + std::set nameTags; + bool displayArmor = true; + bool underline = true; + float opacity = 0.2f; + NameTags(); + ~NameTags(); + + bool* ingameNametagSetting = nullptr; + bool lastSetting = true; + bool gotPrevSetting = false; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Nbt.cpp b/Horion/Module/Modules/Nbt.cpp new file mode 100644 index 0000000..be4f570 --- /dev/null +++ b/Horion/Module/Modules/Nbt.cpp @@ -0,0 +1,39 @@ +#include "Nbt.h" +#include "../../../SDK/Tag.h" +#include "../../../Utils/Utils.h" + +Nbt::Nbt() : IModule(0, Category::PLAYER, "Print NBT tags, right click on mobs (Only works on local worlds!)") { +} + +Nbt::~Nbt() { +} + +const char* Nbt::getModuleName() { + return ("Nbt"); +} + +void Nbt::onTick(C_GameMode* gm) { + if (!GameData::canUseMoveKeys()) { + return; + } + PointingStruct* pointingStruct = g_Data.getClientInstance()->getPointerStruct(); + + if (GameData::isRightClickDown()) { // && Utils::getClipboardText() != this->lastCopy) { + if (pointingStruct->getEntity() != nullptr) { + + if (!(g_Data.getRakNetInstance()->serverIp.getTextLength() < 1)) + return; + std::unique_ptr tag = std::make_unique(); + pointingStruct->getEntity()->save(tag.get()); + std::stringstream build; + tag->write(build); + auto str = build.str(); + if (this->lastCopy == str) + return; + this->lastCopy = str; + Utils::setClipboardText(this->lastCopy); + g_Data.getGuiData()->displayClientMessageF("%s%s", GREEN, "CompoundTag copied:"); + g_Data.getClientInstance()->getGuiData()->displayClientMessage(&str); + } + } +} diff --git a/Horion/Module/Modules/Nbt.h b/Horion/Module/Modules/Nbt.h new file mode 100644 index 0000000..746360e --- /dev/null +++ b/Horion/Module/Modules/Nbt.h @@ -0,0 +1,14 @@ +#pragma once +#include "Module.h" + +class Nbt : public IModule { +private: + std::string lastCopy; + +public: + Nbt(); + ~Nbt(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/NightMode.cpp b/Horion/Module/Modules/NightMode.cpp new file mode 100644 index 0000000..5d37a3f --- /dev/null +++ b/Horion/Module/Modules/NightMode.cpp @@ -0,0 +1,18 @@ +#include "NightMode.h" + +NightMode::NightMode() : IModule(0, Category::VISUAL, "Darkens the environment") { + //registerFloatSetting("modifier", &this->modifier, this->modifier, 0.1f, 1.f); +} + +NightMode::~NightMode() { +} + +const char* NightMode::getModuleName() { + return "NightMode"; +} + +void NightMode::onEnable() { + static auto rainbowSkyMod = moduleMgr->getModule(); + if (rainbowSkyMod->isEnabled()) + rainbowSkyMod->setEnabled(false); +} \ No newline at end of file diff --git a/Horion/Module/Modules/NightMode.h b/Horion/Module/Modules/NightMode.h new file mode 100644 index 0000000..9ed3561 --- /dev/null +++ b/Horion/Module/Modules/NightMode.h @@ -0,0 +1,15 @@ +#pragma once +#include "../ModuleManager.h" +#include "Module.h" + +class NightMode : public IModule { +public: + NightMode(); + ~NightMode(); + + float modifier = 0.5f; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onEnable() override; +}; diff --git a/Horion/Module/Modules/NoFall.cpp b/Horion/Module/Modules/NoFall.cpp new file mode 100644 index 0000000..b14ea63 --- /dev/null +++ b/Horion/Module/Modules/NoFall.cpp @@ -0,0 +1,23 @@ +#include "NoFall.h" + +NoFall::NoFall() : IModule(VK_NUMPAD3, Category::MOVEMENT, "Prevents you from taking falldamage") { +} + +NoFall::~NoFall() { +} + +const char* NoFall::getModuleName() { + return ("NoFall"); +} + +void NoFall::onSendPacket(C_Packet* packet) { + if (g_Data.getLocalPlayer() != nullptr && g_Data.getLocalPlayer()->fallDistance > 2.f) { + if (packet->isInstanceOf()) { + C_MovePlayerPacket* movePacket = reinterpret_cast(packet); + movePacket->onGround = true; + } /*else if (packet->isInstanceOf()) { + C_ActorFallPacket* fallPacket = reinterpret_cast(packet); + fallPacket->fallDistance = 0.f; + }*/ + } +} diff --git a/Horion/Module/Modules/NoFall.h b/Horion/Module/Modules/NoFall.h new file mode 100644 index 0000000..fdf3bbb --- /dev/null +++ b/Horion/Module/Modules/NoFall.h @@ -0,0 +1,14 @@ +#pragma once + +#include "../../DrawUtils.h" +#include "Module.h" + +class NoFall : public IModule { +public: + NoFall(); + ~NoFall(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onSendPacket(C_Packet* packet) override; +}; diff --git a/Horion/Module/Modules/NoFriends.cpp b/Horion/Module/Modules/NoFriends.cpp new file mode 100644 index 0000000..534de25 --- /dev/null +++ b/Horion/Module/Modules/NoFriends.cpp @@ -0,0 +1,11 @@ +#include "NoFriends.h" + +NoFriends::NoFriends() : IModule(0, Category::PLAYER, "Ignores friend list check") { +} + +NoFriends::~NoFriends() { +} + +const char* NoFriends::getModuleName() { + return ("NoFriends"); +} diff --git a/Horion/Module/Modules/NoFriends.h b/Horion/Module/Modules/NoFriends.h new file mode 100644 index 0000000..833e81f --- /dev/null +++ b/Horion/Module/Modules/NoFriends.h @@ -0,0 +1,13 @@ +#pragma once + +#include "../../DrawUtils.h" +#include "Module.h" + +class NoFriends : public IModule { +public: + NoFriends(); + ~NoFriends(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/NoHurtcam.cpp b/Horion/Module/Modules/NoHurtcam.cpp new file mode 100644 index 0000000..68f1425 --- /dev/null +++ b/Horion/Module/Modules/NoHurtcam.cpp @@ -0,0 +1,8 @@ +#include "NoHurtcam.h" +NoHurtcam::~NoHurtcam() { +} +NoHurtcam::NoHurtcam() : IModule(0, Category::VISUAL, "Disables rotation of the camera when hit") { +} +const char* NoHurtcam::getModuleName() { + return "NoHurtcam"; +} diff --git a/Horion/Module/Modules/NoHurtcam.h b/Horion/Module/Modules/NoHurtcam.h new file mode 100644 index 0000000..9180f75 --- /dev/null +++ b/Horion/Module/Modules/NoHurtcam.h @@ -0,0 +1,9 @@ +#pragma once +#include "Module.h" + +class NoHurtcam : public IModule{ +public: + NoHurtcam(); + ~NoHurtcam(); + const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/NoPacket.cpp b/Horion/Module/Modules/NoPacket.cpp new file mode 100644 index 0000000..b2d6381 --- /dev/null +++ b/Horion/Module/Modules/NoPacket.cpp @@ -0,0 +1,18 @@ +#include "NoPacket.h" + +NoPacket::NoPacket() : IModule(VK_NUMPAD7, Category::MISC, "Prevents you from sending InventoryTransaction packets") { +} + +NoPacket::~NoPacket() { +} + +const char* NoPacket::getModuleName() { + return ("NoPacket"); +} +bool NoPacket::allowAutoStart() { + return false; +} +void NoPacket::onEnable() { + if(!g_Data.isInGame()) + this->setEnabled(false); +} diff --git a/Horion/Module/Modules/NoPacket.h b/Horion/Module/Modules/NoPacket.h new file mode 100644 index 0000000..7263472 --- /dev/null +++ b/Horion/Module/Modules/NoPacket.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" +class NoPacket : public IModule { +public: + NoPacket(); + ~NoPacket(); + + // Inherited via IModule + virtual const char* getModuleName() override; + bool allowAutoStart() override; + void onEnable() override; +}; diff --git a/Horion/Module/Modules/NoPaintingCrash.cpp b/Horion/Module/Modules/NoPaintingCrash.cpp new file mode 100644 index 0000000..0649933 --- /dev/null +++ b/Horion/Module/Modules/NoPaintingCrash.cpp @@ -0,0 +1,11 @@ +#include "NoPaintingCrash.h" + +NoPaintingCrash::NoPaintingCrash() : IModule(0, Category::MISC, "Fix Painting crash when using mob spawner !") { +} + +NoPaintingCrash::~NoPaintingCrash() { +} + +const char* NoPaintingCrash::getModuleName() { + return ("NoPaintingCrash"); +} \ No newline at end of file diff --git a/Horion/Module/Modules/NoPaintingCrash.h b/Horion/Module/Modules/NoPaintingCrash.h new file mode 100644 index 0000000..69ad7dd --- /dev/null +++ b/Horion/Module/Modules/NoPaintingCrash.h @@ -0,0 +1,10 @@ +#pragma once +#include "Module.h" +class NoPaintingCrash : public IModule { +public: + NoPaintingCrash(); + ~NoPaintingCrash(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; \ No newline at end of file diff --git a/Horion/Module/Modules/NoSlowDown.cpp b/Horion/Module/Modules/NoSlowDown.cpp new file mode 100644 index 0000000..5b40af4 --- /dev/null +++ b/Horion/Module/Modules/NoSlowDown.cpp @@ -0,0 +1,92 @@ +#include "NoSlowDown.h" + +#include + +#include "../../../Utils/Logger.h" +#include "../../../Utils/Utils.h" + +NoSlowDown::NoSlowDown() : IModule(0, Category::MOVEMENT, "Don't get slowed down when blocking or eating") { +} + +NoSlowDown::~NoSlowDown() { +} + +const char* NoSlowDown::getModuleName() { + return ("NoSlowDown"); +} + +void NoSlowDown::onEnable() { + if (opcode == 0 || opcode1 == 0) { + opcode = reinterpret_cast(FindSignature("F3 0F 11 46 ? 45 89 ? ? F3 0F 10 46 ?")); + opcode1 = reinterpret_cast(FindSignature("F3 0F 11 46 ? F3 0F 10 4E ?")); + } + + DWORD oldProtect = 0; + if (!VirtualProtect(opcode, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + opcode[0] = 0x90; + opcode[1] = 0x90; + opcode[2] = 0x90; + opcode[3] = 0x90; + opcode[4] = 0x90; + VirtualProtect(opcode, 5, oldProtect, &oldProtect); + } + + if (!VirtualProtect(opcode1, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + opcode1[0] = 0x90; + opcode1[1] = 0x90; + opcode1[2] = 0x90; + opcode1[3] = 0x90; + opcode1[4] = 0x90; + VirtualProtect(opcode1, 5, oldProtect, &oldProtect); + } +} + +void NoSlowDown::onDisable() { + if (opcode == 0 || opcode1 == 0) { + opcode = reinterpret_cast(FindSignature("F3 0F 11 46 ? 45 89 ? ? F3 0F 10 46 ?")); + opcode1 = reinterpret_cast(FindSignature("F3 0F 11 46 ? F3 0F 10 4E ?")); + } + + DWORD oldProtect = 0; + if (!VirtualProtect(opcode, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + opcode[0] = 0xF3; + opcode[1] = 0x0F; + opcode[2] = 0x11; + opcode[3] = 0x46; + opcode[4] = 0x0C; + //opcode[5] = {0xF3; 0x0F, 0x11, 0x46, 0x0C}; + VirtualProtect(opcode, 5, oldProtect, &oldProtect); + }; + + if (!VirtualProtect(opcode1, 5, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + opcode1[0] = 0xF3; + opcode1[1] = 0x0F; + opcode1[2] = 0x11; + + opcode1[3] = 0x46; + + opcode1[4] = 0x0C; + //opcode[5] = {0xF3; 0x0F, 0x11, 0x46, 0x0C}; + VirtualProtect(opcode1, 5, oldProtect, &oldProtect); + }; +} diff --git a/Horion/Module/Modules/NoSlowDown.h b/Horion/Module/Modules/NoSlowDown.h new file mode 100644 index 0000000..8805c50 --- /dev/null +++ b/Horion/Module/Modules/NoSlowDown.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class NoSlowDown : public IModule { +private: + uint8_t* opcode = 0; + uint8_t* opcode1 = 0; + +public: + NoSlowDown(); + ~NoSlowDown(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onEnable() override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/NoSwing.cpp b/Horion/Module/Modules/NoSwing.cpp new file mode 100644 index 0000000..49ee436 --- /dev/null +++ b/Horion/Module/Modules/NoSwing.cpp @@ -0,0 +1,11 @@ +#include "NoSwing.h" + +NoSwing::NoSwing() : IModule(0, Category::PLAYER, "Disable arm swing animation") { +} + +NoSwing::~NoSwing() { +} + +const char* NoSwing::getModuleName() { + return ("NoSwing"); +} \ No newline at end of file diff --git a/Horion/Module/Modules/NoSwing.h b/Horion/Module/Modules/NoSwing.h new file mode 100644 index 0000000..052f926 --- /dev/null +++ b/Horion/Module/Modules/NoSwing.h @@ -0,0 +1,10 @@ +#pragma once +#include "Module.h" +class NoSwing : public IModule { +public: + NoSwing(); + ~NoSwing(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/NoWeb.cpp b/Horion/Module/Modules/NoWeb.cpp new file mode 100644 index 0000000..6242b7a --- /dev/null +++ b/Horion/Module/Modules/NoWeb.cpp @@ -0,0 +1,15 @@ +#include "NoWeb.h" + +NoWeb::NoWeb() : IModule(0, Category::MOVEMENT, "Ignore cobwebs slowdown") { +} + +NoWeb ::~NoWeb() { +} + +const char* NoWeb::getModuleName() { + return ("NoWeb"); +} + +void NoWeb::onTick(C_GameMode* gm) { + gm->player->slowdownFactor = {0, 0, 0}; +} diff --git a/Horion/Module/Modules/NoWeb.h b/Horion/Module/Modules/NoWeb.h new file mode 100644 index 0000000..2cf0c87 --- /dev/null +++ b/Horion/Module/Modules/NoWeb.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class NoWeb : public IModule { +public: + NoWeb(); + ~NoWeb(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Nuker.cpp b/Horion/Module/Modules/Nuker.cpp new file mode 100644 index 0000000..fcc5616 --- /dev/null +++ b/Horion/Module/Modules/Nuker.cpp @@ -0,0 +1,31 @@ +#include "Nuker.h" + +Nuker::Nuker() : IModule(VK_NUMPAD5, Category::WORLD, "Break multiple blocks at once") { + this->registerIntSetting("radius", &this->nukerRadius, this->nukerRadius, 1, 10); + this->registerBoolSetting("veinminer", &this->veinMiner, this->veinMiner); + this->registerBoolSetting("auto destroy", &this->autodestroy, this->autodestroy); +} + +Nuker::~Nuker() { +} + +const char* Nuker::getModuleName() { + return ("Nuker"); +} + +void Nuker::onTick(C_GameMode* gm) { + if (!autodestroy) return; + vec3_ti tempPos = *gm->player->getPos(); + for (int x = -nukerRadius; x < nukerRadius; x++) { + for (int y = -nukerRadius; y < nukerRadius; y++) { + for (int z = -nukerRadius; z < nukerRadius; z++) { + tempPos.x = (int)gm->player->getPos()->x + x; + tempPos.y = (int)gm->player->getPos()->y + y; + tempPos.z = (int)gm->player->getPos()->z + z; + if (tempPos.y > 0 && gm->player->region->getBlock(tempPos)->toLegacy()->material->isSolid) { + gm->destroyBlock(&tempPos, 1); + } + } + } + } +} diff --git a/Horion/Module/Modules/Nuker.h b/Horion/Module/Modules/Nuker.h new file mode 100644 index 0000000..b925777 --- /dev/null +++ b/Horion/Module/Modules/Nuker.h @@ -0,0 +1,22 @@ +#pragma once +#include "Module.h" + +class Nuker : public IModule { +private: + int delay = 0; + int nukerRadius = 4; + bool veinMiner = false; + bool autodestroy = true; + +public: + Nuker(); + ~Nuker(); + + inline bool isAutoMode() { return autodestroy; }; + int getNukerRadius() { return nukerRadius; }; + + inline bool isVeinMiner() { return veinMiner; }; + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/PacketLogger.cpp b/Horion/Module/Modules/PacketLogger.cpp new file mode 100644 index 0000000..874c0c6 --- /dev/null +++ b/Horion/Module/Modules/PacketLogger.cpp @@ -0,0 +1,26 @@ +#include "PacketLogger.h" + +PacketLogger::PacketLogger() : IModule(0, Category::MISC, "Logging Packets !") { +} + +PacketLogger::~PacketLogger() { +} + +const char* PacketLogger::getModuleName() { + return ("PacketLogger"); +} + +void PacketLogger::onSendPacket(C_Packet* packet) { + /* if (packet->isInstanceOf()) { + auto pk = reinterpret_cast(packet); + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%s action=%i", packet->getName()->getText(), pk->action); + return; + }*/ +#ifdef _DEBUG + + if (strcmp(packet->getName()->getText(), "PlayerAuthInputPacket") != 0) { + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%s", packet->getName()->getText()); + } +#endif // DEBUG + +} diff --git a/Horion/Module/Modules/PacketLogger.h b/Horion/Module/Modules/PacketLogger.h new file mode 100644 index 0000000..234de9c --- /dev/null +++ b/Horion/Module/Modules/PacketLogger.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class PacketLogger : public IModule { +public: + PacketLogger(); + ~PacketLogger(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onSendPacket(C_Packet* packet) override; +}; diff --git a/Horion/Module/Modules/Phase.cpp b/Horion/Module/Modules/Phase.cpp new file mode 100644 index 0000000..7dc4714 --- /dev/null +++ b/Horion/Module/Modules/Phase.cpp @@ -0,0 +1,20 @@ +#include "Phase.h" + +Phase::Phase() : IModule('I', Category::MOVEMENT, "Walk through walls") { +} + +Phase::~Phase() { +} + +const char* Phase::getModuleName() { + return ("Phase"); +} + +void Phase::onTick(C_GameMode* gm) { + gm->player->aabb.upper.y = gm->player->aabb.lower.y; +} + +void Phase::onDisable() { + if (g_Data.getLocalPlayer() != nullptr) + g_Data.getLocalPlayer()->aabb.upper.y += 1.8f; +} diff --git a/Horion/Module/Modules/Phase.h b/Horion/Module/Modules/Phase.h new file mode 100644 index 0000000..7fefb5e --- /dev/null +++ b/Horion/Module/Modules/Phase.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" + +class Phase : public IModule { +public: + Phase(); + ~Phase(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Radar.cpp b/Horion/Module/Modules/Radar.cpp new file mode 100644 index 0000000..46ae99b --- /dev/null +++ b/Horion/Module/Modules/Radar.cpp @@ -0,0 +1,222 @@ +#include "Radar.h" +#include + +float rcolors[4]; +int size = 100; +float pixelSize = 2.5f; +float cent = size / 2.f; +float pxSize = pixelSize / 2.f; +float topPad = -1; +float zoom = 1; +float pxOpacity = 1; +bool grid = true; +// didn't bother puting this onto the header file and making it non-static... +// it's the only one that could be. since everything else is accessed at renderEntity() +float bgOpacity = 0.2f; + +Radar::Radar() : IModule(0, Category::VISUAL, "Radar") { + registerBoolSetting("Show Grid", &grid, true); + registerIntSetting("Size", &size, size, 50, 200); + registerFloatSetting("Pixel Size", &pixelSize, pixelSize, 2, 4); + registerFloatSetting("Zoom", &zoom, zoom, 1.0f / 4.0f, 4.0f); + registerFloatSetting("Background Opacity", &bgOpacity, bgOpacity, 0.1f, 1.0f); + registerFloatSetting("Pixel Opacity", &pxOpacity, pxOpacity, 0.1f, 1.0f); +} + +Radar::~Radar() { +} + +const char* Radar::getModuleName() { + return "Radar"; +} + +float effectiveZoom = 1; +float angle = 0; +float c, s; +vec3_t playerPos; + +void recalculateScale() { + effectiveZoom = zoom * (size / 100.f); + cent = size / 2.f; + pxSize = pixelSize / 2.f * effectiveZoom; + topPad = g_Data.getGuiData()->heightGame / 2.f; + +} + +void renderEntity(C_Entity* currentEntity, bool isRegularEntity) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + if (currentEntity == nullptr) + return; + + if (currentEntity == player) // Skip Local player + return; + + if (!player->canAttack(currentEntity, false)) + return; + + if (!currentEntity->isAlive()) + return; + + if (!Target::isValidTarget(currentEntity)) + return; + + vec3_t* start = currentEntity->getPosOld(); + vec3_t* end = currentEntity->getPos(); + + vec3_t lerped = start->lerp(end, DrawUtils::getLerpTime()); + + const auto delta = lerped.sub(playerPos); + const float dist = delta.magnitudexz(); + + const vec2_t relPos = vec2_t( + cent - ((delta.x * c) - (delta.z * s)), + topPad - ((delta.x * s) + (delta.z * c)) + ); + if (relPos.x > 0 && relPos.x < size && relPos.y > topPad - cent && relPos.y < topPad + cent) { + DrawUtils::fillRectangle(vec4_t(relPos.x - pxSize, relPos.y - pxSize, relPos.x + pxSize, relPos.y + pxSize), MC_Color(rcolors[0], rcolors[1], rcolors[2]), pxOpacity); + } +} + +void Radar::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + + if (player == nullptr) return; + + if (rcolors[3] < 1) { + rcolors[0] = 0.2f; + rcolors[1] = 0.2f; + rcolors[2] = 1.f; + rcolors[3] = 1; + } + recalculateScale(); + + Utils::ApplyRainbow(rcolors, 0.0015f); + + DrawUtils::fillRectangle(vec4_t(0, topPad - cent, (float)size, topPad + cent), MC_Color(0, 0, 0), bgOpacity); + + auto pPos = g_Data.getClientInstance()->levelRenderer->origin; + playerPos = pPos; + + angle = (180.0f - player->yaw) + 180.0f; + if (angle < 0) angle += 360; + angle *= RAD_DEG; + + s = sin(angle) * effectiveZoom; + c = cos(angle) * effectiveZoom; + + auto computePos = [=](vec2_t pos) { + auto delta = pos.sub(pPos.x, pPos.z); + return vec2_t( + cent - ((delta.x * c) - (delta.y * s)), + topPad - ((delta.x * s) + (delta.y * c))); + }; + + int chunkX = int(floor(pPos.x)) & ~(15); + int chunkZ = int(floor(pPos.z)) & ~(15); + // Draw grid + if (grid) + { + // we start at the player pos, and clip the grid lines to the view rectangle until the lines are no longer inside, then we repeat the process in the opposite direction, then we do the same for the other axis + + struct FiniteLine { + vec2_t a, b; + + // copied straight from wikipedia line-line intersections + bool intersectionPointWithInfOther(vec2_t oa, vec2_t ob, vec2_t& out) { + float den = (a.x - b.x) * (oa.y - ob.y) - (a.y - b.y) * (oa.x - ob.x); + if (den == 0) // lines are parallel + return false; + + float t = ((a.x - oa.x) * (oa.y - ob.y) - (a.y - oa.y) * (oa.x - ob.x)) / den; + if (t >= 0 && t <= 1) { + out = {a.x + t * (b.x - a.x), + a.y + t * (b.y - a.y)}; + return true; + } + return false; + } + }; + + std::array clipRectPoints = {vec2_t{0.f, topPad - cent}, vec2_t{(float)size, topPad - cent}, vec2_t{(float)size, topPad + cent}, vec2_t{0.f, topPad + cent}}; + std::array clipRectLines; + auto last = clipRectPoints[3]; + + for (int i = 0; i < 4; i++) { + auto cur = clipRectPoints[i]; + + clipRectLines[i] = {last, cur}; + last = cur; + } + + std::vector lines; + + auto computeRectIntersections = [&](vec2_t p1, vec2_t p2) { + vec2_t a, b; + bool hadIntersection = false; + for (int i = 0; i < (hadIntersection ? 4 : 3); i++) { + auto& line = clipRectLines[i]; + bool didIntersect = line.intersectionPointWithInfOther(p1, p2, hadIntersection ? b : a); + if (didIntersect) { + if (hadIntersection) { + lines.push_back({a, b}); + return true; + } + hadIntersection = true; + } + } + return false; + }; + + //x axis + for (int gridX = chunkX; true; gridX += 16) { + vec2_t p1 = computePos({gridX, chunkZ}), p2 = computePos({gridX, chunkZ + 1}); + if (!computeRectIntersections(p1, p2)) + break; + } + for (int gridX = chunkX - 16; true; gridX -= 16) { + vec2_t p1 = computePos({gridX, chunkZ}), p2 = computePos({gridX, chunkZ + 1}); + if (!computeRectIntersections(p1, p2)) + break; + } + + //z axis + for (int gridZ = chunkZ; true; gridZ += 16) { + vec2_t p1 = computePos({chunkX, gridZ}), p2 = computePos({chunkX + 1, gridZ}); + if (!computeRectIntersections(p1, p2)) + break; + } + for (int gridZ = chunkZ - 16; true; gridZ -= 16) { + vec2_t p1 = computePos({chunkX, gridZ}), p2 = computePos({chunkX + 1, gridZ}); + if (!computeRectIntersections(p1, p2)) + break; + } + + DrawUtils::setColor(0.7f, 0.7f, 0.7f, 0.1f); + // draw all lines + for (auto line : lines) { + DrawUtils::drawLine(line.a, line.b, 0.25f); + } + } + + // Draw the chunk the player is in + if (grid) + { + DrawUtils::setColor(0.9f, 0.9f, 0.9f, 0.6f); + std::array rect = {computePos({chunkX, chunkZ}), computePos({chunkX + 16, chunkZ}), computePos({chunkX + 16, chunkZ + 16}), computePos({chunkX, chunkZ + 16})}; + auto last = rect[3]; + + for (int i = 0; i < 4; i++) { + auto cur = rect[i]; + + DrawUtils::drawLine(last, cur, 0.25f); + last = cur; + } + } + + g_Data.forEachEntity(renderEntity); + + const float pxSize = pixelSize * 0.75f * effectiveZoom; + DrawUtils::setColor(1, 1, 1, pxOpacity); + vec2_t center(cent, topPad); + DrawUtils::drawTriangle(center.add(-pxSize * 0.9f, pxSize * 2.f), center.add(pxSize * 0.9f, pxSize * 2.f), center); +} diff --git a/Horion/Module/Modules/Radar.h b/Horion/Module/Modules/Radar.h new file mode 100644 index 0000000..fda0781 --- /dev/null +++ b/Horion/Module/Modules/Radar.h @@ -0,0 +1,12 @@ +#pragma once +#include "Module.h" +#include "../../DrawUtils.h" +class Radar : public IModule { +public: + Radar(); + ~Radar(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/RainbowSky.cpp b/Horion/Module/Modules/RainbowSky.cpp new file mode 100644 index 0000000..9c8210c --- /dev/null +++ b/Horion/Module/Modules/RainbowSky.cpp @@ -0,0 +1,11 @@ +#include "RainbowSky.h" + +RainbowSky::RainbowSky() : IModule(0, Category::VISUAL, "Makes your sky look rainbow!") { +} + +RainbowSky::~RainbowSky() { +} + +const char* RainbowSky::getModuleName() { + return ("RainbowSky"); +} diff --git a/Horion/Module/Modules/RainbowSky.h b/Horion/Module/Modules/RainbowSky.h new file mode 100644 index 0000000..7076bcf --- /dev/null +++ b/Horion/Module/Modules/RainbowSky.h @@ -0,0 +1,10 @@ +#pragma once +#include "Module.h" +class RainbowSky : public IModule { +public: + RainbowSky(); + ~RainbowSky(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Reach.cpp b/Horion/Module/Modules/Reach.cpp new file mode 100644 index 0000000..cde7b84 --- /dev/null +++ b/Horion/Module/Modules/Reach.cpp @@ -0,0 +1,48 @@ +#include "Reach.h" + +#include +#include "../../../Utils/Logger.h" +#include "../../../Utils/Utils.h" + +Reach::Reach() : IModule(0, Category::COMBAT, "Increases your reach") { + this->registerFloatSetting("Reach Value", &this->reachValue, this->reachValue, 3.f, 7.f); +} + +Reach::~Reach() { +} + +const char* Reach::getModuleName() { + return ("Reach"); +} + +void Reach::onTick(C_GameMode* gm) { + if (reachPtr != 0) { + *reachPtr = reachValue; + } +} + +void Reach::onEnable() { + static uintptr_t sigOffset = 0x0; + if (sigOffset == 0x0) { + + sigOffset = FindSignature("F3 0F 59 ? ? ? ? ? 80 BE"); + + if (sigOffset != 0x0) { + int offset = *reinterpret_cast((sigOffset + 4)); // Get Offset from code + reachPtr = reinterpret_cast(sigOffset + offset + 8); + originalReach = *reachPtr; + } + } + if (!VirtualProtect(reachPtr, sizeof(float), PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } +} + +void Reach::onDisable() { + *reachPtr = originalReach; + if (reachPtr != 0) + VirtualProtect(reachPtr, sizeof(float), oldProtect, &oldProtect); +} diff --git a/Horion/Module/Modules/Reach.h b/Horion/Module/Modules/Reach.h new file mode 100644 index 0000000..cd28797 --- /dev/null +++ b/Horion/Module/Modules/Reach.h @@ -0,0 +1,20 @@ +#pragma once +#include "Module.h" + +class Reach : public IModule { +private: + float reachValue = 3; + float originalReach = 0; + float* reachPtr = nullptr; + unsigned long oldProtect = 0; + +public: + Reach(); + ~Reach(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onEnable() override; + virtual void onDisable() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Scaffold.cpp b/Horion/Module/Modules/Scaffold.cpp new file mode 100644 index 0000000..852d6f4 --- /dev/null +++ b/Horion/Module/Modules/Scaffold.cpp @@ -0,0 +1,154 @@ +#include "Scaffold.h" + +#include "../../../Utils/Logger.h" + +Scaffold::Scaffold() : IModule(VK_NUMPAD1, Category::WORLD, "Automatically build blocks beneath you") { + registerBoolSetting("Spoof", &this->spoof, this->spoof); + registerBoolSetting("Staircase Mode", &this->staircaseMode, this->staircaseMode); +} + +Scaffold::~Scaffold() { +} + +const char* Scaffold::getModuleName() { + return "Scaffold"; +} + +bool Scaffold::tryScaffold(vec3_t blockBelow) { + blockBelow = blockBelow.floor(); + + C_Block* block = g_Data.getLocalPlayer()->region->getBlock(vec3_ti(blockBelow)); + C_BlockLegacy* blockLegacy = (block->blockLegacy); + if (blockLegacy->material->isReplaceable) { + vec3_ti blok(blockBelow); + + // Find neighbour + static std::vector checklist; + if (checklist.empty()) { + checklist.push_back(new vec3_ti(0, -1, 0)); + checklist.push_back(new vec3_ti(0, 1, 0)); + + checklist.push_back(new vec3_ti(0, 0, -1)); + checklist.push_back(new vec3_ti(0, 0, 1)); + + checklist.push_back(new vec3_ti(-1, 0, 0)); + checklist.push_back(new vec3_ti(1, 0, 0)); + } + + bool foundCandidate = false; + int i = 0; + for (auto current : checklist) { + vec3_ti calc = blok.sub(*current); + bool Y = ((g_Data.getLocalPlayer()->region->getBlock(calc)->blockLegacy))->material->isReplaceable; + if (!((g_Data.getLocalPlayer()->region->getBlock(calc)->blockLegacy))->material->isReplaceable) { + // Found a solid block to click + foundCandidate = true; + blok = calc; + break; + } + i++; + } + if (foundCandidate) { + if (spoof) findBlock(); + g_Data.getCGameMode()->buildBlock(&blok, i); + + return true; + } + } + return false; +} + +bool Scaffold::findBlock() { + __int64 id = *g_Data.getLocalPlayer()->getUniqueId(); + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* inv = supplies->inventory; + for (int n = 0; n < 9; n++) { + C_ItemStack* stack = inv->getItemStack(n); + if (stack->item != nullptr) { + if ((*stack->item)->isBlock() && (*stack->item)->itemId != 0) { + C_MobEquipmentPacket a(id, *stack, n, n); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + return true; + } + } + } + C_MobEquipmentPacket a(id, *g_Data.getLocalPlayer()->getSelectedItem(), supplies->selectedHotbarSlot, supplies->selectedHotbarSlot); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); + return false; +} + +void Scaffold::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer() == nullptr) + return; + if (!g_Data.canUseMoveKeys()) + return; + + auto selectedItem = g_Data.getLocalPlayer()->getSelectedItem(); + if ((selectedItem == nullptr || selectedItem->count == 0 || selectedItem->item == nullptr || !selectedItem->getItem()->isBlock()) && !spoof) // Block in hand? + return; + + + // Adjustment by velocity + float speed = g_Data.getLocalPlayer()->velocity.magnitudexz(); + vec3_t vel = g_Data.getLocalPlayer()->velocity; + vel = vel.normalize(); // Only use values from 0 - 1 + + + + + if (this->staircaseMode) { + vec3_t blockBelow = g_Data.getLocalPlayer()->eyePos0; // Block 1 block below the player + blockBelow.y -= g_Data.getLocalPlayer()->height; + blockBelow.y -= 1.5f; + + vec3_t blockBelowBelow = g_Data.getLocalPlayer()->eyePos0; // Block 2 blocks below the player + blockBelowBelow.y -= g_Data.getLocalPlayer()->height; + blockBelowBelow.y -= 2.0f; + + if (!tryScaffold(blockBelow) && !tryScaffold(blockBelowBelow)) { + if (speed > 0.05f) { // Are we actually walking? + blockBelow.z -= vel.z * 0.4f; + blockBelowBelow.z -= vel.z * 0.4f; + if (!tryScaffold(blockBelow) && !tryScaffold(blockBelowBelow)) { + blockBelow.x -= vel.x * 0.4f; + blockBelowBelow.x -= vel.x * 0.4f; + if (!tryScaffold(blockBelow) && !tryScaffold(blockBelowBelow) && g_Data.getLocalPlayer()->isSprinting()) { + blockBelow.z += vel.z; + blockBelow.x += vel.x; + blockBelowBelow.z += vel.z; + blockBelowBelow.x += vel.x; + tryScaffold(blockBelow); + tryScaffold(blockBelowBelow); + } + } + } + } + } else { + vec3_t blockBelow = g_Data.getLocalPlayer()->eyePos0; // Block below the player + blockBelow.y -= g_Data.getLocalPlayer()->height; + blockBelow.y -= 0.5f; + + if (!tryScaffold(blockBelow)) { + if (speed > 0.05f) { // Are we actually walking? + blockBelow.z -= vel.z * 0.4f; + if (!tryScaffold(blockBelow)) { + blockBelow.x -= vel.x * 0.4f; + if (!tryScaffold(blockBelow) && g_Data.getLocalPlayer()->isSprinting()) { + blockBelow.z += vel.z; + blockBelow.x += vel.x; + tryScaffold(blockBelow); + } + } + } + } + } +} + +void Scaffold::onDisable() { + if (g_Data.getLocalPlayer() == nullptr) + return; + __int64 id = *g_Data.getLocalPlayer()->getUniqueId(); + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_MobEquipmentPacket a(id, *g_Data.getLocalPlayer()->getSelectedItem(), supplies->selectedHotbarSlot, supplies->selectedHotbarSlot); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&a); +} diff --git a/Horion/Module/Modules/Scaffold.h b/Horion/Module/Modules/Scaffold.h new file mode 100644 index 0000000..57866bf --- /dev/null +++ b/Horion/Module/Modules/Scaffold.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +class Scaffold : public IModule { +private: + bool spoof = false; + bool staircaseMode = false; + bool tryScaffold(vec3_t blockBelow); + bool findBlock(); + +public: + Scaffold(); + ~Scaffold(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Spammer.cpp b/Horion/Module/Modules/Spammer.cpp new file mode 100644 index 0000000..36bd4be --- /dev/null +++ b/Horion/Module/Modules/Spammer.cpp @@ -0,0 +1,27 @@ +#include "Spammer.h" +#include "../../../Utils/Utils.h" + +Spammer::Spammer() : IModule(0, Category::MISC, "Spams a message in a specified delay") { + registerIntSetting("delay", &this->delay, this->delay, 1, 10); + registerIntSetting("length", &this->length, this->length, 1, 60); + registerBoolSetting("bypass", &this->bypass, this->bypass); +} + +Spammer::~Spammer() { +} + +const char* Spammer::getModuleName() { + return ("Spammer"); +} + +void Spammer::onTick(C_GameMode* gm) { + Odelay++; + if (Odelay > delay * 20) { + C_TextPacket textPacket; + textPacket.message.setText(bypass ? (message + " | " + Utils::randomString(length)) : message); + textPacket.sourceName.setText(g_Data.getLocalPlayer()->getNameTag()->getText()); + textPacket.xboxUserId = std::to_string(g_Data.getLocalPlayer()->getUserId()); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&textPacket); + Odelay = 0; + } +} diff --git a/Horion/Module/Modules/Spammer.h b/Horion/Module/Modules/Spammer.h new file mode 100644 index 0000000..7f2f4b9 --- /dev/null +++ b/Horion/Module/Modules/Spammer.h @@ -0,0 +1,24 @@ +#pragma once +#include "Module.h" + +class Spammer : public IModule { +private: + int Odelay = 0; + bool bypass = true; + int delay = 2; + int length = 8; + std::string message = "Horion - the best minecraft bedrock utility mod - horion.download"; + +public: + Spammer(); + ~Spammer(); + + inline std::string& getMessage() { return message; }; + inline int& getDelay() { return delay; }; + inline int& getLength() { return length; }; + inline bool& getBypass() { return bypass; }; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Speed.cpp b/Horion/Module/Modules/Speed.cpp new file mode 100644 index 0000000..29e51c8 --- /dev/null +++ b/Horion/Module/Modules/Speed.cpp @@ -0,0 +1,33 @@ +#include "Speed.h" + +Speed::Speed() : IModule(VK_NUMPAD2, Category::MOVEMENT, "Speed up!") { + registerFloatSetting("speed", &this->speed, 1, 0.1f, 3.f); +} + +Speed::~Speed() { +} + +const char* Speed::getModuleName() { + return ("Speed"); // 48 8D 15 ?? ?? ?? ?? 48 8B CB FF 90 ?? ?? ?? ?? 48 8B D8 +} + +void Speed::onTick(C_GameMode* gm) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + + float* speedAdr = reinterpret_cast(g_Data.getLocalPlayer()->getSpeed() + 0x84); + *speedAdr = speed; +} + +void Speed::onEnable() { + if (g_Data.getLocalPlayer() == nullptr) { + this->setEnabled(false); + return; + } else { + origSpeed = *reinterpret_cast(g_Data.getLocalPlayer()->getSpeed() + 0x84); + } +} + +void Speed::onDisable() { + if (g_Data.getLocalPlayer() != nullptr) + *reinterpret_cast(g_Data.getLocalPlayer()->getSpeed() + 0x84) = origSpeed; +} diff --git a/Horion/Module/Modules/Speed.h b/Horion/Module/Modules/Speed.h new file mode 100644 index 0000000..2159969 --- /dev/null +++ b/Horion/Module/Modules/Speed.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" + +class Speed : public IModule { +private: + float origSpeed = 0; + float speed = 1.6f; + +public: + Speed(); + ~Speed(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onEnable() override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Spider.cpp b/Horion/Module/Modules/Spider.cpp new file mode 100644 index 0000000..7db129a --- /dev/null +++ b/Horion/Module/Modules/Spider.cpp @@ -0,0 +1,168 @@ +#include "Spider.h" + +Spider::Spider() : IModule(0, Category::MOVEMENT, "Climb walls") { + registerFloatSetting("Speed", &speed, 0.6f, 0.1f, 1.f); + registerBoolSetting("Avoid Overshooting", &this->dontOvershoot, true); +} + +Spider::~Spider() { +} + +const char* Spider::getModuleName() { + return "Spider"; +} + +void Spider::onMove(C_MoveInputHandler* input) { + C_LocalPlayer* player = g_Data.getLocalPlayer(); + if (player == nullptr) + return; + + if (player->isInLava() || player->isInWater()) + return; + + if (player->isSneaking()) + return; + + std::vector sideBlocks; + sideBlocks.reserve(8); + + vec2_t moveVec2d = {input->forwardMovement, -input->sideMovement}; + bool pressed = moveVec2d.magnitude() > 0.01f; + if (!pressed) + return; + moveVec2d = moveVec2d.normalized(); + + float calcYaw = (player->yaw + 90) * (PI / 180); + vec3_t moveVec; + float c = cos(calcYaw); + float s = sin(calcYaw); + moveVec2d = {moveVec2d.x * c - moveVec2d.y * s, moveVec2d.x * s + moveVec2d.y * c}; + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + if (x == 0 && z == 0) + continue; + + if (moveVec2d.dot(vec2_t(x, z).normalized()) < 0.6f) + continue; + sideBlocks.push_back(vec3_ti(x, 0, z)); + } + } + + auto pPos = *player->getPos(); + pPos.y = player->aabb.lower.y; + auto pPosI = vec3_ti(pPos.floor()); + + auto isObstructed = [&](int yOff, AABB* obstructingBlock = nullptr, bool ignoreYcoll = false) { + for (const auto& current : sideBlocks) { + vec3_ti side = pPosI.add(0, yOff, 0).add(current); + if (side.y < 0 || side.y >= 256) + break; + auto block = player->region->getBlock(side); + if (block == nullptr || block->blockLegacy == nullptr) + continue; + C_BlockLegacy* blockLegacy = block->toLegacy(); + if (blockLegacy == nullptr) + continue; + AABB collisionVec; + if (!blockLegacy->getCollisionShape(&collisionVec, block, player->region, &side, player)) + continue; + bool intersects = ignoreYcoll ? collisionVec.intersectsXZ(player->aabb.expandedXZ(0.1f)) : collisionVec.intersects(player->aabb.expandedXZ(0.1f)); + + if (intersects) { + if (obstructingBlock != nullptr) + *obstructingBlock = collisionVec; + return true; + } + } + return false; + }; + + AABB lowerObsVec, upperObsVec; + bool upperObstructed = isObstructed(1, &upperObsVec); + + bool lowerObstructed = isObstructed(0, &lowerObsVec); + float targetSpeed = speed; + if (this->dontOvershoot && (lowerObstructed || upperObstructed)) { + + // simulate because im too lazy to do the math + const auto distanceError = [](float yVel, float distance) { + int t = 0; + constexpr int numIter = 60; + for (; t < numIter; t++) { + distance -= yVel; + yVel -= 0.08f; // gravity + yVel *= 0.98f; // drag + + if (yVel <= 0) + break; + } + return std::tuple(distance, yVel, t); + }; + + float getOver = lowerObstructed ? lowerObsVec.upper.y : upperObsVec.upper.y; + { + if (upperObstructed) + getOver = std::max(getOver, upperObsVec.upper.y); + // max dist that can be reached with our speed + + const int numIterations = (int)ceil(std::max(5.f, -std::get<0>(distanceError(speed, 0)) + 2)); + + bool lastObstructed = upperObstructed; + for (int iter = 2; iter < numIterations; iter++) { + if (isObstructed(iter, &upperObsVec, true)) { + getOver = std::max(getOver, upperObsVec.upper.y); + lastObstructed = true; + } else { + if (lastObstructed) + lastObstructed = false; + else + break; + } + } + } + + float targetDist = getOver - pPos.y + 0.02f; + if (targetDist <= 0) + return; + + auto [curDist, curYVel, curT] = distanceError(player->velocity.y, targetDist); + + //this->clientMessageF("current trajectory error=%.3f t=%i vel=%.3f total=%.2f", curDist, curT, curYVel, targetDist); + if (curDist <= 0.01f) + return; // We will already get on top of the block + + if (player->velocity.y < speed) { + // do another simulation to determine whether we would overshoot on the next iteration + auto secondTrajectory = distanceError(speed, targetDist); + //this->clientMessageF("secondTrajectory: error=%.3f t=%i vel=%.2f", std::get<0>(secondTrajectory), std::get<2>(secondTrajectory), std::get<1>(secondTrajectory)); + if (std::get<0>(secondTrajectory) <= 0) {// we are overshooting if we give the player our target speed + + // use secant method to approximate perfect start speed + float error = curDist; + float startSpeed = player->velocity.y; + + float error2 = std::get<0>(secondTrajectory); + float startSpeed2 = speed; + int i = 0; + for (; i < 16; i++) { + if (error > -0.05f && error <= 0.001f) + break; // its better to slightly overshoot than to undershoot + + float newSpeed = (startSpeed2 * error - startSpeed * error2) / (error - error2); + startSpeed2 = startSpeed; + startSpeed = newSpeed; + + error2 = error; + error = std::get<0>(distanceError(newSpeed, targetDist)); + } + //this->clientMessageF("Secant method finished with error=%.3f speed=%.3f at t=%i", error, startSpeed, i); + targetSpeed = startSpeed; + } + } + } + if (upperObstructed || lowerObstructed) { + if (player->velocity.y < targetSpeed) + player->velocity.y = targetSpeed; + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/Spider.h b/Horion/Module/Modules/Spider.h new file mode 100644 index 0000000..982f573 --- /dev/null +++ b/Horion/Module/Modules/Spider.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class Spider : public IModule { +private: + float speed = 0.6f; + bool dontOvershoot = true; + +public: + Spider(); + ~Spider(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onMove(C_MoveInputHandler* input) override; +}; diff --git a/Horion/Module/Modules/StackableItem.cpp b/Horion/Module/Modules/StackableItem.cpp new file mode 100644 index 0000000..b3d98e7 --- /dev/null +++ b/Horion/Module/Modules/StackableItem.cpp @@ -0,0 +1,24 @@ +#include "StackableItem.h" + +StackableItem::StackableItem() : IModule(0, Category::PLAYER, "Stack items you normally wouldn't be able to stack (e. g. swords)") { +} + +StackableItem::~StackableItem() { +} + +const char* StackableItem::getModuleName() { + return ("StackableItem"); +} + +void StackableItem::onTick(C_GameMode* gm) { + C_PlayerInventoryProxy* supplies = g_Data.getLocalPlayer()->getSupplies(); + C_Inventory* a = supplies->inventory; + for (int i = 0; i < 36; i++) { + C_ItemStack* stack = a->getItemStack(i); + if (stack->item != NULL) { + C_Item* item = *stack->item; + item->setStackedByData(true); + item->setMaxStackSize(64); + } + } +} diff --git a/Horion/Module/Modules/StackableItem.h b/Horion/Module/Modules/StackableItem.h new file mode 100644 index 0000000..6914891 --- /dev/null +++ b/Horion/Module/Modules/StackableItem.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" + +class StackableItem : public IModule { +public: + StackableItem(); + ~StackableItem(); + + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Step.cpp b/Horion/Module/Modules/Step.cpp new file mode 100644 index 0000000..5224c5c --- /dev/null +++ b/Horion/Module/Modules/Step.cpp @@ -0,0 +1,20 @@ +#include "Step.h" + +Step::Step() : IModule(0, Category::MOVEMENT, "Increases your step height") { + registerFloatSetting("height", &this->height, this->height, 1.f, 10.f); +} + +Step::~Step() { +} + +const char* Step::getModuleName() { + return ("Step"); +} + +void Step::onTick(C_GameMode* gm) { + gm->player->stepHeight = height; +} +void Step::onDisable() { + if (g_Data.getLocalPlayer() != nullptr) + g_Data.getLocalPlayer()->stepHeight = 0.5625f; +} diff --git a/Horion/Module/Modules/Step.h b/Horion/Module/Modules/Step.h new file mode 100644 index 0000000..b931d1a --- /dev/null +++ b/Horion/Module/Modules/Step.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class Step : public IModule { +private: + float height = 2.f; + +public: + Step(); + ~Step(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/StorageESP.cpp b/Horion/Module/Modules/StorageESP.cpp new file mode 100644 index 0000000..572fa99 --- /dev/null +++ b/Horion/Module/Modules/StorageESP.cpp @@ -0,0 +1,55 @@ +#include "StorageESP.h" +#include "../../DrawUtils.h" + +StorageESP::StorageESP() : IModule(0, Category::VISUAL, "ESP for storage blocks") { +} + +StorageESP::~StorageESP() { +} + +const char* StorageESP::getModuleName() { + return ("StorageESP"); +} + +void StorageESP::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + if (!g_Data.isInGame() || !GameData::canUseMoveKeys() || g_Data.getLocalPlayer() == nullptr) + return; + + auto ourListLock = std::scoped_lock(this->listLock); + + for (const auto& chest : bufferedChestList) { + auto storageID = g_Data.getLocalPlayer()->region->getBlock(chest.upper)->blockLegacy->blockId; + float math = (float)fmax(0.3f, (float)fmin(1.f, 15)); + DrawUtils::setColor(1.f, 1.f, 1.f, math); + + vec3_t blockPos = chest.lower; + if (blockPos.x < 0) + blockPos.x -= 1; + if (blockPos.z < 0) + blockPos.z -= 1; + storageID = g_Data.getLocalPlayer()->region->getBlock(blockPos)->toLegacy()->blockId; + + auto mathVect = vec3_t(chest.upper.floor().add(vec3_t(1.f, 1.f, 1.f)).sub(chest.upper)); + mathVect.y = floor(mathVect.y); + + if (storageID == 54) DrawUtils::setColor(1.f, 1.f, 1.f, math); // Normal Chest + if (storageID == 146) DrawUtils::setColor(.92f, .14f, .14f, math); // Trapped Chest + if (storageID == 130) DrawUtils::setColor(0.435294f, 0.215686f, 0.631372f, math); // Ender Chest + if (storageID == 458) DrawUtils::setColor(0.62, 0.31, 0.04, math); // Barrel + if (storageID == 205) DrawUtils::setColor(.49f, .17f, .95f, math); // Undyed Shulker Box + if (storageID == 218) DrawUtils::setColor(.08f, .91f, .99f, math); // Shulker Box + + DrawUtils::drawBox(chest.lower, chest.upper, (float)fmax(0.2f, 1 / (float)fmax(1, g_Data.getLocalPlayer()->eyePos0.dist(chest.lower))), true); // Fancy math to give an illusion of good esp + } +} + +void StorageESP::onTick(C_GameMode* gm) { + // Swap list + auto listLock = g_Data.lockChestList(); + auto& chestList = g_Data.getChestList(); + auto ourListLock = std::scoped_lock(this->listLock); + + this->bufferedChestList.clear(); + this->bufferedChestList.insert(this->bufferedChestList.end(), chestList.begin(), chestList.end()); + chestList.clear(); +} diff --git a/Horion/Module/Modules/StorageESP.h b/Horion/Module/Modules/StorageESP.h new file mode 100644 index 0000000..0393f30 --- /dev/null +++ b/Horion/Module/Modules/StorageESP.h @@ -0,0 +1,19 @@ +#pragma once + +#include "Module.h" + +class StorageESP : public IModule { +private: + int tickTimeout = 0; + std::vector bufferedChestList; + std::mutex listLock; + +public: + StorageESP(); + ~StorageESP(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Teams.cpp b/Horion/Module/Modules/Teams.cpp new file mode 100644 index 0000000..c44c479 --- /dev/null +++ b/Horion/Module/Modules/Teams.cpp @@ -0,0 +1,13 @@ +#include "Teams.h" + +Teams::Teams() : IModule(0, Category::COMBAT, "Don't attack team members!") { + registerBoolSetting("is allied", &this->alliedCheck, this->alliedCheck); + registerBoolSetting("same color", &this->colorCheck, this->colorCheck); +} + +Teams::~Teams() { +} + +const char* Teams::getModuleName() { + return ("Teams"); +} diff --git a/Horion/Module/Modules/Teams.h b/Horion/Module/Modules/Teams.h new file mode 100644 index 0000000..76c5c9d --- /dev/null +++ b/Horion/Module/Modules/Teams.h @@ -0,0 +1,17 @@ +#pragma once +#include "Module.h" +class Teams : public IModule { +private: + bool alliedCheck = false; + bool colorCheck = true; + +public: + Teams(); + ~Teams(); + + bool isAlliedCheckEnabled() { return this->isEnabled() && alliedCheck; }; + bool isColorCheckEnabled() { return this->isEnabled() && colorCheck; }; + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Teleport.cpp b/Horion/Module/Modules/Teleport.cpp new file mode 100644 index 0000000..3eea8f6 --- /dev/null +++ b/Horion/Module/Modules/Teleport.cpp @@ -0,0 +1,57 @@ +#include "Teleport.h" + +Teleport::Teleport() : IModule(0, Category::MISC, "Click a block to teleport to it") { + registerBoolSetting("Only Hand", &this->onlyHand, this->onlyHand); + registerBoolSetting("Push", &this->bypass, this->bypass); +} + +Teleport::~Teleport() { +} + +const char* Teleport::getModuleName() { + return "Teleport"; +} + +void Teleport::onTick(C_GameMode* gm) { + + if (!GameData::canUseMoveKeys()) + return; + if (onlyHand && g_Data.getLocalPlayer()->getSupplies()->inventory->getItemStack(g_Data.getLocalPlayer()->getSupplies()->selectedHotbarSlot)->item != nullptr) + return; + + if (GameData::isRightClickDown() && !hasClicked) { + hasClicked = true; + + vec3_ti block = g_Data.getClientInstance()->getPointerStruct()->block; + if (block == vec3_ti(0, 0, 0)) return; + vec3_t pos = block.toFloatVector(); + pos.x += 0.5f; + pos.z += 0.5f; + + tpPos = pos; + shouldTP = true; + + g_Data.getGuiData()->displayClientMessageF("%sTeleport position set to %sX: %.1f Y: %.1f Z: %.1f%s. Sneak to teleport!", GREEN, GRAY, pos.x, pos.y, pos.z, GREEN); + } + if (!GameData::isRightClickDown()) + hasClicked = false; + + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + if (shouldTP && GameData::isKeyDown(*input->sneakKey)) { + tpPos.y += (gm->player->getPos()->y - gm->player->getAABB()->lower.y) + 1; // eye height + 1 + if (bypass) { + /*int dist = (int)gm->player->getPos()->dist(tpPos); + int i = (int)dist / 5; + for (int n = 0; n < i; n++) { + vec3_t offs = tpPos.sub(*gm->player->getPos()).div(i).mul(n); + C_MovePlayerPacket p = C_MovePlayerPacket(g_Data.getLocalPlayer(), gm->player->getPos()->add(offs)); + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&p); + } + gm->player->setPos(tpPos);*/ + float dist = gm->player->getPos()->dist(tpPos); + g_Data.getLocalPlayer()->lerpTo(tpPos, vec2_t(1, 1), (int)fmax((int)dist * 0.1, 1)); + } + else gm->player->setPos(tpPos); + shouldTP = false; + } +} diff --git a/Horion/Module/Modules/Teleport.h b/Horion/Module/Modules/Teleport.h new file mode 100644 index 0000000..2e418d8 --- /dev/null +++ b/Horion/Module/Modules/Teleport.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +class Teleport : public IModule { +private: + bool hasClicked = false; + bool onlyHand = false; + bool bypass = false; + bool shouldTP = false; + vec3_t tpPos; + +public: + Teleport(); + ~Teleport(); + + // Inherited via IModule + virtual void onTick(C_GameMode* gm) override; + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/TestModule.cpp b/Horion/Module/Modules/TestModule.cpp new file mode 100644 index 0000000..cc56104 --- /dev/null +++ b/Horion/Module/Modules/TestModule.cpp @@ -0,0 +1,257 @@ +#include "TestModule.h" +#include "../../../Utils/Logger.h" +#include "../../../Utils/VoxelIntersector.h" +#include "../../DrawUtils.h" +#include "../../../SDK/MatrixStack.h" +#include +#include +#include +#include +#include //radians +#include // perspective, translate, rotate +#include +#include +#include +#include +#include +#include "../../../Utils/Json.hpp" +#include "../../path/JoePathFinder.h" +#include "../../path/JoeMovementController.h" +#include "../../path/goals/JoeGoal.h" +#include "../../path/goals/JoeGoalXZ.h" + +using json = nlohmann::json; + + +TestModule::TestModule() : IModule(0, Category::MISC, "For testing purposes") { + enum1 = SettingEnum(this) + .addEntry(EnumEntry("1", 1)) + .addEntry(EnumEntry("2", 2)) + .addEntry(EnumEntry("3", 3)); + + registerFloatSetting("float1", &this->float1, 0, -10, 10); + registerIntSetting("int1", &this->int1, 0, -10, 10); + registerEnumSetting("Enum1", &enum1, 0); + registerBoolSetting("bool1", &this->bool1, true); +} + +TestModule::~TestModule() { +} + +const char* TestModule::getModuleName() { + return "TestModule"; +} + +bool TestModule::isFlashMode() { + return false; +} + +__forceinline unsigned __int64 rotBy(int in, unsigned int by) { + auto mut = static_cast(in); + return ((mut & 0x7FFFFFui64) | ((static_cast(in) >> 8u) & 0x800000u) /*copy sign bit*/) << by; +} + +size_t posToHash(const vec3_ti& pos) { + return rotBy(pos.x, 0) | rotBy(pos.z, 24) | (static_cast(pos.y) << 48u); +} + +struct PosHasher { + size_t operator()(const vec3_ti& i) const { return posToHash(i); }; +}; + +std::unordered_set renderPos(8); + +void loadFile(std::wstring filePath) { + std::string contents = Utils::readFileContents(filePath); + if (contents.size() == 0) + return; + + logF("Starting geometry import"); + auto mesh = SkinUtil::objToMesh(contents.c_str(), false); + logF("Mesh created (verts: %i, uvs: %i, normals: %i, faces: %i)", mesh.vertices.size(), mesh.uvs.size(), mesh.normals.size(), mesh.faces.size()); + + auto posHasher2 = [](const vec3_ti& i) { return posToHash(i); }; + std::unordered_set newPoses(8); + int num = 0; + for (const auto& face : mesh.faces) { + + if (face.facesPresent != 3) { + //logF("wierd face %i", face.facesPresent); + continue; + } + + + const auto& v1 = mesh.vertices[face.indices[0].vertIndex]; + const auto& v2 = mesh.vertices[face.indices[1].vertIndex]; + const auto& v3 = mesh.vertices[face.indices[2].vertIndex]; + // intersect tris + Voxel::Triangle3 tri = {{v1[0], v1[1], v1[2]}, + {v2[0], v2[1], v2[2]}, + {v3[0], v3[1], v3[2]}}; + AABB bBox{}; + Voxel::getBoundingBox(bBox, tri); + bBox.lower.y = std::max(0.f, bBox.lower.y); + bBox.upper.y = std::min(255.f, bBox.upper.y); + + for (float x = floorf(bBox.lower.x); x < ceilf(bBox.upper.x); x++) { + for (float y = floorf(bBox.lower.y); y < ceilf(bBox.upper.y); y++) { + for (float z = floorf(bBox.lower.z); z < ceilf(bBox.upper.z); z++) { + vec3_t voxel(x, y, z); + if (!Voxel::intersects(voxel, tri)) + continue; + + newPoses.insert(vec3_ti((int)x, (int)y, (int)z)); + num++; + } + } + } + } + + renderPos = newPoses; + logF("replaced renderPos with %i %i", renderPos.size(), num); +} + +void TestModule::onEnable() { + /* renderPos.clear(); + + HorionDataPacket packet; + packet.cmd = CMD_FILECHOOSER; + auto tmp = std::shared_ptr(new unsigned char[300]); + packet.data.swap(tmp); + memset(packet.data.get(), 0, 300); + strcpy_s((char*)packet.data.get(), 200, "{\"title\": \"Select a 3d object\", \"filter\":\"Object Files (*.obj)|*.obj\"}"); + packet.dataArraySize = (int)strlen((char*)packet.data.get()); + packet.params[0] = g_Data.addInjectorResponseCallback([](std::shared_ptr pk) { + if (pk->params[0] != 1) { // Dialog Canceled, reset geo + auto box = g_Data.addInfoBox("File load", "No file loaded"); + box->closeTimer = 1; + return; + } + + wchar_t* jsonData = reinterpret_cast(pk->data.get()); + std::wstring jsonDataStr(jsonData); + + json parsed = json::parse(jsonDataStr); + if (parsed["path"].is_string()) { + auto box = g_Data.addInfoBox("Importing File", "Please wait..."); + std::thread gamer([parsed, box]() { + loadFile(Utils::stringToWstring(parsed["path"].get())); + box->fadeTarget = 0; + }); + gamer.detach(); + } + }); + + g_Data.sendPacketToInjector(packet);*/ +} + +bool tryPlace(const vec3_ti& blockPos) { + C_Block* block = g_Data.getLocalPlayer()->region->getBlock(blockPos); + C_BlockLegacy* blockLegacy = block->toLegacy(); + if (blockLegacy->material->isReplaceable) { + + // Find neighbour + static std::vector checklist; + if (checklist.empty()) { + checklist.push_back(vec3_ti(0, -1, 0)); + checklist.push_back(vec3_ti(0, 1, 0)); + + checklist.push_back(vec3_ti(0, 0, -1)); + checklist.push_back(vec3_ti(0, 0, 1)); + + checklist.push_back(vec3_ti(-1, 0, 0)); + checklist.push_back(vec3_ti(1, 0, 0)); + } + + bool foundCandidate = false; + int i = 0; + for (const auto& current : checklist) { + + vec3_ti calc = blockPos.sub(current); + if (!((g_Data.getLocalPlayer()->region->getBlock(calc)->blockLegacy))->material->isReplaceable) { + // Found a solid block to click + g_Data.getCGameMode()->buildBlock(&calc, i); + + return true; + break; + } + i++; + } + } + return false; +} + +void TestModule::onTick(C_GameMode* gm) { + + auto player = g_Data.getLocalPlayer(); + auto pPos = player->eyePos0; + vec3_ti startNode((int)floorf(pPos.x), (int)roundf(pPos.y - 1.62f), (int)floorf(pPos.z)); + auto pathFinder = std::make_shared(startNode, player->region, std::make_unique(vec3_ti(143, 0, -41))); + pathFinder->pathSearchTimeout = 1; + pathFinder->findPath(); + + /* if (g_Data.getLocalPlayer() == nullptr) + return; + if (!g_Data.canUseMoveKeys()) + return; + if (renderPos.size() == 0) + return; + + auto selectedItem = g_Data.getLocalPlayer()->getSelectedItem(); + if ((selectedItem == nullptr || selectedItem->count == 0 || selectedItem->item == nullptr || !selectedItem->getItem()->isBlock())) // Block in hand? + return; + + int radius = 4; + int numBlocksPerTick = 1; + for (int x = -radius; x < radius; x++) { + for (int y = -radius; y < radius; y++) { + for (int z = -radius; z < radius; z++) { + auto pos = g_Data.getLocalPlayer()->eyePos0.add((float)x, (float)y, (float)z).floor(); + if (renderPos.count(pos) == 0) + continue; + if (tryPlace(pos) && --numBlocksPerTick == 0) + return; + } + } + + }*/ +} + +void TestModule::onMove(C_MoveInputHandler* hand){ +} + +void TestModule::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + DrawUtils::setColor(0.3f, 0.3f, 0.7f, 1); + +} + +void TestModule::onSendPacket(C_Packet* p) { + +} + +void TestModule::onDisable() { + +} +float t = 0; +void TestModule::onLevelRender() { + + /* + DrawUtils::setColor(0.8f, 0.4f, 0.4f, 1); + int radius = 50; + + const auto origin = g_Data.getLocalPlayer()->eyePos0.floor(); + for (auto pos : renderPos) { + if (fabsf(pos.x - origin.x) > radius) + continue; + if (fabsf(pos.z - origin.z) > radius) + continue; + if (fabsf(pos.y - origin.y) > radius) + continue; + C_Block* block = g_Data.getLocalPlayer()->region->getBlock(pos); + C_BlockLegacy* blockLegacy = block->toLegacy(); + if (!blockLegacy->material->isReplaceable) + continue; + DrawUtils::drawBox3d(pos.toFloatVector(), pos.add(1, 1, 1).toFloatVector()); + }*/ + +} diff --git a/Horion/Module/Modules/TestModule.h b/Horion/Module/Modules/TestModule.h new file mode 100644 index 0000000..d3b2813 --- /dev/null +++ b/Horion/Module/Modules/TestModule.h @@ -0,0 +1,26 @@ +#pragma once +#include "Module.h" +class TestModule : public IModule { +private: + int delay = 0; + +public: + float float1 = 0; + int int1 = 0; + bool bool1 = true; + SettingEnum enum1; + + TestModule(); + ~TestModule(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual bool isFlashMode() override; + virtual void onEnable() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onSendPacket(C_Packet* p) override; + virtual void onMove(C_MoveInputHandler* hand) override; + virtual void onDisable() override; + void onLevelRender() override; +}; diff --git a/Horion/Module/Modules/TimeChanger.cpp b/Horion/Module/Modules/TimeChanger.cpp new file mode 100644 index 0000000..523e115 --- /dev/null +++ b/Horion/Module/Modules/TimeChanger.cpp @@ -0,0 +1,12 @@ +#include "TimeChanger.h" + +TimeChanger::TimeChanger() : IModule(0, Category::VISUAL, "Changes the client-sided time.") { + registerFloatSetting("modifier", &this->modifier, this->modifier, 0.1f, 1.f); +} + +TimeChanger::~TimeChanger() { +} + +const char* TimeChanger::getModuleName() { + return "TimeChanger"; +} diff --git a/Horion/Module/Modules/TimeChanger.h b/Horion/Module/Modules/TimeChanger.h new file mode 100644 index 0000000..81fe8ec --- /dev/null +++ b/Horion/Module/Modules/TimeChanger.h @@ -0,0 +1,14 @@ +#pragma once +#include "../ModuleManager.h" +#include "Module.h" + +class TimeChanger : public IModule { +public: + TimeChanger(); + ~TimeChanger(); + + float modifier = 0.5f; + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/Timer.cpp b/Horion/Module/Modules/Timer.cpp new file mode 100644 index 0000000..8272d4b --- /dev/null +++ b/Horion/Module/Modules/Timer.cpp @@ -0,0 +1,20 @@ +#include "Timer.h" + +Timer::Timer() : IModule(0, Category::MISC, "Increase the ticks per second") { + this->registerIntSetting("ticks per second", &this->timer, this->timer, 0, 500); +} + +Timer::~Timer() { +} + +const char* Timer::getModuleName() { + return ("Timer"); +} + +void Timer::onTick(C_GameMode* gm) { + *g_Data.getClientInstance()->minecraft->timer = static_cast(this->timer); +} + +void Timer::onDisable() { + *g_Data.getClientInstance()->minecraft->timer = 20.f; +} diff --git a/Horion/Module/Modules/Timer.h b/Horion/Module/Modules/Timer.h new file mode 100644 index 0000000..f9ca107 --- /dev/null +++ b/Horion/Module/Modules/Timer.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class Timer : public IModule { +private: + int timer = 50; + +public: + Timer(); + ~Timer(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onDisable() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Tower.cpp b/Horion/Module/Modules/Tower.cpp new file mode 100644 index 0000000..d02d95b --- /dev/null +++ b/Horion/Module/Modules/Tower.cpp @@ -0,0 +1,100 @@ +#include "Tower.h" + +#include "../../DrawUtils.h" + +Tower::Tower() : IModule(0, Category::WORLD, "Like scaffold, but vertically and a lot faster") { + registerFloatSetting("motion", &this->motion, this->motion, 0.3f, 1.f); +} + +Tower::~Tower() { +} + +const char* Tower::getModuleName() { + return ("Tower"); +} + +bool Tower::tryTower(vec3_t blockBelow) { + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + + if (input == nullptr) + return false; + + blockBelow = blockBelow.floor(); + + DrawUtils::drawBox(blockBelow, vec3_t(blockBelow).add(1), 0.4f); + + C_Block* block = g_Data.getLocalPlayer()->region->getBlock(vec3_ti(blockBelow)); + C_BlockLegacy* blockLegacy = (block->blockLegacy); + if (blockLegacy->material->isReplaceable) { + vec3_ti blok(blockBelow); + + // Find neighbour + static std::vector checklist; + if (checklist.empty()) { + checklist.push_back(new vec3_ti(0, -1, 0)); + checklist.push_back(new vec3_ti(0, 1, 0)); + + checklist.push_back(new vec3_ti(0, 0, -1)); + checklist.push_back(new vec3_ti(0, 0, 1)); + + checklist.push_back(new vec3_ti(-1, 0, 0)); + checklist.push_back(new vec3_ti(1, 0, 0)); + } + bool foundCandidate = false; + int i = 0; + for (auto current : checklist) { + vec3_ti calc = blok.sub(*current); + if (!((g_Data.getLocalPlayer()->region->getBlock(calc)->blockLegacy))->material->isReplaceable) { + // Found a solid block to click + foundCandidate = true; + blok = calc; + break; + } + i++; + } + if (foundCandidate && GameData::isKeyDown(*input->spaceBarKey)) { + vec3_t moveVec; + moveVec.x = g_Data.getLocalPlayer()->velocity.x; + moveVec.y = motion; + moveVec.z = g_Data.getLocalPlayer()->velocity.z; + g_Data.getLocalPlayer()->lerpMotion(moveVec); + g_Data.getCGameMode()->buildBlock(&blok, i); + + return true; + } + } + return false; +} + +void Tower::onPostRender(C_MinecraftUIRenderContext* renderCtx) { + if (g_Data.getLocalPlayer() == nullptr) + return; + if (!g_Data.canUseMoveKeys()) + return; + auto selectedItem = g_Data.getLocalPlayer()->getSelectedItem(); + if (!selectedItem->isValid() || !(*selectedItem->item)->isBlock()) // Block in hand? + return; + + vec3_t blockBelow = g_Data.getLocalPlayer()->eyePos0; // Block below the player + blockBelow.y -= g_Data.getLocalPlayer()->height; + blockBelow.y -= 0.5f; + + // Adjustment by velocity + float speed = g_Data.getLocalPlayer()->velocity.magnitudexy(); + vec3_t vel = g_Data.getLocalPlayer()->velocity; + vel.normalize(); // Only use values from 0 - 1 + + if (!tryTower(blockBelow)) { + if (speed > 0.05f) { + blockBelow.z -= vel.z * 0.4f; + if (!tryTower(blockBelow)) { + blockBelow.x -= vel.x * 0.4f; + if (!tryTower(blockBelow) && g_Data.getLocalPlayer()->isSprinting()) { + blockBelow.z += vel.z; + blockBelow.x += vel.x; + tryTower(blockBelow); + } + } + } + } +} diff --git a/Horion/Module/Modules/Tower.h b/Horion/Module/Modules/Tower.h new file mode 100644 index 0000000..b48b287 --- /dev/null +++ b/Horion/Module/Modules/Tower.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" + +class Tower : public IModule { +private: + float motion = 0.5f; + bool tryTower(vec3_t blockBelow); + +public: + Tower(); + ~Tower(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPostRender(C_MinecraftUIRenderContext* renderCtx) override; +}; diff --git a/Horion/Module/Modules/Tracer.cpp b/Horion/Module/Modules/Tracer.cpp new file mode 100644 index 0000000..7459169 --- /dev/null +++ b/Horion/Module/Modules/Tracer.cpp @@ -0,0 +1,33 @@ +#include "Tracer.h" +#include "../../DrawUtils.h" + +#include "../../../SDK/CCamera.h" + +Tracer::Tracer() : IModule('R', Category::VISUAL, "Draws lines to ESP highlighted entities") { +} + +Tracer::~Tracer() { +} + +const char* Tracer::getModuleName() { + return "Tracer"; +} +void Tracer::onLevelRender() { + + auto cameraMgr = g_Data.getClientInstance()->getCameraManager(); + if(cameraMgr == nullptr) + return; + auto cam = cameraMgr->getCameraOrDebugCamera(); + if(cam == nullptr) + return; + vec3_t forward{}; + cam->getForwardVector(&forward); + + const vec3_t origin = g_Data.getClientInstance()->levelRenderer->origin.add(forward.mul(0.2f) /*place the start of the line slightly forward so it won't get clipped*/); + g_Data.forEachEntity([&](C_Entity* ent, bool valid) { + if(ent != g_Data.getLocalPlayer() && Target::isValidTarget(ent)){ + DrawUtils::setColor(255, 255, 255, 1); + DrawUtils::drawLine3d(origin, *ent->getPos()); + } + }); +} diff --git a/Horion/Module/Modules/Tracer.h b/Horion/Module/Modules/Tracer.h new file mode 100644 index 0000000..c8c2110 --- /dev/null +++ b/Horion/Module/Modules/Tracer.h @@ -0,0 +1,11 @@ +#pragma once +#include "Module.h" +class Tracer : public IModule { +public: + Tracer(); + ~Tracer(); + + // Inherited via IModule + virtual const char* getModuleName() override; + void onLevelRender() override; +}; diff --git a/Horion/Module/Modules/TriggerBot.cpp b/Horion/Module/Modules/TriggerBot.cpp new file mode 100644 index 0000000..3f874b6 --- /dev/null +++ b/Horion/Module/Modules/TriggerBot.cpp @@ -0,0 +1,29 @@ +#include "TriggerBot.h" + +#include "../../../Utils/Target.h" + +TriggerBot::TriggerBot() : IModule(0, Category::COMBAT, "Attacks entities you're looking at") { + this->registerIntSetting("delay", &this->delay, this->delay, 0, 20); +} + +TriggerBot::~TriggerBot() { +} + +const char* TriggerBot::getModuleName() { + return ("TriggerBot"); +} +void TriggerBot::onTick(C_GameMode* gm) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + C_Entity* target = g_Data.getClientInstance()->getPointerStruct()->getEntity(); + + Odelay++; + if (target != 0 && Odelay >= delay) { + if (!Target::isValidTarget(target)) + return; + + localPlayer->swingArm(); + gm->attack(target); + + Odelay = 0; + } +} diff --git a/Horion/Module/Modules/TriggerBot.h b/Horion/Module/Modules/TriggerBot.h new file mode 100644 index 0000000..0fd3d77 --- /dev/null +++ b/Horion/Module/Modules/TriggerBot.h @@ -0,0 +1,18 @@ +#pragma once +#include "Module.h" +#include "../ModuleManager.h" + +class TriggerBot : public IModule { +private: + int delay = 0; + int Odelay = 0; + bool sword = true; + +public: + TriggerBot(); + ~TriggerBot(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Twerk.cpp b/Horion/Module/Modules/Twerk.cpp new file mode 100644 index 0000000..5fe8653 --- /dev/null +++ b/Horion/Module/Modules/Twerk.cpp @@ -0,0 +1,29 @@ +#include "Twerk.h" + +Twerk::Twerk() : IModule(0x0, Category::MOVEMENT, "Crouch Spam") { + registerFloatSetting("delay", &this->delay, this->delay, 0.05f, 10); +} + +Twerk::~Twerk() { +} + +const char* Twerk::getModuleName() { + return ("Twerk"); +} + +void Twerk::onTick(C_GameMode* gm) { + Odelay++; + if (Odelay > delay * 20) { + C_GameSettingsInput* input = g_Data.getClientInstance()->getGameSettingsInput(); + if (gm->player->isSneaking()) { + isSneaking = false; + } + else { + if (!gm->player->isSneaking()) { + isSneaking = true; + } + } + g_Data.getClientInstance()->getMoveTurnInput()->isSneakDown = isSneaking; + Odelay = 0; + } +} \ No newline at end of file diff --git a/Horion/Module/Modules/Twerk.h b/Horion/Module/Modules/Twerk.h new file mode 100644 index 0000000..5dab3b6 --- /dev/null +++ b/Horion/Module/Modules/Twerk.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class Twerk : public IModule { +public: + Twerk(); + ~Twerk(); + +private: + bool isSneaking = false; + int Odelay = 0; + float delay = 1; + inline float& getDelay() { return delay; }; + virtual const char* getModuleName() override; + void onTick(C_GameMode* gm); +}; diff --git a/Horion/Module/Modules/VanillaPlus.cpp b/Horion/Module/Modules/VanillaPlus.cpp new file mode 100644 index 0000000..74f391a --- /dev/null +++ b/Horion/Module/Modules/VanillaPlus.cpp @@ -0,0 +1,79 @@ +#include "VanillaPlus.h" +#include "../../../Utils/Utils.h" +#include + +#include "../../../Utils/Logger.h" + +unsigned char flyingItemsPrevCodeBuf[26]; +unsigned char* flyingItemsFuncPtr = 0; + +bool lastFastFlyingItems = false; + +VanillaPlus::VanillaPlus() : IModule(0, Category::MISC, "Tweaks the minecraft experience") { + registerBoolSetting("Fast Item Lerp", &fastFlyingItems, true); +} + +const char* VanillaPlus::getModuleName() { + return "Vanilla+"; +} + +void VanillaPlus::onEnable() { + // flying items + { + if (flyingItemsFuncPtr == nullptr) + flyingItemsFuncPtr = reinterpret_cast(10 + FindSignature("48 3B 5E ?? 0F 84 ?? ?? ?? ?? 4C 8D 25")); + memcpy(flyingItemsPrevCodeBuf, flyingItemsFuncPtr, 26); + + DWORD oldProtect = 0; + if (!VirtualProtect(flyingItemsFuncPtr, 26, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + auto code = std::initializer_list({0xB9, 0x00, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x6E, 0xC9, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x66, 0x44, 0x0F, 0x6E, 0xD9, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}); + std::copy(code.begin(), code.end(), flyingItemsFuncPtr); + *reinterpret_cast(&flyingItemsFuncPtr[1]) = 0.15f; + *reinterpret_cast(&flyingItemsFuncPtr[11]) = 1 / 0.15f; + VirtualProtect(flyingItemsFuncPtr, 26, oldProtect, &oldProtect); + } + } +} + + +void VanillaPlus::onTick(C_GameMode*) { + if (flyingItemsFuncPtr && lastFastFlyingItems != fastFlyingItems) { + DWORD oldProtect = 0; + if (!VirtualProtect(flyingItemsFuncPtr, 26, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + float val = fastFlyingItems ? 0.025f : 0.15f; + *reinterpret_cast(&flyingItemsFuncPtr[1]) = val; + *reinterpret_cast(&flyingItemsFuncPtr[11]) = 1 / val; + VirtualProtect(flyingItemsFuncPtr, 26, oldProtect, &oldProtect); + } + + + lastFastFlyingItems = fastFlyingItems; + } +} + + +void VanillaPlus::onDisable() { + // flying items + if (flyingItemsFuncPtr) { + DWORD oldProtect = 0; + if (!VirtualProtect(flyingItemsFuncPtr, 26, PAGE_EXECUTE_READWRITE, &oldProtect)) { +#ifdef _DEBUG + logF("couldnt unprotect memory send help"); + __debugbreak(); +#endif + } else { + memcpy(flyingItemsFuncPtr, flyingItemsPrevCodeBuf, 26); + VirtualProtect(flyingItemsFuncPtr, 26, oldProtect, &oldProtect); + } + } +} diff --git a/Horion/Module/Modules/VanillaPlus.h b/Horion/Module/Modules/VanillaPlus.h new file mode 100644 index 0000000..7a069ca --- /dev/null +++ b/Horion/Module/Modules/VanillaPlus.h @@ -0,0 +1,15 @@ +#pragma once +#include "Module.h" +class VanillaPlus : public IModule { + +public: + bool fastFlyingItems = true; + + VanillaPlus(); + virtual ~VanillaPlus(){}; + + virtual const char* getModuleName() override; + virtual void onEnable() override; + virtual void onDisable() override; + virtual void onTick(C_GameMode*) override; +}; diff --git a/Horion/Module/Modules/Velocity.cpp b/Horion/Module/Modules/Velocity.cpp new file mode 100644 index 0000000..402e709 --- /dev/null +++ b/Horion/Module/Modules/Velocity.cpp @@ -0,0 +1,13 @@ +#include "Velocity.h" + +Velocity::Velocity() : IModule(0, Category::MOVEMENT, "Don't ever take knockback again") { + this->registerFloatSetting("Linear Modifier", &this->xModifier, this->xModifier, 0.f, 1.f); + this->registerFloatSetting("Height Modifier", &this->yModifier, this->yModifier, 0.f, 1.f); +} + +Velocity::~Velocity() { +} + +const char* Velocity::getModuleName() { + return ("Velocity"); +} diff --git a/Horion/Module/Modules/Velocity.h b/Horion/Module/Modules/Velocity.h new file mode 100644 index 0000000..6f4af22 --- /dev/null +++ b/Horion/Module/Modules/Velocity.h @@ -0,0 +1,14 @@ +#pragma once + +#include "Module.h" + +class Velocity : public IModule { +public: + float xModifier = 0.f; + float yModifier = 0.f; + Velocity(); + ~Velocity(); + + // Inherited via IModule + virtual const char* getModuleName() override; +}; diff --git a/Horion/Module/Modules/ViewModel.cpp b/Horion/Module/Modules/ViewModel.cpp new file mode 100644 index 0000000..a76d5c5 --- /dev/null +++ b/Horion/Module/Modules/ViewModel.cpp @@ -0,0 +1,40 @@ +#include "ViewModel.h" + + +ViewModel::ViewModel() : IModule(0, Category::VISUAL, "Custom item view model") { + this->registerBoolSetting("Reset", &this->Reset, this->Reset); + this->registerBoolSetting("Translate", &this->doTranslate, this->doTranslate); + this->registerBoolSetting("Scale", &this->doScale, this->doScale); + + this->registerFloatSetting("TranslateX", &this->xTrans, 0.f, -2.f, 2.f); + this->registerFloatSetting("TranslateY", &this->yTrans, 0.f, -2.f, 2.f); + this->registerFloatSetting("TranslateZ", &this->zTrans, 0.f, -2.f, 2.f); + + this->registerFloatSetting("ScaleX", &this->xMod, 1.f, 0.f, 2.f); + this->registerFloatSetting("ScaleY", &this->yMod, 1.f, 0.f, 2.f); + this->registerFloatSetting("ScaleZ", &this->zMod, 1.f, 0.f, 2.f); +} + +ViewModel::~ViewModel() { +} + +const char* ViewModel::getModuleName() { + return "ViewModel"; +} + +void ViewModel::onTick(C_GameMode* gm) { + if (g_Data.getLocalPlayer() == nullptr) + return; + + if (Reset) { + xTrans = 0.f; + yTrans = 0.f; + zTrans = 0.f; + + xMod = 1.f; + yMod = 1.f; + zMod = 1.f; + Reset = false; + } +} + diff --git a/Horion/Module/Modules/ViewModel.h b/Horion/Module/Modules/ViewModel.h new file mode 100644 index 0000000..b8b107b --- /dev/null +++ b/Horion/Module/Modules/ViewModel.h @@ -0,0 +1,27 @@ +#pragma once +#include "Module.h" +class ViewModel : public IModule { +private: + int delay = 0; + +public: + bool Reset = false; + bool doTranslate = true; + bool doScale = true; + + float float1 = 0; + float xMod = 1.f; + float yMod = 1.f; + float zMod = 1.f; + + float xTrans = 0.f; + float yTrans = 0.f; + float zTrans = 0.f; + + ViewModel(); + ~ViewModel(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; +}; diff --git a/Horion/Module/Modules/Waypoints.cpp b/Horion/Module/Modules/Waypoints.cpp new file mode 100644 index 0000000..5ee34ba --- /dev/null +++ b/Horion/Module/Modules/Waypoints.cpp @@ -0,0 +1,210 @@ +#include "Waypoints.h" + +#include + +Waypoints::Waypoints() : IModule(0, Category::VISUAL, "Shows holograms for user-defined coordinates") { + registerFloatSetting("Size", &size, size, 0.3f, 1.6f); + registerBoolSetting("Interdimensional", &interdimensional, interdimensional); + registerBoolSetting("Show coordinates", &showCoordinates, showCoordinates); +} + +Waypoints::~Waypoints() { +} + +const char* Waypoints::getModuleName() { + return "Waypoints"; +} + +void Waypoints::onPreRender(C_MinecraftUIRenderContext* renderCtx) { + C_LocalPlayer* localPlayer = g_Data.getLocalPlayer(); + if (localPlayer == nullptr || !GameData::canUseMoveKeys()) + return; + int currentDimension = -1; + + localPlayer->getDimensionId(¤tDimension); + + for (auto it = waypoints->begin(); it != waypoints->end(); it++) { + vec3_t pos = it->second.pos; + int wpDimension = it->second.dimension; + if (!interdimensional && currentDimension != wpDimension) + continue; + if (currentDimension == 1 && wpDimension == 0) { + // we are in nether, wp in overworld + pos.x /= 8; + pos.z /= 8; + } else if (currentDimension == 0 && wpDimension == 1) { + // we are in overworld, wp in nether + pos.x *= 8; + pos.z *= 8; + } else if (currentDimension != wpDimension) + continue; + float dist = pos.dist(*g_Data.getLocalPlayer()->getPos()); + + constexpr bool useFloatingPoint = false; + constexpr bool fadeOutAtDistance = true; + + std::string txt; + if (useFloatingPoint) { + std::ostringstream out; + out.precision(2); + out << it->first << " (" << std::fixed << dist << " m"; + txt = out.str(); + } else { + txt = it->first + " (" + std::to_string(int(dist)) + "m"; + } + if (currentDimension != wpDimension) { + if (wpDimension == 0) + txt = txt + ", overworld)"; + else if (wpDimension == 1) + txt = txt + ", nether)"; + }else + txt = txt + ")"; + + float alpha = 1; + + if (fadeOutAtDistance && dist > 15) { + + vec2_t angle = localPlayer->currentPos.CalcAngle(pos); + float diff = angle.sub(localPlayer->viewAngles).normAngles().magnitude(); + if (dist > 30) { + float neededDiff = lerp(40, 15, std::min((dist - 30) / 300, 1.f)); + float minAlpha = lerp(0.6f, 0.3f, std::min((dist - 30) / 50, 1.f)); + if (diff < neededDiff) + alpha = 1.f; + else if (diff > neededDiff + 10) + alpha = minAlpha; + else + alpha = lerp(1.f, minAlpha, (diff - neededDiff) / 10); + } + } + + if (alpha < 0.01f) + continue; + + vec4_t rectPos; + + txt = Utils::sanitize(txt); + + float textWidth = DrawUtils::getTextWidth(&txt, size) + 0.5f; + float textHeight = DrawUtils::getFont(Fonts::RUNE)->getLineHeight() * size; + + vec2_t textPos = DrawUtils::worldToScreen(pos); + if (textPos.x != -1) { + std::string coordText; + textPos.y -= textHeight; + textPos.x -= textWidth / 2.f; + + if (this->showCoordinates) { + std::ostringstream out; + out.precision(1); + out << "(" << std::fixed << pos.x << ", " << pos.y << ", " << pos.z << ")"; + coordText = out.str(); + textWidth = std::max(textWidth, DrawUtils::getTextWidth(&coordText, size * 0.75f) + 0.5f); + } + + rectPos.x = textPos.x - 1.f * size; + rectPos.y = textPos.y - 1.05f * size; + rectPos.z = textPos.x + textWidth + 1.f * size; + rectPos.w = textPos.y + textHeight + 2.f * size; + + if (this->showCoordinates) + rectPos.w += textHeight * 0.75f + 1.f * size; + + MC_Color color(0, 0, 0); + if (currentDimension == 0 && wpDimension == 1) + color.r = 0.2f; + + if (currentDimension == 1 && wpDimension == 0) + color.b = 0.2f; + + DrawUtils::fillRectangle(rectPos, color, alpha * 0.5f); + DrawUtils::drawText(textPos, &txt, MC_Color(255, 255, 255), size, alpha); + if (this->showCoordinates) { + textPos.y += textHeight + 1.f * size; + + DrawUtils::drawText(textPos, &coordText, MC_Color(255, 255, 255), size * 0.75f, alpha); + } + } + DrawUtils::flush(); + } + +} + +using json = nlohmann::json; +void Waypoints::onLoadConfig(void* confVoid) { + IModule::onLoadConfig(confVoid); // retain keybinds & enabled state + waypoints->clear(); + json* conf = reinterpret_cast(confVoid); + std::string modName = getRawModuleName(); + if (conf->contains(modName.c_str())) { + auto obj = conf->at(modName.c_str()); + if (obj.is_null()) + return; + if (obj.contains("list")) { + auto value = obj.at("list"); + if (value.is_null() || !value.is_object()) + return; + + for (json::iterator it = value.begin(); it != value.end(); ++it) { + vec3_t _pos; + int dim = 0; + auto val = it.value(); + if (!val.contains("pos")) + continue; + auto pos = val.at("pos"); + if (!pos.is_null() && pos.contains("x") && pos["x"].is_number_float() && pos.contains("y") && pos["y"].is_number_float() && pos.contains("z") && pos["z"].is_number_float()) { + try { + _pos = vec3_t(pos["x"].get(), pos["y"].get(), pos["z"].get()); + } catch (std::exception e) { + } + } else { + continue; + } + if (val.contains("dim")) { + auto dimVal = val.at("dim"); + if (!dimVal.is_null() && dimVal.is_number_integer()) { + try { + dim = dimVal.get(); + } catch (std::exception e) { + } + } + } + waypoints->emplace(it.key().c_str(), WaypointInstance(_pos, dim)); + } + } + } +} + +void Waypoints::onSaveConfig(void* confVoid) { + IModule::onSaveConfig(confVoid); // retain keybinds & enabled state + json* conf = reinterpret_cast(confVoid); + + std::string modName = getRawModuleName(); + json obj = {}; + + if (conf->contains(modName.c_str())) { + obj = conf->at(modName.c_str()); + conf->erase(modName.c_str()); + } + if (obj.contains("list")) { + obj.erase("list"); + } + + json myList = {}; + + for (auto it = waypoints->begin(); it != waypoints->end(); it++) { + json subObj = {}; + auto wp = it->second; + subObj["pos"]["x"] = (float)wp.pos.x; + subObj["pos"]["y"] = (float)wp.pos.y; + subObj["pos"]["z"] = (float)wp.pos.z; + subObj["dim"] = wp.dimension; + myList.emplace(it->first.c_str(), subObj); + } + + if (waypoints->size() > 0) { + obj.emplace("list", myList); + } + + conf->emplace(modName.c_str(), obj); +} diff --git a/Horion/Module/Modules/Waypoints.h b/Horion/Module/Modules/Waypoints.h new file mode 100644 index 0000000..20644fe --- /dev/null +++ b/Horion/Module/Modules/Waypoints.h @@ -0,0 +1,64 @@ +#pragma once + +#include +#include "../../DrawUtils.h" +#include "Module.h" +#include "../../../Utils/Json.hpp" +#include + +struct WaypointInstance { + vec3_t pos; + int dimension; + + WaypointInstance(vec3_t pos, int dim) : pos(pos), dimension(dim){}; +}; + +class Waypoints : public IModule { +private: + std::shared_ptr> waypoints = std::make_shared>(); + +public: + Waypoints(); + ~Waypoints(); + + bool interdimensional = true; + bool showCoordinates = false; + float size = 0.6f; + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onPreRender(C_MinecraftUIRenderContext* renderCtx) override; + virtual void onLoadConfig(void* confVoid) override; + virtual void onSaveConfig(void* confVoid) override; + + bool add(std::string text, vec3_t pos, int dimension) { + for (auto it = waypoints->begin(); it != waypoints->end(); it++) { + if (text == it->first) { + return false; + } + } + waypoints->emplace(text, WaypointInstance(pos, dimension)); + return true; + } + + bool remove(std::string name) { + for (auto it = waypoints->begin(); it != waypoints->end(); it++) { + if (name == it->first) { + waypoints->erase(name); + return true; + } + } + return false; + } + + std::optional getWaypoint(std::string name) { + if (waypoints->find(name) == waypoints->end()) + return {}; + + return waypoints->at(name); + }; + + std::shared_ptr> getWaypoints() { + return waypoints; + } +}; \ No newline at end of file diff --git a/Horion/Module/Modules/Xray.cpp b/Horion/Module/Modules/Xray.cpp new file mode 100644 index 0000000..d3e9478 --- /dev/null +++ b/Horion/Module/Modules/Xray.cpp @@ -0,0 +1,28 @@ +#include "Xray.h" + +Xray::Xray() : IModule(0, Category::VISUAL, "Allows you to see certain blocks easier") { +} + +Xray::~Xray() { +} + +const char* Xray::getModuleName() { + return ("Xray"); +} + +void Xray::onTick(C_GameMode* gm) { + if (smoothLightningSetting != nullptr) { + if (!gotSmoothInfo) { + gotSmoothInfo = true; + wasSmooth = *smoothLightningSetting; + } + *smoothLightningSetting = 0; + } +} + +void Xray::onDisable() { + if (smoothLightningSetting != nullptr && gotSmoothInfo) { + *smoothLightningSetting = wasSmooth; + } + gotSmoothInfo = false; +} \ No newline at end of file diff --git a/Horion/Module/Modules/Xray.h b/Horion/Module/Modules/Xray.h new file mode 100644 index 0000000..3bbe14f --- /dev/null +++ b/Horion/Module/Modules/Xray.h @@ -0,0 +1,16 @@ +#pragma once +#include "Module.h" +class Xray : public IModule { +public: + bool* smoothLightningSetting = nullptr; + bool gotSmoothInfo = false; + bool wasSmooth = false; + + Xray(); + ~Xray(); + + // Inherited via IModule + virtual const char* getModuleName() override; + virtual void onTick(C_GameMode* gm) override; + virtual void onDisable() override; +}; diff --git a/Horion/Module/Modules/Zoom.cpp b/Horion/Module/Modules/Zoom.cpp new file mode 100644 index 0000000..74f5b83 --- /dev/null +++ b/Horion/Module/Modules/Zoom.cpp @@ -0,0 +1,25 @@ +#include "Zoom.h" + +Zoom::Zoom() : IModule('C', Category::VISUAL, "Zoom in or out!") { + registerFloatSetting("Strength", &this->strength, this->strength, -100.f, 100.f); + registerBoolSetting("Smooth", &this->smooth, this->smooth); +} + +Zoom::~Zoom() { +} + +bool Zoom::isFlashMode() { + return true; +} + +const char* Zoom::getModuleName() { + return ("Zoom"); +} + +void Zoom::onEnable() { + zooming = true; +} + +void Zoom::onDisable() { + target = g_Data.fov; +} diff --git a/Horion/Module/Modules/Zoom.h b/Horion/Module/Modules/Zoom.h new file mode 100644 index 0000000..e734354 --- /dev/null +++ b/Horion/Module/Modules/Zoom.h @@ -0,0 +1,19 @@ +#pragma once +#include "Module.h" +class Zoom : public IModule { +public: + Zoom(); + ~Zoom(); + + bool smooth = true; + bool zooming = false; + float strength = 20.f; + float target = 20.f; + float modifier = 20.f; + + // Inherited via IModule + virtual bool isFlashMode() override; + virtual const char* getModuleName() override; + virtual void onEnable() override; + virtual void onDisable() override; +}; diff --git a/Horion/Scripting/Functions/CommandManagerFunctions.cpp b/Horion/Scripting/Functions/CommandManagerFunctions.cpp new file mode 100644 index 0000000..de9b95b --- /dev/null +++ b/Horion/Scripting/Functions/CommandManagerFunctions.cpp @@ -0,0 +1,15 @@ +#include "CommandManagerFunctions.h" + +JsValueRef CALLBACK CommandManagerFunctions::executeCommand(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto commandOpt = chakra.tryGetStringFromArgs(arguments[1], argumentCount - 1); + if (!commandOpt.has_value()) { + THROW(L"Invalid command specified"); + } + + char* coolBeanBuffer = new char[commandOpt.value().size() + 2]; + sprintf_s(coolBeanBuffer, commandOpt.value().size() + 2, ".%S", commandOpt.value().c_str()); + cmdMgr->execute(coolBeanBuffer); + delete[] coolBeanBuffer; + + return chakra.trueValue(); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/CommandManagerFunctions.h b/Horion/Scripting/Functions/CommandManagerFunctions.h new file mode 100644 index 0000000..027d448 --- /dev/null +++ b/Horion/Scripting/Functions/CommandManagerFunctions.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../ScriptManager.h" +#include "../../Command/CommandMgr.h" + +class CommandManagerFunctions { +public: + DECL_FUN(executeCommand); +}; diff --git a/Horion/Scripting/Functions/DrawFunctions.cpp b/Horion/Scripting/Functions/DrawFunctions.cpp new file mode 100644 index 0000000..a3639c4 --- /dev/null +++ b/Horion/Scripting/Functions/DrawFunctions.cpp @@ -0,0 +1,265 @@ +#include "DrawFunctions.h" +#include "../../DrawUtils.h" + +JsValueRef CALLBACK DrawFunctions::drawLine3d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + auto startOpt = Vector3Functions::getVec3FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!startOpt.has_value()) { + THROW(L"Invalid start vector!"); + } + // Note that &arguments[argIndex] might point to invalid memory here, but the function should abort because argumentCount - argIndex equals 0 + auto endOpt = Vector3Functions::getVec3FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!endOpt.has_value()) { + THROW(L"Invalid end vector!"); + } + DrawUtils::drawLine3d(*startOpt, *endOpt); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::drawLinestrip3d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + if (argumentCount < 2){ + THROW(L"Not enough arguments supplied"); + } + + auto arr = arguments[1]; + JsValueType type = JsUndefined; + chakra.JsGetValueType_(arr, &type); + if(type != JsArray){ + THROW(L"Array required as first argument"); + } + + JsValueRef lengthProp; + chakra.getProperty(arr, L"length", &lengthProp); + int arrayLength = -1; + chakra.JsNumberToInt_(lengthProp, &arrayLength); + + if(arrayLength < 2){ + THROW(L"Array needs at least 2 points"); + } + if(arrayLength > 100000){ + THROW(L"Array too big"); + } + + std::vector pointList; + pointList.reserve(arrayLength); + for(int i = 0; i < arrayLength; i++){ + auto val = chakra.arrayGet(arr, i); + auto valueOpt = Vector3Functions::getVec3FromValue(val); + if(!valueOpt.has_value()){ + THROW(L"Points in array need to be of type \"Vec3\""); + } + + pointList.push_back(*valueOpt); + } + + DrawUtils::drawLinestrip3d(pointList); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::setColor(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + if (argumentCount < 4){ + THROW(L"Invalid arguments (3 floats needed, 4th optional)!"); + } + + bool hasAlpha = argumentCount >= 5; + + bool isValid = true; + JsValueType type; + for (int i = 0; i < (hasAlpha ? 4 : 3); i++) { + auto err = chakra.JsGetValueType_(arguments[i + 1], &type); + if (err != JsNoError || type != JsNumber) { + isValid = false; + break; + } + } + + if (!isValid){ + THROW(L"Invalid arguments (3 doubles needed, 4th optional)!"); + } + + double r, g, b, a = 1; + int err = 0; + err |= (int)chakra.JsNumberToDouble_(arguments[1], &r); + err |= (int)chakra.JsNumberToDouble_(arguments[2], &g); + err |= (int)chakra.JsNumberToDouble_(arguments[3], &b); + if(hasAlpha) + err |= (int)chakra.JsNumberToDouble_(arguments[4], &a); + if ((JsErrorCode)err != JsNoError){ + THROW(L"Invalid arguments (can't convert to double)"); + } + + DrawUtils::setColor((float)r, (float)g, (float)b, (float)a); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::drawLine2d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + auto startOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!startOpt.has_value()) { + THROW(L"Invalid start vector!"); + } + + auto endOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!endOpt.has_value()) { + THROW(L"Invalid end vector!"); + } + double lineWidth = 1; + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &lineWidth); + THROW_IF_ERROR(status, L"invalid line width"); + argIndex++; + } + DrawUtils::drawLine(*startOpt, *endOpt, (float)lineWidth); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::drawRectangle2d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + auto startOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!startOpt.has_value()) { + THROW(L"Invalid start vector!"); + } + + auto endOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!endOpt.has_value()) { + THROW(L"Invalid end vector!"); + } + + + double lineWidth = 1; + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &lineWidth); + THROW_IF_ERROR(status, L"invalid line width"); + argIndex++; + } + + vec2_t lower = {std::min(startOpt->x, endOpt->x), std::min(startOpt->y, endOpt->y)}; + vec2_t upper = {std::max(startOpt->x, endOpt->x), std::max(startOpt->y, endOpt->y)}; + DrawUtils::drawRectangle(lower, upper, (float)lineWidth); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::fillRectangle2d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + auto startOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!startOpt.has_value()) { + THROW(L"Invalid start vector!"); + } + + auto endOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!endOpt.has_value()) { + THROW(L"Invalid end vector!"); + } + + vec2_t lower = {std::min(startOpt->x, endOpt->x), std::min(startOpt->y, endOpt->y)}; + vec2_t upper = {std::max(startOpt->x, endOpt->x), std::max(startOpt->y, endOpt->y)}; + DrawUtils::fillRectangle(lower, upper); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::drawText2d(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + + auto textOpt = chakra.tryGetStringFromArgs(arguments[argIndex], argumentCount - argIndex); + if (!textOpt.has_value()) { + THROW(L"Invalid text specified"); + } + argIndex++; + + auto posOpt = Vector2Functions::getVec2FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (!posOpt.has_value()) { + THROW(L"Invalid pos vector!"); + } + + MC_Color color(1,1,1,1); + double textSize = 1, alpha = 1; + + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &textSize); + THROW_IF_ERROR(status, L"invalid text size"); + argIndex++; + } + + auto colorOpt = Vector3Functions::getVec3FromArguments(&arguments[argIndex], argumentCount - argIndex, &argIndex); + if (colorOpt.has_value()) { + color.r = std::clamp(colorOpt->x, 0.f, 1.f); + color.g = std::clamp(colorOpt->y, 0.f, 1.f); + color.b = std::clamp(colorOpt->z, 0.f, 1.f); + + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &alpha); + THROW_IF_ERROR(status, L"invalid alpha value"); + argIndex++; + } + } + + char* coolBeanBuffer = new char[textOpt.value().size() + 1]; + sprintf_s(coolBeanBuffer, textOpt.value().size() + 1, "%S", textOpt.value().c_str()); + std::string textStr(coolBeanBuffer); + + DrawUtils::drawText(*posOpt, &textStr, color, (float)textSize, (float)alpha); + + delete[] coolBeanBuffer; + + return chakra.trueValue(); +} + +JsValueRef CALLBACK DrawFunctions::getTextWidth(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + + auto textOpt = chakra.tryGetStringFromArgs(arguments[argIndex], argumentCount - argIndex); + if (!textOpt.has_value()) { + THROW(L"Invalid text specified"); + } + argIndex++; + + double textSize = 1; + + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &textSize); + THROW_IF_ERROR(status, L"invalid text size"); + argIndex++; + } + + char* coolBeanBuffer = new char[textOpt.value().size() + 1]; + sprintf_s(coolBeanBuffer, textOpt.value().size() + 1, "%S", textOpt.value().c_str()); + std::string textStr(coolBeanBuffer); + + auto width = (double)DrawUtils::getTextWidth(&textStr, (float)textSize); + + delete[] coolBeanBuffer; + + return chakra.toNumber(width); +} + +JsValueRef CALLBACK DrawFunctions::getTextLineHeight(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + int argIndex = 1; + + double textSize = 1; + + if (argumentCount - argIndex >= 1) { + auto status = chakra.JsNumberToDouble_(arguments[argIndex], &textSize); + THROW_IF_ERROR(status, L"invalid text size"); + argIndex++; + } + + auto height = (double)DrawUtils::getFontHeight((float)textSize); + + return chakra.toNumber(height); +} + +JsValueRef CALLBACK DrawFunctions::getOrigin(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto origin = DrawUtils::getOrigin(); + return scriptMgr.prepareVector3(origin, reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK DrawFunctions::getWindowSize(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto windowSize = g_Data.getGuiData()->windowSize; + return scriptMgr.prepareVector2(windowSize, reinterpret_cast(callbackState)); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/DrawFunctions.h b/Horion/Scripting/Functions/DrawFunctions.h new file mode 100644 index 0000000..056b8bf --- /dev/null +++ b/Horion/Scripting/Functions/DrawFunctions.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../ScriptManager.h" + +class DrawFunctions { +public: + DECL_FUN(drawLine3d); + DECL_FUN(setColor); + DECL_FUN(drawLinestrip3d); + DECL_FUN(drawLine2d); + DECL_FUN(drawRectangle2d); + DECL_FUN(fillRectangle2d); + + DECL_FUN(drawText2d); + DECL_FUN(getTextWidth); + DECL_FUN(getTextLineHeight); + + DECL_FUN(getWindowSize); + DECL_FUN(getOrigin); +}; diff --git a/Horion/Scripting/Functions/EntityFunctions.cpp b/Horion/Scripting/Functions/EntityFunctions.cpp new file mode 100644 index 0000000..a9fefa8 --- /dev/null +++ b/Horion/Scripting/Functions/EntityFunctions.cpp @@ -0,0 +1,145 @@ +#include "EntityFunctions.h" +#include "../../DrawUtils.h" + +// this fixes intellisense somehow +#ifndef ENTITY_INVALID +#define ENTITY_INVALID \ + THROW(L"Entity is invalid! Check if your entity is still valid with entity.isValid()") +#endif + +JsValueRef CALLBACK EntityFunctions::isValid(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + bool isValid = EntityFunctions::getEntityFromValue(arguments[0]) != nullptr; + JsValueRef isValidBoolean; + chakra.JsBoolToBoolean_(isValid, &isValidBoolean); + + return isValidBoolean; +} + +JsValueRef CALLBACK EntityFunctions::getPosition(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return scriptMgr.prepareVector3(*ent->getPos(), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK EntityFunctions::getInterpolatedPosition(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + vec3_t* start = ent->getPosOld(); + vec3_t* end = ent->getPos(); + + auto t = DrawUtils::getLerpTime(); + vec3_t lerped = start->lerp(end, t); + + return scriptMgr.prepareVector3(lerped, reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK EntityFunctions::getVelocity(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return scriptMgr.prepareVector3(ent->velocity, reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK EntityFunctions::isOnGround(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toBoolean(ent->onGround); +} + +JsValueRef CALLBACK EntityFunctions::isInvisible(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toBoolean(ent->isInvisible()); +} + +JsValueRef CALLBACK EntityFunctions::isInWater(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toBoolean(ent->isInWater()); +} + +JsValueRef CALLBACK EntityFunctions::isInLava(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toBoolean(ent->isInLava()); +} + +JsValueRef CALLBACK EntityFunctions::isSneaking(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toBoolean(ent->isSneaking()); +} + +JsValueRef CALLBACK EntityFunctions::getSize(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return scriptMgr.prepareVector3(vec3_t(ent->width, ent->height, ent->width), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK EntityFunctions::toString(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + const wchar_t* name = L"Entity(invalid)"; + JsValueRef ref; + chakra.JsPointerToString_(name, wcslen(name), &ref); + return ref; + } + + const wchar_t* name = L"Entity(isValid=true)"; + JsValueRef ref; + chakra.JsPointerToString_(name, wcslen(name), &ref); + return ref; +} + +JsValueRef CALLBACK EntityFunctions::getViewAngles(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return scriptMgr.prepareVector3(vec3_t(ent->viewAngles, 0), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK EntityFunctions::getPitch(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toNumber(ent->pitch); +} + +JsValueRef CALLBACK EntityFunctions::getYaw(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return chakra.toNumber(ent->yaw); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/EntityFunctions.h b/Horion/Scripting/Functions/EntityFunctions.h new file mode 100644 index 0000000..62f1c79 --- /dev/null +++ b/Horion/Scripting/Functions/EntityFunctions.h @@ -0,0 +1,53 @@ +#pragma once + +#include "../../../Memory/GameData.h" +#include "../../../SDK/CEntity.h" +#include "../ScriptManager.h" + +class EntityFunctions { +public: + static C_Entity* getEntityFromValue(JsValueRef value) { + JsValueType type; + chakra.JsGetValueType_(value, &type); + if (type != JsObject) + return 0; + + bool hasExternalData = false; + chakra.JsHasExternalData_(value, &hasExternalData); + if (!hasExternalData) + return 0; + + EntityInfo* entityInfo; + chakra.JsGetExternalData_(value, reinterpret_cast(&entityInfo)); + if (entityInfo->dataType != EntityDataType) + return 0; + + if (entityInfo->isLocalPlayer) + return g_Data.getLocalPlayer(); + + C_Entity* foundEntity; + auto func = [](C_Entity* ent, bool b, __int64 idCaptured, C_Entity** foundEntityCaptured) { + if (ent->entityRuntimeId == idCaptured) { + *foundEntityCaptured = ent; + } + }; + g_Data.forEachEntity(std::bind(func, std::placeholders::_1, std::placeholders::_2, entityInfo->runtimeId, &foundEntity)); + + return foundEntity; + } + + DECL_FUN(isValid); + DECL_FUN(getPosition); + DECL_FUN(getInterpolatedPosition); + DECL_FUN(getVelocity); + DECL_FUN(isOnGround); + DECL_FUN(isInvisible); + DECL_FUN(isInWater); + DECL_FUN(isInLava); + DECL_FUN(isSneaking); + DECL_FUN(getSize); + DECL_FUN(toString); + DECL_FUN(getViewAngles); + DECL_FUN(getPitch); + DECL_FUN(getYaw); +}; diff --git a/Horion/Scripting/Functions/GameFunctions.cpp b/Horion/Scripting/Functions/GameFunctions.cpp new file mode 100644 index 0000000..817f774 --- /dev/null +++ b/Horion/Scripting/Functions/GameFunctions.cpp @@ -0,0 +1,16 @@ +#include "GameFunctions.h" + +JsValueRef CALLBACK GameFunctions::getClient(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + std::wstring name(L"Horion"); + JsValueRef ref; + chakra.JsPointerToString_(name.c_str(), name.size(), &ref); + return ref; +} + +JsValueRef CALLBACK GameFunctions::getLocalPlayer(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return scriptMgr.getLocalPlayer(reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK GameFunctions::getLevel(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return reinterpret_cast(callbackState)->levelObject; +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/GameFunctions.h b/Horion/Scripting/Functions/GameFunctions.h new file mode 100644 index 0000000..e0598a4 --- /dev/null +++ b/Horion/Scripting/Functions/GameFunctions.h @@ -0,0 +1,10 @@ +#pragma once + +#include "../ScriptManager.h" + +class GameFunctions { +public: + DECL_FUN(getClient); + DECL_FUN(getLocalPlayer); + DECL_FUN(getLevel); +}; diff --git a/Horion/Scripting/Functions/GlobalFunctions.cpp b/Horion/Scripting/Functions/GlobalFunctions.cpp new file mode 100644 index 0000000..e769b13 --- /dev/null +++ b/Horion/Scripting/Functions/GlobalFunctions.cpp @@ -0,0 +1,39 @@ +#include "GlobalFunctions.h" + +#include + +JsValueRef CALLBACK GlobalFunctions::log(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + std::wstringstream strstream; + /*JsValueRef calleString; + chakra.JsConvertValueToString_(callee, &calleString); + const wchar_t* coolBoi; + size_t length1; + chakra.JsStringToPointer_(calleString, &coolBoi, &length1); + strstream << coolBoi << L": ";*/ + for (unsigned int index = 1; index < argumentCount; index++) { + if (index > 1) { + strstream << L" "; + } + + auto string = chakra.valueToString(arguments[index]); + + strstream << string; + } + + #ifdef _DEBUG + auto string = strstream.str(); + Logger::WriteBigLogFileF(string.size() + 11, "Script: %S", string.c_str()); + #else + + auto obj = reinterpret_cast(callbackState); + if (obj->scriptInstance == nullptr) { + GameData::log("[inline]: %S", strstream.str().c_str()); + } else { + GameData::log("[script]: %S", strstream.str().c_str()); + } + + + #endif + + return JS_INVALID_REFERENCE; +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/GlobalFunctions.h b/Horion/Scripting/Functions/GlobalFunctions.h new file mode 100644 index 0000000..614eabb --- /dev/null +++ b/Horion/Scripting/Functions/GlobalFunctions.h @@ -0,0 +1,9 @@ +#pragma once + +#include "../ScriptManager.h" +#include "Vector3Functions.h" + +class GlobalFunctions { +public: + DECL_FUN(log); +}; diff --git a/Horion/Scripting/Functions/HorionFunctions.cpp b/Horion/Scripting/Functions/HorionFunctions.cpp new file mode 100644 index 0000000..735593b --- /dev/null +++ b/Horion/Scripting/Functions/HorionFunctions.cpp @@ -0,0 +1,13 @@ +#include "HorionFunctions.h" + +JsValueRef CALLBACK HorionFunctions::getCommandManager(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return reinterpret_cast(callbackState)->commandManager; +} + +JsValueRef CALLBACK HorionFunctions::getModuleManager(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return reinterpret_cast(callbackState)->moduleManager; +} + +JsValueRef CALLBACK HorionFunctions::getDrawUtils(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return reinterpret_cast(callbackState)->drawUtils; +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/HorionFunctions.h b/Horion/Scripting/Functions/HorionFunctions.h new file mode 100644 index 0000000..0d36ea1 --- /dev/null +++ b/Horion/Scripting/Functions/HorionFunctions.h @@ -0,0 +1,10 @@ +#pragma once + +#include "../ScriptManager.h" + +class HorionFunctions { +public: + DECL_FUN(getCommandManager); + DECL_FUN(getModuleManager); + DECL_FUN(getDrawUtils); +}; diff --git a/Horion/Scripting/Functions/InventoryFunctions.cpp b/Horion/Scripting/Functions/InventoryFunctions.cpp new file mode 100644 index 0000000..1da7261 --- /dev/null +++ b/Horion/Scripting/Functions/InventoryFunctions.cpp @@ -0,0 +1,170 @@ +#include "InventoryFunctions.h" + +const wchar_t* airName = L"air"; + +JsValueRef createItem(C_ItemStack *stack) { + JsValueRef obj; + chakra.JsCreateObject_(&obj); + + if (stack == nullptr || !stack->isValid()) { + JsValueRef itemName; + chakra.JsPointerToString_(airName, wcslen(airName), &itemName); + + chakra.addPropertyToObj(obj, L"name", itemName); + chakra.addPropertyToObj(obj, L"id", chakra.toNumber(0)); + chakra.addPropertyToObj(obj, L"amount", chakra.toNumber(0)); + } else { + auto name = stack->getItem()->name.getText(); + JsValueRef itemName; + + std::wstring charName = Utils::stringToWstring(name); + + chakra.JsPointerToString_(charName.c_str(), charName.size(), &itemName); + + chakra.addPropertyToObj(obj, L"name", itemName); + chakra.addPropertyToObj(obj, L"id", chakra.toNumber(stack->getItem()->itemId)); + chakra.addPropertyToObj(obj, L"amount", chakra.toNumber(stack->count)); + } + + return obj; +} + +JsValueRef CALLBACK InventoryFunctions::getItems(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + JsValueRef inventoryArr; + chakra.JsCreateArray_(36, &inventoryArr); + + for (int i = 0; i < 36; i++) { + auto stack = plr->getSupplies()->inventory->getItemStack(i); + chakra.arraySet(inventoryArr, i, createItem(stack)); + }; + + return inventoryArr; +} + +JsValueRef CALLBACK InventoryFunctions::getArmor(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + JsValueRef armorArr; + chakra.JsCreateArray_(4, &armorArr); + + for (int i = 0; i < 4; i++) { + auto stack = plr->getArmor(i); + chakra.arraySet(armorArr, i, createItem(stack)); + }; + + return armorArr; +} + +JsValueRef CALLBACK InventoryFunctions::getHeld(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + int slot; + + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + if (type != JsNumber) { + THROW(L"Argument 1 not a valid integer"); + } + if (chakra.JsNumberToInt_(arguments[1], &slot) != JsNoError) { + THROW(L"Argument 1 not a valid integer"); + } + + auto stack = plr->getSupplies()->inventory->getItemStack(slot); + return createItem(stack); +} + +JsValueRef CALLBACK InventoryFunctions::setSelected(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + int slot; + + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + if (type != JsNumber) { + THROW(L"Argument 1 not a valid integer"); + } + if (chakra.JsNumberToInt_(arguments[1], &slot) != JsNoError) { + THROW(L"Argument 1 not a valid integer"); + } + + slot = std::clamp(slot, 0, 8); + + plr->getSupplies()->selectedHotbarSlot = slot; + + return chakra.trueValue(); +} + +JsValueRef CALLBACK InventoryFunctions::getSlot(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + const int currSlot = plr->getSupplies()->selectedHotbarSlot; + + auto stack = plr->getSupplies()->inventory->getItemStack(currSlot); + return createItem(stack); +} + +JsValueRef CALLBACK InventoryFunctions::isFull(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + return chakra.toBoolean(plr->getSupplies()->inventory->isFull()); +} + +JsValueRef CALLBACK InventoryFunctions::moveItem(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = g_Data.getLocalPlayer(); + if (ent == nullptr) { + THROW(L"Player not valid"); + } + + const auto plr = reinterpret_cast(ent); + + int slot[2]; + + for (int i = 0; i < 2; i++) { + JsValueType type; + chakra.JsGetValueType_(arguments[i + 1], &type); + if (type != JsNumber) { + THROW(L"Argument 1 or 2 not valid integers"); + } + if (chakra.JsNumberToInt_(arguments[i + 1], &slot[i]) != JsNoError) { + THROW(L"Argument 1 or 2 not valid integers"); + } + } + + if (slot[0] < 0) slot[0] = 0; + if (slot[1] < 0) slot[1] = 0; + + plr->getSupplies()->inventory->swapSlots(slot[0], slot[1]); + + return chakra.trueValue(); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/InventoryFunctions.h b/Horion/Scripting/Functions/InventoryFunctions.h new file mode 100644 index 0000000..0f919eb --- /dev/null +++ b/Horion/Scripting/Functions/InventoryFunctions.h @@ -0,0 +1,15 @@ +#pragma once + +#include "../ScriptManager.h" + +class InventoryFunctions { +public: + DECL_FUN(getItems); + DECL_FUN(getArmor); + DECL_FUN(getHeld); + DECL_FUN(getSlot); + DECL_FUN(moveItem); + DECL_FUN(setSelected); + + DECL_FUN(isFull); +}; diff --git a/Horion/Scripting/Functions/LevelFunctions.cpp b/Horion/Scripting/Functions/LevelFunctions.cpp new file mode 100644 index 0000000..532cc09 --- /dev/null +++ b/Horion/Scripting/Functions/LevelFunctions.cpp @@ -0,0 +1,85 @@ +#include "LevelFunctions.h" + +JsValueRef createBlock(C_BlockLegacy *block) { + JsValueRef ref; + chakra.JsCreateObject_(&ref); + + std::wstring blockName = Utils::stringToWstring(block->name.getText()); + + JsValueRef bName; + chakra.JsPointerToString_(blockName.c_str(), blockName.size(), &bName); + + std::wstring tileName = Utils::stringToWstring(block->tileName.getText()); + + JsValueRef tName; + chakra.JsPointerToString_(tileName.c_str(), tileName.size(), &tName); + + JsValueRef id = chakra.toNumber((double)block->blockId); + + chakra.addPropertyToObj(ref, L"name", bName); + chakra.addPropertyToObj(ref, L"tileName", tName); + chakra.addPropertyToObj(ref, L"blockId", id); + + return ref; +} + +JsValueRef CALLBACK LevelFunctions::isValid(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + return chakra.toBoolean(g_Data.isInGame() && g_Data.getLocalPlayer()->isAlive()); +} + +JsValueRef CALLBACK LevelFunctions::getAllEntities(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + std::vector entList; + g_Data.forEachEntity([&](auto ent, bool isNew) { + entList.push_back(ent); + }); + + JsValueRef jsList; + chakra.JsCreateArray_((unsigned int)entList.size(), &jsList); + + for (int i = 0; i < entList.size(); i++) { + auto entityRef = scriptMgr.prepareEntity(entList[i]->entityRuntimeId, reinterpret_cast(callbackState)); + chakra.arraySet(jsList, i, entityRef); + } + + return jsList; +} + +JsValueRef CALLBACK LevelFunctions::getAllTargetEntities(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + std::vector entList; + g_Data.forEachEntity([&](auto ent, bool isNew) { + static auto noFriendsMod = moduleMgr->getModule(); + if (!noFriendsMod->isEnabled() && FriendList::findPlayer(ent->getNameTag()->getText())) + return; + + if (!Target::isValidTarget(ent)) + return; + + entList.push_back(ent); + }); + + JsValueRef jsList; + chakra.JsCreateArray_((unsigned int)entList.size(), &jsList); + + for (int i = 0; i < entList.size(); i++) { + auto entityRef = scriptMgr.prepareEntity(entList[i]->entityRuntimeId, reinterpret_cast(callbackState)); + chakra.arraySet(jsList, i, entityRef); + } + + return jsList; +} + +JsValueRef CALLBACK LevelFunctions::getBlock(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto plr = g_Data.getLocalPlayer(); + + if (plr == nullptr) { + THROW(L"Player not valid"); + } + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + auto block = plr->region->getBlock(vecOpt.value())->toLegacy(); + return createBlock(block); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/LevelFunctions.h b/Horion/Scripting/Functions/LevelFunctions.h new file mode 100644 index 0000000..a01bc18 --- /dev/null +++ b/Horion/Scripting/Functions/LevelFunctions.h @@ -0,0 +1,11 @@ +#pragma once + +#include "../ScriptManager.h" + +class LevelFunctions { +public: + DECL_FUN(isValid); + DECL_FUN(getAllEntities); + DECL_FUN(getAllTargetEntities); + DECL_FUN(getBlock); +}; diff --git a/Horion/Scripting/Functions/LocalPlayerFunctions.cpp b/Horion/Scripting/Functions/LocalPlayerFunctions.cpp new file mode 100644 index 0000000..5e40ffe --- /dev/null +++ b/Horion/Scripting/Functions/LocalPlayerFunctions.cpp @@ -0,0 +1,210 @@ +#include "LocalPlayerFunctions.h" + +#ifndef ENTITY_INVALID +#define ENTITY_INVALID \ + THROW(L"Entity is invalid! Check if your entity is still valid with entity.isValid()") + +#endif + +JsValueRef CALLBACK LocalPlayerFunctions::setPosition(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + ent->setPos(vecOpt.value()); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::setVelocity(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + ent->velocity = vecOpt.value(); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::toString(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + const wchar_t* name = L"LocalPlayer(invalid)"; + JsValueRef ref; + chakra.JsPointerToString_(name, wcslen(name), &ref); + return ref; + } + + const wchar_t* name = L"LocalPlayer(isValid=true)"; + JsValueRef ref; + chakra.JsPointerToString_(name, wcslen(name), &ref); + return ref; +} + +JsValueRef CALLBACK LocalPlayerFunctions::setViewAngles(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + vec2_t temp = vec2_t(vecOpt.value().x, vecOpt.value().y).sub(ent->viewAngles); + reinterpret_cast(ent)->applyTurnDelta(&temp); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::setIsOnGround(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + auto isOnGroundOptional = chakra.tryGetBoolFromArgs(&arguments[1], argumentCount - 1); + + if (!isOnGroundOptional.has_value()) { + THROW(L"Invalid boolean!"); + } + + ent->onGround = isOnGroundOptional.value(); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::getInventory(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + return reinterpret_cast(callbackState)->inventoryObject; + + const auto plr = reinterpret_cast(ent); + + JsValueRef inventoryArr; + chakra.JsCreateArray_(35, &inventoryArr); + + const wchar_t* airName = L"air"; + + for (int i = 0; i < 36; i++) { + auto stack = plr->getSupplies()->inventory->getItemStack(i); + + if (stack == nullptr || !stack->isValid()) { + JsValueRef jsItem; + chakra.JsCreateObject_(&jsItem); + + JsValueRef itemName; + chakra.JsPointerToString_(airName, wcslen(airName), &itemName); + + chakra.addPropertyToObj(jsItem, L"name", itemName); + chakra.addPropertyToObj(jsItem, L"id", chakra.toNumber(0)); + chakra.addPropertyToObj(jsItem, L"amount", chakra.toNumber(0)); + + chakra.arraySet(inventoryArr, i, jsItem); + } else { + JsValueRef jsItem; + chakra.JsCreateObject_(&jsItem); + + auto name = stack->getItem()->name.getText(); + JsValueRef itemName; + + std::wstring charName = Utils::stringToWstring(name); + + chakra.JsPointerToString_(charName.c_str(), wcslen(charName.c_str()), &itemName); + + chakra.addPropertyToObj(jsItem, L"name", itemName); + chakra.addPropertyToObj(jsItem, L"id", chakra.toNumber(stack->getItem()->itemId)); + chakra.addPropertyToObj(jsItem, L"amount", chakra.toNumber(stack->count)); + + chakra.arraySet(inventoryArr, i, jsItem); + } + }; + + return inventoryArr; +} + +JsValueRef CALLBACK LocalPlayerFunctions::breakBlock(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + const auto plr = reinterpret_cast(ent); + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + vec3_ti pos = vecOpt.value(); + + g_Data.getCGameMode()->destroyBlock(&pos, 1); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::placeBlock(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + const auto plr = reinterpret_cast(ent); + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + vec3_ti pos = vecOpt.value(); + + g_Data.getCGameMode()->buildBlock(&pos, 1); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::breakBlockRelativeToPlr(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + const auto plr = reinterpret_cast(ent); + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + vec3_ti pos = vecOpt.value().add(*plr->getPos()); + + g_Data.getCGameMode()->destroyBlock(&pos, 1); + return chakra.trueValue(); +} + +JsValueRef CALLBACK LocalPlayerFunctions::placeBlockRelativeToPlr(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto ent = EntityFunctions::getEntityFromValue(arguments[0]); + if (ent == nullptr) { + ENTITY_INVALID; + } + + const auto plr = reinterpret_cast(ent); + + auto vecOpt = Vector3Functions::getVec3FromArguments(&arguments[1], argumentCount - 1); + if (!vecOpt.has_value()) { + THROW(L"Invalid vector!"); + } + + vec3_ti pos = vecOpt.value().add(*plr->getPos()); + + g_Data.getCGameMode()->buildBlock(&pos, 1); + return chakra.trueValue(); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/LocalPlayerFunctions.h b/Horion/Scripting/Functions/LocalPlayerFunctions.h new file mode 100644 index 0000000..acd2f5c --- /dev/null +++ b/Horion/Scripting/Functions/LocalPlayerFunctions.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../ScriptManager.h" +#include "Vector3Functions.h" +#include "InventoryFunctions.h" + + +class LocalPlayerFunctions { +public: + DECL_FUN(setPosition); + DECL_FUN(setVelocity); + DECL_FUN(toString); + DECL_FUN(setViewAngles); + DECL_FUN(setIsOnGround); + DECL_FUN(getInventory); + DECL_FUN(breakBlock); + DECL_FUN(placeBlock); + DECL_FUN(breakBlockRelativeToPlr); + DECL_FUN(placeBlockRelativeToPlr); +}; diff --git a/Horion/Scripting/Functions/ModuleManagerFunctions.cpp b/Horion/Scripting/Functions/ModuleManagerFunctions.cpp new file mode 100644 index 0000000..12b86f0 --- /dev/null +++ b/Horion/Scripting/Functions/ModuleManagerFunctions.cpp @@ -0,0 +1,189 @@ +#include "ModuleManagerFunctions.h" + +std::optional> ModuleManagerFunctions::getModuleFromValue(JsValueRef ref) { + if (ref == JS_INVALID_REFERENCE) + return std::optional>(); + JsValueType type; + auto err = chakra.JsGetValueType_(ref, &type); + if (type != JsObject || err != JsNoError) + return std::optional>(); + + bool hasExternalData = false; + err = chakra.JsHasExternalData_(ref, &hasExternalData); + if (!hasExternalData || err != JsNoError) + return std::optional>(); + + JModule* modInfo; + err = chakra.JsGetExternalData_(ref, reinterpret_cast(&modInfo)); + if (modInfo->dataType != ModuleDataType || err != JsNoError) + return std::optional>(); + + return std::optional>(modInfo->modPtr); +} + +JsValueRef CALLBACK ModuleManagerFunctions::getModuleByName(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleNameOpt = chakra.tryGetStringFromArgs(arguments[1], argumentCount - 1); + if (!moduleNameOpt.has_value()) { + THROW(L"Invalid module name specified"); + } + + char* coolBeanBuffer = new char[moduleNameOpt.value().size() + 1]; + sprintf_s(coolBeanBuffer, moduleNameOpt.value().size() + 1, "%S", moduleNameOpt.value().c_str()); + auto moduleOpt = moduleMgr->getModuleByName(coolBeanBuffer); + delete[] coolBeanBuffer; + + if (!moduleOpt.has_value()) + return chakra.nullValue(); + + return scriptMgr.prepareModule(moduleOpt.value(), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK ModuleManagerFunctions::registerModule(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleNameOpt = chakra.tryGetStringFromArgs(arguments[1], argumentCount - 1); + if (!moduleNameOpt.has_value()) { + THROW(L"Invalid module name specified"); + } + size_t length = moduleNameOpt.value().size(); + if (length < 3 || length > 30) { + THROW(L"Module name should be between 3 and 30 characters long"); + } + + char* coolBeanBuffer = new char[moduleNameOpt.value().size() + 1]; + sprintf_s(coolBeanBuffer, moduleNameOpt.value().size() + 1, "%S", moduleNameOpt.value().c_str()); + std::string moduleName = coolBeanBuffer; + delete[] coolBeanBuffer; + + auto ctxObj = reinterpret_cast(callbackState); + + std::shared_ptr newModule; + std::shared_ptr jsScriptModule; + { + auto lock = moduleMgr->lockModuleListExclusive(); + // Check if module already exists with that name + auto modList = moduleMgr->getModuleList(); + bool found = false; + { + std::string nameCopy = moduleName; + std::transform(nameCopy.begin(), nameCopy.end(), nameCopy.begin(), ::tolower); + + for (std::vector>::iterator it = modList->begin(); it != modList->end(); ++it) { + std::shared_ptr mod = *it; + std::string modNameCopy = mod->getRawModuleName(); + std::transform(modNameCopy.begin(), modNameCopy.end(), modNameCopy.begin(), ::tolower); + if (modNameCopy == nameCopy) { + found = true; + break; + } + } + } + + if (found) { + THROW(L"Module name is already in use"); + } + + newModule = std::make_shared(); + jsScriptModule = std::make_shared(moduleName, newModule, ctxObj->scriptInstance); + newModule->setBackingScript(jsScriptModule); + modList->push_back(newModule); + ctxObj->scriptInstance->registerModule(jsScriptModule); + } + + return scriptMgr.prepareJsModule(newModule, ctxObj); +} + +JsValueRef CALLBACK ModuleManagerFunctions::Module_getName(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + + auto wstr = Utils::stringToWstring(moduleOpt.value()->getModuleName()); + JsValueRef ref; + chakra.JsPointerToString_(wstr.c_str(), wstr.size(), &ref); + + return ref; +} + +JsValueRef CALLBACK ModuleManagerFunctions::Module_toString(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + + auto wstr = Utils::stringToWstring(moduleOpt.value()->getModuleName()); + auto strComp = std::wstring(L"Module(name=") + wstr + L")"; + JsValueRef ref; + chakra.JsPointerToString_(strComp.c_str(), strComp.size(), &ref); + return ref; +} + +JsValueRef CALLBACK ModuleManagerFunctions::Module_isEnabled(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + + return chakra.toBoolean(moduleOpt.value()->isEnabled()); +} + +JsValueRef CALLBACK ModuleManagerFunctions::Module_setEnabled(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + + auto bolOpt = chakra.tryGetBoolFromArgs(&arguments[1], argumentCount - 1); + if (!bolOpt.has_value()) { + THROW(L"Invalid boolean specified"); + } + + moduleOpt.value()->setEnabled(bolOpt.value()); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK ModuleManagerFunctions::Module_toggle(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + + moduleOpt.value()->toggle(); + + return chakra.trueValue(); +} + +JsValueRef CALLBACK ModuleManagerFunctions::JsModule_registerCallback(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto moduleOpt = ModuleManagerFunctions::getModuleFromValue(arguments[0]); + if (!moduleOpt.has_value()) { + THROW(L"Invalid module specified"); + } + auto mod = moduleOpt.value(); + if (dynamic_cast(mod.get()) == nullptr) { + THROW(L"Module is not JavascriptModule"); + } + auto jsMod = dynamic_cast(mod.get()); + auto callbackNameOpt = chakra.tryGetStringFromArgs(arguments[1], argumentCount - 1); + if (!callbackNameOpt.has_value()) { + THROW(L"Invalid callback name specified"); + } + auto funcOpt = chakra.tryGetFunctionFromArgs(arguments[2], argumentCount - 2); + if (!funcOpt.has_value()) { + THROW(L"Invalid callback function specified"); + } + + logF("name: %s", jsMod->getModuleName()); + auto weakPtr = jsMod->getBackingScriptModule(); + auto ptr = weakPtr.lock(); + if (!ptr) { + THROW(L"Invalid module specified 2"); + } + + if (!ptr->registerCallback(callbackNameOpt.value(), funcOpt.value())) { + THROW(L"Invalid callback name"); + } + + logF("Callback registered"); + + return chakra.trueValue(); +} diff --git a/Horion/Scripting/Functions/ModuleManagerFunctions.h b/Horion/Scripting/Functions/ModuleManagerFunctions.h new file mode 100644 index 0000000..8692203 --- /dev/null +++ b/Horion/Scripting/Functions/ModuleManagerFunctions.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../ScriptManager.h" + +class ModuleManagerFunctions { +private: + static std::optional> getModuleFromValue(JsValueRef); + +public: + DECL_FUN(getModuleByName); + DECL_FUN(registerModule); + + DECL_FUN(Module_getName); + DECL_FUN(Module_toString); + DECL_FUN(Module_isEnabled); + DECL_FUN(Module_setEnabled); + DECL_FUN(Module_toggle); + + DECL_FUN(JsModule_registerCallback); +}; diff --git a/Horion/Scripting/Functions/Vector2Functions.cpp b/Horion/Scripting/Functions/Vector2Functions.cpp new file mode 100644 index 0000000..9136e99 --- /dev/null +++ b/Horion/Scripting/Functions/Vector2Functions.cpp @@ -0,0 +1,341 @@ +#include "Vector2Functions.h" + +std::optional Vector2Functions::getVec2FromValue(JsValueRef ref) { + JsValueType type; + auto err = chakra.JsGetValueType_(ref, &type); + if (type != JsObject || err != JsNoError) + return std::optional(); + + bool hasExternalData = false; + err = chakra.JsHasExternalData_(ref, &hasExternalData); + if (!hasExternalData || err != JsNoError) + return std::optional(); + + JVector2* vecInfo; + err = chakra.JsGetExternalData_(ref, reinterpret_cast(&vecInfo)); + if (vecInfo->dataType != Vector2DataType || err != JsNoError) + return std::optional(); + return std::optional(vecInfo->vec); +} + +std::optional Vector2Functions::getVec2FromArguments(JsValueRef* args, int argCount, int* nextArg) { + if (argCount <= 0) + return std::optional(); + + auto vec = Vector2Functions::getVec2FromValue(args[0]); + + if (vec.has_value()){ + if(nextArg) + *nextArg += 1; + return vec.value(); + } + + if (argCount < 2) + return std::optional(); + + bool isValid = true; + JsValueType type; + for (int i = 0; i < 2; i++) { + auto err = chakra.JsGetValueType_(args[i], &type); + if (err != JsNoError || type != JsNumber) { + isValid = false; + break; + } + } + + if (!isValid) + return std::optional(); + + double x, y; + int err = 0; + err |= (int)chakra.JsNumberToDouble_(args[0], &x); + err |= (int)chakra.JsNumberToDouble_(args[1], &y); + if ((JsErrorCode)err != JsNoError) + return std::optional(); + + if(nextArg) + *nextArg += 2; + + return std::optional(vec2_t((float)x, (float)y)); +} + +JsValueRef CALLBACK Vector2Functions::isValid(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + JsValueRef isValidBoolean; + chakra.JsBoolToBoolean_(vecOpt.has_value(), &isValidBoolean); + + return isValidBoolean; +} + +JsValueRef CALLBACK Vector2Functions::getX(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + + return chakra.toNumber(vecOpt->x); +} + +JsValueRef CALLBACK Vector2Functions::getY(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + + return chakra.toNumber(vecOpt->y); +} + +JsValueRef CALLBACK Vector2Functions::toString(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + auto vec = vecOpt.value(); + + wchar_t name[80]; + int length = swprintf_s(name, L"Vec2(x=%.2f, y=%.2f)", vec.x, vec.y); + JsValueRef ref; + chakra.JsPointerToString_(name, length, &ref); + return ref; +} + +JsValueRef CALLBACK Vector2Functions::constructor(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + if (argumentCount != 3) { + chakra.throwTypeException(L"Vec2 constructor needs 2 parameters!"); + return JS_INVALID_REFERENCE; + } + + double x, y; + chakra.JsNumberToDouble_(arguments[1], &x); + chakra.JsNumberToDouble_(arguments[2], &y); + + return scriptMgr.prepareVector2(vec2_t((float)x, (float)y), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK Vector2Functions::add(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch(argumentCount - 1){ + case 1: { + // either adding a Vec2 or a float to all 2 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if(type == JsNumber){ + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError){ + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector2(vecOpt->add((float)val), reinterpret_cast(callbackState)); + }else if(type == JsObject){ + auto oVec = Vector2Functions::getVec2FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector2(vecOpt->add(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 2: { + // adding with 2 individual floats + vec2_t oVec; + for(int i = 0; i < 2; i++){ + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if(type != JsNumber){ + THROW(L"Invalid argument supplied"); + } + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError){ + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector2(vecOpt->add(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + +JsValueRef CALLBACK Vector2Functions::sub(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch(argumentCount - 1){ + case 1: { + // either subtracting a Vec2 or a float to all 2 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if(type == JsNumber){ + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError){ + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector2(vecOpt->sub((float)val), reinterpret_cast(callbackState)); + }else if(type == JsObject){ + auto oVec = Vector2Functions::getVec2FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector2(vecOpt->sub(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 2: { + // adding with 2 individual floats + vec2_t oVec; + for(int i = 0; i < 2; i++){ + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if(type != JsNumber){ + THROW(L"Invalid argument supplied"); + } + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError){ + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector2(vecOpt->sub(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + +JsValueRef CALLBACK Vector2Functions::div(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch (argumentCount - 1) { + case 1: { + // either adding a Vec2 or a float to all 2 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if (type == JsNumber) { + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError) { + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector2(vecOpt->div((float)val), reinterpret_cast(callbackState)); + } else if (type == JsObject) { + auto oVec = Vector2Functions::getVec2FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector2(vecOpt->div(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 2: { + // adding with 2 individual floats + vec2_t oVec; + for (int i = 0; i < 2; i++) { + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if (type != JsNumber) { + THROW(L"Invalid argument supplied"); + } + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError) { + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector2(vecOpt->div(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + + +JsValueRef CALLBACK Vector2Functions::mul(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector2Functions::getVec2FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch (argumentCount - 1) { + case 1: { + // either adding a Vec2 or a float to all 2 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if (type == JsNumber) { + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError) { + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector2(vecOpt->mul((float)val), reinterpret_cast(callbackState)); + } else if (type == JsObject) { + auto oVec = Vector2Functions::getVec2FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector2(vecOpt->mul(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 2: { + // adding with 2 individual floats + vec2_t oVec; + for (int i = 0; i < 2; i++) { + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if (type != JsNumber) { + THROW(L"Invalid argument supplied"); + } + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError) { + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector2(vecOpt->mul(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/Vector2Functions.h b/Horion/Scripting/Functions/Vector2Functions.h new file mode 100644 index 0000000..c8e4f53 --- /dev/null +++ b/Horion/Scripting/Functions/Vector2Functions.h @@ -0,0 +1,22 @@ +#pragma once + +#include "../../../Utils/HMath.h" +#include "../ScriptManager.h" +#include + +class Vector2Functions { +public: + static std::optional getVec2FromValue(JsValueRef); + static std::optional getVec2FromArguments(JsValueRef*, int argCount, int* nextArg = nullptr); + + DECL_FUN(isValid); + DECL_FUN(getX); + DECL_FUN(getY); + DECL_FUN(toString); + DECL_FUN(constructor); + + DECL_FUN(add); + DECL_FUN(sub); + DECL_FUN(div); + DECL_FUN(mul); +}; diff --git a/Horion/Scripting/Functions/Vector3Functions.cpp b/Horion/Scripting/Functions/Vector3Functions.cpp new file mode 100644 index 0000000..518a519 --- /dev/null +++ b/Horion/Scripting/Functions/Vector3Functions.cpp @@ -0,0 +1,352 @@ +#include "Vector3Functions.h" + +std::optional Vector3Functions::getVec3FromValue(JsValueRef ref) { + JsValueType type; + auto err = chakra.JsGetValueType_(ref, &type); + if (type != JsObject || err != JsNoError) + return std::optional(); + + bool hasExternalData = false; + err = chakra.JsHasExternalData_(ref, &hasExternalData); + if (!hasExternalData || err != JsNoError) + return std::optional(); + + JVector3* vecInfo; + err = chakra.JsGetExternalData_(ref, reinterpret_cast(&vecInfo)); + if (vecInfo->dataType != Vector3DataType || err != JsNoError) + return std::optional(); + return std::optional(vecInfo->vec); +} + +std::optional Vector3Functions::getVec3FromArguments(JsValueRef* args, int argCount, int* nextArg) { + if (argCount <= 0) + return std::optional(); + + auto vec = Vector3Functions::getVec3FromValue(args[0]); + + if (vec.has_value()){ + if(nextArg) + *nextArg += 1; + return vec.value(); + } + + if (argCount < 3) + return std::optional(); + + bool isValid = true; + JsValueType type; + for (int i = 0; i < 3; i++) { + auto err = chakra.JsGetValueType_(args[i], &type); + if (err != JsNoError || type != JsNumber) { + isValid = false; + break; + } + } + + if (!isValid) + return std::optional(); + + double x, y, z; + int err = 0; + err |= (int)chakra.JsNumberToDouble_(args[0], &x); + err |= (int)chakra.JsNumberToDouble_(args[1], &y); + err |= (int)chakra.JsNumberToDouble_(args[2], &z); + if ((JsErrorCode)err != JsNoError) + return std::optional(); + + if(nextArg) + *nextArg += 3; + + return std::optional(vec3_t(x, y, z)); +} + +JsValueRef CALLBACK Vector3Functions::isValid(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + JsValueRef isValidBoolean; + chakra.JsBoolToBoolean_(vecOpt.has_value(), &isValidBoolean); + + return isValidBoolean; +} + +JsValueRef CALLBACK Vector3Functions::getX(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + + return chakra.toNumber(vecOpt->x); +} + +JsValueRef CALLBACK Vector3Functions::getY(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + + return chakra.toNumber(vecOpt->y); +} + +JsValueRef CALLBACK Vector3Functions::getZ(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + + return chakra.toNumber(vecOpt->z); +} + +JsValueRef CALLBACK Vector3Functions::toString(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + chakra.throwTypeException(L"Vector is invalid!"); + return JS_INVALID_REFERENCE; + } + auto vec = vecOpt.value(); + + wchar_t name[80]; + int length = swprintf_s(name, L"Vec3(x=%.2f, y=%.2f, z=%.2f)", vec.x, vec.y, vec.z); + JsValueRef ref; + chakra.JsPointerToString_(name, length, &ref); + return ref; +} + +JsValueRef CALLBACK Vector3Functions::constructor(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + if (argumentCount != 4) { + chakra.throwTypeException(L"Vec3 constructor needs 3 parameters!"); + return JS_INVALID_REFERENCE; + } + + double x, y, z; + chakra.JsNumberToDouble_(arguments[1], &x); + chakra.JsNumberToDouble_(arguments[2], &y); + chakra.JsNumberToDouble_(arguments[3], &z); + + return scriptMgr.prepareVector3(vec3_t((float)x, (float)y, (float)z), reinterpret_cast(callbackState)); +} + +JsValueRef CALLBACK Vector3Functions::add(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch(argumentCount - 1){ + case 1: { + // either adding a Vec3 or a float to all 3 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if(type == JsNumber){ + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError){ + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector3(vecOpt->add((float)val), reinterpret_cast(callbackState)); + }else if(type == JsObject){ + auto oVec = Vector3Functions::getVec3FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector3(vecOpt->add(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 3: { + // adding with 3 individual floats + vec3_t oVec; + for(int i = 0; i < 3; i++){ + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if(type != JsNumber){ + THROW(L"Invalid argument supplied"); + } + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError){ + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector3(vecOpt->add(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + +JsValueRef CALLBACK Vector3Functions::sub(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch(argumentCount - 1){ + case 1: { + // either subtracting a Vec3 or a float to all 3 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if(type == JsNumber){ + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError){ + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector3(vecOpt->sub((float)val), reinterpret_cast(callbackState)); + }else if(type == JsObject){ + auto oVec = Vector3Functions::getVec3FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector3(vecOpt->sub(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 3: { + // adding with 3 individual floats + vec3_t oVec; + for(int i = 0; i < 3; i++){ + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if(type != JsNumber){ + THROW(L"Invalid argument supplied"); + } + double val = 0; + if(chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError){ + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector3(vecOpt->sub(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + +JsValueRef CALLBACK Vector3Functions::div(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch (argumentCount - 1) { + case 1: { + // either adding a Vec3 or a float to all 3 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if (type == JsNumber) { + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError) { + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector3(vecOpt->div((float)val), reinterpret_cast(callbackState)); + } else if (type == JsObject) { + auto oVec = Vector3Functions::getVec3FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector3(vecOpt->div(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 3: { + // adding with 3 individual floats + vec3_t oVec; + for (int i = 0; i < 3; i++) { + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if (type != JsNumber) { + THROW(L"Invalid argument supplied"); + } + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError) { + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector3(vecOpt->div(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} + +JsValueRef CALLBACK Vector3Functions::mul(JsValueRef callee, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) { + auto vecOpt = Vector3Functions::getVec3FromValue(arguments[0]); + if (!vecOpt.has_value()) { + THROW(L"Vector is invalid!"); + } + + if (argumentCount < 2) { + THROW(L"At least 1 argument needed"); + } + + switch (argumentCount - 1) { + case 1: { + // either adding a Vec3 or a float to all 3 components + JsValueType type; + chakra.JsGetValueType_(arguments[1], &type); + + if (type == JsNumber) { + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1], &val) != JsNoError) { + THROW(L"Argument 1 not a valid number"); + } + + return scriptMgr.prepareVector3(vecOpt->mul((float)val), reinterpret_cast(callbackState)); + } else if (type == JsObject) { + auto oVec = Vector3Functions::getVec3FromValue(arguments[1]); + if (!oVec.has_value()) { + THROW(L"Supplied Vector is invalid!"); + } + + return scriptMgr.prepareVector3(vecOpt->mul(*oVec), reinterpret_cast(callbackState)); + } + } break; + case 3: { + // adding with 3 individual floats + vec3_t oVec; + for (int i = 0; i < 3; i++) { + JsValueType type; + chakra.JsGetValueType_(arguments[1 + i], &type); + if (type != JsNumber) { + THROW(L"Invalid argument supplied"); + } + double val = 0; + if (chakra.JsNumberToDouble_(arguments[1 + i], &val) != JsNoError) { + THROW(L"Argument not a valid number"); + } + + oVec.floatArr[i] = (float)val; + } + + return scriptMgr.prepareVector3(vecOpt->mul(oVec), reinterpret_cast(callbackState)); + } break; + } + + THROW(L"Invalid arguments"); +} \ No newline at end of file diff --git a/Horion/Scripting/Functions/Vector3Functions.h b/Horion/Scripting/Functions/Vector3Functions.h new file mode 100644 index 0000000..72f9b28 --- /dev/null +++ b/Horion/Scripting/Functions/Vector3Functions.h @@ -0,0 +1,23 @@ +#pragma once + +#include "../../../Utils/HMath.h" +#include "../ScriptManager.h" +#include + +class Vector3Functions { +public: + static std::optional getVec3FromValue(JsValueRef); + static std::optional getVec3FromArguments(JsValueRef*, int argCount, int* nextArg = nullptr); + + DECL_FUN(isValid); + DECL_FUN(getX); + DECL_FUN(getY); + DECL_FUN(getZ); + DECL_FUN(toString); + DECL_FUN(constructor); + + DECL_FUN(add); + DECL_FUN(sub); + DECL_FUN(div); + DECL_FUN(mul); +}; diff --git a/Horion/Scripting/JsScriptModule.cpp b/Horion/Scripting/JsScriptModule.cpp new file mode 100644 index 0000000..8dd2417 --- /dev/null +++ b/Horion/Scripting/JsScriptModule.cpp @@ -0,0 +1,29 @@ +#include "JsScriptModule.h" + +JsScriptModule::JsScriptModule(std::string modName, std::shared_ptr mod, ScriptInstance* sc) : moduleName(modName), myModule(mod), scriptInstance(sc) { + strcpy_s(this->moduleNameCh, moduleName.c_str()); +} + +JsValueRef JsScriptModule::getCallback(std::wstring callbackName) { + if (callbacks.find(callbackName) == callbacks.end()) { + return JS_INVALID_REFERENCE; + } + return callbacks[callbackName]; +} + +bool JsScriptModule::registerCallback(std::wstring callbackName, JsValueRef jsFunc) { + if (callbackName != L"onTick" && callbackName != L"onEnable" && callbackName != L"onDisable" && callbackName != L"onAttack" && callbackName != L"onRender" && callbackName != L"onRender2d") + return false; + + chakra.JsAddRef_(jsFunc, 0); + if (callbacks.find(callbackName) != callbacks.end()) { + // Remove old + auto old = callbacks[callbackName]; + if (old != JS_INVALID_REFERENCE) + chakra.JsRelease_(old, 0); + } + + callbacks[callbackName] = jsFunc; + + return true; +} diff --git a/Horion/Scripting/JsScriptModule.h b/Horion/Scripting/JsScriptModule.h new file mode 100644 index 0000000..e0021ff --- /dev/null +++ b/Horion/Scripting/JsScriptModule.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../Module/Modules/JavascriptModule.h" +#include + +class JavascriptModule; +class ScriptInstance; + +class JsScriptModule { +private: + ScriptInstance* scriptInstance; + std::shared_ptr myModule; + std::string moduleName; + std::mutex callbackLock; + std::map callbacks; + char moduleNameCh[30]; + +public: + JsScriptModule(std::string modName, std::shared_ptr, ScriptInstance* ); + + std::shared_ptr getModule() { return this->myModule; } + inline std::string getModuleName() { return this->moduleName; } + inline char* getModuleNameCh() { return moduleNameCh; } + inline ScriptInstance* getScriptInstance() { return scriptInstance; } + + std::unique_lock lockCallbacks() { return std::unique_lock(callbackLock); } + JsValueRef getCallback(std::wstring callbackName); + bool registerCallback(std::wstring callbackName, JsValueRef jsFunc); +}; \ No newline at end of file diff --git a/Horion/Scripting/ScriptInstance.cpp b/Horion/Scripting/ScriptInstance.cpp new file mode 100644 index 0000000..f223854 --- /dev/null +++ b/Horion/Scripting/ScriptInstance.cpp @@ -0,0 +1,156 @@ +#include "ScriptInstance.h" + +ScriptInstance::ScriptInstance(std::wstring startScript) { + this->startScriptPath = startScript; +} + +ScriptInstance::~ScriptInstance() { + if (this->isRunning) { + if (this->runtimeHandle != JS_INVALID_RUNTIME_HANDLE) + chakra.JsDisableRuntimeExecution_(this->runtimeHandle); + this->isRunning = false; + } + if (this->scriptThread.joinable()) + this->scriptThread.join(); + + { + auto lock = moduleMgr->lockModuleListExclusive(); + auto list = moduleMgr->getModuleList(); + for (const auto& p : this->registeredModules) { + auto pos = std::find(list->begin(), list->end(), p->getModule()); + if (pos == list->end()) { + logF("couldn't find module???"); + continue; + } + list->erase(pos); + } + this->registeredModules.clear(); + } +} + +void CALLBACK promiseContinuationCallback(JsValueRef task, void* callbackState) { + // Save promise task in taskQueue. + auto q = (std::queue*)callbackState; + q->push(task); + chakra.JsAddRef_(task, nullptr); +} + +void ScriptInstance::runPromises() { + JsValueRef global; + chakra.JsGetGlobalObject_(&global); + JsValueRef result; + + while (!taskQueue.empty()) { + JsValueRef task = taskQueue.front(); + taskQueue.pop(); + chakra.JsCallFunction_(task, &global, 1, &result); + chakra.JsRelease_(task, nullptr); + this->checkPrintError(); + } +} + +void ScriptInstance::runSync() { + std::wstring contents = Utils::wreadFileContents(this->startScriptPath); + if (contents.empty()) { + isRunning = false; + return; + } + + JsContextRef context; + JsValueRef result = nullptr; + + chakra.JsCreateRuntime_((_JsRuntimeAttributes)((int)JsRuntimeAttributeDisableFatalOnOOM | (int)JsRuntimeAttributeAllowScriptInterrupt | (int)JsRuntimeAttributeDisableBackgroundWork), nullptr, &this->runtimeHandle); + if (!isRunning) { + chakra.JsDisposeRuntime_(this->runtimeHandle); + this->runtimeHandle = JS_INVALID_RUNTIME_HANDLE; + return; + } + chakra.JsSetRuntimeMemoryLimit_(this->runtimeHandle, 50000000); // 50MB + + chakra.JsCreateContext_(this->runtimeHandle, &context); + chakra.JsSetCurrentContext_(context); + ContextObjects obj; + obj.scriptInstance = this; + scriptMgr.prepareContext(&context, &obj); + JsValueRef global; + chakra.JsGetGlobalObject_(&global); + + auto err = chakra.JsRunScript_(contents.c_str(), JS_SOURCE_CONTEXT_NONE, L"", &result); + + std::wstring returnString = L"No result"; + + if (err != JsNoError || this->checkPrintError()) { + +#define errLog(x, ...) (Logger::isActive() ? logF(x, __VA_ARGS__) : GameData::log(x, __VA_ARGS__)) + + switch (err) { + case JsErrorScriptCompile: + errLog("Script failed to compile (code: %X)", err); + break; + default: + errLog("Script run failed: %X", err); + break; + } + +#undef errLog + returnString = L"Error! " + std::to_wstring(err) + L", you may find a stack trace in the console"; + + goto stopExecution; + } + + returnString = chakra.valueToString(result); + logF("Initial Script return: %S", returnString.c_str()); + this->runPromises(); + + while (this->isRunning && !GameData::shouldTerminate()) { + { + std::unique_lock lk(callbackMutex); + this->callbackWaiter.wait_for(lk, std::chrono::milliseconds(1)); + + while (!this->callbackQueue.empty()) { + auto callb = this->callbackQueue.front(); + this->callbackQueue.pop(); + chakra.JsCallFunction_(callb, &global, 1, &result); + this->checkPrintError(); + } + } + this->callbacksExecuted.notify_all(); + + this->runPromises(); + } + +stopExecution: + chakra.JsSetCurrentContext_(JS_INVALID_REFERENCE); + chakra.JsDisposeRuntime_(this->runtimeHandle); + this->runtimeHandle = JS_INVALID_RUNTIME_HANDLE; + this->isRunning = false; +} + +void ScriptInstance::run() { + if (this->isRunning) { + logF("tried to run a script that's already running"); + return; + } + auto thisPtr = this; + this->isRunning = true; + this->scriptThread = std::thread([thisPtr]() { + thisPtr->runSync(); + logF("Script Execution finished"); + }); +} +bool ScriptInstance::checkPrintError() { + bool hasException; + chakra.JsHasException_(&hasException); + + if (hasException) { + JsValueRef exception; + chakra.JsGetAndClearException_(&exception); + auto exceptionStr = chakra.exceptionToString(exception); + logF("Exception: %S", exceptionStr.c_str()); + if(exceptionStr.size() > 70){ + logF("check the logfile for exceptions"); + } + } + + return hasException; +} diff --git a/Horion/Scripting/ScriptInstance.h b/Horion/Scripting/ScriptInstance.h new file mode 100644 index 0000000..749babf --- /dev/null +++ b/Horion/Scripting/ScriptInstance.h @@ -0,0 +1,61 @@ +#pragma once + +#include +#include +#include +#include "../../Utils/Logger.h" +#include "ScriptManager.h" +#include +#include +#include "JsScriptModule.h" + +class JsScriptModule; + +class ScriptInstance { +private: + std::vector> registeredModules; + std::wstring startScriptPath; + bool isRunning = false; + std::thread scriptThread; + std::queue taskQueue; + std::queue callbackQueue; + std::mutex callbackMutex; + std::condition_variable callbacksExecuted; + std::condition_variable callbackWaiter; + JsRuntimeHandle runtimeHandle = JS_INVALID_RUNTIME_HANDLE; + void runPromises(); + bool checkPrintError(); + +public: + ScriptInstance(std::wstring startScript); + ~ScriptInstance(); + + std::wstring getStartScriptPath() { + return this->startScriptPath; + } + + void callCallback(JsValueRef ref) { + if(!isRunning) + return; + std::lock_guard lock(callbackMutex); + this->callbackQueue.push(ref); + } + + void callCallbackImmediate(JsValueRef ref) { + if(!isRunning) + return; + std::unique_lock lock(callbackMutex); + this->callbackQueue.push(ref); + this->callbackWaiter.notify_all(); + if(this->callbacksExecuted.wait_for(lock, std::chrono::milliseconds(20)) == std::cv_status::timeout){ + logF("Callback timeout!"); + } + } + + void registerModule(std::shared_ptr jsMod) { + this->registeredModules.push_back(jsMod); + } + + void runSync(); + void run(); +}; diff --git a/Horion/Scripting/ScriptManager.cpp b/Horion/Scripting/ScriptManager.cpp new file mode 100644 index 0000000..c76cc6a --- /dev/null +++ b/Horion/Scripting/ScriptManager.cpp @@ -0,0 +1,439 @@ +#include "ScriptManager.h" + +#include + +ChakraApi chakra; +ScriptManager scriptMgr; + +JsValueRef ScriptManager::prepareEntity(long long runtimeId, ContextObjects* objs) { + JsValueRef obj = JS_INVALID_REFERENCE; + if(g_Data.isInGame() && g_Data.getLocalPlayer()->entityRuntimeId == runtimeId) + runtimeId = -1; + EntityInfo* data = new EntityInfo(runtimeId); + auto err = chakra.JsCreateExternalObject_( + data, [](void* buf) { + delete buf; + }, + &obj); + + if (err != JsNoError) { + logF("prepareEntityFunctions error: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + if (data->isLocalPlayer) + chakra.JsSetPrototype_(obj, objs->localPlayerPrototype); + else + chakra.JsSetPrototype_(obj, objs->entityPrototype); + + return obj; +} + +void ScriptManager::prepareGlobals(JsValueRef global, ContextObjects* obj) { + chakra.defineFunction(global, L"log", GlobalFunctions::log, obj); +} + +void ScriptManager::prepareVector3Prototype(JsValueRef global, ContextObjects* obj) { + chakra.JsCreateObject_(&obj->vec3Prototype); + chakra.JsAddRef_(obj->vec3Prototype, 0); + + chakra.defineFunction(obj->vec3Prototype, L"isValid", Vector3Functions::isValid, obj); + + chakra.defineProp(obj->vec3Prototype, L"x", Vector3Functions::getX, 0); + chakra.defineProp(obj->vec3Prototype, L"y", Vector3Functions::getY, 0); + chakra.defineProp(obj->vec3Prototype, L"z", Vector3Functions::getZ, 0); + chakra.defineFunction(obj->vec3Prototype, L"getX", Vector3Functions::getX, obj); + chakra.defineFunction(obj->vec3Prototype, L"getY", Vector3Functions::getY, obj); + chakra.defineFunction(obj->vec3Prototype, L"getZ", Vector3Functions::getZ, obj); + + chakra.defineFunction(obj->vec3Prototype, L"toString", Vector3Functions::toString, obj); + + chakra.defineFunction(obj->vec3Prototype, L"add", Vector3Functions::add, obj); + chakra.defineFunction(obj->vec3Prototype, L"sub", Vector3Functions::sub, obj); + chakra.defineFunction(obj->vec3Prototype, L"div", Vector3Functions::div, obj); + chakra.defineFunction(obj->vec3Prototype, L"mul", Vector3Functions::mul, obj); + + auto con = chakra.defineFunction(global, L"Vec3", Vector3Functions::constructor, obj); + chakra.addPropertyToObj(con, L"prototype", obj->vec3Prototype); +} + +void ScriptManager::prepareVector2Prototype(JsValueRef global, ContextObjects* obj) { + chakra.JsCreateObject_(&obj->vec2Prototype); + chakra.JsAddRef_(obj->vec2Prototype, 0); + + chakra.defineFunction(obj->vec2Prototype, L"isValid", Vector2Functions::isValid, obj); + + chakra.defineProp(obj->vec2Prototype, L"x", Vector2Functions::getX, 0); + chakra.defineProp(obj->vec2Prototype, L"y", Vector2Functions::getY, 0); + chakra.defineFunction(obj->vec2Prototype, L"getX", Vector2Functions::getX, obj); + chakra.defineFunction(obj->vec2Prototype, L"getY", Vector2Functions::getY, obj); + + chakra.defineFunction(obj->vec2Prototype, L"toString", Vector2Functions::toString, obj); + + chakra.defineFunction(obj->vec2Prototype, L"add", Vector2Functions::add, obj); + chakra.defineFunction(obj->vec2Prototype, L"sub", Vector2Functions::sub, obj); + chakra.defineFunction(obj->vec2Prototype, L"div", Vector2Functions::div, obj); + chakra.defineFunction(obj->vec2Prototype, L"mul", Vector2Functions::mul, obj); + + auto con = chakra.defineFunction(global, L"Vec2", Vector2Functions::constructor, obj); + chakra.addPropertyToObj(con, L"prototype", obj->vec2Prototype); +} + +void ScriptManager::prepareEntityPrototype(JsValueRef proto, ContextObjects* objs) { + chakra.defineFunction(proto, L"isValid", EntityFunctions::isValid, objs); + chakra.defineFunction(proto, L"getPosition", EntityFunctions::getPosition, objs); + chakra.defineFunction(proto, L"getInterpolatedPosition", EntityFunctions::getInterpolatedPosition, objs); + chakra.defineFunction(proto, L"getVelocity", EntityFunctions::getVelocity, objs); + chakra.defineFunction(proto, L"isOnGround", EntityFunctions::isOnGround, objs); + chakra.defineFunction(proto, L"isInvisible", EntityFunctions::isInvisible, objs); + chakra.defineFunction(proto, L"isInWater", EntityFunctions::isInWater, objs); + chakra.defineFunction(proto, L"isInLava", EntityFunctions::isInLava, objs); + chakra.defineFunction(proto, L"isSneaking", EntityFunctions::isSneaking, objs); + chakra.defineFunction(proto, L"getSize", EntityFunctions::getSize, objs); + chakra.defineFunction(proto, L"toString", EntityFunctions::toString, objs); + chakra.defineFunction(proto, L"getViewAngles", EntityFunctions::getViewAngles, objs); + chakra.defineFunction(proto, L"getYaw", EntityFunctions::getYaw, objs); + chakra.defineFunction(proto, L"getPitch", EntityFunctions::getPitch, objs); +} + +void ScriptManager::prepareLocalPlayerPrototype(JsValueRef proto, ContextObjects* objs) { + prepareEntityPrototype(proto, objs); + + chakra.defineFunction(proto, L"setPosition", LocalPlayerFunctions::setPosition, objs); + chakra.defineFunction(proto, L"setVelocity", LocalPlayerFunctions::setVelocity, objs); + chakra.defineFunction(proto, L"toString", LocalPlayerFunctions::toString, objs); + chakra.defineFunction(proto, L"setViewAngles", LocalPlayerFunctions::setViewAngles, objs); + chakra.defineFunction(proto, L"setIsOnGround", LocalPlayerFunctions::setIsOnGround, objs); + chakra.defineFunction(proto, L"getInventory", LocalPlayerFunctions::getInventory, objs); + + chakra.defineFunction(proto, L"placeBlock", LocalPlayerFunctions::placeBlock, objs); + chakra.defineFunction(proto, L"placeBlockRelative", LocalPlayerFunctions::placeBlockRelativeToPlr, objs); + chakra.defineFunction(proto, L"breakBlock", LocalPlayerFunctions::breakBlock, objs); + chakra.defineFunction(proto, L"breakBlockRelative", LocalPlayerFunctions::breakBlockRelativeToPlr, objs); +} + +void ScriptManager::prepareInventoryFunctions(JsValueRef proto, ContextObjects* objs) { + chakra.defineFunction(proto, L"getItems", InventoryFunctions::getItems, objs); + chakra.defineFunction(proto, L"getArmor", InventoryFunctions::getArmor, objs); + chakra.defineFunction(proto, L"getHeld", InventoryFunctions::getHeld, objs); + chakra.defineFunction(proto, L"getSlot", InventoryFunctions::getSlot, objs); + chakra.defineFunction(proto, L"setSelected", InventoryFunctions::setSelected, objs); + chakra.defineFunction(proto, L"moveItem", InventoryFunctions::moveItem, objs); + + chakra.defineProp(proto, L"isFull", InventoryFunctions::isFull, 0); +} + +void ScriptManager::prepareGameFunctions(JsValueRef global, ContextObjects* objs) { + JsValueRef gameObject; + chakra.JsCreateObject_(&gameObject); + + chakra.addPropertyToObj(global, L"Game", gameObject); + + chakra.defineFunction(gameObject, L"getClient", GameFunctions::getClient, objs); + chakra.defineFunction(gameObject, L"getLocalPlayer", GameFunctions::getLocalPlayer, objs); + chakra.defineFunction(gameObject, L"getLevel", GameFunctions::getLevel, objs); +} + +void ScriptManager::prepareHorionFunctions(JsValueRef global, ContextObjects* obj) { + this->prepareDrawFunctions(global, obj); + this->prepareCommandManagerFunctions(global, obj); + this->prepareModuleManagerFunctions(global, obj); + + JsValueRef horionObject; + chakra.JsCreateObject_(&horionObject); + + chakra.addPropertyToObj(global, L"Horion", horionObject); + + chakra.defineFunction(horionObject, L"getCommandManager", HorionFunctions::getCommandManager, obj); + chakra.defineFunction(horionObject, L"getModuleManager", HorionFunctions::getModuleManager, obj); + chakra.defineFunction(horionObject, L"getDrawUtils", HorionFunctions::getDrawUtils, obj); +} + +void ScriptManager::prepareDrawFunctions(JsValueRef global, ContextObjects* objs) { + chakra.JsCreateObject_(&objs->drawUtils); + chakra.JsAddRef_(objs->drawUtils, 0); + + chakra.defineFunction(objs->drawUtils, L"setColor", DrawFunctions::setColor, objs); + + chakra.defineFunction(objs->drawUtils, L"drawLine2d", DrawFunctions::drawLine2d, objs); + chakra.defineFunction(objs->drawUtils, L"drawRectangle2d", DrawFunctions::drawRectangle2d, objs); + chakra.defineFunction(objs->drawUtils, L"fillRectangle2d", DrawFunctions::fillRectangle2d, objs); + chakra.defineFunction(objs->drawUtils, L"drawText2d", DrawFunctions::drawText2d, objs); + chakra.defineFunction(objs->drawUtils, L"getTextWidth", DrawFunctions::getTextWidth, objs); + chakra.defineFunction(objs->drawUtils, L"getTextLineHeight", DrawFunctions::getTextLineHeight, objs); + + chakra.defineFunction(objs->drawUtils, L"drawLine3d", DrawFunctions::drawLine3d, objs); + chakra.defineFunction(objs->drawUtils, L"drawLinestrip3d", DrawFunctions::drawLinestrip3d, objs); + + chakra.defineFunction(objs->drawUtils, L"getOrigin", DrawFunctions::getOrigin, objs); + chakra.defineFunction(objs->drawUtils, L"getWindowSize", DrawFunctions::getWindowSize, objs); +} + +void ScriptManager::prepareCommandManagerFunctions(JsValueRef global, ContextObjects* objs) { + chakra.JsCreateObject_(&objs->commandManager); + chakra.JsAddRef_(objs->commandManager, 0); + + chakra.defineFunction(objs->commandManager, L"executeCommand", CommandManagerFunctions::executeCommand, objs); +} + +void ScriptManager::prepareModuleManagerFunctions(JsValueRef global, ContextObjects* obj) { + chakra.JsCreateObject_(&obj->modulePrototype); + chakra.JsAddRef_(obj->modulePrototype, 0); + prepareModuleFunctions(obj->modulePrototype, obj); + + chakra.JsCreateObject_(&obj->jsModulePrototype); + chakra.JsAddRef_(obj->jsModulePrototype, 0); + prepareJsModuleFunctions(obj->jsModulePrototype, obj); + + chakra.JsCreateObject_(&obj->moduleManager); + chakra.JsAddRef_(obj->moduleManager, 0); + + chakra.defineFunction(obj->moduleManager, L"getModuleByName", ModuleManagerFunctions::getModuleByName, obj); + + if (obj->scriptInstance != nullptr) { + // enable module register support + + chakra.defineFunction(obj->moduleManager, L"registerModule", ModuleManagerFunctions::registerModule, obj); + } +} + +void ScriptManager::prepareModuleFunctions(JsValueRef proto, ContextObjects* obj) { + chakra.defineFunction(proto, L"getName", ModuleManagerFunctions::Module_getName, obj); + chakra.defineFunction(proto, L"toString", ModuleManagerFunctions::Module_toString, obj); + chakra.defineFunction(proto, L"isEnabled", ModuleManagerFunctions::Module_isEnabled, obj); + chakra.defineFunction(proto, L"setEnabled", ModuleManagerFunctions::Module_setEnabled, obj); + chakra.defineFunction(proto, L"toggle", ModuleManagerFunctions::Module_toggle, obj); +} + +void ScriptManager::prepareJsModuleFunctions(JsValueRef proto, ContextObjects* obj) { + prepareModuleFunctions(proto, obj); + + chakra.defineFunction(proto, L"registerCallback", ModuleManagerFunctions::JsModule_registerCallback, obj); +} + +void ScriptManager::prepareContext(JsContextRef* ctx, ContextObjects* obj) { + chakra.JsSetCurrentContext_(*ctx); + + JsValueRef globalObject; + chakra.JsGetGlobalObject_(&globalObject); + + prepareGlobals(globalObject, obj); + prepareHorionFunctions(globalObject, obj); + prepareGameFunctions(globalObject, obj); + prepareVector2Prototype(globalObject, obj); + prepareVector3Prototype(globalObject, obj); + prepareLevelFunctions(globalObject, obj); + + chakra.JsCreateObject_(&obj->entityPrototype); + chakra.JsAddRef_(obj->entityPrototype, 0); + prepareEntityPrototype(obj->entityPrototype, obj); + + chakra.JsCreateObject_(&obj->localPlayerPrototype); + chakra.JsAddRef_(obj->localPlayerPrototype, 0); + prepareLocalPlayerPrototype(obj->localPlayerPrototype, obj); + + chakra.JsCreateObject_(&obj->inventoryObject); + chakra.JsAddRef_(obj->inventoryObject, 0); + prepareInventoryFunctions(obj->inventoryObject, obj); +} + +JsValueRef ScriptManager::prepareVector3(vec3_t vec, ContextObjects* objs) { + JsValueRef obj; + JVector3* data = new JVector3(vec); + auto err = chakra.JsCreateExternalObject_( + data, [](void* buf) { + delete buf; + }, + &obj); + + if (err != JsNoError) { + logF("prepareVector3 error: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + chakra.JsSetPrototype_(obj, objs->vec3Prototype); + + return obj; +} + +JsValueRef ScriptManager::prepareVector2(vec2_t vec, ContextObjects* objs) { + JsValueRef obj; + JVector2* data = new JVector2(vec); + auto err = chakra.JsCreateExternalObject_( + data, [](void* buf) { + delete buf; + }, + &obj); + + if (err != JsNoError) { + logF("prepareVector2 error: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + chakra.JsSetPrototype_(obj, objs->vec2Prototype); + + return obj; +} + +JsValueRef ScriptManager::prepareModule(std::shared_ptr mod, ContextObjects* objs) { + JsValueRef obj = 0; + JModule* data = new JModule(mod); + auto err = chakra.JsCreateExternalObject_( + data, [](void* buf) { + delete buf; + }, + &obj); + + if (err != JsNoError) { + logF("prepareModule error: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + err = chakra.JsSetPrototype_(obj, objs->modulePrototype); + + if (err != JsNoError) { + logF("prepareModule error2: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + return obj; +} + +JsValueRef ScriptManager::prepareJsModule(std::shared_ptr mod, ContextObjects* objs) { + JsValueRef obj = 0; + JModule* data = new JModule(mod); + auto err = chakra.JsCreateExternalObject_( + data, [](void* buf) { + delete buf; + }, + &obj); + + if (err != JsNoError) { + logF("prepareModule2 error: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + err = chakra.JsSetPrototype_(obj, objs->jsModulePrototype); + + if (err != JsNoError) { + logF("prepareModule2 error2: %X", err); + JsValueRef null; + chakra.JsGetNullValue_(&null); + return null; + } + + return obj; +} + +void ScriptManager::prepareLevelFunctions(JsValueRef global, ContextObjects* objs) { + chakra.JsCreateObject_(&objs->levelObject); + chakra.JsAddRef_(objs->levelObject, 0); + + chakra.defineFunction(objs->levelObject, L"isValid", LevelFunctions::isValid, objs); + chakra.defineFunction(objs->levelObject, L"getAllEntities", LevelFunctions::getAllEntities, objs); + chakra.defineFunction(objs->levelObject, L"getAllTargetEntities", LevelFunctions::getAllTargetEntities, objs); + chakra.defineFunction(objs->levelObject, L"getBlock", LevelFunctions::getBlock, objs); +} + +JsValueRef ScriptManager::getLocalPlayer(ContextObjects* obs) { + return this->prepareEntity(-1, obs); +} + +std::wstring ScriptManager::runScript(std::wstring script) { + JsRuntimeHandle runtime; + JsContextRef context; + JsValueRef result = 0; + + chakra.JsCreateRuntime_((_JsRuntimeAttributes)((int)JsRuntimeAttributeDisableFatalOnOOM | (int)JsRuntimeAttributeAllowScriptInterrupt | (int)JsRuntimeAttributeDisableBackgroundWork), nullptr, &runtime); + chakra.JsSetRuntimeMemoryLimit_(runtime, 50000000); // 50MB + + chakra.JsCreateContext_(runtime, &context); + chakra.JsSetCurrentContext_(context); + ContextObjects objs; + prepareContext(&context, &objs); + + auto err = chakra.JsRunScript_(script.c_str(), JS_SOURCE_CONTEXT_NONE, L"", &result); + + std::wstring returnString = L"No result"; + bool hasException; + chakra.JsHasException_(&hasException); + + if (err != JsNoError || hasException) { +#define errLog(x, ...) (Logger::isActive() ? logF(x, __VA_ARGS__) : GameData::log(x, __VA_ARGS__)) + + switch (err) { + case JsErrorScriptCompile: + errLog("Script failed to compile (code: %X)", err); + break; + default: + errLog("Script run failed: %X", err); + break; + } + +#undef errLog + returnString = L"Error! " + std::to_wstring(err) + L", you can find a stack trace in the console"; + + if (hasException) { + JsValueRef exception; + chakra.JsGetAndClearException_(&exception); + logF("Exception: %S", chakra.exceptionToString(exception).c_str()); + } + } + + if (result != JS_INVALID_REFERENCE) + returnString = chakra.valueToString(result); + + chakra.JsSetCurrentContext_(JS_INVALID_REFERENCE); + chakra.JsDisposeRuntime_(runtime); + + return returnString; +} + +bool ScriptManager::importScriptFolder(std::string path) { + for (const auto& entry : std::filesystem::directory_iterator(path)) { + if (entry.is_regular_file()) { + wchar_t fname[100]; + wchar_t ext[7]; + auto err = _wsplitpath_s(entry.path().c_str(), 0, 0, 0, 0, fname, 100, ext, 7); + if (err != 0) + continue; + std::wstring fileName = std::wstring(fname) + ext; + if (fileName == L"start.js") { + // check if script with that name is active already + for (auto it = this->scriptInstances.begin(); it != this->scriptInstances.end(); it++) { + auto startScriptPath = (*it)->getStartScriptPath(); + if (entry.path() == startScriptPath) { + logF("Script already loaded!!!"); + return false; + } + } + auto script = std::make_unique(entry.path()); + script->run(); + this->scriptInstances.push_back(std::move(script)); + + return true; + } + } + } + logF("Could not find start script! Create a file called start.js in your folder."); + return false; +} + +void ScriptManager::unloadAllScripts() { + this->scriptInstances.clear(); +} +size_t ScriptManager::getNumEnabledScripts() { + return this->scriptInstances.size(); +} diff --git a/Horion/Scripting/ScriptManager.h b/Horion/Scripting/ScriptManager.h new file mode 100644 index 0000000..073468c --- /dev/null +++ b/Horion/Scripting/ScriptManager.h @@ -0,0 +1,150 @@ +#pragma once + +#include "../../Utils/ChakraHelper.h" +#include "../../Utils/Logger.h" +#include "../../Utils/HMath.h" + +typedef enum _ExternalDataType { + Invalid = 0, + EntityDataType, + Vector3DataType, + ModuleDataType, + Vector2DataType +} ExternalDataType; + +struct ExternalDataStruct { +public: + ExternalDataType dataType; +}; + +struct EntityInfo : ExternalDataStruct { + bool isLocalPlayer = false; + long long runtimeId = 0; + + EntityInfo(long long runt) { + this->dataType = EntityDataType; + isLocalPlayer = runt == -1; + runtimeId = runt; + } +}; + +struct JVector3 : ExternalDataStruct { + vec3_t vec; + + JVector3(vec3_t set) { + this->dataType = Vector3DataType; + this->vec = set; + } +}; + +struct JVector2 : ExternalDataStruct { + vec2_t vec; + + JVector2(vec2_t set) { + this->dataType = Vector2DataType; + this->vec = set; + } +}; + +class IModule; + +struct JModule : ExternalDataStruct { + std::shared_ptr modPtr; + + JModule(std::shared_ptr mod) { + this->dataType = ModuleDataType; + this->modPtr = mod; + } + + ~JModule() { + logF("JModule destroyed"); + + } +}; +class ScriptManager; + +extern ChakraApi chakra; +extern ScriptManager scriptMgr; +#define DECL_FUN(m) static JsValueRef CALLBACK m(JsValueRef, bool isConstructCall, JsValueRef* arguments, unsigned short argumentCount, void* callbackState) + +#define chok chakra + +#define THROW(m) \ + chok.throwTypeException(m); \ + return JS_INVALID_REFERENCE + +#define THROW_IF_ERROR(code, m) \ + if (code != JsNoError) { \ + THROW(m); \ + } + +#include "Functions/GameFunctions.h" +#include "Functions/EntityFunctions.h" +#include "Functions/GlobalFunctions.h" +#include "Functions/Vector2Functions.h" +#include "Functions/Vector3Functions.h" +#include "Functions/LocalPlayerFunctions.h" +#include "Functions/HorionFunctions.h" +#include "Functions/CommandManagerFunctions.h" +#include "Functions/ModuleManagerFunctions.h" +#include "Functions/LevelFunctions.h" +#include "Functions/DrawFunctions.h" +#include "Functions/InventoryFunctions.h" + +#include "ScriptInstance.h" + +class ScriptInstance; +class JavascriptModule; + +struct ContextObjects { +public: + JsValueRef vec3Prototype = JS_INVALID_REFERENCE; + JsValueRef vec2Prototype = JS_INVALID_REFERENCE; + JsValueRef entityPrototype = JS_INVALID_REFERENCE; + JsValueRef localPlayerPrototype = JS_INVALID_REFERENCE; + JsValueRef inventoryObject = JS_INVALID_REFERENCE; + JsValueRef moduleManager = JS_INVALID_REFERENCE; + JsValueRef commandManager = JS_INVALID_REFERENCE; + JsValueRef drawUtils = JS_INVALID_REFERENCE; + JsValueRef levelObject = JS_INVALID_REFERENCE; + JsValueRef modulePrototype = JS_INVALID_REFERENCE; + JsValueRef jsModulePrototype = JS_INVALID_REFERENCE; + ScriptInstance* scriptInstance = 0; +}; + +class ScriptManager { +private: + + std::vector> scriptInstances; + + void prepareGlobals(JsValueRef global, ContextObjects*); + + void prepareVector3Prototype(JsValueRef global, ContextObjects*); + void prepareVector2Prototype(JsValueRef global, ContextObjects*); + void prepareEntityPrototype(JsValueRef proto, ContextObjects* objs); + void prepareLocalPlayerPrototype(JsValueRef proto, ContextObjects* objs); + + void prepareInventoryFunctions(JsValueRef proto, ContextObjects* objs); + void prepareGameFunctions(JsValueRef global, ContextObjects* objs); + void prepareHorionFunctions(JsValueRef global, ContextObjects* obj); + void prepareDrawFunctions(JsValueRef global, ContextObjects* obj); + void prepareCommandManagerFunctions(JsValueRef global, ContextObjects* obj); + void prepareModuleManagerFunctions(JsValueRef global, ContextObjects* obj); + void prepareModuleFunctions(JsValueRef proto, ContextObjects* obj); + void prepareJsModuleFunctions(JsValueRef proto, ContextObjects* obj); + void prepareLevelFunctions(JsValueRef global, ContextObjects* objs); + +public: + void prepareContext(JsContextRef* ctx, ContextObjects* obj); + JsValueRef prepareEntity(__int64 runtimeId, ContextObjects* obj); + JsValueRef prepareVector3(vec3_t vec, ContextObjects* obj); + JsValueRef prepareVector2(vec2_t vec, ContextObjects* obj); + JsValueRef prepareModule(std::shared_ptr mod, ContextObjects* objs); + JsValueRef prepareJsModule(std::shared_ptr mod, ContextObjects* objs); + JsValueRef getLocalPlayer(ContextObjects* obs); + std::wstring runScript(std::wstring); + bool importScriptFolder(std::string path); + void unloadAllScripts(); + size_t getNumEnabledScripts(); +}; + diff --git a/Horion/path/JoeConstants.cpp b/Horion/path/JoeConstants.cpp new file mode 100644 index 0000000..2377203 --- /dev/null +++ b/Horion/path/JoeConstants.cpp @@ -0,0 +1,30 @@ +#include "JoeConstants.h" + +#include +float distanceToTicks(float dist) { + if(dist == 0) + return 0; + + float tmp = dist; + int tickCnt = 0; + while(true){ + float fallDist = minecraftFallVel(tickCnt); + if(tmp <= fallDist){ + return tickCnt + tmp / fallDist; + } + tmp -= fallDist; + tickCnt++; + } +} +float minecraftFallVel(int ticks) { + return (powf(0.98f, (float)ticks) - 1) * -3.92f; +} +float* generateFallNBlocksCost() { + float* costs = new float[257]; + for(int i = 0; i < 257; i++){ + costs[i] = distanceToTicks((float)i) * (1.f / 20); + } + return costs; +} + +const float* FALL_N_BLOCKS_COST = generateFallNBlocksCost(); \ No newline at end of file diff --git a/Horion/path/JoeConstants.h b/Horion/path/JoeConstants.h new file mode 100644 index 0000000..a963ce9 --- /dev/null +++ b/Horion/path/JoeConstants.h @@ -0,0 +1,17 @@ +#pragma once + +constexpr float WALKING_SPEED = 4.32f; +constexpr float SPRINT_SPEED = 5.61f; +constexpr float WATER_SPEED = 1.8f; +constexpr float JUMP_TIME = 0.6f; +constexpr float PARKOUR_JUMP1_TIME = 0.5f; +constexpr float WATER_UP_SPEED = 2.5f; +constexpr float WATER_SINK_SPEED = 3.5f; + +float minecraftFallVel(int ticks); + +float distanceToTicks(float dist); + +float* generateFallNBlocksCost(); + +extern const float* FALL_N_BLOCKS_COST; \ No newline at end of file diff --git a/Horion/path/JoeMovementController.cpp b/Horion/path/JoeMovementController.cpp new file mode 100644 index 0000000..deda623 --- /dev/null +++ b/Horion/path/JoeMovementController.cpp @@ -0,0 +1,268 @@ +#include "JoeMovementController.h" + +#include "../../Utils/Logger.h" +#include +JoeMovementController::JoeMovementController(std::shared_ptr path) : currentPath(path) { +} + +void JoeMovementController::step(C_LocalPlayer *player, C_MoveInputHandler *movementHandler) { + movementHandler->clearMovementState(); + if(this->stateInfo.currentPathSegment < 0 || this->stateInfo.currentPathSegment >= this->currentPath->getNumSegments()){ + this->overrideViewAngles = false; + return; + } + + if(!this->currentPath->isInitialized1()){ + this->currentPath->initPathSegments(); + } + + auto pPos = player->eyePos0; + pPos.y -= 1.62f; + vec3_ti playerNode((int)floorf(pPos.x), (int)roundf(pPos.y), (int)floorf(pPos.z)); + + auto curSeg = this->currentPath->getSegment(this->stateInfo.currentPathSegment); + + if(!curSeg.isInValidPosition(playerNode)){ + logF("invalid position %i %i %i, %i %i %i", curSeg.getSegmentType(), this->stateInfo.currentPathSegment, this->stateInfo.currentPathSegment > 0 ? this->currentPath->getSegment(this->stateInfo.currentPathSegment - 1).getSegmentType() : 0, playerNode.x, playerNode.y, playerNode.z); + this->stateInfo.currentPathSegment = (int)this->currentPath->getNumSegments(); + this->stateInfo.recoverToStartPos = false; + return; + } + + auto startBpos = curSeg.getStart(); + auto start = startBpos.toVec3t().add(0.5f, 0, 0.5f); + auto endBpos = curSeg.getEnd(); + auto end = endBpos.toVec3t().add(0.5f, 0, 0.5f); + + auto nextSegEnd = vec3_t(); + + bool hasNextSeg = this->stateInfo.currentPathSegment < this->currentPath->getNumSegments() - 1; + if(hasNextSeg) + nextSegEnd = this->currentPath->getSegment(this->stateInfo.currentPathSegment + 1).getEnd().toVec3t().add(0.5f, 0, 0.5f); + + auto walkTarget = end; + bool enableNextSegmentSmoothing = true; + float dComp = 0.5f; + vec3_t addedDiff{0, 0, 0}; + + // we should probably make seperate classes for each segment type at some point, but im just doing it here for now for faster prototyping + switch(curSeg.getSegmentType()){ + case JUMP: { + if(player->onGround){ + if(fabsf(pPos.y - end.y) < 0.1f && pPos.dist(end) < 0.5f) { // Check for end condition + this->stateInfo.nextSegment(); + break; + } + auto tangent = end.sub(start); + tangent.y = 0; + tangent = tangent.normalize(); + auto crossTangent = tangent.cross({0, 1, 0}); + + if((player->getTicksUsingItem() > 0 || fabsf(player->velocity.dot(crossTangent)) > 0.02f) && fabsf(pPos.y - end.y) > 0.1f){ + walkTarget = start; + goto WALK; + } + + if (pPos.y - end.y > -0.01f) { + goto WALK; + } + + auto lastPossibleJumpTarget = start.add(tangent.mul(0.25f)); + walkTarget = start.add(tangent); // This is not actually on a block anymore, but if we make this smaller the movement controller will stop moving at the jump target + + auto posToJumpTarg = lastPossibleJumpTarget.sub(pPos).dot(tangent); + + float maxJumpDist = 0.5f; + + if(posToJumpTarg < maxJumpDist && posToJumpTarg > 0){ + // jump + movementHandler->isJumping = 1; + goto WALK; + } + } + goto WALK; + } break; + case DROP: { + bool inWater = player->isInWater(); + if(player->onGround || inWater){ + dComp = 1; + if(fabsf(pPos.y - end.y) < (inWater ? 0.2f : 0.1f) && pPos.sub(end).magnitudexz() < 0.5f && player->velocity.y > -0.1f){// Check for end condition + this->stateInfo.nextSegment(); + break; + }else if(inWater){ + if(pPos.y < end.y || player->velocity.y < 0.12f) + movementHandler->isJumping = 1; + } + }else{ + dComp = 3; + } + /* if (start.sub(end).magnitudexz() < 1.1f) { + // hug the wall on drop + auto tangent = end.sub(start); + tangent.y = 0; + walkTarget = start.add(tangent.mul(0.5f + player->width * 0.5f + 0.1f)); + walkTarget.y = end.y; + }*/ + + goto WALK; + } break; + case PARKOUR_JUMP_SINGLE: { + if(player->isSprinting()) + player->setSprinting(false); + if(player->onGround){ + if(fabsf(pPos.y - end.y) < 0.1f && pPos.dist(end) < 0.5f){// Check for end condition + this->stateInfo.nextSegment(); + break; + } + if(player->getTicksUsingItem() > 0 && fabsf(pPos.y - start.y) < 0.1f && pPos.dist(end) > 0.85f){ + walkTarget = start; + goto WALK; + } + auto tangent = end.sub(start); + tangent.y = 0; + tangent = tangent.normalize(); + + float distToEnd = end.sub(pPos).dot(tangent); + if(distToEnd > 0.f && distToEnd < 0.5f + 0.35f){ + // maybe stuck on the block above end pos? + walkTarget = end; + goto WALK; + } + + auto lastPossibleJumpTarget = start.add(tangent.mul(0.5f + 0.3f)); + walkTarget = start.add(tangent); // This is not actually on a block anymore, but if we make this smaller the movement controller will stop moving at the jump target + + auto posToJumpTarg = lastPossibleJumpTarget.sub(pPos).dot(tangent); + + float maxJumpDist = 0.3f; + if(start.sub(end).magnitudexz() <= 1.1f) + maxJumpDist = 0.7f; + if(posToJumpTarg < maxJumpDist && posToJumpTarg > 0 && player->velocity.dot(tangent) > 0.07f){ + // jump + movementHandler->isJumping = 1; + goto WALK; + } + goto WALK; + }else{ + enableNextSegmentSmoothing = false; + auto tangent = end.sub(start); + tangent.y = 0; + tangent = tangent.normalize(); + walkTarget = end.sub(tangent.mul(0.4f)); + dComp = 2; + goto WALK; + } + } break; + case WATER_WALK: { + { + auto tangent = end.sub(start); + bool isVertical = tangent.magnitudexz() < 0.1f && fabsf(tangent.y) > 0.5f; + + if(isVertical){ + if(pPos.sub(end).magnitudexz() < 0.3f && fabsf(pPos.y - end.y) < 0.35f){ + this->stateInfo.nextSegment(); + break; + } + + if(pPos.y + 0.1f < end.y) + movementHandler->isJumping = 1; + else if(pPos.y > end.y) + movementHandler->isSneakDown = 1; + + }else{ + + if(player->isInWater()) + movementHandler->isJumping = 1; + + tangent.y = 0; + tangent = tangent.normalize(); + auto crossTangent = tangent.cross({0, 1, 0}); + float sideError = fabsf(pPos.sub(end).dot(crossTangent)); + if(sideError < 0.2f /*make sure we're not drifting to the side to much*/ && fabsf(pPos.sub(end).dot(tangent)) < 0.4f){ + this->stateInfo.nextSegment(); + break; + } + if(end.y > start.y && sideError > 0.15f && pPos.y - end.y < -0.1f) + walkTarget = start.add(tangent.mul(0.2f)); // center if we need to get up a block + } + + vec3_t flow{}; + + auto block = player->region->getBlock(playerNode); + if(!block->toLegacy()->material->isLiquid){ + auto mod = playerNode.add(0, -1, 0); + block = player->region->getBlock(mod); + + if(block->toLegacy()->material->isLiquid) + block->toLegacy()->liquidGetFlow(&flow, player->region, &mod); + }else{ + block->toLegacy()->liquidGetFlow(&flow, player->region, &playerNode); + } + + flow = flow.mul(-1 * 0.07f * 10); + addedDiff = flow; + } + goto WALK; + } break; + WALK:; + case WALK: { + player->setSprinting(curSeg.isAllowingSprint()); + + auto pPosD = pPos; // p + + if(!player->onGround && dComp < 2){ + dComp = 2; + } + + pPosD = pPosD.add(player->velocity.mul(dComp, 0, dComp)); // d + + if(player->onGround && end.y < start.y && fabsf(start.y - pPosD.y) < 0.1f && player->getTicksUsingItem() > 0 && end.sub(start).magnitudexz() > 1.5f){ + // drop with a gap + // player is using item, walk back to start pos + walkTarget = start; + } + + vec3_t diff3d = walkTarget.sub(pPosD); + vec2_t diff2d = {diff3d.x, diff3d.z}; + float diffMag = diff2d.magnitude(); + if(enableNextSegmentSmoothing && hasNextSeg && diffMag < 0.2f && fabsf(end.y - pPosD.y) < (player->isInWater() ? 0.5f : 0.1f)){ // Start taking the next segment into account when we're very close to our destination + auto tangent = nextSegEnd.sub(end).normalize(); + diff3d = end.add(tangent.mul(0.3f)).sub(pPosD); + diff2d = {diff3d.x, diff3d.z}; + diffMag = diff2d.magnitude(); + } + diff2d = diff2d.div(fmaxf(0.15f, diffMag)); + + addedDiff.y = 0; + if(!addedDiff.iszero()){ // water flow + diff2d = diff2d.add(addedDiff.x, addedDiff.z); + diff2d = diff2d.div(fmaxf(1, diff2d.magnitude())); + } + + float yaw = player->yaw; + auto forward = vec2_t::fromAngle(yaw * RAD_DEG); + auto right = forward.cross(); + + movementHandler->forwardMovement = forward.dot(diff2d); + movementHandler->sideMovement = -right.dot(diff2d); + + //logF("%.2f %.2f %.2f %i", diff2d.x, diff2d.y, pPos.y, player->onGround); + + if(pPos.dist(end) < 0.2f){ + if(hasNextSeg || player->velocity.magnitudexz() < 0.02f /*slow down for last segment*/){ + this->stateInfo.nextSegment(); + break; + } + } + + } break; + default: + __debugbreak(); + } +} +int JoeMovementController::getCurrentPathSegment() const { + return stateInfo.currentPathSegment; +} +const std::shared_ptr &JoeMovementController::getCurrentPath() const { + return currentPath; +} diff --git a/Horion/path/JoeMovementController.h b/Horion/path/JoeMovementController.h new file mode 100644 index 0000000..2d668a8 --- /dev/null +++ b/Horion/path/JoeMovementController.h @@ -0,0 +1,32 @@ +#pragma once + +#include "JoePath.h" +#include "../../SDK/CEntity.h" +#include "../../SDK/CMoveInputHandler.h" + +class JoeMovementController { +private: + std::shared_ptr currentPath; + struct { + int currentPathSegment = 0; + bool recoverToStartPos = false; + + void nextSegment(){ + currentPathSegment++; + recoverToStartPos = false; + } + } stateInfo; + +public: + bool overrideViewAngles = false; + vec2_t targetViewAngles = {0, 0}; + + JoeMovementController(std::shared_ptr path); + + void step(C_LocalPlayer* player, C_MoveInputHandler* movementHandler); + bool isDone(){ + return stateInfo.currentPathSegment >= currentPath->getNumSegments(); + } + int getCurrentPathSegment() const; + const std::shared_ptr& getCurrentPath() const; +}; diff --git a/Horion/path/JoePath.cpp b/Horion/path/JoePath.cpp new file mode 100644 index 0000000..ca1b687 --- /dev/null +++ b/Horion/path/JoePath.cpp @@ -0,0 +1,65 @@ +#include "JoePath.h" +#include "../DrawUtils.h" +#include "../../Utils/Logger.h" +JoePath::JoePath(const std::vector& segments, bool isIncomplete) : segments(segments), isIncomplete(isIncomplete) { + +} +JoePath::JoePath() : segments(), isIncomplete(false) { +} +void JoePath::draw(int highlight) const { + DrawUtils::setColor(13 / 255.f, 29 / 255.f, 48 / 255.f, 1); + bool changedColor = false; + for(int i = 0; i < segments.size(); i++){ + auto seg = segments[i]; + + if(i == highlight){ + DrawUtils::setColor(39 / 255.f, 87 / 255.f, 144 / 255.f, 1); + changedColor = true; + }else if(changedColor) + DrawUtils::setColor(13 / 255.f, 29 / 255.f, 48 / 255.f, 1); + seg.draw(); + } +} +bool JoePath::isIncomplete1() const { + return isIncomplete; +} +void JoePath::cutoff(float percentageKeep) { + if(this->getNumSegments() == 0) + return; + int numKeep = (int)ceilf(this->getNumSegments() * percentageKeep); + this->segments.erase(this->segments.begin() + numKeep, this->segments.end()); +} +void JoePath::initPathSegments() { + // Init segments + for(auto& seg : segments){ + seg.init(); + } + + // Check whether we can sprint or not + if(segments.size() > 1){ + + for(int i = 0; i < segments.size() - 2; i++){ + auto& curSeg = segments.at(i); + auto& nextSeg = segments.at(i + 1); + if(curSeg.getSegmentType() != JoeSegmentType::WALK || nextSeg.getSegmentType() != JoeSegmentType::WALK){ + curSeg.setAllowSprint(false); + continue; + } + if(curSeg.getStart().y != curSeg.getEnd().y){ + curSeg.setAllowSprint(false); + continue; + } + + auto currentTangent = curSeg.getEnd().sub(curSeg.getStart()).toFloatVector().normalize(); + auto nextTangent = nextSeg.getEnd().sub(nextSeg.getStart()).toFloatVector().normalize(); + if(currentTangent.dot(nextTangent) > 0.3f){ // make sure we're running in a similar direction + curSeg.setAllowSprint(true); + } + } + } + + this->isInitialized = true; +} +bool JoePath::isInitialized1() const { + return isInitialized; +} diff --git a/Horion/path/JoePath.h b/Horion/path/JoePath.h new file mode 100644 index 0000000..de7d5d8 --- /dev/null +++ b/Horion/path/JoePath.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "JoeSegment.h" + +class JoePath { +private: + std::vector segments; + bool isIncomplete; + bool isInitialized = 0; +public: + JoePath(const std::vector& segments, bool isIncomplete); + JoePath(); + + void cutoff(float percentageKeep); + + auto& getAllSegments(){ + return segments; + } + size_t getNumSegments(){ + return this->segments.size(); + } + auto getSegment(size_t seg){ + return this->segments[seg]; + } + + bool isInitialized1() const; + void initPathSegments(); + bool isIncomplete1() const; + void draw(int) const; +}; diff --git a/Horion/path/JoePathFinder.cpp b/Horion/path/JoePathFinder.cpp new file mode 100644 index 0000000..10d7c03 --- /dev/null +++ b/Horion/path/JoePathFinder.cpp @@ -0,0 +1,575 @@ +#include "JoePathFinder.h" + +#include +#include +#include "../../Utils/Logger.h" +#include "../../Utils/Utils.h" +#include +#include +#include +#include "../../Memory/GameData.h" +#include + +JoePathFinder::JoePathFinder(vec3_ti start, C_BlockSource* reg, std::shared_ptr goal) : startPos(start), region(reg), goal(goal) { +} + +struct NodeRef { + __int64 hash; + __forceinline bool isInvalid() const{ + return hash == 0xFFFFFFFFFFFFFFFF; + } + NodeRef(__int64 hash) : hash(hash) {} + NodeRef() : hash(-1) {}; +}; + +struct Node { + vec3_ti pos; + float fScore; // heuristic + float gScore; // total cost + struct { + NodeRef nodeBefore = { -1 }; + JoeSegmentType edgeType = JoeSegmentType::INVALID; + } cameFrom; + bool isClosed; + bool isInOpenSet; + + Node(const vec3_ti& pos, float fScore, float gScore) : pos(pos), fScore(fScore), gScore(gScore), isClosed(false), isInOpenSet(false) {} +}; + +struct Edge { + NodeRef startNode, endNode; + float cost; + JoeSegmentType type; + + Edge(const NodeRef& startNode, const NodeRef& endNode, float cost, JoeSegmentType type) : startNode(startNode), endNode(endNode), cost(cost), type(type) {} +}; +__forceinline unsigned __int64 rotBy(int in, unsigned int by){ + auto mut = static_cast(in); + return ((mut & 0x7FFFFFui64) | ((static_cast(in) >> 8u) & 0x800000u)/*copy sign bit*/) << by; +} + +__forceinline unsigned __int64 posToHash(const vec3_ti& pos){ + return rotBy(pos.x, 0) | rotBy(pos.z, 24) | (static_cast(pos.y) << 48u); +} + +NodeRef findNode(std::unordered_map& allNodes, vec3_ti& pos){ + auto posHash = posToHash(pos); + auto res = allNodes.find(posHash); + if(res != allNodes.end()){ + return NodeRef(posHash); + } + + allNodes.emplace(posHash, Node(pos, 0.f, 10000000.f)); + return NodeRef(posHash); +} + +__forceinline bool isDangerous(const vec3_ti& pos, C_BlockSource* reg, bool allowWater){ + auto obs1 = reg->getBlock(pos)->toLegacy(); + if(obs1->material->isSuperHot) + return true; + if(!allowWater && (obs1->material->isLiquid || obs1->hasWater(reg, pos))) + return true; + + // contact damage based + { + // there is a function called dealsContactDamage but it takes in so many parameters + plant growth that its not useful anymore + static std::set knownVtableSet; + static std::vector dangerousTiles{"sweet_berry_bush", "magma", "wither_rose", "cactus", "web"}; + + for (uintptr_t** vtable : knownVtableSet) + if (obs1->Vtable == vtable) + return true; + + + if (obs1->tileName.getTextLength() < 6) + return false; + + for (int i = 0; i < dangerousTiles.size(); i++){ + const char* tile = dangerousTiles[i]; + if (strcmp(obs1->tileName.getText() + 5 /*cutoff tile. prefix*/, tile) != 0) + continue; + + knownVtableSet.insert(obs1->Vtable); + dangerousTiles.erase(dangerousTiles.begin() + i); + return true; + } + } + return false; +} +__forceinline bool isDangerousPlayer(const vec3_ti& pos, C_BlockSource* reg, bool allowWater = false){ + return isDangerous(pos, reg, allowWater) || isDangerous(pos.add(0, 1, 0), reg, allowWater); +} + +__forceinline bool canStandOn(const vec3_ti& pos, C_BlockSource* reg, bool inWater = false){ + auto block = reg->getBlock(pos); + auto standOn = block->toLegacy(); + bool validWater = inWater && standOn->hasWater(reg, pos); + if(validWater){ + // block above has to be water as well + auto swimPos = pos.add(0, 1, 0); + auto swimIn = reg->getBlock(swimPos)->toLegacy(); + validWater = swimIn->hasWater(reg, swimPos); + } + if(!standOn->material->isSolid && !validWater) + return false; + if(isDangerous(pos, reg, inWater)) + return false; + + if(validWater) + return true; + if (true) + return true; + + AABB aabb; + if(!standOn->getCollisionShape(&aabb, block, reg, &pos, nullptr)) + return false; + + auto diff = aabb.lower.sub(aabb.upper); + + if(ceilf(aabb.upper.y) - aabb.upper.y > 0.13f /* 0.125 for soulsand and farmland*/) + return false; + + if(ceilf(aabb.upper.x) - aabb.upper.x > 0.07f /* 0.0625 for chests*/) + return false; + if(ceilf(aabb.upper.z) - aabb.upper.z > 0.07f /* 0.0625 for chests*/) + return false; + return fabsf(diff.x) > 0.85f && fabsf(diff.z) > 0.85f; +} +__forceinline bool isObstructed(const vec3_ti& pos, C_BlockSource* reg, bool allowWater = false){ + auto block = reg->getBlock(pos); + auto obs1 = block->toLegacy(); + if(obs1->material->isBlockingMotion) + return true; + + AABB aabb{}; + bool hasBox = obs1->getCollisionShape(&aabb, block, reg, &pos, nullptr); + + if(hasBox) + return true; + + return isDangerous(pos, reg, allowWater); +} +__forceinline bool isObstructedPlayer(const vec3_ti& pos, C_BlockSource* reg, bool allowWater = false){ + return isObstructed(pos, reg, allowWater) || isObstructed(pos.add(0, 1, 0), reg); +} + +std::vector findEdges(std::unordered_map& allNodes, const Node& startNode, C_BlockSource* reg, NodeRef startNodeRef){ + std::vector edges; + auto startBlock = reg->getBlock(startNode.pos)->toLegacy(); + bool isInWater = startBlock->hasWater(reg, startNode.pos); + + float maxWalkSpeed = isInWater ? WATER_SPEED : SPRINT_SPEED; + + static const float SQRT2 = sqrtf(2); + + const float diagonalSpeed = SQRT2 / maxWalkSpeed; + const float straightSpeed = 1 / maxWalkSpeed; + const float diagonalSlowSpeed = SQRT2 / fminf(maxWalkSpeed, WALKING_SPEED); + const float walkOffBlockTime = 0.8f / maxWalkSpeed; + + if(isInWater){ + { + auto mod = startNode.pos.add(0, 1, 0); + auto block = reg->getBlock(mod); + if (block->toLegacy()->material->isLiquid && !block->toLegacy()->material->isSuperHot) { + if (!isObstructed(startNode.pos.add(0, 1, 0), reg, true) && !isObstructed(startNode.pos.add(0, 2, 0), reg, true)) + edges.emplace_back(startNodeRef, findNode(allNodes, mod), 1 / WATER_UP_SPEED, JoeSegmentType::WATER_WALK); + } + } + if(!isObstructed(startNode.pos.add(0, -1, 0), reg, true) && canStandOn(startNode.pos.add(0, -2, 0), reg, true)){ + auto mod = startNode.pos.add(0, -1, 0); + edges.emplace_back(startNodeRef, findNode(allNodes, mod), 1 / WATER_SINK_SPEED, JoeSegmentType::WATER_WALK); + } + } + + for(int x = -1; x <= 1; x++){ + for(int z = -1; z <= 1; z++){ + if(x == 0 && z == 0) + continue; + bool isDiagonal = x != 0 && z != 0; + + vec3_ti newPos = startNode.pos.add(x,0, z); + + // lower block obstructed + if(isObstructed(newPos, reg, true)){ + // maybe jump? + if(isDiagonal) + continue; + + if(!canStandOn(newPos, reg)) + continue; + if(isObstructed(startNode.pos.add(0, 2, 0), reg)) + continue; // can we jump straight up? + + newPos = newPos.add(0, 1, 0); + if(isObstructedPlayer(newPos, reg)) + continue; + + edges.emplace_back(startNodeRef, findNode(allNodes, newPos), JUMP_TIME, isInWater ? JoeSegmentType::WATER_WALK : JoeSegmentType::JUMP); + continue; + } + + // Check if we can stand on the block + if(!canStandOn(newPos.add(0, -1, 0), reg, isInWater)){ + if(isDiagonal || isInWater) + continue; + // maybe drop? + + if(isObstructedPlayer(newPos, reg)) // walk to drop + continue; + + // Drop down + { + int numWaterBlocks = 0; + int dropLength = 0; + while(dropLength < 3){ + dropLength++; + auto dropPos = newPos.add(0, -1 * dropLength, 0); // drop down 1 block + + if(isObstructed(dropPos, reg, true)){// block below walk to drop + dropLength = -1; + break; + } + + if(!canStandOn(dropPos.add(0, -1, 0), reg, false)) // block to stand on after drop + continue; + + int waterDepth = 0; + while(waterDepth < dropLength){ + auto testPos = dropPos.add(0, waterDepth, 0); + auto blockTest = reg->getBlock(testPos)->toLegacy(); + if(!blockTest->hasWater(reg, testPos)) + break; + + waterDepth++; + } + if(waterDepth > 0){ + dropPos = dropPos.add(0, waterDepth - 1, 0); + } + + const float dropTime = FALL_N_BLOCKS_COST[dropLength] + walkOffBlockTime; + edges.emplace_back(startNodeRef, findNode(allNodes, dropPos), dropTime, JoeSegmentType::DROP); + dropLength = -1; + break; // Also allow parkour jump + } + if(dropLength == 3){ // no drop found, lets try water drops + auto dropPos = newPos.add(0, -1 * dropLength, 0); + + while(dropPos.y > 1){ + dropPos.y--; + dropLength++; + + if(isObstructed(dropPos, reg, true))// block below walk to drop + break; + + auto block = reg->getBlock(dropPos)->toLegacy(); + auto isWaterBlock = block->hasWater(reg, dropPos); + if(isWaterBlock) + numWaterBlocks++; + else{ + numWaterBlocks = 0; + continue; + } + + if(!canStandOn(dropPos.add(0, -1, 0), reg) && numWaterBlocks < 17 /*we dont need a block to stand on with that much water*/) // block to stand on after drop + continue; + + // find out how deep the water is + int waterDepth = 1; + while(waterDepth < 19){ // make sure we don't drop too deep + auto testPos = dropPos.add(0, waterDepth, 0); + auto blockTest = reg->getBlock(testPos)->toLegacy(); + if(!blockTest->hasWater(reg, testPos)) + break; + + waterDepth++; + } + + const float dropTime = FALL_N_BLOCKS_COST[dropLength] + walkOffBlockTime; + dropPos = dropPos.add(0, waterDepth - 1, 0); + edges.emplace_back(startNodeRef, findNode(allNodes, dropPos), dropTime, JoeSegmentType::DROP); + break; + } + } + } + + // maybe parkour jump? + bool canJump = !isObstructed(startNode.pos.add(0, 2, 0), reg);// directly above our head + + if(isObstructed(newPos.add(0, 2, 0), reg)) // above old walk target + canJump = false; + + newPos = startNode.pos.add(x * 2,0, z * 2); // 2 block distance, 1 block gap + if(isObstructedPlayer(newPos, reg)){// landing zone + // maybe jump up? + if(!canJump) + continue; + auto jumpPos = newPos.add(0, 1, 0); + + if(!canStandOn(jumpPos.add(0, -1, 0), reg)) + continue; + if(isObstructedPlayer(jumpPos, reg, false)) + continue; + + edges.emplace_back(startNodeRef, findNode(allNodes, jumpPos), PARKOUR_JUMP1_TIME, JoeSegmentType::PARKOUR_JUMP_SINGLE); + continue; + } + + if(!canStandOn(newPos.add(0, -1, 0), reg)){ // we can't stand on parkour jump landing zone, move it down and walk there? + for(int dropLength = 1; dropLength <= 3; dropLength++){ + auto dropPos = newPos.add(0, -1 * dropLength, 0); + if(isObstructed(dropPos, reg)) // we can't move it down, something in the way + goto tryLargerParkourJump; + if(isObstructed(startNode.pos.add(x,-1 * dropLength, z), reg, false)) + goto tryLargerParkourJump; + + // can we stand + if(!canStandOn(dropPos.add(0, -1, 0), reg)) // we can't stand on the lowered landing zone :( + continue; + + // walk to lower landing zone + float time = fmaxf((2 + 0.05f /*small penalty*/) / maxWalkSpeed, FALL_N_BLOCKS_COST[dropLength] + walkOffBlockTime); + edges.emplace_back(startNodeRef, findNode(allNodes, dropPos), time, JoeSegmentType::WALK); + goto tryLargerParkourJump; + } + goto tryLargerParkourJump; + } + + if(canJump){ + edges.emplace_back(startNodeRef, findNode(allNodes, newPos), PARKOUR_JUMP1_TIME, JoeSegmentType::PARKOUR_JUMP_SINGLE); + continue; // we don't need to try a larger jump, we could just walk there + } + tryLargerParkourJump: + // TODO + + continue; + } + + // upper block obstructed? + if(isObstructed(newPos.add(0, 1, 0), reg)) + continue; + + int isDiagonalObstructed = 0; + if(isDiagonal){ + // Check if either x or z are obstruction-less + isDiagonalObstructed += isObstructedPlayer(startNode.pos.add(x, 0, 0), reg, true); + isDiagonalObstructed += isObstructedPlayer(startNode.pos.add(0, 0, z), reg, true); + if(isDiagonalObstructed == 2) // both obstructed + continue; + + // Check if both x and z aren't dangerous (we don't want to run into cacti) + if(isDangerousPlayer(startNode.pos.add(x, 0, 0), reg) || isDangerousPlayer(startNode.pos.add(0, 0, z), reg)) + continue; + } + + float cost = isDiagonal ? (isDiagonalObstructed ? diagonalSlowSpeed : diagonalSpeed) : straightSpeed; + if(isInWater){ + // check if the block is a flowing block + auto block = reg->getBlock(newPos)->toLegacy(); + if (block->material->isLiquid) { + vec3_t flow{}; + block->liquidGetFlow(&flow, reg, &newPos); + if(!flow.iszero()){ + auto tangent = newPos.sub(startNode.pos).toVec3t(); + tangent.y = 0; + tangent = tangent.normalize(); + + auto prevCost = cost; + cost = 1 / fmaxf(0.1f, maxWalkSpeed + tangent.dot(flow) * 0.07f * 20); + } + } + } + edges.emplace_back(startNodeRef, findNode(allNodes, newPos), cost, isInWater ? JoeSegmentType::WATER_WALK : JoeSegmentType::WALK); + } + } + + return edges; +} + +std::pair getSlope(std::vector& x, std::vector& y){ + const auto n = x.size(); + const auto s_x = std::accumulate(x.begin(), x.end(), 0.0); + const auto s_y = std::accumulate(y.begin(), y.end(), 0.0); + const auto s_xx = std::inner_product(x.begin(), x.end(), x.begin(), 0.0); + const auto s_xy = std::inner_product(x.begin(), x.end(), y.begin(), 0.0); + const auto a = (n * s_xy - s_x * s_y) / (n * s_xx - s_x * s_x); + return std::make_pair((float)a, (float)((s_y / n) - (a * (s_x / n)))); +} + +JoePath JoePathFinder::findPath() { + if(this->goal->isInGoal(startPos)) + return JoePath(); + std::unordered_map allNodes; + + auto cmp = [&](NodeRef left, NodeRef right) { + if(left.isInvalid()) + return false; + if(right.isInvalid()) + return true; + return allNodes.at(left.hash).fScore > allNodes.at(right.hash).fScore; + }; + std::priority_queue, decltype(cmp)> openSet(cmp); + + auto startHash = posToHash(startPos); + allNodes.emplace(startHash, Node(startPos, this->goal->getHeuristicEstimation(startPos), 0.f)); + openSet.emplace(startHash); + + int numNodes = 0; + int numEdges = 0; + + if(this->pathSearchTimeout < 0 || this->pathSearchTimeout > 50) + this->pathSearchTimeout = 10; + + auto pathSearchStart = std::chrono::high_resolution_clock::now(); + + while(!openSet.empty()){ + auto curRef = openSet.top(); + openSet.pop(); + if(curRef.isInvalid()) + continue; + Node& cur = allNodes.at(curRef.hash); + + numNodes++; + + if(this->terminateSearch) + break; + + if(this->goal->isInGoal(cur.pos) || numNodes % 1200 == 0){ + std::vector segments; + auto node = cur; + + while(node.pos != startPos){ + auto prev = node.cameFrom; + auto prevNode = allNodes.at(prev.nodeBefore.hash); + + segments.emplace_back(prev.edgeType, prevNode.pos, node.pos, node.gScore - prevNode.gScore); + node = prevNode; + } + std::reverse(segments.begin(), segments.end()); + + if(this->goal->isInGoal(cur.pos)){ + auto now = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = now - pathSearchStart; + logF("Found path! Traversal: %.2f Segments: %i Time: %.2fs Total Nodes: %i NodesVisited: %i Edges: %i", cur.gScore, segments.size(), diff.count(), allNodes.size(), numNodes, numEdges); + return JoePath(segments, false); + } + + this->currentPath = JoePath(segments, false); + + // check for timeout + auto now = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = now - pathSearchStart; + if(diff.count() > this->pathSearchTimeout) + break; + } + cur.isClosed = true; + cur.isInOpenSet = false; + + auto edges = findEdges(allNodes, cur, this->region, curRef); // cur gets invalidated here + cur = allNodes.at(curRef.hash); + numEdges += (int)edges.size(); + for(const auto& edge : edges){ + auto& edgeEndNode = allNodes.at(edge.endNode.hash); + //logF("(%i %i %i) %i -> (%i %i %i)", cur.pos.x, cur.pos.y, cur.pos.z, edge.type, edgeEndNode.pos.x, edgeEndNode.pos.y, edgeEndNode.pos.z); + if(edgeEndNode.isClosed) + continue; + float tentativeScore = cur.gScore + edge.cost; + if(tentativeScore >= edgeEndNode.gScore) + continue; + float heuristic = tentativeScore + this->goal->getHeuristicEstimation(edgeEndNode.pos); + + edgeEndNode.cameFrom.edgeType = edge.type; + edgeEndNode.cameFrom.nodeBefore = curRef; + edgeEndNode.gScore = tentativeScore; + edgeEndNode.fScore = heuristic; + + if(!edgeEndNode.isInOpenSet){ // not in open set + edgeEndNode.isInOpenSet = true; + openSet.push(edge.endNode); + }else{ + // remove from openset + openSet.push(edge.endNode); + } + } + } + auto now = std::chrono::high_resolution_clock::now(); + std::chrono::duration diff = now - pathSearchStart; + + if(this->terminateSearch) + return JoePath(); + + const float coefficients[] = { 1.1f, 1.5f, 2.f, 2.5f, 3.f, 3.5f, 4.f, 3.5f, 5.f, 10.f, 20.f, 30.f }; + constexpr auto coefficientSize = 12; + constexpr float maxCost = 1000000; + float bestHeuristicSoFar[coefficientSize] = { }; + std::fill_n(bestHeuristicSoFar, coefficientSize, maxCost); + NodeRef bestSoFar[coefficientSize] = {}; + + int numDist[coefficientSize][150] = {}; + float heuristicByDist[coefficientSize][150] = {}; + for(auto& nodeDesc : allNodes){ + + auto& node = nodeDesc.second; + auto dist = (int)roundf(node.pos.toVec3t().dist(startPos.toVec3t())); + + for(int i = 0; i < coefficientSize; i++){ + + float heuristic = (node.fScore - node.gScore) + node.gScore / coefficients[i]; + if(dist < 150){ + heuristicByDist[i][dist] += heuristic; + numDist[i][dist]++; + } + if (heuristic < bestHeuristicSoFar[i]) { + bestHeuristicSoFar[i] = heuristic; + bestSoFar[i] = NodeRef(static_cast<__int64>(nodeDesc.first)); + } + } + } + + auto chosenCoeff = -1; + float coeffSlope = 10; + for(int coeff = 0; coeff < coefficientSize; coeff++){ + std::vector xAxis, yAxis; + for(int i = 0; i < 150; i++){ + if(numDist[coeff][i] == 0) + continue; + xAxis.push_back((float)i); + yAxis.push_back(heuristicByDist[coeff][i] / (float)numDist[coeff][i]); + } + auto slope = getSlope(xAxis, yAxis); + + if(slope.first < coeffSlope){ + chosenCoeff = coeff; + coeffSlope = slope.first; + if(slope.first < 0) + break; + } + } + + for(int i = 0; i < coefficientSize; i++){ + if(bestHeuristicSoFar[i] == maxCost){ + continue; + } + + auto& bestNode = allNodes.at(bestSoFar[i].hash); + float dist = startPos.toFloatVector().dist(bestNode.pos.toFloatVector()); + if((chosenCoeff == i && dist > 5) || dist >= 100){ + // reconstruct path from here + std::vector segments; + auto node = bestNode; + while(node.pos != startPos){ + auto prev = node.cameFrom; + auto prevNode = allNodes.at(prev.nodeBefore.hash); + segments.emplace_back(prev.edgeType, prevNode.pos, node.pos, node.gScore - prevNode.gScore); + node = prevNode; + } + std::reverse(segments.begin(), segments.end()); + return JoePath(segments, true); + } + } + + return JoePath(); +} +const JoePath& JoePathFinder::getCurrentPath() const { + return currentPath; +} diff --git a/Horion/path/JoePathFinder.h b/Horion/path/JoePathFinder.h new file mode 100644 index 0000000..fde331b --- /dev/null +++ b/Horion/path/JoePathFinder.h @@ -0,0 +1,25 @@ +#pragma once + +#include "../../Utils/HMath.h" +#include "JoePath.h" +#include "JoeSegment.h" +#include "goals/JoeGoal.h" +#include "../../SDK/CBlockLegacy.h" +#include "JoeConstants.h" +#include + +class JoePathFinder { +private: + vec3_ti startPos; + JoePath currentPath; + C_BlockSource* region; + std::shared_ptr goal; +public: + bool terminateSearch = false; + float pathSearchTimeout = 5.f; + + JoePathFinder(vec3_ti start, C_BlockSource* reg, std::shared_ptr goal); + + JoePath findPath(); + const JoePath& getCurrentPath() const; +}; diff --git a/Horion/path/JoeSegment.cpp b/Horion/path/JoeSegment.cpp new file mode 100644 index 0000000..e0a7699 --- /dev/null +++ b/Horion/path/JoeSegment.cpp @@ -0,0 +1,150 @@ +#include "JoeSegment.h" + +#include "../DrawUtils.h" + +JoeSegment::JoeSegment(JoeSegmentType type, vec3_ti& start, vec3_ti& stop, float cost, bool allowSprint) : segmentType(type), start(start), end(stop), cost(cost), allowSprint(allowSprint) { + +} +void JoeSegment::draw() { + //for(auto p : this->validPositions){ + // DrawUtils::drawLine3d(p.toFloatVector(), p.add(1, 1, 1).toFloatVector()); + //} + + switch (segmentType) { + case DROP: { + auto dropPoint = start.toVec3t().add(0.5f, 0.05f, 0.5f); + dropPoint.x = end.x + 0.5f; + dropPoint.z = end.z + 0.5f; + DrawUtils::drawLine3d(start.toVec3t().add(0.5f, 0.05f, 0.5f), dropPoint); + DrawUtils::drawLine3d(dropPoint, end.toVec3t().add(0.5f, 0.05f, 0.5f)); + } break; + case JUMP: + DrawUtils::drawLine3d(start.toVec3t().add(0.5f, 0.05f, 0.5f), start.toVec3t().add(0.5f, 1.05f, 0.5f)); + DrawUtils::drawLine3d(start.toVec3t().add(0.5f, 1.05f, 0.5f), end.toVec3t().add(0.5f, 0.05f, 0.5f)); + break; + case PARKOUR_JUMP_SINGLE:{ + auto middle = start.toVec3t().add(0.5f, 0.05f, 0.5f).add(end.sub(start).toVec3t().mul(0.5f).add(0, 1, 0)); + DrawUtils::drawLine3d(start.toVec3t().add(0.5f, 0.05f, 0.5f), middle); + DrawUtils::drawLine3d(middle, end.toVec3t().add(0.5f, 0.05f, 0.5f)); + } break; + case WALK: + default: + DrawUtils::drawLine3d(start.toVec3t().add(0.5f, 0.05f, 0.5f), end.toVec3t().add(0.5f, 0.05f, 0.5f)); + break; + } +} +JoeSegmentType JoeSegment::getSegmentType() const { + return segmentType; +} +const vec3_ti& JoeSegment::getStart() const { + return start; +} +const vec3_ti& JoeSegment::getEnd() const { + return end; +} +float JoeSegment::getCost() const { + return cost; +} +bool JoeSegment::isAllowingSprint() const { + return allowSprint; +} +void JoeSegment::setAllowSprint(bool allowSprint) { + JoeSegment::allowSprint = allowSprint; +} +bool JoeSegment::isInValidPosition(const vec3_ti& pos) const { + for(const auto& validPos : this->validPositions){ + if(pos == validPos) + return true; + } + return false; +} +void JoeSegment::setValidPositions(const std::vector& validPositions) { + JoeSegment::validPositions = validPositions; +} +void JoeSegment::init() { + std::vector positions = {start, end}; + + auto player = g_Data.getLocalPlayer(); + auto reg = player->region; + + switch(this->segmentType){ + case JoeSegmentType::WALK: { + if(start.y == end.y){ + int isDiagonal = 0; + isDiagonal += start.x != end.x; + isDiagonal += start.z != end.z; + if(!isDiagonal){ + break; + } + + auto mod = start; + mod.x = end.x; + positions.push_back(mod); + mod.x = start.x; + mod.z = end.z; + positions.push_back(mod); + break; + } + + vec3_t tangentF = end.sub(start).toFloatVector(); + tangentF.y = 0; + tangentF = tangentF.normalize(); + vec3_ti tangent((int)roundf(tangentF.x), 0, (int)roundf(tangentF.z)); + + positions.push_back(start.add(tangent)); + positions.push_back(start.add(tangent).add(0, -1, 0)); + + for(int yLevel = start.y; yLevel > end.y; yLevel--){ + auto mod = end; + mod.y = yLevel; + positions.push_back(mod); + } + } break; + case JoeSegmentType::DROP: { + for(int yLevel = start.y; yLevel > end.y; yLevel--){ + auto mod = end; + mod.y = yLevel; + positions.push_back(mod); + } + auto pos = end; + auto block = reg->getBlock(pos); + while(block->toLegacy()->hasWater(reg, pos) && pos.y > 1 && end.y - pos.y < 19){ + positions.push_back(pos); + pos.y--; + } + } break; + case JoeSegmentType::JUMP: { + auto mod = start; + mod.y = end.y; + positions.push_back(mod); + } break; + case JoeSegmentType::PARKOUR_JUMP_SINGLE: { + vec3_t tangentF = end.sub(start).toFloatVector(); + tangentF.y = 0; + tangentF = tangentF.normalize(); + vec3_ti tangent((int)roundf(tangentF.x), 0, (int)roundf(tangentF.z)); + + positions.push_back(start.add(0, 1, 0)); + + auto mod = start.add(tangent); + positions.push_back(mod); + positions.push_back(mod.add(0, 1, 0)); + + mod = end; + for(int yLevel = end.y; yLevel <= start.y + 1; yLevel++){ + mod.y = yLevel; + positions.push_back(mod); + } + } break; + case JoeSegmentType::WATER_WALK: { + positions.push_back(start.add(0, 1, 0)); + if(end.y > start.y) + positions.push_back(start.add(0, 2, 0)); + positions.push_back(end.add(0, 1, 0)); + } break; + default: { + + } break; + } + this->setValidPositions(positions); +} diff --git a/Horion/path/JoeSegment.h b/Horion/path/JoeSegment.h new file mode 100644 index 0000000..46a31dc --- /dev/null +++ b/Horion/path/JoeSegment.h @@ -0,0 +1,34 @@ +#pragma once + +#include "../../Utils/HMath.h" +#include + +enum JoeSegmentType{ + INVALID = -1, + WALK = 0, + JUMP, + DROP, + PARKOUR_JUMP_SINGLE, + WATER_WALK +}; + +class JoeSegment { +private: + JoeSegmentType segmentType; + vec3_ti start, end; + float cost; + bool allowSprint; + std::vector validPositions; +public: + JoeSegment(JoeSegmentType type, vec3_ti& start, vec3_ti& stop, float cost, bool allowSprint = false); + void draw(); + bool isAllowingSprint() const; + void setAllowSprint(bool allowSprint); + JoeSegmentType getSegmentType() const; + const vec3_ti& getStart() const; + const vec3_ti& getEnd() const; + bool isInValidPosition(const vec3_ti& pos) const; + void setValidPositions(const std::vector& validPositions); + float getCost() const; + void init(); +}; diff --git a/Horion/path/goals/JoeGoal.cpp b/Horion/path/goals/JoeGoal.cpp new file mode 100644 index 0000000..04b895e --- /dev/null +++ b/Horion/path/goals/JoeGoal.cpp @@ -0,0 +1,3 @@ +#include "JoeGoal.h" +JoeGoal::~JoeGoal() { +} diff --git a/Horion/path/goals/JoeGoal.h b/Horion/path/goals/JoeGoal.h new file mode 100644 index 0000000..0c5fa4c --- /dev/null +++ b/Horion/path/goals/JoeGoal.h @@ -0,0 +1,12 @@ +#pragma once + +#include "../../../Utils/HMath.h" + +class JoeGoal { +private: +public: + virtual ~JoeGoal(); + + virtual bool isInGoal(vec3_ti pos) = 0; + virtual float getHeuristicEstimation(vec3_ti pos) = 0; +}; diff --git a/Horion/path/goals/JoeGoalXYZ.cpp b/Horion/path/goals/JoeGoalXYZ.cpp new file mode 100644 index 0000000..0bd9953 --- /dev/null +++ b/Horion/path/goals/JoeGoalXYZ.cpp @@ -0,0 +1,8 @@ +#include "JoeGoalXYZ.h" +bool JoeGoalXYZ::isInGoal(vec3_ti pos) { + return pos == targetPos; +} +float JoeGoalXYZ::getHeuristicEstimation(vec3_ti pos) { + return JoeGoalXZ::heuristicEstimation(pos, targetPos) + JoeGoalY::heuristicEstimation(pos, (float)targetPos.y); +} +JoeGoalXYZ::JoeGoalXYZ(const vec3_ti& targetPos) : targetPos(targetPos) {} diff --git a/Horion/path/goals/JoeGoalXYZ.h b/Horion/path/goals/JoeGoalXYZ.h new file mode 100644 index 0000000..38ec88a --- /dev/null +++ b/Horion/path/goals/JoeGoalXYZ.h @@ -0,0 +1,15 @@ +#pragma once + +#include "JoeGoal.h" +#include "JoeGoalY.h" +#include "JoeGoalXZ.h" + +class JoeGoalXYZ : public JoeGoal { +private: + vec3_ti targetPos; +public: + JoeGoalXYZ(const vec3_ti& targetPos); + + bool isInGoal(vec3_ti pos) override; + float getHeuristicEstimation(vec3_ti pos) override; +}; diff --git a/Horion/path/goals/JoeGoalXZ.cpp b/Horion/path/goals/JoeGoalXZ.cpp new file mode 100644 index 0000000..80979dc --- /dev/null +++ b/Horion/path/goals/JoeGoalXZ.cpp @@ -0,0 +1,28 @@ +#include "JoeGoalXZ.h" + +#include "../JoeConstants.h" + +bool JoeGoalXZ::isInGoal(vec3_ti pos) { + return pos.x == targetPos.x && pos.z == targetPos.z; +} +float JoeGoalXZ::getHeuristicEstimation(vec3_ti pos) { + return JoeGoalXZ::heuristicEstimation(targetPos, pos); +} +float JoeGoalXZ::heuristicEstimation(vec3_ti node, vec3_ti target) { + vec3_ti diff = node.sub(target); + int x = abs(diff.x); + int z = abs(diff.z); + float straight; + float diagonal; + if (x < z) { + straight = (float)z - x; + diagonal = (float)x; + } else { + straight = (float)x - z; + diagonal = (float)z; + } + static const float SQRT_2 = sqrtf(2); + diagonal *= SQRT_2; + return (straight + diagonal) / SPRINT_SPEED; +} +JoeGoalXZ::JoeGoalXZ(const vec3_ti& targetPos) : targetPos(targetPos) {} diff --git a/Horion/path/goals/JoeGoalXZ.h b/Horion/path/goals/JoeGoalXZ.h new file mode 100644 index 0000000..1a7e662 --- /dev/null +++ b/Horion/path/goals/JoeGoalXZ.h @@ -0,0 +1,15 @@ +#pragma once + +#include "JoeGoal.h" + +class JoeGoalXZ : public JoeGoal{ +private: + vec3_ti targetPos; +public: + JoeGoalXZ(const vec3_ti& targetPos); + + bool isInGoal(vec3_ti pos) override; + float getHeuristicEstimation(vec3_ti pos) override; + + static float heuristicEstimation(vec3_ti node, vec3_ti target); +}; diff --git a/Horion/path/goals/JoeGoalY.cpp b/Horion/path/goals/JoeGoalY.cpp new file mode 100644 index 0000000..bd4b5df --- /dev/null +++ b/Horion/path/goals/JoeGoalY.cpp @@ -0,0 +1,18 @@ +#include "JoeGoalY.h" + +#include "../JoeConstants.h" + +JoeGoalY::JoeGoalY(float target) : target(target) {} +bool JoeGoalY::isInGoal(vec3_ti pos) { + return pos.y == target; +} +float JoeGoalY::getHeuristicEstimation(vec3_ti pos) { + return heuristicEstimation(pos, target); +} +float JoeGoalY::heuristicEstimation(vec3_ti node, float target) { + if(node.y > target) + return FALL_N_BLOCKS_COST[(int)floorf(node.y - target)] * 0.99f; + if(target > node.y) + return (target - node.y) * JUMP_TIME * 0.99f; + return 0; +} diff --git a/Horion/path/goals/JoeGoalY.h b/Horion/path/goals/JoeGoalY.h new file mode 100644 index 0000000..a0f7785 --- /dev/null +++ b/Horion/path/goals/JoeGoalY.h @@ -0,0 +1,15 @@ +#pragma once + +#include "JoeGoal.h" + +class JoeGoalY : public JoeGoal { +private: + float target; +public: + JoeGoalY(float target); + + bool isInGoal(vec3_ti pos) override; + float getHeuristicEstimation(vec3_ti pos) override; + + static float heuristicEstimation(vec3_ti node, float target); +}; diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..7a6572e --- /dev/null +++ b/LICENSE @@ -0,0 +1,407 @@ +Attribution-NonCommercial 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More_considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution-NonCommercial 4.0 International Public +License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution-NonCommercial 4.0 International Public License ("Public +License"). To the extent this Public License may be interpreted as a +contract, You are granted the Licensed Rights in consideration of Your +acceptance of these terms and conditions, and the Licensor grants You +such rights in consideration of benefits the Licensor receives from +making the Licensed Material available under these terms and +conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. NonCommercial means not primarily intended for or directed towards + commercial advantage or monetary compensation. For purposes of + this Public License, the exchange of the Licensed Material for + other material subject to Copyright and Similar Rights by digital + file-sharing or similar means is NonCommercial provided there is + no payment of monetary compensation in connection with the + exchange. + + j. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + k. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + l. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part, for NonCommercial purposes only; and + + b. produce, reproduce, and Share Adapted Material for + NonCommercial purposes only. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties, including when + the Licensed Material is used other than for NonCommercial + purposes. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database for NonCommercial purposes + only; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. \ No newline at end of file diff --git a/Memory/GameData.cpp b/Memory/GameData.cpp new file mode 100644 index 0000000..8fb223c --- /dev/null +++ b/Memory/GameData.cpp @@ -0,0 +1,255 @@ +#include "GameData.h" + +#include +#include +#include "../Utils/Logger.h" +#include "../Utils/Utils.h" + +GameData g_Data; + +size_t AABBHasher::operator()(const AABB& i) const { + return Utils::posToHash(i.lower); +} + +void GameData::retrieveClientInstance() { + static uintptr_t clientInstanceOffset = 0x0; + uintptr_t sigOffset = 0x0; + if (clientInstanceOffset == 0x0) { + sigOffset = FindSignature("48 8B 15 ? ? ? ? 4C 8B 02 4C 89 06 40 84 FF 74 ? 48 8B CD E8 ? ? ? ? 48 8B C6 48 8B 4C 24 ? 48 33 CC E8 ? ? ? ? 48 8B 5C 24 ? 48 8B 6C 24 ? 48 8B 74 24 ? 48 83 C4 ? 5F C3 B9 ? ? ? ? E8 ? ? ? ? CC E8 ? ? ? ? CC CC CC CC CC CC CC CC CC CC CC 48 89 5C 24 ? 48 89 6C 24 ? 56"); + if (sigOffset != 0x0) { + int offset = *reinterpret_cast((sigOffset + 3)); // Get Offset from code + clientInstanceOffset = sigOffset - g_Data.gameModule->ptrBase + offset + /*length of instruction*/ 7; // Offset is relative + logF("client: %llX", clientInstanceOffset); + } + } + // clientInstanceOffset = 0x03CD5058; // pointer scanned, can't find good signatures so it'll stay + g_Data.clientInstance = reinterpret_cast(g_Data.slimMem->ReadPtr(g_Data.gameModule->ptrBase + clientInstanceOffset, {0x0, 0x0, 0x50})); +#ifdef _DEBUG + if (g_Data.clientInstance == 0) + throw std::exception("Client Instance is 0"); +#endif +} + +bool GameData::canUseMoveKeys() { + MinecraftGame* mc = g_Data.clientInstance->minecraftGame; + if (mc == nullptr) { + return false; + } + + return mc->canUseKeybinds(); +} + +bool GameData::isKeyDown(int key) { + static uintptr_t keyMapOffset = 0x0; + if (keyMapOffset == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ?? ?? ?? ?? 89 1C B9"); + if (sigOffset != 0x0) { + int offset = *reinterpret_cast((sigOffset + 3)); // Get Offset from code + keyMapOffset = sigOffset - g_Data.gameModule->ptrBase + offset + /*length of instruction*/ 7; // Offset is relative + logF("KeyMap: %llX", keyMapOffset + g_Data.gameModule->ptrBase); + } + } + // All keys are mapped as bools, though aligned as ints (4 byte) + // key0 00 00 00 key1 00 00 00 key2 00 00 00 ... + return *reinterpret_cast(g_Data.gameModule->ptrBase + keyMapOffset + ((uintptr_t)key * 0x4)); +} +bool GameData::isKeyPressed(int key) { + if (isKeyDown(key)) { + while (isKeyDown(key)) + Sleep(1); + return true; + } + return false; +} + +bool GameData::isRightClickDown() { + if (g_Data.hidController == 0) + return false; + return g_Data.hidController->rightClickDown; +} + +bool GameData::isLeftClickDown() { + if (g_Data.hidController == 0) + return false; + return g_Data.hidController->leftClickDown; +} + +bool GameData::isWheelDown() { + if (g_Data.hidController == 0) + return false; + return g_Data.hidController->wheelDown; +} + +bool GameData::shouldTerminate() { + return g_Data.shouldTerminateB; +} + +void GameData::terminate() { + g_Data.shouldTerminateB = true; +} + +bool GameData::shouldHide() { + return g_Data.shouldHideB; +} + +void GameData::hide() { + g_Data.shouldHideB = !(g_Data.shouldHideB); +} + +void GameData::updateGameData(C_GameMode* gameMode) { + retrieveClientInstance(); + g_Data.localPlayer = g_Data.getLocalPlayer(); + + if (g_Data.localPlayer != nullptr && gameMode->player == g_Data.localPlayer) { // GameMode::tick might also be run on the local server + g_Data.gameMode = gameMode; + QueryPerformanceCounter(reinterpret_cast(&g_Data.lastUpdate)); + + if (g_Data.localPlayer != nullptr) { + C_GuiData* guiData = g_Data.clientInstance->getGuiData(); + + if (guiData != nullptr) { + { + auto vecLock = Logger::GetTextToPrintLock(); + auto* stringPrintVector = Logger::GetTextToPrint(); +#ifdef _DEBUG + int numPrinted = 0; + std::vector::iterator it; + for (it = stringPrintVector->begin(); it != stringPrintVector->end(); ++it) { + numPrinted++; + if (numPrinted > 20) { + break; + } + + guiData->displayClientMessageNoSendF("%s%s%s%s", GOLD, it->time, RESET, it->text); + } + stringPrintVector->erase(stringPrintVector->begin(), it); +#else + stringPrintVector->clear(); +#endif + } + { + auto lock = std::lock_guard(g_Data.textPrintLock); + + auto& stringPrintVector = g_Data.textPrintList; + int numPrinted = 0; + std::vector::iterator it; + for (it = stringPrintVector.begin(); it != stringPrintVector.end(); ++it) { + numPrinted++; + if (numPrinted > 20) { + break; + } + + guiData->displayClientMessageNoSendF(it->c_str()); + } + stringPrintVector.erase(stringPrintVector.begin(), it); + } + } + } + } +} + +void GameData::EntityList_tick(C_EntityList* list) { + g_Data.entityList = list; +} + +void GameData::setHIDController(C_HIDController* Hid) { + g_Data.hidController = Hid; +} + +void GameData::setRakNetInstance(C_RakNetInstance* raknet) { + g_Data.raknetInstance = raknet; +} + +void GameData::forEachEntity(std::function callback) { + //Player EntityList + C_EntityList* entityList = (C_EntityList*)g_Data.getClientInstance()->getPointerStruct(); + uintptr_t start = ((uintptr_t)entityList + 0x70); + uintptr_t stop = ((uintptr_t)entityList + 0x78); + start = *(uintptr_t*)start; + stop = *(uintptr_t*)stop; + + std::set knownEnts; + + while (start < stop) { + C_Entity* ent = *(C_Entity**)start; + if (ent != nullptr && knownEnts.count(ent) == 0) { + callback(ent, false); + knownEnts.insert(ent); + } + + start += 8; + } + + // New EntityList + { + // MultiplayerLevel::directTickEntities + __int64 region = reinterpret_cast<__int64>(g_Data.getLocalPlayer()->region); + __int64* entityIdMap = *(__int64**)(*(__int64*)(region + 0x20) + 0x138i64); + for (__int64* i = (__int64*)*entityIdMap; i != entityIdMap; i = (__int64*)*i) { + __int64 actor = i[3]; + C_Entity* ent = reinterpret_cast(actor); + // !isRemoved() && !isGlobal() + if (actor && !*(char*)(actor + 993) && !*(char*)(actor + 994) && knownEnts.count(ent) == 0) { + callback(ent, false); + knownEnts.insert(ent); + } + } + } +} + +void GameData::addChestToList(C_ChestBlockActor* chest) { + if (chest == nullptr || !chest->isMainSubchest()) + return; + AABB chestAabb = chest->getFullAABB(); + std::lock_guard listGuard(g_Data.chestListMutex); + if (g_Data.chestList.count(chestAabb) > 0) + return; + + g_Data.chestList.insert(chestAabb); +} + +void GameData::initGameData(const SlimUtils::SlimModule* gameModule, SlimUtils::SlimMem* slimMem, void* hDllInst) { + g_Data.gameModule = gameModule; + g_Data.slimMem = slimMem; + g_Data.hDllInst = hDllInst; + g_Data.networkedData.xorKey = rand() % 0xFFFF | ((rand() % 0xFFFF) << 16); + retrieveClientInstance(); +#ifdef _DEBUG + logF("base: %llX", g_Data.getModule()->ptrBase); + logF("clientInstance %llX", g_Data.clientInstance); + logF("localPlayer %llX", g_Data.getLocalPlayer()); + if (g_Data.clientInstance != nullptr) { + logF("minecraftGame: %llX", g_Data.clientInstance->minecraftGame); + logF("levelRenderer: %llX", g_Data.clientInstance->levelRenderer); + } + +#endif +} +void GameData::sendPacketToInjector(HorionDataPacket horionDataPack) { + if (!isInjectorConnectionActive()) + throw std::exception("Horion injector connection not active"); + if (horionDataPack.dataArraySize >= 3000) { + logF("Tried to send data packet with array size: %i %llX", horionDataPack.dataArraySize, horionDataPack.data.get()); + throw std::exception("Data packet data too big"); + } + + horionToInjectorQueue.push(horionDataPack); +} +void GameData::callInjectorResponseCallback(int id, std::shared_ptr packet) { + if (this->injectorToHorionResponseCallbacks.find(id) == this->injectorToHorionResponseCallbacks.end()) { + logF("No response callback for request with id=%i!", id); + return; + } + this->injectorToHorionResponseCallbacks[id](packet); + this->injectorToHorionResponseCallbacks.erase(id); +} +void GameData::log(const char* fmt, ...) { + auto lock = std::lock_guard(g_Data.textPrintLock); + va_list arg; + va_start(arg, fmt); + char message[300]; + vsprintf_s(message, 300, fmt, arg); + std::string msg(message); + g_Data.textPrintList.push_back(msg); + va_end(arg); +} diff --git a/Memory/GameData.h b/Memory/GameData.h new file mode 100644 index 0000000..ea57dc1 --- /dev/null +++ b/Memory/GameData.h @@ -0,0 +1,251 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "../Horion/Config/AccountInformation.h" +#include "../SDK/CChestBlockActor.h" +#include "../SDK/CClientInstance.h" +#include "../SDK/CGameMode.h" +#include "../SDK/CHIDController.h" +#include "../SDK/CMoveInputHandler.h" +#include "../SDK/CRakNetInstance.h" +#include "../Utils/SkinUtil.h" +#include "../Utils/TextFormat.h" +#include "SlimMem.h" + +enum DATAPACKET_CMD : int { + CMD_INIT = 0, + CMD_PING, + CMD_PONG, + CMD_OPENBROWSER, + CMD_FILECHOOSER, + CMD_RESPONSE, + CMD_FOLDERCHOOSER, // sets permissions for a whole folder and sends the path over + CMD_LOG +}; + +struct HorionDataPacket { + DATAPACKET_CMD cmd; + int params[5] = {0}; + int dataArraySize = 0; + std::shared_ptr data; + + HorionDataPacket() { + } +}; + +struct NetworkedData { + unsigned int xorKey = 0; + unsigned int localPlayerOffset = 0x94; // Scrambled data + bool dataSet = false; +}; + +struct InfoBoxData { + bool isOpen = true; + float fadeTarget = 1; + float fadeVal = 0; + float closeTimer = -1; + std::string title; + std::string message; + + InfoBoxData(std::string title, std::string message) : title(title), message(message){}; + + void fade() { + fadeVal = fadeTarget - ((fadeTarget - fadeVal) * 0.65f); + if (fadeTarget == 0 && fadeVal < 0.001f) + isOpen = false; + } +}; + +struct SkinData; + +struct AABBHasher { + size_t operator()(const AABB& i) const; +}; + +class GameData { +private: + C_ClientInstance* clientInstance = nullptr; + C_LocalPlayer* localPlayer = nullptr; + C_GameMode* gameMode = nullptr; + C_EntityList* entityList = nullptr; + C_HIDController* hidController = nullptr; + C_RakNetInstance* raknetInstance = nullptr; + void* hDllInst = 0; + std::unordered_set chestList; + std::vector textPrintList; + std::mutex textPrintLock; + std::mutex chestListMutex; + std::queue horionToInjectorQueue; + std::map)>> injectorToHorionResponseCallbacks; + int lastRequestId = 0; + std::shared_ptr customGeometry; + bool customGeoActive = false; + std::shared_ptr, size_t>> customTexture; + bool customTextureActive = false; + std::queue> infoBoxQueue; + + bool injectorConnectionActive = false; + const SlimUtils::SlimModule* gameModule = 0; + SlimUtils::SlimMem* slimMem; + bool shouldTerminateB = false; + bool shouldHideB = false; + bool isAllowingWIPFeatures = false; + __int64 lastUpdate; + AccountInformation accountInformation = AccountInformation::asGuest(); + static void retrieveClientInstance(); + TextHolder* fakeName; + +public: + NetworkedData networkedData; + + static bool canUseMoveKeys(); + static bool isKeyDown(int key); + static bool isKeyPressed(int key); + static bool isRightClickDown(); + static bool isLeftClickDown(); + static bool isWheelDown(); + static bool shouldTerminate(); + static bool shouldHide(); + static void hide(); + static void terminate(); + static void updateGameData(C_GameMode* gameMode); + static void initGameData(const SlimUtils::SlimModule* gameModule, SlimUtils::SlimMem* slimMem, void* hDllInst); + static void addChestToList(C_ChestBlockActor* ChestBlock2); + static void EntityList_tick(C_EntityList* list); + static void setHIDController(C_HIDController* Hid); + static void setRakNetInstance(C_RakNetInstance* raknet); + static void log(const char* fmt, ...); + float fov = 0.f; + int fps = 0; + int frameCount = 0; + int cpsLeft = 0; + int cpsRight = 0; + int leftclickCount = 0; + int rightclickCount = 0; + + void clearChestList() { + std::lock_guard listGuard(chestListMutex); + this->chestList.clear(); + } + inline std::shared_ptr getFreshInfoBox() { + while (!this->infoBoxQueue.empty()) { + auto box = this->infoBoxQueue.front(); + if (!box->isOpen) { + this->infoBoxQueue.pop(); + continue; + } + return box; + } + return std::shared_ptr(); + } + inline std::shared_ptr addInfoBox(std::string title, std::string message) { + auto box = std::make_shared(title, message); + this->infoBoxQueue.push(box); + return box; + } + inline void setCustomGeometryOverride(bool setActive, std::shared_ptr customGeoPtr) { + this->customGeoActive = setActive; + if (setActive) + this->customGeometry.swap(customGeoPtr); + else + this->customGeometry.reset(); + } + inline std::tuple> getCustomGeoOverride() { + return std::make_tuple(this->customGeoActive, this->customGeometry); + } + inline void setCustomTextureOverride(bool setActive, std::shared_ptr, size_t>> customTexturePtr) { + this->customTextureActive = setActive; + if (setActive) + this->customTexture.swap(customTexturePtr); + else + this->customTexture.reset(); + } + inline auto getCustomTextureOverride() { + return std::make_tuple(this->customTextureActive, this->customTexture); + } + inline AccountInformation getAccountInformation() { return this->accountInformation; }; + inline void setAccountInformation(AccountInformation newAcc) { + if (newAcc.verify()) + this->accountInformation = newAcc; + else { + #ifdef _BETA + this->terminate(); + *reinterpret_cast(0) = 1; + #endif + } + } + void sendPacketToInjector(HorionDataPacket horionDataPack); + inline int addInjectorResponseCallback(std::function)> callback) { + lastRequestId++; + this->injectorToHorionResponseCallbacks[lastRequestId] = callback; + return lastRequestId; + } + void callInjectorResponseCallback(int id, std::shared_ptr packet); + inline bool allowWIPFeatures() { +#ifdef _DEBUG + return true; +#else + return isAllowingWIPFeatures; +#endif + } + inline void setAllowWIPFeatures(bool enable = false) { isAllowingWIPFeatures = enable; }; + inline bool isInjectorConnectionActive() { return injectorConnectionActive; }; + inline void setInjectorConnectionActive(bool isActive) { + if (injectorConnectionActive && !isActive) { + std::queue empty; + horionToInjectorQueue.swap(empty); + } + injectorConnectionActive = isActive; + }; + inline bool isPacketToInjectorQueueEmpty() { return horionToInjectorQueue.empty(); }; + inline HorionDataPacket getPacketToInjector() { + if (isPacketToInjectorQueueEmpty()) + throw std::exception("Packet send queue is empty"); + HorionDataPacket pk = horionToInjectorQueue.front(); + horionToInjectorQueue.pop(); + return pk; + }; + inline void* getDllModule() { return hDllInst; }; + inline C_ClientInstance* getClientInstance() { return clientInstance; }; + inline C_GuiData* getGuiData() { return clientInstance->getGuiData(); }; + inline C_LocalPlayer* getLocalPlayer() { + + localPlayer = clientInstance->localPlayer; + + if (localPlayer == nullptr) + gameMode = nullptr; + return localPlayer; + }; + C_LocalPlayer** getPtrLocalPlayer() { + return &localPlayer; + }; + bool isInGame() { + return localPlayer != nullptr; + } + const SlimUtils::SlimModule* getModule() { + return gameModule; + }; + const SlimUtils::SlimMem* getSlimMem() { + return slimMem; + }; + C_GameMode* getCGameMode() { return gameMode; }; + C_EntityList* getEntityList() { return entityList; }; + C_HIDController** getHIDController() { return &hidController; }; + C_RakNetInstance* getRakNetInstance() { return raknetInstance; }; + std::unordered_set& getChestList() { return chestList; }; + auto lockChestList() { return std::lock_guard(this->chestListMutex); } + void setFakeName(TextHolder* name) { fakeName = name; }; + TextHolder* getFakeName() { return fakeName; }; + inline __int64 getLastUpdateTime() { return lastUpdate; }; + void forEachEntity(std::function); + int getFPS() { return fps; }; + int getLeftCPS() { return cpsLeft; }; + int getRightCPS() { return cpsRight; }; +}; + +extern GameData g_Data; diff --git a/Memory/Hooks.cpp b/Memory/Hooks.cpp new file mode 100644 index 0000000..a32d793 --- /dev/null +++ b/Memory/Hooks.cpp @@ -0,0 +1,1790 @@ +#include "Hooks.h" + +#include +#include +#include +#include // perspective, translate, rotate +#include +#include // mat4 +#include //radians + +#include "../SDK/Tag.h" + +Hooks g_Hooks; +bool isTicked = false; +bool overrideStyledReturn = false; +TextHolder styledReturnText; +//#define TEST_DEBUG + +void Hooks::Init() { + logF("Setting up Hooks..."); + // clang-format off + // Vtables + { + // GameMode::vtable + { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 8B D9 48 89 01 8B FA 48 8B 89 ? ? ? ? 48 85 C9 74 ? 48 8B 01 BA ? ? ? ? FF 10 48 8B 8B"); + int offset = *reinterpret_cast(sigOffset + 3); + uintptr_t** gameModeVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (gameModeVtable == 0x0 || sigOffset == 0x0) + logF("C_GameMode signature not working!!!"); + else { + g_Hooks.GameMode_startDestroyBlockHook = std::make_unique(gameModeVtable[1], Hooks::GameMode_startDestroyBlock); + + g_Hooks.GameMode_getPickRangeHook = std::make_unique(gameModeVtable[10], Hooks::GameMode_getPickRange); + + g_Hooks.GameMode_attackHook = std::make_unique(gameModeVtable[14], Hooks::GameMode_attack); + } + } + + // BlockLegacy::vtable + { + intptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 01 4C 8B 72 ? 48 B9"); // BlockLegacy constructor + int offset = *reinterpret_cast(sigOffset + 3); + uintptr_t** blockLegacyVtable = reinterpret_cast(sigOffset + offset + 7); + if (blockLegacyVtable == 0x0 || sigOffset == 0x0) + logF("C_BlockLegacy signature not working!!!"); + else { + g_Hooks.BlockLegacy_getRenderLayerHook = std::make_unique(blockLegacyVtable[180], Hooks::BlockLegacy_getRenderLayer); + } + } + + // LocalPlayer::vtable + { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 07 48 8D 8F ?? ?? ?? ?? 48 8B 87"); + int offset = *reinterpret_cast(sigOffset + 3); + uintptr_t** localPlayerVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (localPlayerVtable == 0x0 || sigOffset == 0x0) + logF("C_LocalPlayer signature not working!!!"); + else { + g_Hooks.Actor_startSwimmingHook = std::make_unique(localPlayerVtable[196], Hooks::Actor_startSwimming); + + g_Hooks.Actor_ascendLadderHook = std::make_unique(localPlayerVtable[351], Hooks::Actor_ascendLadder); + + g_Hooks.Actor_lerpMotionHook = std::make_unique(localPlayerVtable[40], Hooks::Actor_lerpMotion); + + g_Hooks.Mob__isImmobileHook = std::make_unique(localPlayerVtable[88], Hooks::Mob__isImmobile); + + g_Hooks.Actor_isInWaterHook = std::make_unique(localPlayerVtable[67], Hooks::Actor_isInWater); + + g_Hooks.Actor_swingHook = std::make_unique(localPlayerVtable[214], Hooks::Actor_swing); + + g_Hooks.JumpPowerHook = std::make_unique(localPlayerVtable[357], Hooks::JumpPower); + } + } + + // MoveInputHandler::vtable + { + uintptr_t sigOffset = FindSignature("48 8D 0D ? ? ? ? 49 89 48 ? 49 89 80 ? ? ? ? 49 89 80 ? ? ? ? 48 39 87 ? ? ? ? 74 20 48 8B 8F"); + int offset = *reinterpret_cast(sigOffset + 3); + uintptr_t** moveInputVtable = reinterpret_cast(sigOffset + offset + 7); + if (moveInputVtable == 0x0 || sigOffset == 0x0) + logF("C_MoveInputHandler signature not working!!!"); + else { + g_Hooks.MoveInputHandler_tickHook = std::make_unique(moveInputVtable[1], Hooks::MoveInputHandler_tick); + } + } + + // PackAccessStrategy vtables for isTrusted + { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 49 89 06 49 8D 76 50"); + int offset = *reinterpret_cast(sigOffset + 3); + uintptr_t** directoryPackVtable = reinterpret_cast(sigOffset + offset + 7); + + { + g_Hooks.DirectoryPackAccessStrategy__isTrustedHook = std::make_unique(directoryPackVtable[6], Hooks::DirectoryPackAccessStrategy__isTrusted); + } + + uintptr_t sigOffset2 = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 03 49 8D 57"); + int offset2 = *reinterpret_cast(sigOffset2 + 3); + uintptr_t** directoryPackVtable2 = reinterpret_cast(sigOffset2 + offset2 + 7); + + { + g_Hooks.ZipPackAccessStrategy__isTrustedHook = std::make_unique(directoryPackVtable2[6], Hooks::ReturnTrue); + } + g_Hooks.SkinRepository___checkSignatureFileInPack = std::make_unique(FindSignature("48 89 5C 24 ? 57 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 ? 48 8B 39 48 8B 59 ? 48 85 DB"), Hooks::ReturnTrue); + } + } + + // Signatures + { + // vtables better than sigs + + /*void* lerpFunc = reinterpret_cast(FindSignature("8B 02 89 81 ? ? ? ? 8B 42 ? 89 81 ? ? ? ? 8B 42 ? 89 81 ? ? ? ? C3 CC CC CC CC CC 48 89 5C 24")); + g_Hooks.Actor_lerpMotionHook = std::make_unique(lerpFunc, Hooks::Actor_lerpMotion); + + void* ascendLadder = reinterpret_cast(FindSignature("C7 81 ? ? ? ? ? ? ? ? C3 CC CC CC CC CC C7 81 ? ? ? ? ? ? ? ? C3 CC CC CC CC CC C7 81")); + g_Hooks.Actor_ascendLadderHook = std::make_unique(ascendLadder, Hooks::Actor_ascendLadder); + + void* isInWater = reinterpret_cast(FindSignature("0F B6 81 ? ? ? ? C3 CC CC CC CC CC CC CC CC 0F B6 81 ? ? ? ? C3 CC CC CC CC CC CC CC CC 48 89 5C 24 ? 48 89 6C 24")); + g_Hooks.Actor_isInWaterHook = std::make_unique(isInWater, Hooks::Actor_isInWater); + + void* jump = reinterpret_cast(FindSignature("48 89 5C 24 10 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 48 8B 19 48 8D")); + g_Hooks.JumpPowerHook = std::make_unique(jump, Hooks::JumpPower); + + void* MobIsImmobile = reinterpret_cast(FindSignature("40 53 48 83 EC ? 48 8B D9 E8 ? ? ? ? 84 C0 75 ? 48 8B 03 48 8B CB")); + g_Hooks.Mob__isImmobileHook = std::make_unique(MobIsImmobile, Hooks::Mob__isImmobile);*/ + + void* player_tickworld = reinterpret_cast(FindSignature("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 0F 29 B4 24 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 ?? 48 89 55 ?? 48 8B F9")); + g_Hooks.Player_tickWorldHook = std::make_unique(player_tickworld, Hooks::Player_tickWorld); + + void* _sendChatMessage = reinterpret_cast(FindSignature("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 4C 8B EA 4C 8B F9 48 8B 49")); + g_Hooks.ClientInstanceScreenModel_sendChatMessageHook = std::make_unique(_sendChatMessage, Hooks::ClientInstanceScreenModel_sendChatMessage); + + void* _renderText = reinterpret_cast(FindSignature("48 8B C4 48 89 58 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B FA 48 89 54 24 ? 4C 8B E9")); + g_Hooks.RenderTextHook = std::make_unique(_renderText, Hooks::RenderText); + g_Hooks.RenderTextHook->enableHook(); + + void* setupRender = reinterpret_cast(FindSignature("48 89 5C 24 10 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B DA 48 8B F9 33 D2 41 B8")); + g_Hooks.UIScene_setupAndRenderHook = std::make_unique(setupRender, Hooks::UIScene_setupAndRender); + + void* render = reinterpret_cast(FindSignature("48 89 5C 24 18 56 57 41 56 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 48 8B FA 48 8B D9 41")); + g_Hooks.UIScene_renderHook = std::make_unique(render, Hooks::UIScene_render); + + void* fogColorFunc = reinterpret_cast(FindSignature("41 0F 10 08 48 8B C2 0F")); + g_Hooks.Dimension_getFogColorHook = std::make_unique(fogColorFunc, Hooks::Dimension_getFogColor); + + void* timeOfDay = reinterpret_cast(FindSignature("44 8B C2 B8 F1 19 76 05 F7 EA")); + g_Hooks.Dimension_getTimeOfDayHook = std::make_unique(timeOfDay, Hooks::Dimension_getTimeOfDay); + + void* chestTick = reinterpret_cast(FindSignature("40 53 57 48 83 EC ?? 48 83 79 ?? ?? 48")); + g_Hooks.ChestBlockActor_tickHook = std::make_unique(chestTick, Hooks::ChestBlockActor_tick); + + void* getGameEdition = reinterpret_cast(FindSignature("8B 91 ?? ?? ?? ?? 85 D2 74 1C 83 EA 01")); + g_Hooks.AppPlatform_getGameEditionHook = std::make_unique(getGameEdition, Hooks::AppPlatform_getGameEdition); + + void* autoComplete = reinterpret_cast(FindSignature("48 8B C4 55 57 41 56 48 8D 68 ?? 48 81 EC ?? ?? ?? ?? 48 C7 45 ?? FE FF FF FF 48 89 58 ?? 48 89 70 ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 ?? 48 8B F9")); + g_Hooks.PleaseAutoCompleteHook = std::make_unique(autoComplete, Hooks::PleaseAutoComplete); + + uintptr_t** packetSenderVtable = reinterpret_cast(*(uintptr_t*)g_Data.getClientInstance()->loopbackPacketSender); + g_Hooks.LoopbackPacketSender_sendToServerHook = std::make_unique(packetSenderVtable[2], Hooks::LoopbackPacketSender_sendToServer); + + void* getFov = reinterpret_cast(FindSignature("40 53 48 83 EC ?? 0F 29 7C 24 ?? 44")); + g_Hooks.LevelRendererPlayer_getFovHook = std::make_unique(getFov, Hooks::LevelRendererPlayer_getFov); + + void* tick_entityList = reinterpret_cast(FindSignature("48 89 ?? ?? ?? 57 48 83 EC ?? 48 8B ?? E8 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? 48 8B D8 ?? ?? ?? ?? ?? ?? 48 99")); + g_Hooks.MultiLevelPlayer_tickHook = std::make_unique(tick_entityList, Hooks::MultiLevelPlayer_tick); + + void* keyMouseFunc = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8B EC 48 81 EC ? ? ? ? 0F 29 74 24 ? 0F 29 7C 24 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 ? 49 8B F0")); + g_Hooks.HIDController_keyMouseHook = std::make_unique(keyMouseFunc, Hooks::HIDController_keyMouse); + + void* renderLevel = reinterpret_cast(FindSignature("48 89 5C 24 10 48 89 74 24 20 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F8 48 8B DA")); + g_Hooks.LevelRenderer_renderLevelHook = std::make_unique(renderLevel, Hooks::LevelRenderer_renderLevel); + + void* clickHook = reinterpret_cast(FindSignature("48 8B C4 48 89 58 ? 48 89 68 ? 48 89 70 ? 57 41 54 41 55 41 56 41 57 48 83 EC ? 44 0F B7 BC 24 ? ? ? ? 48 8B D9")); + g_Hooks.ClickFuncHook = std::make_unique(clickHook, Hooks::ClickFunc); + + void* chestScreenControllerTick = reinterpret_cast(FindSignature("48 89 5C 24 08 57 48 83 EC 20 48 8B F9 E8 ?? ?? ?? ?? 48 8B 17 48 8B CF 8B D8 FF 92 ?? ?? ?? ?? 84 C0 74 31")); + g_Hooks.ChestScreenController_tickHook = std::make_unique(chestScreenControllerTick, Hooks::ChestScreenController_tick); + + void* fullbright = reinterpret_cast(FindSignature("48 83 EC ?? 80 B9 ?? ?? ?? ?? ?? 48 8D 54 24 ?? 48 8B 01 74 35 41 B8 0D 01 00 00")); + g_Hooks.GetGammaHook = std::make_unique(fullbright, Hooks::GetGamma); + + void* onAppSuspended = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 56 48 8B EC 48 83 EC ? 48 8B F1 E8")); + g_Hooks.MinecraftGame_onAppSuspendedHook = std::make_unique(onAppSuspended, Hooks::MinecraftGame_onAppSuspended); + + void* RakNetInstance__tick = reinterpret_cast(FindSignature("48 89 5C 24 10 48 89 74 24 18 55 57 41 54 41 56 41 57 48 8D ?? 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 8B F9 45 33 E4 4C")); + g_Hooks.RakNetInstance_tickHook = std::make_unique(RakNetInstance__tick, Hooks::RakNetInstance_tick); + + void* ConnectionRequest__create = reinterpret_cast(FindSignature("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 4D 8B E1 4D 8B F8 48 89 55")); + g_Hooks.ConnectionRequest_createHook = std::make_unique(ConnectionRequest__create, Hooks::ConnectionRequest_create); + + void* PaintingRenderer__renderAddr = reinterpret_cast(FindSignature("48 89 5C 24 ?? 55 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 45 ?? 49 8B F0 4C 89 45 ?? 4C 8B E2 4C 8B E9")); + g_Hooks.PaintingRenderer__renderHook = std::make_unique(PaintingRenderer__renderAddr, Hooks::PaintingRenderer__render); + + void* _getSkinPack = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? B8 ? ? ? ? E8 ? ? ? ? 48 2B E0 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B E2 48 8B F1")); + g_Hooks.SkinRepository___loadSkinPackHook = std::make_unique(_getSkinPack, Hooks::SkinRepository___loadSkinPack); + + void* _toStyledString = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 74 24 ? 57 48 81 EC ? ? ? ? 49 8B D8 48 8B F9")); + g_Hooks.toStyledStringHook = std::make_unique(_toStyledString, Hooks::toStyledString); + + void* InGamePlayScreen___renderLevel = reinterpret_cast(FindSignature("48 89 5C 24 20 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 0F 29 B4 24 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 41 8B D8 4C")); + g_Hooks.InGamePlayScreen___renderLevelHook = std::make_unique(InGamePlayScreen___renderLevel, Hooks::InGamePlayScreen___renderLevel); + +#ifdef TEST_DEBUG + void* addAction = reinterpret_cast(FindSignature("40 56 57 41 54 41 56 41 57 48 83 EC 30 48 C7 44 24 ? ? ? ? ? 48 89 5C 24 ? 48 89 6C 24 ? 45 0F B6 F8 4C 8B F2 48 8B F9 48 8B 01 48 8B 88 ? ? ? ?")); + g_Hooks.InventoryTransactionManager__addActionHook = std::make_unique(addAction, Hooks::InventoryTransactionManager__addAction); +#endif + + void* localPlayerUpdateFromCam = reinterpret_cast(FindSignature("48 89 5C 24 10 57 48 81 EC ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 80 ?? ?? ?? ?? ?? 00 48 8B FA 48 8B D9")); + g_Hooks.LocalPlayer__updateFromCameraHook = std::make_unique(localPlayerUpdateFromCam, Hooks::LocalPlayer__updateFromCamera); + + void* renderNameTags = reinterpret_cast(FindSignature("4C 8B DC 49 89 5B ? 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ? ? ? ? 41 0F 29 73 ? 41 0F 29 7B ? 45 0F 29 43 ? 48 8B 05")); + g_Hooks.LevelRendererPlayer__renderNameTagsHook = std::make_unique(renderNameTags, Hooks::LevelRendererPlayer__renderNameTags); + + static constexpr auto counterStart = __COUNTER__ + 1; + #define lambda_counter (__COUNTER__ - counterStart) + + void* levelRendererBobView = reinterpret_cast(FindSignature("48 89 5C 24 ?? 57 48 81 EC ?? ?? ?? ?? 48 8B D9 0F 29 B4 24 ?? ?? ?? ?? 48 8B 89")); + + static auto bobViewHookF = [](__int64 _this, glm::mat4& matrix, float lerpT){ + static auto origFunc = g_Hooks.lambdaHooks.at(lambda_counter)->GetFastcall(); + + static auto testMod = moduleMgr->getModule(); + auto p = g_Data.getLocalPlayer(); + float degrees = fmodf(p->getPosOld()->lerp(p->getPos(), lerpT).x, 5) - 2.5f; + degrees *= 180 / 2.5f; + + auto pos = g_Data.getClientInstance()->levelRenderer->origin; + + glm::mat4 View = matrix; + + matrix = View; + if (testMod->isEnabled()) { + if (testMod->doTranslate) + matrix = glm::translate(matrix, glm::vec3(testMod->xTrans, testMod->yTrans, testMod->zTrans)); + + if (testMod->doScale) + matrix = glm::scale(matrix, glm::vec3(testMod->xMod, testMod->yMod, testMod->zMod)); + } + return origFunc(_this, matrix, lerpT); + }; + + std::shared_ptr bobViewHook = std::make_shared(levelRendererBobView, (decltype(&bobViewHookF.operator()))bobViewHookF); + + g_Hooks.lambdaHooks.push_back(bobViewHook); + + #undef lambda_counter + + + + logF("Hooks initialized"); + } + +// clang-format on +} + +void Hooks::Restore() { + MH_DisableHook(MH_ALL_HOOKS); + Sleep(10); +} + +void Hooks::Enable() { + logF("Hooks enabled"); + MH_EnableHook(MH_ALL_HOOKS); +} + +void* Hooks::Player_tickWorld(C_Player* _this, __int64 unk) { + static auto oTick = g_Hooks.Player_tickWorldHook->GetFastcall(); + auto o = oTick(_this, unk); + + if (_this == g_Data.getLocalPlayer()) { + // TODO: refactor all modules to not use GameMode + C_GameMode* gm = *reinterpret_cast(reinterpret_cast<__int64>(_this) + 4840); + GameData::updateGameData(gm); + moduleMgr->onTick(gm); + } + return o; +} + +void Hooks::ClientInstanceScreenModel_sendChatMessage(void* _this, TextHolder* text) { + static auto oSendMessage = g_Hooks.ClientInstanceScreenModel_sendChatMessageHook->GetFastcall(); + + + if (text->getTextLength() > 0) { + char* message = text->getText(); + + if (*message == cmdMgr->prefix) { + cmdMgr->execute(message); + + return; + } else if (*message == '.') { + // maybe the user forgot his prefix, give him some helpful advice + static bool helpedUser = false; + if (!helpedUser) { + helpedUser = true; + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%sYour Horion prefix is: \"%s%c%s\"", RED, YELLOW, cmdMgr->prefix, RED); + g_Data.getClientInstance()->getGuiData()->displayClientMessageF("%sEnter \"%s%cprefix .%s\" to reset your prefix", RED, YELLOW, cmdMgr->prefix, RED); + } + } + } + oSendMessage(_this, text); +} + +__int64 Hooks::UIScene_setupAndRender(C_UIScene* uiscene, __int64 screencontext) { + static auto oSetup = g_Hooks.UIScene_setupAndRenderHook->GetFastcall<__int64, C_UIScene*, __int64>(); + g_Hooks.shouldRender = false; + + return oSetup(uiscene, screencontext); +} + +__int64 Hooks::UIScene_render(C_UIScene* uiscene, __int64 screencontext) { + static auto oRender = g_Hooks.UIScene_renderHook->GetFastcall<__int64, C_UIScene*, __int64>(); + + g_Hooks.shouldRender = false; + + TextHolder alloc{}; + uiscene->getScreenName(&alloc); + + if (alloc.getTextLength() < 100) { + strcpy_s(g_Hooks.currentScreenName, alloc.getText()); + } + + if (!g_Hooks.shouldRender) { + g_Hooks.shouldRender = (strcmp(alloc.getText(), "start_screen") == 0 || strcmp(alloc.getText(), "hud_screen") == 0); + } + alloc.alignedTextLength = 0; + + return oRender(uiscene, screencontext); +} + +__int64 Hooks::RenderText(__int64 a1, C_MinecraftUIRenderContext* renderCtx) { + static auto oText = g_Hooks.RenderTextHook->GetFastcall<__int64, __int64, C_MinecraftUIRenderContext*>(); + + C_GuiData* dat = g_Data.getClientInstance()->getGuiData(); + + DrawUtils::setCtx(renderCtx, dat); + + /* + { + static bool wasConnectedBefore = false; + static LARGE_INTEGER start; + static LARGE_INTEGER frequency; + if (frequency.QuadPart == 0) { + QueryPerformanceFrequency(&frequency); + QueryPerformanceCounter(&start); + } + static bool hasSentWarning = false; + if (!g_Data.isInjectorConnectionActive() && !hasSentWarning) { + __int64 retval = oText(a1, renderCtx); + + LARGE_INTEGER end, elapsed; + QueryPerformanceCounter(&end); + elapsed.QuadPart = end.QuadPart - start.QuadPart; + float elapsedFlot = (float)elapsed.QuadPart / frequency.QuadPart; + if (elapsedFlot > 1.5f && !hasSentWarning) { + hasSentWarning = true; + auto box = g_Data.addInfoBox("Warning", "Your injector doesn't seem to connect to Horion correctly.\nYou can ignore this, but some features may not work as expected."); + box->closeTimer = 5; + vec2_t windowSize = dat->windowSize; + + DrawUtils::fillRectangle(vec4_t(0, 0, windowSize.x, windowSize.y), MC_Color(0.2f, 0.2f, 0.2f), 0.8f); + + std::string text = "Download the new injector at http://horionbeta.club/"; + if (!wasConnectedBefore) + DrawUtils::drawText(vec2_t(windowSize.x / 2 - DrawUtils::getTextWidth(&text, 1.5f) / 2, windowSize.y * 0.4f), &text, MC_Color(), 1.5f); + text = "Remember to keep the injector open while playing"; + DrawUtils::drawText(vec2_t(windowSize.x / 2 - DrawUtils::getTextWidth(&text, wasConnectedBefore ? 1.5f : 0.7f) / 2, windowSize.y * (wasConnectedBefore ? 0.5f : 0.7f)), &text, MC_Color(), wasConnectedBefore ? 1.5f : 0.7f); + text = "Uninject by holding down CTRL + L"; + DrawUtils::drawText(vec2_t(windowSize.x / 2 - DrawUtils::getTextWidth(&text, 0.7f) / 2, windowSize.y * 0.8f), &text, MC_Color(), 0.7f); + + DrawUtils::flush(); + } + + if (!hasSentWarning) // Wait for injector, it might connect in time + return retval; + } else + wasConnectedBefore = true; + } + */ + + if (GameData::shouldHide() || !g_Hooks.shouldRender || !moduleMgr->isInitialized()) + return oText(a1, renderCtx); + + static auto hudModule = moduleMgr->getModule(); + static auto clickGuiModule = moduleMgr->getModule(); + + HImGui.startFrame(); + + g_Data.frameCount++; + + auto wid = g_Data.getClientInstance()->getGuiData()->windowSize; + + // Call PreRender() functions + moduleMgr->onPreRender(renderCtx); + DrawUtils::flush(); + + __int64 retval = oText(a1, renderCtx); + + bool shouldPostRender = true; + bool shouldRenderArrayList = true; + bool shouldRenderTabGui = true; + bool shouldRenderWatermark = true; + + static float rcolors[4]; // Rainbow color array RGBA + static float disabledRcolors[4]; // Rainbow Colors, but for disabled modules + static float currColor[4]; // ArrayList colors + + // Rainbow color updates + { + Utils::ApplyRainbow(rcolors); // Increase Hue of rainbow color array + disabledRcolors[0] = std::min(1.f, rcolors[0] * 0.4f + 0.2f); + disabledRcolors[1] = std::min(1.f, rcolors[1] * 0.4f + 0.2f); + disabledRcolors[2] = std::min(1.f, rcolors[2] * 0.4f + 0.2f); + disabledRcolors[3] = 1; + } + + { + // Main Menu + std::string screenName(g_Hooks.currentScreenName); + if (strcmp(screenName.c_str(), "start_screen") == 0) { + // Draw BIG epic horion watermark + /*{ + std::string text = "H O R I O N"; + vec2_t textPos = vec2_t(wid.x / 2.f - DrawUtils::getTextWidth(&text, 8.f) / 2.f, wid.y / 9.5f); + vec4_t rectPos = vec4_t(textPos.x - 55.f, textPos.y - 15.f, textPos.x + DrawUtils::getTextWidth(&text, 8.f) + 55.f, textPos.y + 75.f); + DrawUtils::fillRectangle(rectPos, MC_Color(13, 29, 48, 1), 1.f); + DrawUtils::drawRectangle(rectPos, rcolors, 1.f, 2.f); + DrawUtils::drawText(textPos, &text, MC_Color(255, 255, 255, 1), 8.f); + }*/ + + // Draw Custom Geo Button + if (g_Data.allowWIPFeatures() && g_Data.isInjectorConnectionActive()) { + if (HImGui.Button("Load Script Folder", vec2_t(wid.x * (0.765f - 0.5f), wid.y * 0.92f), true)) { + HorionDataPacket packet; + packet.cmd = CMD_FOLDERCHOOSER; + auto tmp = std::shared_ptr(new unsigned char[300]); + packet.data.swap(tmp); + memset(packet.data.get(), 0, 300); + strcpy_s((char*)packet.data.get(), 200, "{\"title\": \"Select a Script Folder\", \"filter\":\".js\"}"); + packet.dataArraySize = (int)strlen((char*)packet.data.get()); + packet.params[0] = g_Data.addInjectorResponseCallback([](std::shared_ptr pk) { + if (pk->params[0] != 1) { // Dialog Canceled, reset geo + auto box = g_Data.addInfoBox("Scripting", "Invalid Folder"); + box->closeTimer = 1; + return; + } + + wchar_t* jsonData = reinterpret_cast(pk->data.get()); + std::wstring jsonDataStr(jsonData); + + json parsed = json::parse(jsonDataStr); + if (parsed["path"].is_string()) { + auto box = g_Data.addInfoBox("Importing Script", "Please wait..."); + std::thread gamer([parsed, box]() { + auto result = scriptMgr.importScriptFolder(parsed["path"].get()); + if (result) + box->fadeTarget = 0; + else { + box->message = "Script import error, \ncheck the console"; + box->closeTimer = 2; + } + }); + gamer.detach(); + } + }); + + g_Data.sendPacketToInjector(packet); + } + if (HImGui.Button("Custom Geometry", vec2_t(wid.x * 0.765f, wid.y * 0.92f), true)) { + HorionDataPacket packet; + packet.cmd = CMD_FILECHOOSER; + auto tmp = std::shared_ptr(new unsigned char[300]); + packet.data.swap(tmp); + memset(packet.data.get(), 0, 300); + strcpy_s((char*)packet.data.get(), 200, "{\"title\": \"Select a 3d object\", \"filter\":\"Object Files (*.obj)|*.obj\"}"); + packet.dataArraySize = (int)strlen((char*)packet.data.get()); + packet.params[0] = g_Data.addInjectorResponseCallback([](std::shared_ptr pk) { + if (pk->params[0] != 1 && std::get<0>(g_Data.getCustomGeoOverride())) { // Dialog Canceled, reset geo + auto box = g_Data.addInfoBox("Geometry reset", "Geometry override removed"); + box->closeTimer = 1; + return; + } + + wchar_t* jsonData = reinterpret_cast(pk->data.get()); + std::wstring jsonDataStr(jsonData); + + json parsed = json::parse(jsonDataStr); + if (parsed["path"].is_string()) { + auto box = g_Data.addInfoBox("Importing Skin", "Please wait..."); + std::thread gamer([parsed, box]() { + SkinUtil::importGeo(Utils::stringToWstring(parsed["path"].get())); + box->fadeTarget = 0; + }); + gamer.detach(); + } + }); + + g_Data.sendPacketToInjector(packet); + } + if (HImGui.Button("Custom Texture", vec2_t(wid.x * 0.5f, wid.y * 0.92f), true)) { + HorionDataPacket packet; + packet.cmd = CMD_FILECHOOSER; + auto tmp = std::shared_ptr(new unsigned char[500]); + packet.data.swap(tmp); + memset(packet.data.get(), 0, 500); + strcpy_s((char*)packet.data.get(), 400, "{\"title\": \"Select a raw image file\", \"filter\":\"Raw image files (*.data, *.raw)|*.data;*.raw\"}"); + packet.dataArraySize = (int)strlen((char*)packet.data.get()); + packet.params[0] = g_Data.addInjectorResponseCallback([](std::shared_ptr pk) { + if (pk->params[0] != 1 && std::get<0>(g_Data.getCustomTextureOverride())) { // Dialog Canceled, reset texture + auto box = g_Data.addInfoBox("Texture reset", "Texture override removed"); + box->closeTimer = 1; + return; + } + + wchar_t* jsonData = reinterpret_cast(pk->data.get()); + std::wstring jsonDataStr(jsonData); + + json parsed = json::parse(jsonDataStr); + if (parsed["path"].is_string()) { + auto box = g_Data.addInfoBox("Importing texture...", ""); + std::thread gamer([parsed, box]() { + auto contents = Utils::readFileContents(Utils::stringToWstring(parsed["path"].get())); + if (contents.size() > 0) { + auto texturePtr = std::shared_ptr(new unsigned char[contents.size() + 1]); + memcpy(texturePtr.get(), contents.c_str(), contents.size()); + texturePtr.get()[contents.size()] = 0; + g_Data.setCustomTextureOverride(true, std::make_shared, size_t>>(texturePtr, contents.size())); + box->title = "Success"; + box->closeTimer = 0.3f; + } else { + box->title = "Error!"; + box->message = "Could not read texture file (empty?)"; + box->closeTimer = 2.f; + } + }); + gamer.detach(); + } + }); + + g_Data.sendPacketToInjector(packet); + } + } + } else { + shouldRenderTabGui = hudModule->tabgui && hudModule->isEnabled(); + shouldRenderArrayList = hudModule->arraylist && hudModule->isEnabled(); + shouldRenderWatermark = hudModule->watermark && hudModule->isEnabled(); + + if (clickGuiModule->isEnabled()) { + ClickGui::render(); + shouldPostRender = false; + shouldRenderArrayList = false; + shouldRenderTabGui = false; + shouldRenderWatermark = false; + } + + if (shouldRenderTabGui) TabGui::render(); + + { + // Display ArrayList on the Right? + static constexpr bool isOnRightSide = true; + + float yOffset = 0; // Offset of next Text + vec2_t windowSize = g_Data.getClientInstance()->getGuiData()->windowSize; + vec2_t windowSizeReal = g_Data.getClientInstance()->getGuiData()->windowSizeReal; + + vec2_t mousePos = *g_Data.getClientInstance()->getMousePos(); + mousePos.div(windowSizeReal); + mousePos.mul(windowSize); + + // Draw Horion logo + if (shouldRenderWatermark) { + constexpr float nameTextSize = 1.5f; + constexpr float versionTextSize = 0.7f; + static const float textHeight = (nameTextSize + versionTextSize * 0.7f /* We don't quite want the version string in its own line, just a bit below the name */) * DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight(); + constexpr float borderPadding = 1; + constexpr float margin = 5; + + static std::string name = "Horion"; +#ifdef _DEBUG + static std::string version = "dev"; +#elif defined _BETA + static std::string version = "beta"; +#else + static std::string version = "public"; +#endif + + float nameLength = DrawUtils::getTextWidth(&name, nameTextSize); + float fullTextLength = nameLength + DrawUtils::getTextWidth(&version, versionTextSize); + vec4_t rect = vec4_t( + windowSize.x - margin - fullTextLength - borderPadding * 2, + windowSize.y - margin - textHeight, + windowSize.x - margin + borderPadding, + windowSize.y - margin); + + DrawUtils::drawRectangle(rect, MC_Color(rcolors), 1.f, 2.f); + DrawUtils::fillRectangle(rect, MC_Color(12, 12, 12), 1.f); + DrawUtils::drawText(vec2_t(rect.x + borderPadding, rect.y), &name, MC_Color(rcolors), nameTextSize); + DrawUtils::drawText(vec2_t(rect.x + borderPadding + nameLength, rect.w - 7), &version, MC_Color(rcolors), versionTextSize); + } + + // Draw ArrayList + if (moduleMgr->isInitialized() && shouldRenderArrayList) { + // Parameters + float textSize = hudModule->scale; + float textPadding = 1.0f * textSize; + float textHeight = 10.0f * textSize; + float smoothness = 2; + + struct IModuleContainer { + // Struct used to Sort IModules in a std::set + std::shared_ptr backingModule; + std::string moduleName; + bool enabled; + int keybind; + float textWidth; + vec2_t* pos; + bool shouldRender = true; + + IModuleContainer(std::shared_ptr mod) { + const char* moduleNameChr = mod->getModuleName(); + this->enabled = mod->isEnabled(); + this->keybind = mod->getKeybind(); + this->backingModule = mod; + this->pos = mod->getPos(); + + if (keybind == 0x0) + moduleName = moduleNameChr; + else { + char text[50]; + sprintf_s(text, 50, "%s%s", moduleNameChr, hudModule->keybinds ? std::string(" [" + std::string(Utils::getKeybindName(keybind)) + "]").c_str() : ""); + moduleName = text; + } + + if (!this->enabled && *this->pos == vec2_t(0.f, 0.f)) + this->shouldRender = false; + this->textWidth = DrawUtils::getTextWidth(&moduleName, hudModule->scale); + } + + bool operator<(const IModuleContainer& other) const { + /*if (enabled) { + if (!other.enabled) // We are enabled + return true; + } else if (other.enabled) // They are enabled + return false;*/ + + if (this->textWidth == other.textWidth) + return moduleName < other.moduleName; + return this->textWidth > other.textWidth; + } + }; + + // Mouse click detector + static bool wasLeftMouseDown = GameData::isLeftClickDown(); // Last isDown value + bool leftMouseDown = GameData::isLeftClickDown(); // current isDown value + + bool executeClick = leftMouseDown && leftMouseDown != wasLeftMouseDown; // isDown == true AND (current state IS NOT last state) + wasLeftMouseDown = leftMouseDown; // Set last isDown value + + std::set modContainerList; + // Fill modContainerList with Modules + { + auto lock = moduleMgr->lockModuleList(); + std::vector>* moduleList = moduleMgr->getModuleList(); + for (auto it : *moduleList) { + if (it.get() != hudModule) + modContainerList.emplace(IModuleContainer(it)); + } + } + + int a = 0; + int b = 0; + int c = 0; + + // Loop through mods to display Labels + for (std::set::iterator it = modContainerList.begin(); it != modContainerList.end(); ++it) { + if (!it->shouldRender) + continue; + + std::string textStr = it->moduleName; + float textWidth = it->textWidth; + + float xOffsetOri = windowSize.x - textWidth - (textPadding * 2); + + float xOffset = windowSize.x - it->pos->x; + + it->pos->x += smoothness; + + if (xOffset < xOffsetOri) { + xOffset = xOffsetOri; + } + if (!it->enabled) { + xOffset += it->pos->y; + it->pos->y += smoothness; + } + if (xOffset >= windowSize.x && !it->enabled) { + it->pos->x = 0.f; + it->pos->y = 0.f; + } + + vec2_t textPos = vec2_t( + xOffset + textPadding, + yOffset + textPadding); + vec4_t rectPos = vec4_t( + xOffset - 2, + yOffset, + isOnRightSide ? windowSize.x : textWidth + (textPadding * 2), + yOffset + textPadding * 2 + textHeight); + vec4_t leftRect = vec4_t( + xOffset - 2, + yOffset, + xOffset - 1, + yOffset + textPadding * 2 + textHeight); + c++; + b++; + if (b < 20) + a = moduleMgr->getEnabledModuleCount() * 2; + else + b = 0; + currColor[3] = rcolors[3]; + Utils::ColorConvertRGBtoHSV(rcolors[0], rcolors[1], rcolors[2], currColor[0], currColor[1], currColor[2]); + currColor[0] += 1.f / a * c; + Utils::ColorConvertHSVtoRGB(currColor[0], currColor[1], currColor[2], currColor[0], currColor[1], currColor[2]); + + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), 1.f); + DrawUtils::fillRectangle(leftRect, MC_Color(currColor), 1.f); + if (!GameData::canUseMoveKeys() && rectPos.contains(&mousePos) && hudModule->clickToggle) { + vec4_t selectedRect = rectPos; + selectedRect.x = leftRect.z; + if (leftMouseDown) { + DrawUtils::fillRectangle(selectedRect, MC_Color(0.8f, 0.8f, 0.8f), 0.8f); + if (executeClick) + it->backingModule->toggle(); + } else + DrawUtils::fillRectangle(selectedRect, MC_Color(0.8f, 0.8f, 0.8f, 0.8f), 0.3f); + } + DrawUtils::drawText(textPos, &textStr, MC_Color(currColor), textSize); + + yOffset += textHeight + (textPadding * 2); + } + c = 0; + modContainerList.clear(); + } + } + } + } + + // Zoom calc + { + static auto zoomModule = moduleMgr->getModule(); + if (zoomModule->isEnabled()) zoomModule->target = zoomModule->strength; + zoomModule->modifier = zoomModule->target - ((zoomModule->target - zoomModule->modifier) * 0.8f); + if (abs(zoomModule->modifier - zoomModule->target) < 0.1f && !zoomModule->isEnabled()) + zoomModule->zooming = false; + } + + if (shouldPostRender) moduleMgr->onPostRender(renderCtx); + HImGui.endFrame(); + DrawUtils::flush(); + + // Draw Info / Alert Boxes + { + auto box = g_Data.getFreshInfoBox(); + if (box) { + box->fade(); + if (box->fadeTarget == 1 && box->closeTimer <= 0 && box->closeTimer > -1) + box->fadeTarget = 0; + else if (box->closeTimer > 0 && box->fadeVal > 0.9f) + box->closeTimer -= 1.f / 60; + const float paddingHoriz = 40 * box->fadeVal; + const float paddingVert = 10 * box->fadeVal; + const float titleTextSize = box->fadeVal * 2; + const float messageTextSize = box->fadeVal * 1; + const float titleTextHeight = DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() * titleTextSize; + + int lines = 1; + std::string substring = box->message; + while (lines < 5) { + auto brea = substring.find("\n"); + if (brea == std::string::npos || brea + 1 >= substring.size()) + break; + substring = substring.substr(brea + 1); + lines++; + } + if (box->message.size() == 0) + lines = 0; + + const float messageHeight = DrawUtils::getFont(Fonts::SMOOTH)->getLineHeight() * messageTextSize * lines; + + float titleWidth = DrawUtils::getTextWidth(&box->title, titleTextSize); + float msgWidth = DrawUtils::getTextWidth(&box->message, messageTextSize); + vec2_t centerPos(wid.x / 2.f, wid.y / 9.f); + vec2_t textPos = vec2_t(wid.x / 2.f - titleWidth / 2.f, wid.y / 9.f); + vec2_t msgPos = vec2_t(wid.x / 2.f - msgWidth / 2.f, textPos.y + titleTextHeight + paddingVert); + vec4_t rectPos = vec4_t( + centerPos.x - paddingHoriz - std::max(titleWidth, msgWidth) / 2, + centerPos.y - paddingVert, + centerPos.x + paddingHoriz + std::max(titleWidth, msgWidth) / 2, + centerPos.y + paddingVert * 2 + titleTextHeight + messageHeight * lines); + DrawUtils::fillRectangle(rectPos, MC_Color(12, 12, 12), box->fadeVal); + DrawUtils::drawRectangle(rectPos, rcolors, box->fadeVal, 2.f); + DrawUtils::drawText(textPos, &box->title, MC_Color(), titleTextSize, box->fadeVal); + DrawUtils::drawText(msgPos, &box->message, MC_Color(), messageTextSize, box->fadeVal); + } + } + DrawUtils::flush(); + + return retval; +} + +float* Hooks::Dimension_getFogColor(__int64 _this, float* color, __int64 a3, float a4) { + static auto oGetFogColor = g_Hooks.Dimension_getFogColorHook->GetFastcall(); + + static float rcolors[4]; + + static auto nightMod = moduleMgr->getModule(); + if (nightMod->isEnabled()) { + color[0] = 0.f; + color[1] = 0.f; + color[2] = 0.2f; + color[3] = 1; + return color; + } + + static auto rainbowSkyMod = moduleMgr->getModule(); + if (rainbowSkyMod->isEnabled()) { + if (rcolors[3] < 1) { + rcolors[0] = 1; + rcolors[1] = 0.2f; + rcolors[2] = 0.2f; + rcolors[3] = 1; + } + + Utils::ColorConvertRGBtoHSV(rcolors[0], rcolors[1], rcolors[2], rcolors[0], rcolors[1], rcolors[2]); // perfect code, dont question this + + rcolors[0] += 0.001f; + if (rcolors[0] >= 1) + rcolors[0] = 0; + + Utils::ColorConvertHSVtoRGB(rcolors[0], rcolors[1], rcolors[2], rcolors[0], rcolors[1], rcolors[2]); + + return rcolors; + } + return oGetFogColor(_this, color, a3, a4); +} + +float Hooks::Dimension_getTimeOfDay(__int64 _this, int a2, float a3) { + static auto oGetTimeOfDay = g_Hooks.Dimension_getTimeOfDayHook->GetFastcall(); + + static auto timeChange = moduleMgr->getModule(); + if (timeChange->isEnabled()) { + return timeChange->modifier; + } + + return oGetTimeOfDay(_this, a2, a3); +} + +float Hooks::Dimension_getSunIntensity(__int64 a1, float a2, vec3_t* a3, float a4) { + static auto oGetSunIntensity = g_Hooks.Dimension_getSunIntensityHook->GetFastcall(); + + static auto nightMod = moduleMgr->getModule(); + if (nightMod->isEnabled()) { + return -0.5f; + } + + return oGetSunIntensity(a1, a2, a3, a4); +} + +void Hooks::ChestBlockActor_tick(C_ChestBlockActor* _this, void* a) { + static auto oTick = g_Hooks.ChestBlockActor_tickHook->GetFastcall(); + oTick(_this, a); + static auto* storageEspMod = moduleMgr->getModule(); + if (_this != nullptr && storageEspMod->isEnabled()) + GameData::addChestToList(_this); +} + +void Hooks::Actor_lerpMotion(C_Entity* _this, vec3_t motVec) { + static auto oLerp = g_Hooks.Actor_lerpMotionHook->GetFastcall(); + + if (g_Data.getLocalPlayer() != _this) + return oLerp(_this, motVec); + + static auto noKnockbackmod = moduleMgr->getModule(); + if (noKnockbackmod->isEnabled()) { + static void* networkSender = nullptr; + if (!networkSender) + networkSender = reinterpret_cast(9 + FindSignature("48 8B CB FF ?? ?? ?? ?? 00 C6 47 ?? 01 48 8B 5C 24")); + + if (networkSender == _ReturnAddress()) { + motVec = _this->velocity.lerp(motVec, noKnockbackmod->xModifier, noKnockbackmod->yModifier, noKnockbackmod->xModifier); + } + } + + oLerp(_this, motVec); +} + +int Hooks::AppPlatform_getGameEdition(__int64 _this) { + static auto oGetEditon = g_Hooks.AppPlatform_getGameEditionHook->GetFastcall(); + + static auto mod = moduleMgr->getModule(); + if (mod->isEnabled()) { + return mod->getFakedEditon(); + } + + return oGetEditon(_this); +} + +void Hooks::PleaseAutoComplete(__int64 a1, __int64 a2, TextHolder* text, int a4) { + static auto oAutoComplete = g_Hooks.PleaseAutoCompleteHook->GetFastcall(); + char* tx = text->getText(); + + using syncShit_t = void(__fastcall*)(__int64*, TextHolder*); + static syncShit_t syncShit = nullptr; + if (syncShit == nullptr) { + uintptr_t sigOffset = 0; + // sig of function: (present 3 times in the exe) + sigOffset = FindSignature("48 8B D7 48 8B 8B ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B 9C") + 11; + auto funcOffset = *reinterpret_cast(sigOffset); + sigOffset += 4 + funcOffset; + + syncShit = reinterpret_cast(sigOffset); + } + + if (tx != nullptr && text->getTextLength() >= 1 && tx[0] == '.') { + std::string search = tx + 1; // Dont include the '.' + std::transform(search.begin(), search.end(), search.begin(), ::tolower); // make the search text lowercase + + struct LilPlump { + std::string cmdAlias; + IMCCommand* command = 0; + bool shouldReplace = true; // Should replace the current text in the box (autocomplete) + + bool operator<(const LilPlump& o) const { + return cmdAlias < o.cmdAlias; + } + }; // This is needed so the std::set sorts it alphabetically + + std::set searchResults; + + std::vector* commandList = cmdMgr->getCommandList(); + for (auto it = commandList->begin(); it != commandList->end(); ++it) { // Loop through commands + IMCCommand* c = *it; + auto* aliasList = c->getAliasList(); + for (auto it = aliasList->begin(); it != aliasList->end(); ++it) { // Loop through aliases + std::string cmd = *it; + LilPlump plump; + + for (size_t i = 0; i < search.size(); i++) { // Loop through search string + char car = search.at(i); + if (car == ' ' && i == cmd.size()) { + plump.shouldReplace = false; + break; + } else if (i >= cmd.size()) + goto outerContinue; + + if (car != cmd.at(i)) // and compare + goto outerContinue; + } + // Not at outerContinue? Then we got a good result! + { + cmd.insert(0, 1, '.'); // Prepend the '.' + + plump.cmdAlias = cmd; + plump.command = c; + searchResults.emplace(plump); + } + + outerContinue: + continue; + } + } + + if (!searchResults.empty()) { + LilPlump firstResult = *searchResults.begin(); + + size_t maxReplaceLength = firstResult.cmdAlias.size(); + if (searchResults.size() > 1) { + for (auto it = searchResults.begin()++; it != searchResults.end(); it++) { + auto alias = it->cmdAlias; + maxReplaceLength = std::min(maxReplaceLength, alias.size()); + + for (int i = 0; i < maxReplaceLength; i++) { + if (alias[i] != firstResult.cmdAlias[i]) { + maxReplaceLength = i; + break; + } + } + } + } else + maxReplaceLength = firstResult.cmdAlias.size(); + + g_Data.getGuiData()->displayClientMessageF("=========="); + if (searchResults.size() > 1) { + for (auto it = searchResults.begin(); it != searchResults.end(); ++it) { + LilPlump plump = *it; + g_Data.getGuiData()->displayClientMessageF("%s%s - %s%s", plump.cmdAlias.c_str(), GRAY, ITALIC, plump.command->getDescription()); + } + } + if (firstResult.command->getUsage(firstResult.cmdAlias.c_str() + 1)[0] == 0) + g_Data.getGuiData()->displayClientMessageF("%s%s %s- %s", WHITE, firstResult.cmdAlias.c_str(), GRAY, firstResult.command->getDescription()); + else + g_Data.getGuiData()->displayClientMessageF("%s%s %s %s- %s", WHITE, firstResult.cmdAlias.c_str(), firstResult.command->getUsage(firstResult.cmdAlias.c_str() + 1 /*exclude prefix*/), GRAY, firstResult.command->getDescription()); + + if (firstResult.shouldReplace) { + if (search.size() == firstResult.cmdAlias.size() - 1 && searchResults.size() == 1) { + maxReplaceLength++; + firstResult.cmdAlias.append(" "); + } + + text->setText(firstResult.cmdAlias.substr(0, maxReplaceLength)); // Set text + // now sync with the UI thread + syncShit(0, text); + } + } + + return; + } + oAutoComplete(a1, a2, text, a4); +} + +void Hooks::LoopbackPacketSender_sendToServer(C_LoopbackPacketSender* a, C_Packet* packet) { + static auto oFunc = g_Hooks.LoopbackPacketSender_sendToServerHook->GetFastcall(); + + static auto autoSneakMod = moduleMgr->getModule(); + static auto freecamMod = moduleMgr->getModule(); + static auto blinkMod = moduleMgr->getModule(); + static auto noPacketMod = moduleMgr->getModule(); + + if (noPacketMod->isEnabled() && g_Data.isInGame()) + return; + + if (freecamMod->isEnabled() || blinkMod->isEnabled()) { + if (packet->isInstanceOf() || packet->isInstanceOf()) { + if (blinkMod->isEnabled()) { + if (packet->isInstanceOf()) { + C_MovePlayerPacket* meme = reinterpret_cast(packet); + meme->onGround = true; //Don't take Fall Damages when turned off + blinkMod->getMovePlayerPacketHolder()->push_back(new C_MovePlayerPacket(*meme)); // Saving the packets + } else { + blinkMod->getPlayerAuthInputPacketHolder()->push_back(new PlayerAuthInputPacket(*reinterpret_cast(packet))); + } + } + return; // Dont call LoopbackPacketSender_sendToServer + } + } else if (!blinkMod->isEnabled()) { + if (blinkMod->getMovePlayerPacketHolder()->size() > 0) { + for (auto it : *blinkMod->getMovePlayerPacketHolder()) { + oFunc(a, (it)); + delete it; + it = nullptr; + } + blinkMod->getMovePlayerPacketHolder()->clear(); + return; + } + if (blinkMod->getPlayerAuthInputPacketHolder()->size() > 0) { + for (auto it : *blinkMod->getPlayerAuthInputPacketHolder()) { + oFunc(a, (it)); + delete it; + it = nullptr; + } + blinkMod->getPlayerAuthInputPacketHolder()->clear(); + return; + } + } + + if (autoSneakMod->isEnabled() && g_Data.getLocalPlayer() != nullptr && autoSneakMod->doSilent && packet->isInstanceOf()) { + auto* pp = reinterpret_cast(packet); + + if (pp->action == 12 && pp->entityRuntimeId == g_Data.getLocalPlayer()->entityRuntimeId) + return; //dont send uncrouch + } + + moduleMgr->onSendPacket(packet); + + /*if (strcmp(packet->getName()->getText(), "EmotePacket") == 0) { + auto varInt = reinterpret_cast<__int64*>(reinterpret_cast<__int64>(packet) + 0x28); + auto text = reinterpret_cast(reinterpret_cast<__int64>(packet) + 0x30); + auto bet = reinterpret_cast(reinterpret_cast<__int64>(packet) + 0x50); + logF("emote %llX %s %i", *varInt, text->getText(), *bet); + } fix emote crashing*/ + + oFunc(a, packet); +} + +float Hooks::LevelRendererPlayer_getFov(__int64 _this, float a2, bool a3) { + static auto oGetFov = g_Hooks.LevelRendererPlayer_getFovHook->GetFastcall(); + static void* renderItemInHand = reinterpret_cast(FindSignature("F3 0F 59 05 ?? ?? ?? ?? 45 0F 28 C2 F3")); + + static void* setupCamera = reinterpret_cast(FindSignature("0F 28 F8 F3 0F 59 3D ?? ?? ?? ?? F3 0F 11 7C 24 24 F3 0F 10 87")); + + static auto zoomModule = moduleMgr->getModule(); + + if (_ReturnAddress() == renderItemInHand) { + return oGetFov(_this, a2, a3); + } + if (_ReturnAddress() == setupCamera) { + g_Data.fov = -oGetFov(_this, a2, a3) + 110.f; + if (moduleMgr->isInitialized()) { + if (!zoomModule->smooth && zoomModule->isEnabled()) return -zoomModule->target + 110.f; + if (zoomModule->smooth && zoomModule->zooming) return -zoomModule->modifier + 110.f; + } + return oGetFov(_this, a2, a3); + } +#ifdef _DEBUG + logF("LevelRendererPlayer_getFov Return Address: %llX", _ReturnAddress()); + __debugbreak(); // IF we reach here, a sig is broken +#endif + return oGetFov(_this, a2, a3); +} + +void Hooks::MultiLevelPlayer_tick(C_EntityList* _this) { + static auto oTick = g_Hooks.MultiLevelPlayer_tickHook->GetFastcall(); + oTick(_this); + GameData::EntityList_tick(_this); +} + +void Hooks::GameMode_startDestroyBlock(C_GameMode* _this, vec3_ti* a2, uint8_t face, void* a4, void* a5) { + static auto oFunc = g_Hooks.GameMode_startDestroyBlockHook->GetFastcall(); + + static auto nukerModule = moduleMgr->getModule(); + static auto instaBreakModule = moduleMgr->getModule(); + + if (nukerModule->isEnabled()) { + vec3_ti tempPos; + + int range = nukerModule->getNukerRadius(); + const bool isVeinMiner = nukerModule->isVeinMiner(); + const bool isAutoMode = nukerModule->isAutoMode(); + + C_BlockSource* region = g_Data.getLocalPlayer()->region; + auto selectedBlockId = ((region->getBlock(*a2)->blockLegacy))->blockId; + uint8_t selectedBlockData = region->getBlock(*a2)->data; + + if (!isAutoMode) { + for (int x = -range; x < range; x++) { + for (int y = -range; y < range; y++) { + for (int z = -range; z < range; z++) { + tempPos.x = a2->x + x; + tempPos.y = a2->y + y; + tempPos.z = a2->z + z; + if (tempPos.y > 0) { + C_Block* blok = region->getBlock(tempPos); + uint8_t data = blok->data; + auto id = blok->blockLegacy->blockId; + if (blok->blockLegacy->material->isSolid == true && (!isVeinMiner || (id == selectedBlockId && data == selectedBlockData))) + _this->destroyBlock(&tempPos, face); + } + } + } + } + } + return; + } + if (instaBreakModule->isEnabled()) { + _this->destroyBlock(a2, face); + return; + } + + oFunc(_this, a2, face, a4, a5); +} + +void Hooks::HIDController_keyMouse(C_HIDController* _this, void* a2, void* a3) { + static auto oFunc = g_Hooks.HIDController_keyMouseHook->GetFastcall(); + GameData::setHIDController(_this); + isTicked = true; + oFunc(_this, a2, a3); + return; +} + +int Hooks::BlockLegacy_getRenderLayer(C_BlockLegacy* a1) { + static auto oFunc = g_Hooks.BlockLegacy_getRenderLayerHook->GetFastcall(); + + static auto xrayMod = moduleMgr->getModule(); + if (xrayMod->isEnabled()) { + char* text = a1->name.getText(); + if (strstr(text, "ore") == NULL) + if (strcmp(text, "lava") != NULL) + if (strcmp(text, "water") != NULL) + if (strcmp(text, "portal") != NULL) + if (strcmp(text, "amethyst_block") != NULL) + if (strcmp(text, "ancient_debris") != NULL) + if (strcmp(text, "command_block") != NULL) + if (strcmp(text, "repeating_command_block") != NULL) + if (strcmp(text, "chain_command_block") != NULL) + if (strcmp(text, "structure_block") != NULL) + if (strcmp(text, "deny") != NULL) + if (strcmp(text, "allow") != NULL) + if (strcmp(text, "bedrock") != NULL) + if (strcmp(text, "border_block") != NULL) + return 10; + } + return oFunc(a1); +} + +__int8* Hooks::BlockLegacy_getLightEmission(C_BlockLegacy* a1, __int8* a2) { + static auto oFunc = g_Hooks.BlockLegacy_getLightEmissionHook->GetFastcall<__int8*, C_BlockLegacy*, __int8*>(); + + static auto xrayMod = moduleMgr->getModule(); + if (xrayMod->isEnabled()) { + *a2 = 15; + return a2; + } + return oFunc(a1, a2); +} + +__int64 Hooks::LevelRenderer_renderLevel(__int64 _this, __int64 a2, __int64 a3) { + static auto oFunc = g_Hooks.LevelRenderer_renderLevelHook->GetFastcall<__int64, __int64, __int64, __int64>(); + + using reloadShit_t = void(__fastcall*)(__int64); + static reloadShit_t reloadChunk = nullptr; + + if (!reloadChunk) { + // RenderChunkCoordinator::rebuildAllRenderChunkGeometry + reloadChunk = reinterpret_cast(FindSignature("48 89 5C 24 10 48 89 6C 24 18 48 89 74 24 20 57 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 48 8B F9 48 8D A9")); + } + + static auto xrayMod = moduleMgr->getModule(); + + static bool lastState = false; + if (lastState != xrayMod->isEnabled()) { + // LevelRenderer::rebuildAllRenderChunkGeometry + lastState = xrayMod->isEnabled(); + unsigned long long* v5; // rdi + unsigned long long* i; // rbx + + v5 = *(unsigned long long**)(_this + 32); + for (i = (unsigned long long*)*v5; i != v5; i = (unsigned long long*)*i) + reloadChunk(i[3]); + } + + auto ret = oFunc(_this, a2, a3); + + DrawUtils::setGameRenderContext(a2); + moduleMgr->onLevelRender(); + DrawUtils::setGameRenderContext(0); + + return ret; +} + +void Hooks::ClickFunc(__int64 a1, char mouseButton, char isDown, __int16 mouseX, __int16 mouseY, __int16 relativeMovementX, __int16 relativeMovementY, char a8) { + static auto oFunc = g_Hooks.ClickFuncHook->GetFastcall(); + static auto clickGuiModule = moduleMgr->getModule(); + + //MouseButtons + //0 = mouse move + //1 = left click + //2 = right click + //3 = middle click + //4 = scroll (isDown: 120 (SCROLL UP) and -120 (SCROLL DOWN)) + + ClickGui::onMouseClickUpdate((int)mouseButton, isDown); + HImGui.onMouseClickUpdate((int)mouseButton, isDown); + + if (isDown) + if (mouseButton == 1) + g_Data.leftclickCount++; + else if (mouseButton == 2) + g_Data.rightclickCount++; + + if (clickGuiModule->isEnabled()) { + if (mouseButton == 4) { + ClickGui::onWheelScroll(isDown > 0); + } + if (mouseButton != 0) // Mouse click event + return; + } + return oFunc(a1, mouseButton, isDown, mouseX, mouseY, relativeMovementX, relativeMovementY, a8); +} + +__int64 Hooks::MoveInputHandler_tick(C_MoveInputHandler* a1, C_Entity* a2) { + static auto oTick = g_Hooks.MoveInputHandler_tickHook->GetFastcall<__int64, C_MoveInputHandler*, C_Entity*>(); + + auto ret = oTick(a1, a2); + moduleMgr->onMove(a1); + + return 0; +} + +__int64 Hooks::ChestScreenController_tick(C_ChestScreenController* a1) { + static auto oFunc = g_Hooks.ChestScreenController_tickHook->GetFastcall<__int64, C_ChestScreenController*>(); + + static auto chestStealerMod = moduleMgr->getModule(); + if (chestStealerMod->isEnabled()) chestStealerMod->chestScreenController_tick(a1); + + return oFunc(a1); +} + +float Hooks::GetGamma(uintptr_t* a1) { + static auto fullbright = moduleMgr->getModule(); + static auto xrayMod = moduleMgr->getModule(); + static auto nametagmod = moduleMgr->getModule(); + + uintptr_t** list = (uintptr_t**)a1; + + char obtainedSettings = 0; + bool hadIt = false; + for (uint16_t i = 3; i < 450; i++) { + if (list[i] == nullptr) continue; + uintptr_t* info = *(uintptr_t**)((uintptr_t)list[i] + 8); + if (info == nullptr) continue; + + TextHolder* translateName = (TextHolder*)((uintptr_t)info + 0x1D8); + TextHolder* settingname = (TextHolder*)((uintptr_t)info + 0x188); + + if (!strcmp(translateName->getText(), "options.smoothlighting")) { + if (hadIt) continue; + bool* smoothlightning = (bool*)((uintptr_t)list[i] + 16); + xrayMod->smoothLightningSetting = smoothlightning; + obtainedSettings++; + hadIt = true; + } else if (!strcmp(settingname->getText(), "gfx_ingame_player_names")) { + bool* ingamePlayerName = (bool*)((uintptr_t)list[i] + 16); + nametagmod->ingameNametagSetting = ingamePlayerName; + obtainedSettings++; + } + + if (obtainedSettings == 2) break; + } + + if (xrayMod->isEnabled()) + return 25.f; + + if (fullbright->isEnabled()) + return fullbright->intensity; + + static auto ofunc = g_Hooks.GetGammaHook->GetFastcall(); + return ofunc(a1); +} + +bool Hooks::Actor_isInWater(C_Entity* _this) { + static auto oFunc = g_Hooks.Actor_isInWaterHook->GetFastcall(); + + if (g_Data.getLocalPlayer() != _this) + return oFunc(_this); + + static auto airSwimModule = moduleMgr->getModule(); + if (airSwimModule->isEnabled()) + return true; + + return oFunc(_this); +} + +void Hooks::JumpPower(C_Entity* a1, float a2) { + static auto oFunc = g_Hooks.JumpPowerHook->GetFastcall(); + static auto highJumpMod = moduleMgr->getModule(); + if (highJumpMod->isEnabled() && g_Data.getLocalPlayer() == a1) { + a1->velocity.y = highJumpMod->jumpPower; + return; + } + oFunc(a1, a2); +} + +__int64 Hooks::MinecraftGame_onAppSuspended(__int64 _this) { + static auto oFunc = g_Hooks.MinecraftGame_onAppSuspendedHook->GetFastcall<__int64, __int64>(); + configMgr->saveConfig(); + return oFunc(_this); +} + +void Hooks::Actor_ascendLadder(C_Entity* _this) { + static auto oFunc = g_Hooks.Actor_ascendLadderHook->GetFastcall(); + + static auto fastLadderModule = moduleMgr->getModule(); + if (fastLadderModule->isEnabled() && g_Data.getLocalPlayer() == _this) { + _this->velocity.y = fastLadderModule->speed; + return; + } + return oFunc(_this); +} + +void Hooks::Actor_swing(C_Entity* _this) { + static auto oFunc = g_Hooks.Actor_swingHook->GetFastcall(); + static auto noSwingMod = moduleMgr->getModule(); + if(!noSwingMod->isEnabled()) return oFunc(_this); +} + +void Hooks::Actor_startSwimming(C_Entity* _this) { + static auto oFunc = g_Hooks.Actor_startSwimmingHook->GetFastcall(); + + static auto jesusModule = moduleMgr->getModule(); + if (jesusModule->isEnabled() && g_Data.getLocalPlayer() == _this) + return; + + oFunc(_this); +} + +void Hooks::RakNetInstance_tick(C_RakNetInstance* _this, __int64 a2, __int64 a3) { + static auto oTick = g_Hooks.RakNetInstance_tickHook->GetFastcall(); + GameData::setRakNetInstance(_this); + oTick(_this, a2, a3); +} + +float Hooks::GameMode_getPickRange(C_GameMode* _this, __int64 a2, char a3) { + static auto oFunc = g_Hooks.GameMode_getPickRangeHook->GetFastcall(); + + if (g_Data.getLocalPlayer() != nullptr) { + static auto extendedBlockReachModule = moduleMgr->getModule(); + if (extendedBlockReachModule->isEnabled()) + return extendedBlockReachModule->getBlockReach(); + + static auto teleportModule = moduleMgr->getModule(); + if (teleportModule->isEnabled()) + return 255; + } + + return oFunc(_this, a2, a3); +} + +__int64 Hooks::ConnectionRequest_create(__int64 _this, __int64 privateKeyManager, void* a3, TextHolder* selfSignedId, TextHolder* serverAddress, __int64 clientRandomId, TextHolder* skinId, SkinData* skinData, __int64 capeData, CoolSkinData* coolSkinStuff, TextHolder* deviceId, int inputMode, int uiProfile, int guiScale, TextHolder* languageCode, bool sendEduModeParams, TextHolder* tenantId, __int64 unused, TextHolder* platformUserId, TextHolder* thirdPartyName, bool thirdPartyNameOnly, TextHolder* platformOnlineId, TextHolder* platformOfflineId, TextHolder* capeId) { + static auto oFunc = g_Hooks.ConnectionRequest_createHook->GetFastcall<__int64, __int64, __int64, void*, TextHolder*, TextHolder*, __int64, TextHolder*, SkinData*, __int64, CoolSkinData*, TextHolder*, int, int, int, TextHolder*, bool, TextHolder*, __int64, TextHolder*, TextHolder*, bool, TextHolder*, TextHolder*, TextHolder*>(); + + auto geoOverride = g_Data.getCustomGeoOverride(); + + if (g_Data.allowWIPFeatures()) { + logF("Connection Request: InputMode: %i UiProfile: %i GuiScale: %i", inputMode, uiProfile, guiScale); + + //Logger::WriteBigLogFileF(skinGeometryData->getTextLength() + 20, "Geometry: %s", skinGeometryData->getText()); + auto hResourceGeometry = FindResourceA((HMODULE)g_Data.getDllModule(), MAKEINTRESOURCEA(IDR_TEXT1), "TEXT"); + auto hMemoryGeometry = LoadResource((HMODULE)g_Data.getDllModule(), hResourceGeometry); + + auto sizeGeometry = SizeofResource((HMODULE)g_Data.getDllModule(), hResourceGeometry); + auto ptrGeometry = LockResource(hMemoryGeometry); + + auto hResourceSteve = FindResourceA((HMODULE)g_Data.getDllModule(), MAKEINTRESOURCEA(IDR_STEVE), (char*)RT_RCDATA); + auto hMemorySteve = LoadResource((HMODULE)g_Data.getDllModule(), hResourceSteve); + + auto sizeSteve = SizeofResource((HMODULE)g_Data.getDllModule(), hResourceSteve); + auto ptrSteve = LockResource(hMemorySteve); + + //std::unique_ptr newGeometryData(new TextHolder(ptrGeometry, sizeGeometry)); + TextHolder* newGeometryData = nullptr; + + if (std::get<0>(geoOverride)) { // Is overriding geometry + auto overrideGeo = std::get<1>(geoOverride); + newGeometryData = new TextHolder(*overrideGeo.get()); + } else { // Default Skin + /*char* str; // Obj text + { + auto hResourceObj = FindResourceA(g_Data.getDllModule(), MAKEINTRESOURCEA(IDR_OBJ), "TEXT"); + auto hMemoryObj = LoadResource(g_Data.getDllModule(), hResourceObj); + + auto sizeObj = SizeofResource(g_Data.getDllModule(), hResourceObj); + auto ptrObj = LockResource(hMemoryObj); + + str = new char[sizeObj + 1]; + memset(str, 0, sizeObj + 1); + memcpy(str, ptrObj, sizeObj); + } + + newGeometryData = new TextHolder(SkinUtil::modGeometry(reinterpret_cast(ptrGeometry), SkinUtil::objToMesh(str)));*/ + } + + SkinData* newSkinData = new SkinData(); + newSkinData->SkinWidth = 128; + newSkinData->SkinHeight = 128; + newSkinData->skinData = ptrSteve; + newSkinData->skinSize = sizeSteve; + + auto texOverride = g_Data.getCustomTextureOverride(); + auto texture = std::get<1>(texOverride); // Put it here so it won't go out of scope until after it has been used + if (std::get<0>(texOverride)) { // Enabled + newSkinData->skinData = std::get<0>(*texture.get()).get(); + newSkinData->skinSize = std::get<1>(*texture.get()); + } + + //Logger::WriteBigLogFileF(newGeometryData->getTextLength() + 20, "Geometry: %s", newGeometryData->getText()); + TextHolder* newSkinResourcePatch = new TextHolder(Utils::base64_decode("ewogICAiZ2VvbWV0cnkiIDogewogICAgICAiYW5pbWF0ZWRfZmFjZSIgOiAiZ2VvbWV0cnkuYW5pbWF0ZWRfZmFjZV9wZXJzb25hXzRjZGJiZmFjYTI0YTk2OGVfMF8wIiwKICAgICAgImRlZmF1bHQiIDogImdlb21ldHJ5LnBlcnNvbmFfNGNkYmJmYWNhMjRhOTY4ZV8wXzAiCiAgIH0KfQo=")); + + TextHolder* fakeName = g_Data.getFakeName(); + TextHolder resourcePatchBackup; + + if (newGeometryData != nullptr) { + memcpy(&resourcePatchBackup, &coolSkinStuff->skinResourcePatch, sizeof(TextHolder)); + memcpy(&coolSkinStuff->skinResourcePatch, newSkinResourcePatch, sizeof(TextHolder)); + styledReturnText = *newGeometryData; + overrideStyledReturn = true; + } + + // newGeometryData == nullptr ? skinResourcePatch : newSkinResourcePatch, newGeometryData == nullptr ? skinGeometryData : newGeometryData, skinAnimationData, isPremiumSkin, isPersonaSkin, + __int64 res = oFunc(_this, privateKeyManager, a3, selfSignedId, serverAddress, clientRandomId, skinId, (newGeometryData == nullptr && !std::get<0>(texOverride)) ? skinData : newSkinData, capeData, coolSkinStuff, deviceId, inputMode, uiProfile, guiScale, languageCode, sendEduModeParams, tenantId, unused, platformUserId, fakeName != nullptr ? fakeName : thirdPartyName, fakeName != nullptr ? true : thirdPartyNameOnly, platformOnlineId, platformOfflineId, capeId); + + if (newGeometryData != nullptr) { + memcpy(&coolSkinStuff->skinResourcePatch, &resourcePatchBackup, sizeof(TextHolder)); + resourcePatchBackup.resetWithoutDelete(); + } + overrideStyledReturn = false; + + styledReturnText = TextHolder(); + + if (hMemoryGeometry) + FreeResource(hMemoryGeometry); + if (hMemorySteve) + FreeResource(hMemorySteve); + + if (newGeometryData) + delete newGeometryData; + delete newSkinData; + delete newSkinResourcePatch; + return res; + } else { + TextHolder* fakeName = g_Data.getFakeName(); + __int64 res = oFunc(_this, privateKeyManager, a3, selfSignedId, serverAddress, clientRandomId, skinId, skinData, capeData, coolSkinStuff, deviceId, inputMode, uiProfile, guiScale, languageCode, sendEduModeParams, tenantId, unused, platformUserId, fakeName != nullptr ? fakeName : thirdPartyName, fakeName != nullptr ? true : thirdPartyNameOnly, platformOnlineId, platformOfflineId, capeId); + return res; + } +} + +void Hooks::InventoryTransactionManager_addAction(C_InventoryTransactionManager* a1, C_InventoryAction* a2) { + static auto Func = g_Hooks.InventoryTransactionManager_addActionHook->GetFastcall(); + Func(a1, a2); +} + +__int64 Hooks::PaintingRenderer__render(__int64 _this, __int64 a2, __int64 a3) { + static auto Func = g_Hooks.PaintingRenderer__renderHook->GetFastcall<__int64, __int64, __int64, __int64>(); + + static auto NoPaintingCrashMod = moduleMgr->getModule(); + if (NoPaintingCrashMod->isEnabled()) + return 0; + + return Func(_this, a2, a3); +} + +bool Hooks::DirectoryPackAccessStrategy__isTrusted(__int64 _this) { + static auto func = g_Hooks.DirectoryPackAccessStrategy__isTrustedHook->GetFastcall(); + + static uintptr_t** directoryPackAccessStrategyVtable = 0; + + if (!directoryPackAccessStrategyVtable) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 49 89 06 49 8D 76 50"); + int offset = *reinterpret_cast(sigOffset + 3); + directoryPackAccessStrategyVtable = reinterpret_cast(sigOffset + offset + 7); + } + + if (*reinterpret_cast(_this) == (uintptr_t)directoryPackAccessStrategyVtable) + return true; + + return func(_this); +} + +bool Hooks::ReturnTrue(__int64 _this) { + return true; +} + +__int64 Hooks::SkinRepository___loadSkinPack(__int64 _this, __int64 pack, __int64 a3) { + static auto func = g_Hooks.SkinRepository___loadSkinPackHook->GetFastcall<__int64, __int64, __int64, __int64>(); + + //auto res = (*(unsigned __int8 (**)(void))(**(__int64**)(pack + 8) + 48i64))(); + //logF("SkinRepository___loadSkinPack: origin %i, is Trusted: %i", *(int*)((*(__int64*)pack) + 888i64), res); + *(int*)((*(__int64*)pack) + 888i64) = 2; // Set pack origin to "2" + + return func(_this, pack, a3); +} + +GamerTextHolder* Hooks::toStyledString(__int64 strIn, GamerTextHolder* strOut) { + static auto func = g_Hooks.toStyledStringHook->GetFastcall(); + + static auto conRequest = reinterpret_cast<__int64>(g_Hooks.ConnectionRequest_createHook->funcPtr); + if (reinterpret_cast<__int64>(_ReturnAddress()) > conRequest && reinterpret_cast<__int64>(_ReturnAddress()) < conRequest + 10000 && overrideStyledReturn) { + // Return address is within boundaries of connection request function + + strOut->copyFrom(&styledReturnText); + + return strOut; + } + + return func(strIn, strOut); +} + +void prepCoolBean() { + if (g_Data.getClientInstance() && g_Data.getClientInstance()->minecraftGame->getServerEntries() && *reinterpret_cast<__int64*>(g_Data.getClientInstance()->minecraftGame->getServerEntries() + 0x50)) { + auto serverEntries = g_Data.getClientInstance()->minecraftGame->getServerEntries() + 0x48; + + struct ThirdPartyServer { + TextHolder serverName; + TextHolder uuid; + TextHolder masterPlayerAccount; + TextHolder serverName2; + TextHolder lobbyDescription; + TextHolder domain; // contains the last two parts of the domain .hivebedrock.network .mineplex.com + TextHolder pathToServerIcon; // C:\Users\user\AppData\Local\Packages\Microsoft.MinecraftUWP_8wekyb3d8bbwe\LocalCache\minecraftpe\ContentCache\ThirdPartyServer\\.jpg + TextHolder serverAddress; + int coolBoye; + + ThirdPartyServer() { + memset(this, 0, sizeof(ThirdPartyServer)); + } + }; + + struct BeansEntry { + BeansEntry* nextEntry; + BeansEntry* prevEntry; + TextHolder masterPlayer; + float unk; + char filler[0x3c]; + TextHolder masterPlayer2; + TextHolder serverName; + char filler2[8]; + std::shared_ptr* start; // array + std::shared_ptr* end; // end of array + }; + + auto listEnd = *reinterpret_cast(serverEntries); + + auto current = listEnd; + int count = 0; + while (listEnd != current->nextEntry) { + current = current->nextEntry; + count++; + } + if (count > 5) // we already added a server + goto end; + + // make new one + BeansEntry* epic = new BeansEntry(); + epic->nextEntry = listEnd; + epic->prevEntry = current; + epic->masterPlayer.setText(""); + epic->unk = current->unk; + memcpy(epic->filler, current->filler, sizeof(BeansEntry::filler)); + epic->masterPlayer2.setText(""); + epic->serverName.setText("Epic"); + memcpy(epic->filler2, current->filler2, sizeof(BeansEntry::filler2)); + + auto cT = current->start[0].get(); + + std::shared_ptr* start = new std::shared_ptr[1]; + + { + ThirdPartyServer* t = new ThirdPartyServer(); + + t->coolBoye = cT->coolBoye; + t->uuid.setText(""); + t->masterPlayerAccount = cT->masterPlayerAccount; + t->lobbyDescription = cT->lobbyDescription; + t->pathToServerIcon.setText(""); + t->serverName.setText("Horion Server"); + t->serverName2.setText("Horion Server"); // This is the one actually displayed + t->domain.setText(".horionbeta.club"); + t->serverAddress.setText("mc.horionbeta.club"); + start[0] = std::shared_ptr(t); + } + + epic->start = start; + epic->end = &start[1]; + + current->nextEntry = epic; + + // increase count + *reinterpret_cast<__int64*>(g_Data.getClientInstance()->minecraftGame->getServerEntries() + 0x50) += 1; + end:; + } +} + +__int64 Hooks::prepFeaturedServers(__int64 a1) { + static auto func = g_Hooks.prepFeaturedServersHook->GetFastcall<__int64, __int64>(); + auto ret = func(a1); + + if (g_Data.getClientInstance() == nullptr) + return ret; + + if (g_Data.allowWIPFeatures()) + prepCoolBean(); + + return ret; +} + +__int64 Hooks::prepFeaturedServersFirstTime(__int64 a1, __int64 a2) { + static auto func = g_Hooks.prepFeaturedServersFirstTimeHook->GetFastcall<__int64, __int64, __int64>(); + + if (g_Data.allowWIPFeatures()) + prepCoolBean(); + + auto ret = func(a1, a2); + + return ret; +} + + +__int64 Hooks::Cube__compile(__int64 a1, __int64 a2) { + auto func = g_Hooks.cube__compileHook->GetFastcall<__int64, __int64, __int64>(); + + auto ret = func(a1, a2); + + auto end = *reinterpret_cast<__int64*>(a1 + 0x38); + auto it = *reinterpret_cast<__int64*>(a1 + 0x30); + auto boi = it + 0x1C; + while (it != end) { // loop through PolygonQuad + if (it != boi + 0x34) { + auto iter2 = boi - 0xC; + do { + // PolygonQuad::compile + float* floatyBoi = reinterpret_cast(iter2 - 16); + logF("%.1f %.1f %.1f", floatyBoi[0], floatyBoi[1], floatyBoi[2]); + iter2 += 0x14; + } while (iter2 - 0x10 != boi + 0x34); + } + boi += 0x50; + it += 0x50; + } + + return ret; +} + +__int64 Hooks::InGamePlayScreen___renderLevel(__int64 playScreen, __int64 a2, __int64 a3) { + auto func = g_Hooks.InGamePlayScreen___renderLevelHook->GetFastcall<__int64, __int64, __int64, __int64>(); + return func(playScreen, a2, a3); +} +__int64 Hooks::GameMode_attack(C_GameMode* _this, C_Entity* ent) { + auto func = g_Hooks.GameMode_attackHook->GetFastcall<__int64, C_GameMode*, C_Entity*>(); + moduleMgr->onAttack(ent); + return func(_this, ent); +} +void Hooks::LocalPlayer__updateFromCamera(__int64 a1, C_Camera* camera) { + auto func = g_Hooks.LocalPlayer__updateFromCameraHook->GetFastcall<__int64, __int64, C_Camera*>(); + auto freelookMod = moduleMgr->getModule(); + auto noHurtcamMod = moduleMgr->getModule(); + + if (freelookMod->redirectMouse) { + freelookMod->cameraFacesFront = camera->facesPlayerFront; + freelookMod->isThirdPerson = camera->renderPlayerModel; + if (freelookMod->resetViewTick >= 0) { + camera->setOrientationDeg(freelookMod->lastCameraAngle.x, freelookMod->lastCameraAngle.y, 0); + } else { + camera->getPlayerRotation(&freelookMod->lastCameraAngle); + } + + return; + } + if (noHurtcamMod->isEnabled() && g_Data.isInGame() && g_Data.getLocalPlayer()->isAlive()) { + vec2_t rot; + camera->getPlayerRotation(&rot); + if (camera->facesPlayerFront) { + rot.x *= -1; // rotate back + rot.y += 180; + rot = rot.normAngles(); + } + + camera->setOrientationDeg(rot.x, rot.y + 180, 0); + } + + func(a1, camera); +} +bool Hooks::Mob__isImmobile(C_Entity* ent) { + auto func = g_Hooks.Mob__isImmobileHook->GetFastcall(); + + static auto antiImmobileMod = moduleMgr->getModule(); + if (antiImmobileMod->isEnabled() && ent == g_Data.getLocalPlayer()) + return false; + + return func(ent); +} +void Hooks::InventoryTransactionManager__addAction(C_InventoryTransactionManager* _this, C_InventoryAction& action) { + auto func = g_Hooks.InventoryTransactionManager__addActionHook->GetFastcall(); + +#ifdef TEST_DEBUG + char* srcName = "none"; + if (action.sourceItem.item && *action.sourceItem.item) + srcName = (*action.sourceItem.item)->name.getText(); + char* targetName = "none"; + if (action.targetItem.item && *action.targetItem.item) + targetName = (*action.targetItem.item)->name.getText(); + logF("%i %i %i %s %s", action.type, action.slot, action.sourceType, srcName, targetName, action.sourceType); + + /*if(/*action.slot == 14 && action.sourceType == 124 && strcmp(targetName, "none") == 0 && *strcmp(srcName, "stone_shovel") == 0){ + std::string tag = "{ench:[{id:9s,lvl:1s}]}"; + action.sourceItem.setUserData(std::move(Mojangson::parseTag(tag))); + } + if(/*action.slot == 2 && action.sourceType == 256 && strcmp(srcName, "none") == 0 &&* strcmp(targetName, "stone_shovel") == 0){ + std::string tag = "{ench:[{id:9s,lvl:1s}]}"; + action.targetItem.setUserData(std::move(Mojangson::parseTag(tag))); + }*/ +#endif + + func(_this, action); +} + +void Hooks::LevelRendererPlayer__renderNameTags(__int64 a1, __int64 a2, TextHolder* a3, __int64 a4) { + static auto func = g_Hooks.LevelRendererPlayer__renderNameTagsHook->GetFastcall(); + static auto nameTagsMod = moduleMgr->getModule(); + + if (nameTagsMod->isEnabled() && nameTagsMod->nameTags.size() > 0) { + std::string text = Utils::sanitize(a3->getText()); + std::size_t found = text.find('\n'); + + if (found != std::string::npos) + text = text.substr(0, found); + + if (nameTagsMod->nameTags.find(text) != nameTagsMod->nameTags.end()) + return; + } + + return func(a1, a2, a3, a4); +} diff --git a/Memory/Hooks.h b/Memory/Hooks.h new file mode 100644 index 0000000..87332c9 --- /dev/null +++ b/Memory/Hooks.h @@ -0,0 +1,224 @@ +#pragma once + +#ifndef PERFORMANCE_TEST +//#define PERFORMANCE_TEST +#endif + +#include "../Horion/Command/CommandMgr.h" +#include "../Horion/Config/ConfigManager.h" +#include "../Horion/DrawUtils.h" +#include "../Horion/ImmediateGui.h" +#include "../Horion/Menu/ClickGui.h" +#include "../Horion/Menu/TabGui.h" +#include "../Horion/Module/ModuleManager.h" +#include "../SDK/CBlockLegacy.h" +#include "../SDK/CCamera.h" +#include "../SDK/CChestBlockActor.h" +#include "../SDK/CGameMode.h" +#include "../SDK/CMinecraftUIRenderContext.h" +#include "../SDK/CMoveInputHandler.h" +#include "../SDK/CRakNetInstance.h" +#include "../SDK/CUIScene.h" +#include "../SDK/TextHolder.h" +#include "../Utils/SkinUtil.h" +#include "../Utils/TextFormat.h" +#include "../resource.h" +#include "GameData.h" +#include "MinHook.h" +//#include "../Horion/Game/Game.h" + +#include +#include +#include +#include + +#include + +class VMTHook; +class FuncHook; + +struct CoolSkinData { + TextHolder unknown; + TextHolder unknown2; + TextHolder skinResourcePatch; // 0x040 + TextHolder geometryName; // 0x060 "geometry.humanoid.custom" + unsigned char gap2[0x40]; // 0x080 + void* startAnimatedFrames; // 0x0C0 + void* endAnimatedFrames; // 0x0C8 + unsigned char gap3[0x8]; // 0x0D0 + TextHolder geometryData; // 0x0D8 + TextHolder skinAnimationData; // 0x0F8 + unsigned char gap4[0x20]; // 0x118 + bool isPremiumSkin; // 0x138 + bool isPersonaSkin; + bool isCapeOnClassicSkin; + void* startPersonaPieces; + void* endPersonaPieces; + unsigned char gap5[0x8]; // 0x150 + TextHolder armSize; // 0x158 + unsigned char gap6[0x8]; // 0x178 + void* startPieces; +}; + +class Hooks { +private: + bool shouldRender = true; + char currentScreenName[100]; + +public: + std::vector> lambdaHooks; + + static void Init(); + static void Restore(); + static void Enable(); + +private: + static void* Player_tickWorld(C_Player* _this, __int64); + static void ClientInstanceScreenModel_sendChatMessage(void* _this, TextHolder* text); + static __int64 UIScene_setupAndRender(C_UIScene* uiscene, __int64 screencontext); + static __int64 UIScene_render(C_UIScene* uiscene, __int64 screencontext); + static __int64 RenderText(__int64 a1, C_MinecraftUIRenderContext* renderCtx); + static float* Dimension_getFogColor(__int64, float* color, __int64 brightness, float a4); + static float Dimension_getTimeOfDay(__int64, int a2, float a3); + static float Dimension_getSunIntensity(__int64, float a2, vec3_t* a3, float a4); + static void ChestBlockActor_tick(C_ChestBlockActor*, void* a); + static void Actor_lerpMotion(C_Entity* _this, vec3_t); + static int AppPlatform_getGameEdition(__int64 _this); + static void PleaseAutoComplete(__int64 _this, __int64 a2, TextHolder* text, int a4); + static void LoopbackPacketSender_sendToServer(C_LoopbackPacketSender* a, C_Packet* packet); + static float LevelRendererPlayer_getFov(__int64 _this, float a2, bool a3); + static void MultiLevelPlayer_tick(C_EntityList* entityList); + static void GameMode_startDestroyBlock(C_GameMode* _this, vec3_ti* a2, uint8_t face, void* a4, void* a5); + static void HIDController_keyMouse(C_HIDController* _this, void* a2, void* a3); + static int BlockLegacy_getRenderLayer(C_BlockLegacy* a1); + static __int8* BlockLegacy_getLightEmission(C_BlockLegacy* _this, __int8* a2); + static __int64 LevelRenderer_renderLevel(__int64 _this, __int64 a2, __int64 a3); + static void ClickFunc(__int64 a1, char a2, char a3, __int16 a4, __int16 a5, __int16 a6, __int16 a7, char a8); + static __int64 MoveInputHandler_tick(C_MoveInputHandler* _this, C_Entity* a2); + static __int64 ChestScreenController_tick(C_ChestScreenController* _this); + static float GetGamma(uintptr_t* a1); + static bool Actor_isInWater(C_Entity* _this); + static void JumpPower(C_Entity* _this, float a2); + static __int64 MinecraftGame_onAppSuspended(__int64 _this); + static void Actor_ascendLadder(C_Entity* _this); + static void Actor_swing(C_Entity* _this); + static void Actor_startSwimming(C_Entity* _this); + static void RakNetInstance_tick(C_RakNetInstance* _this, __int64 a2, __int64 a3); + static float GameMode_getPickRange(C_GameMode* _this, __int64 a2, char a3); + static __int64 GameMode_attack(C_GameMode* _this, C_Entity*); + static __int64 ConnectionRequest_create(__int64 _this, __int64 privateKeyManager, void* a3, TextHolder* selfSignedId, TextHolder* serverAddress, __int64 clientRandomId, TextHolder* skinId, SkinData* skinData, __int64 capeData, CoolSkinData* coolSkinStuff, TextHolder* deviceId, int inputMode, int uiProfile, int guiScale, TextHolder* languageCode, bool sendEduModeParams, TextHolder* tenantId, __int64 unused, TextHolder* platformUserId, TextHolder* thirdPartyName, bool thirdPartyNameOnly, TextHolder* platformOnlineId, TextHolder* platformOfflineId, TextHolder* capeId); + static void InventoryTransactionManager_addAction(C_InventoryTransactionManager* a1, C_InventoryAction* a2); + static __int64 PaintingRenderer__render(__int64 _this, __int64 a2, __int64 a3); + static bool DirectoryPackAccessStrategy__isTrusted(__int64 _this); + static bool ReturnTrue(__int64 _this); + static __int64 SkinRepository___loadSkinPack(__int64 _this, __int64 pack, __int64 a3); + static GamerTextHolder* toStyledString(__int64 strIn, GamerTextHolder* strOut); + static __int64 prepFeaturedServers(__int64 a1); + static __int64 prepFeaturedServersFirstTime(__int64 a1, __int64 a2); + static __int64 InGamePlayScreen___renderLevel(__int64 playScreen, __int64 a2, __int64 a3); + static __int64 Cube__compile(__int64 a1, __int64 a2); + static void LocalPlayer__updateFromCamera(__int64 a1, C_Camera* a2); + static bool Mob__isImmobile(C_Entity*); + static void InventoryTransactionManager__addAction(C_InventoryTransactionManager*, C_InventoryAction&); + static void LevelRendererPlayer__renderNameTags(__int64 a1, __int64 a2, TextHolder* name, __int64 a4); + + std::unique_ptr Player_tickWorldHook; + std::unique_ptr ClientInstanceScreenModel_sendChatMessageHook; + std::unique_ptr UIScene_setupAndRenderHook; + std::unique_ptr UIScene_renderHook; + std::unique_ptr RenderTextHook; + std::unique_ptr Dimension_getFogColorHook; + std::unique_ptr Dimension_getTimeOfDayHook; + std::unique_ptr Dimension_getSunIntensityHook; + std::unique_ptr ChestBlockActor_tickHook; + std::unique_ptr Actor_lerpMotionHook; + std::unique_ptr AppPlatform_getGameEditionHook; + std::unique_ptr PleaseAutoCompleteHook; + std::unique_ptr LoopbackPacketSender_sendToServerHook; + std::unique_ptr LevelRendererPlayer_getFovHook; + std::unique_ptr MultiLevelPlayer_tickHook; + std::unique_ptr GameMode_startDestroyBlockHook; + std::unique_ptr HIDController_keyMouseHook; + std::unique_ptr BlockLegacy_getRenderLayerHook; + std::unique_ptr BlockLegacy_getLightEmissionHook; + std::unique_ptr LevelRenderer_renderLevelHook; + std::unique_ptr ClickFuncHook; + std::unique_ptr MoveInputHandler_tickHook; + std::unique_ptr ChestScreenController_tickHook; + std::unique_ptr GetGammaHook; + std::unique_ptr Actor_isInWaterHook; + std::unique_ptr JumpPowerHook; + std::unique_ptr MinecraftGame_onAppSuspendedHook; + std::unique_ptr Actor_ascendLadderHook; + std::unique_ptr Actor_swingHook; + std::unique_ptr Actor_startSwimmingHook; + std::unique_ptr RakNetInstance_tickHook; + std::unique_ptr GameMode_getPickRangeHook; + std::unique_ptr GameMode_attackHook; + std::unique_ptr ConnectionRequest_createHook; + std::unique_ptr InventoryTransactionManager_addActionHook; + std::unique_ptr PaintingRenderer__renderHook; + std::unique_ptr DirectoryPackAccessStrategy__isTrustedHook; + std::unique_ptr ZipPackAccessStrategy__isTrustedHook; + std::unique_ptr SkinRepository___checkSignatureFileInPack; + std::unique_ptr SkinRepository___loadSkinPackHook; + std::unique_ptr toStyledStringHook; + std::unique_ptr prepFeaturedServersHook; + std::unique_ptr prepFeaturedServersFirstTimeHook; + std::unique_ptr InGamePlayScreen___renderLevelHook; + std::unique_ptr cube__compileHook; + std::unique_ptr LocalPlayer__updateFromCameraHook; + std::unique_ptr Mob__isImmobileHook; + std::unique_ptr InventoryTransactionManager__addActionHook; + std::unique_ptr LevelRendererPlayer__renderNameTagsHook; +}; + +extern Hooks g_Hooks; + +class FuncHook { +public: + void* funcPtr; + void* funcReal; + + FuncHook(void* func, void* hooked) { + funcPtr = func; + + MH_STATUS ret = MH_CreateHook(func, hooked, &funcReal); + if (ret == MH_OK && (__int64)func > 10) { + } else + logF("MH_CreateHook = %i", ret); + }; + + FuncHook(uintptr_t func, void* hooked) { + funcPtr = reinterpret_cast(func); + + MH_STATUS ret = MH_CreateHook(funcPtr, hooked, &funcReal); + if (ret == MH_OK && (__int64)funcPtr > 10) { + } else + logF("MH_CreateHook = %i", ret); + }; + + void enableHook(bool enable = true) { + if (funcPtr != nullptr) { + int ret = enable ? MH_EnableHook(funcPtr) : MH_DisableHook(funcPtr); + if (ret != MH_OK) + logF("MH_EnableHook = %i", ret); + } else + logF("enableHook() called with nullptr func!"); + } + + ~FuncHook() { + Restore(); + } + + void Restore() { + if (funcPtr != nullptr) + MH_DisableHook(funcPtr); + } + + template + inline auto* GetFastcall() { + using Fn = TRet(__fastcall*)(TArgs...); + return reinterpret_cast(funcReal); + }; +}; \ No newline at end of file diff --git a/Memory/MinHook.h b/Memory/MinHook.h new file mode 100644 index 0000000..487c34f --- /dev/null +++ b/Memory/MinHook.h @@ -0,0 +1,183 @@ +/* + * MinHook - The Minimalistic API Hooking Library for x64/x86 + * Copyright (C) 2009-2017 Tsuda Kageyu. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if !(defined _M_IX86) && !(defined _M_X64) && !(defined __i386__) && !(defined __x86_64__) +#error MinHook supports only x86 and x64 systems. +#endif + +#include + +// MinHook Error Codes. +typedef enum MH_STATUS { + // Unknown error. Should not be returned. + MH_UNKNOWN = -1, + + // Successful. + MH_OK = 0, + + // MinHook is already initialized. + MH_ERROR_ALREADY_INITIALIZED, + + // MinHook is not initialized yet, or already uninitialized. + MH_ERROR_NOT_INITIALIZED, + + // The hook for the specified target function is already created. + MH_ERROR_ALREADY_CREATED, + + // The hook for the specified target function is not created yet. + MH_ERROR_NOT_CREATED, + + // The hook for the specified target function is already enabled. + MH_ERROR_ENABLED, + + // The hook for the specified target function is not enabled yet, or already + // disabled. + MH_ERROR_DISABLED, + + // The specified pointer is invalid. It points the address of non-allocated + // and/or non-executable region. + MH_ERROR_NOT_EXECUTABLE, + + // The specified target function cannot be hooked. + MH_ERROR_UNSUPPORTED_FUNCTION, + + // Failed to allocate memory. + MH_ERROR_MEMORY_ALLOC, + + // Failed to change the memory protection. + MH_ERROR_MEMORY_PROTECT, + + // The specified module is not loaded. + MH_ERROR_MODULE_NOT_FOUND, + + // The specified function is not found. + MH_ERROR_FUNCTION_NOT_FOUND +} MH_STATUS; + +// Can be passed as a parameter to MH_EnableHook, MH_DisableHook, +// MH_QueueEnableHook or MH_QueueDisableHook. +#define MH_ALL_HOOKS NULL + +#ifdef __cplusplus +extern "C" { +#endif + +// Initialize the MinHook library. You must call this function EXACTLY ONCE +// at the beginning of your program. +MH_STATUS WINAPI MH_Initialize(VOID); + +// Uninitialize the MinHook library. You must call this function EXACTLY +// ONCE at the end of your program. +MH_STATUS WINAPI MH_Uninitialize(VOID); + +// Creates a Hook for the specified target function, in disabled state. +// Parameters: +// pTarget [in] A pointer to the target function, which will be +// overridden by the detour function. +// pDetour [in] A pointer to the detour function, which will override +// the target function. +// ppOriginal [out] A pointer to the trampoline function, which will be +// used to call the original target function. +// This parameter can be NULL. +MH_STATUS WINAPI MH_CreateHook(LPVOID pTarget, LPVOID pDetour, LPVOID *ppOriginal); + +// Creates a Hook for the specified API function, in disabled state. +// Parameters: +// pszModule [in] A pointer to the loaded module name which contains the +// target function. +// pszTarget [in] A pointer to the target function name, which will be +// overridden by the detour function. +// pDetour [in] A pointer to the detour function, which will override +// the target function. +// ppOriginal [out] A pointer to the trampoline function, which will be +// used to call the original target function. +// This parameter can be NULL. +MH_STATUS WINAPI MH_CreateHookApi( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal); + +// Creates a Hook for the specified API function, in disabled state. +// Parameters: +// pszModule [in] A pointer to the loaded module name which contains the +// target function. +// pszTarget [in] A pointer to the target function name, which will be +// overridden by the detour function. +// pDetour [in] A pointer to the detour function, which will override +// the target function. +// ppOriginal [out] A pointer to the trampoline function, which will be +// used to call the original target function. +// This parameter can be NULL. +// ppTarget [out] A pointer to the target function, which will be used +// with other functions. +// This parameter can be NULL. +MH_STATUS WINAPI MH_CreateHookApiEx( + LPCWSTR pszModule, LPCSTR pszProcName, LPVOID pDetour, LPVOID *ppOriginal, LPVOID *ppTarget); + +// Removes an already created hook. +// Parameters: +// pTarget [in] A pointer to the target function. +MH_STATUS WINAPI MH_RemoveHook(LPVOID pTarget); + +// Enables an already created hook. +// Parameters: +// pTarget [in] A pointer to the target function. +// If this parameter is MH_ALL_HOOKS, all created hooks are +// enabled in one go. +MH_STATUS WINAPI MH_EnableHook(LPVOID pTarget); + +// Disables an already created hook. +// Parameters: +// pTarget [in] A pointer to the target function. +// If this parameter is MH_ALL_HOOKS, all created hooks are +// disabled in one go. +MH_STATUS WINAPI MH_DisableHook(LPVOID pTarget); + +// Queues to enable an already created hook. +// Parameters: +// pTarget [in] A pointer to the target function. +// If this parameter is MH_ALL_HOOKS, all created hooks are +// queued to be enabled. +MH_STATUS WINAPI MH_QueueEnableHook(LPVOID pTarget); + +// Queues to disable an already created hook. +// Parameters: +// pTarget [in] A pointer to the target function. +// If this parameter is MH_ALL_HOOKS, all created hooks are +// queued to be disabled. +MH_STATUS WINAPI MH_QueueDisableHook(LPVOID pTarget); + +// Applies all queued changes in one go. +MH_STATUS WINAPI MH_ApplyQueued(VOID); + +// Translates the MH_STATUS to its name as a string. +const char *WINAPI MH_StatusToString(MH_STATUS status); + +#ifdef __cplusplus +} +#endif diff --git a/Memory/SlimMem.cpp b/Memory/SlimMem.cpp new file mode 100644 index 0000000..3f8a18f --- /dev/null +++ b/Memory/SlimMem.cpp @@ -0,0 +1,214 @@ +#include "SlimMem.h" +#include +#include +#include + +inline bool IsProcessHandleValid(HANDLE h) { return h > (void*)0 && h != INVALID_HANDLE_VALUE; }; +inline bool IsHandleValid(HANDLE h) { return h != INVALID_HANDLE_VALUE; } +inline BOOL ProperlyCloseHandle(HANDLE h) { + auto const b = CloseHandle(h); + assert(b); + return b; +} + +static std::wstring ToLower(std::wstring string) { + transform(string.begin(), string.end(), string.begin(), tolower); + return string; +} + +namespace SlimUtils { + +bool SlimMem::HasProcessHandle() const { return IsProcessHandleValid(m_hProc); } + +#pragma region Constructors/Destructors + SlimMem::SlimMem(const SlimMem & copy) + { + this->m_dwPID = 0; + DuplicateHandle(GetCurrentProcess(), copy.m_hProc, GetCurrentProcess(), &m_hProc, NULL, FALSE, DUPLICATE_SAME_ACCESS); + } + + SlimMem::~SlimMem() + { + this->Close(); + } +#pragma endregion + +#pragma region Open/Close + void SlimMem::Close() + { + m_mModules.clear(); + + //Close the handle to the process in case it's still open + if (IsProcessHandleValid(m_hProc)) { + ProperlyCloseHandle(m_hProc); + } + } + + bool SlimMem::Open(const wchar_t * lpwstrProcessName, ProcessAccess flags) + { + return this->Open(lpwstrProcessName, (DWORD)flags); + } + + bool SlimMem::Open(const wchar_t * lpwstrProcessName, DWORD flags) + { + DWORD pid; + if (GetPID(lpwstrProcessName, &pid)) + return this->Open(pid, flags); + return false; + } + + bool SlimMem::Open(DWORD dwPID, ProcessAccess flags) + { + return this->Open(dwPID, (DWORD)flags); + } + + bool SlimMem::Open(DWORD dwPID, DWORD dwFlags) + { + if (this->HasProcessHandle()) { + + return false; + } + + + m_hProc = OpenProcess(dwFlags | PROCESS_DUP_HANDLE, false, dwPID); + m_dwPID = dwPID; + if (this->HasProcessHandle()) + this->ParseModules(); + + + return this->HasProcessHandle(); + } +#pragma endregion + +#pragma region Utility + /* + Attempts to find a process with a given name and sets the given PID + Returns whether a matching process was found or not + */ + bool SlimMem::GetPID(const wchar_t * lpwstrProcessName, DWORD* pid) + { + PROCESSENTRY32W proc; + proc.dwSize = sizeof(PROCESSENTRY32W); + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + *pid = 0; + + if (!IsHandleValid(hSnap)) + return false; + + if (Process32FirstW(hSnap, &proc)) { + do { + if (wcscmp(lpwstrProcessName, proc.szExeFile) == 0) + { + ProperlyCloseHandle(hSnap); + *pid = proc.th32ProcessID; + return true; + } + } while (Process32NextW(hSnap, &proc)); + } + + ProperlyCloseHandle(hSnap); + return false; + } + + /* + Caches basic information of modules loaded by the opened-process + + */ + bool SlimMem::ParseModules() + { + if (!this->HasProcessHandle()) + return false; + + m_mModules.clear(); + + MODULEENTRY32W mod; + mod.dwSize = sizeof(MODULEENTRY32W); + + HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, m_dwPID); + if (!IsHandleValid(hSnap)) + return false; + + if (Module32FirstW(hSnap, &mod)) { + do { + try { + if (m_mModules.find(std::wstring(mod.szModule)) == m_mModules.end()) + m_mModules[ToLower(mod.szModule)] = std::make_unique((std::uintptr_t) mod.modBaseAddr, mod.modBaseSize); + } + catch (...) { + + } + } while (Module32NextW(hSnap, &mod)); + } + + ProperlyCloseHandle(hSnap); + return true; + } + + SigScanResult SlimMem::PerformSigScan(const BYTE * bufPattern, const char * lpcstrMask, const SlimModule * Module, DWORD startFromOffset) + { + auto module = Module; + if (module == nullptr) + return SigScanResult(false); + std::string mask(lpcstrMask); + + if (mask.empty()) + return SigScanResult(false); + + if (module->dwSize <= startFromOffset) + return SigScanResult(false); + + if (startFromOffset > module->dwSize - mask.size()) + return SigScanResult(false); + + if (mask[0] != 'x') { + + return SigScanResult(false); + } + + + + BYTE *dump = new BYTE[module->dwSize]; + + SIZE_T bytesRead; + + if (!ReadProcessMemory(this->m_hProc, (LPCVOID)module->ptrBase, dump, module->dwSize, &bytesRead) || bytesRead != module->dwSize) + return SigScanResult(false); + + bool found = false; + size_t maskSize = mask.size(); + const char * goodMask = mask.c_str(); + DWORD count = (DWORD)(module->dwSize - maskSize); + for (DWORD i = startFromOffset; i < count; i++) { + if (bufPattern[0] == dump[i]) { + found = true; + for (DWORD idx = 1; idx < maskSize; idx++) { + + if (goodMask[idx] == 0x78 && bufPattern[idx] != dump[i + idx]) { + found = false; + break; + } + } + if (found) { + SigScanResult result(true, i, dump + i, (DWORD)maskSize); + delete[] dump; + return result; + } + } + } + delete[] dump; + + return SigScanResult(false); + } + + const SlimModule* SlimMem::GetModule(const wchar_t * lpwstrModuleName) const + { + std::wstring name = ToLower(std::wstring(lpwstrModuleName)); + auto val = m_mModules.find(name); + if (val == m_mModules.end()) + return nullptr; + + return (*val).second.get(); + } + +#pragma endregion +} \ No newline at end of file diff --git a/Memory/SlimMem.h b/Memory/SlimMem.h new file mode 100644 index 0000000..76834be --- /dev/null +++ b/Memory/SlimMem.h @@ -0,0 +1,292 @@ +#pragma once + +/* --------------------------------------------------------------------------- +** This software is in the public domain, furnished "as is", without technical +** support, and with no warranty, express or implied, as to its usefulness for +** any purpose. +** +** SlimMem.h +** A simple to use memory-manipulation class +** +** Author: Zat +** -------------------------------------------------------------------------*/ + +// clang-format off +//#include //Windows-functions (OpenProcess, RPM, WPM, etc) +//#include //Functions that gather process-information +//#include //Functions that gather module-information + +#include //transform-function that is used to apply the tolower-function to a wstring +#include //Used for debugging +#include //tolower-function that converts a char to lowercase +//#include //cout +#include //Data-container that saves parsed modules +#include //unique_ptr +#include //String/WString implementation +#include //Used to restrict usage of template functions Read and Write to specific types +#include + +// clang-format on + +namespace SlimUtils { + +//Exclude module-names from SlimModule-structs +#define VERYSLIM_SLIMMODULE +//Enable error-reports +#define REPORT_ERRORS + +struct SlimModule; +struct SigScanResult; +class SlimMem; + +/* + Contains basic information about a single module + */ +struct SlimModule { + std::uintptr_t ptrBase; + unsigned long dwSize; + + SlimModule(std::uintptr_t base, unsigned long baseSize) { + ptrBase = base; + dwSize = baseSize; + } +}; + +/* + Holds information about a signature-scan + */ +struct SigScanResult { + bool m_Success; + unsigned char* m_Data = 0; + unsigned long m_DataLength; + unsigned long m_Offset; + + SigScanResult() : m_Success(false), m_Data(nullptr), m_DataLength(0), m_Offset(0) { + } + + SigScanResult(bool p_Success) : m_Success(p_Success), m_Data(nullptr), m_DataLength(0), m_Offset(0) { + } + + SigScanResult(bool p_Success, unsigned long p_Offset, unsigned char* p_Data, unsigned long p_DataLength) : m_Success(p_Success), m_DataLength(p_DataLength), m_Offset(p_Offset) { + if (p_Data != nullptr) { + m_Data = new unsigned char[m_DataLength]; + memcpy_s(m_Data, m_DataLength, p_Data, m_DataLength); + } + } + + SigScanResult(const SigScanResult& other) : SigScanResult(other.m_Success, other.m_Offset, other.m_Data, other.m_DataLength) { + } + + ~SigScanResult() { + if (m_Data != nullptr) + delete[] m_Data; + } + + SigScanResult& operator=(const SigScanResult& other) { + if (this->m_Data != nullptr) { + delete[] this->m_Data; + this->m_Data = nullptr; + } + this->m_Success = other.m_Success; + this->m_Offset = other.m_Offset; + + if (other.m_Data != nullptr) { + this->m_DataLength = other.m_DataLength; + this->m_Data = new unsigned char[other.m_DataLength]; + memcpy_s(this->m_Data, this->m_DataLength, other.m_Data, other.m_DataLength); + } + return *this; + } + + template + bool Read(T& value, unsigned long index) const { + if (index + sizeof(T) >= m_DataLength) + return false; + + value = *(T*)(reinterpret_cast(m_Data) + index); + return true; + } +}; + +/* + Offers a simple collection of combination of process-access flags + */ +enum ProcessAccess : unsigned long { + Full = ((0x000F0000L) | (0x00100000L) | 0xFFFF), + ReadOnly = 0x0008 | 0x0010, + WriteOnly = 0x0008 | 0x0020, + ReadWrite = ReadOnly | WriteOnly +}; + +/* + A class that provides basic functions that are used to write to/read from process memory + */ +class SlimMem { +public: + SlimMem() : m_hProc((void*)-1), m_dwPID(0) {} + SlimMem(const SlimMem& copy); + ~SlimMem(); + + SlimMem& operator=(const SlimMem& other) { + this->m_hProc = other.m_hProc; + this->m_dwPID = other.m_dwPID; + return *this; + } + + bool Open(const wchar_t* lpwstrProcessName, ProcessAccess flags); + bool Open(const wchar_t* lpwstrProcessName, unsigned long dwFlags); + bool Open(unsigned long dwPID, ProcessAccess flags); + bool Open(unsigned long dwPID, unsigned long dwFlags); + void Close(); + + bool HasProcessHandle() const; + const SlimModule* GetModule(const wchar_t* lpwstrModuleName) const; + bool ParseModules(); + SigScanResult PerformSigScan(const unsigned char* bufPattern, const char* lpcstrMask, const SlimModule* Module, unsigned long startFromOffset); + + template + T Read(std::uintptr_t ptrAddress) const; + + // template + //bool Read(std::uintptr_t ptrAddress, T& value) const; + + //unsigned char* ReadRaw(std::uintptr_t ptrAddress, int size) const; + //wchar_t * ReadRawWide(std::uintptr_t ptrAddress, int size) const; + + template + T ReadPtr(std::uintptr_t ptrAddress, std::initializer_list ilOffsets) const; + + template + bool Write(std::uintptr_t ptrAddress, T value) const; + + //inline bool WriteRaw(std::uintptr_t ptrAddress, uint8_t value[], size_t length) const; + //inline bool WriteRawChar(std::uintptr_t ptrAddress, char value[], size_t length) const; + + static bool GetPID(const wchar_t* lpwstrProcessName, unsigned long* pid); + void* m_hProc; + unsigned long m_dwPID; + std::map> m_mModules; + +private: +}; + +#pragma region Read / Write +/* + Reads data from memory + Returns the value read from memory; Returns default-value in case an error occured + */ +template +inline T SlimMem::Read(std::uintptr_t ptrAddress) const { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + //T val = T(); + //if (!this->HasProcessHandle()) + //return val; + + return *reinterpret_cast(ptrAddress); + //ReadProcessMemory(this->m_hProc, (LPCVOID)ptrAddress, &val, sizeof(T), NULL); + //return val; +} + +/* + Reads data from memory + Returns whether the operation was successful or not! + */ +/*template + inline bool SlimUtils::SlimMem::Read(std::uintptr_t ptrAddress, T & value) const + { + static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + SIZE_T unsigned charsRead; + + if (!this->HasProcessHandle()) + return false; + + return ReadProcessMemory(m_hProc, (LPCVOID)ptrAddress, &value, sizeof(T), &bytesRead) && bytesRead == sizeof(T); + } + + + + inline unsigned char * SlimMem::ReadRaw(std::uintptr_t ptrAddress, int size) const + { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + unsigned char* arr = new unsigned char[size]; + if (!this->HasProcessHandle()) + return arr; + + + ReadProcessMemory(this->m_hProc, (LPCVOID)ptrAddress, (LPVOID)arr, size, NULL); + return arr; + } + + inline wchar_t* SlimMem::ReadRawWide(std::uintptr_t ptrAddress, int size) const + { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + wchar_t* arr = new wchar_t[size]; + if (!this->HasProcessHandle()) + return arr; + + ReadProcessMemory(this->m_hProc, (LPCVOID)ptrAddress, (LPVOID)arr, size * sizeof(wchar_t), NULL); + return arr; + }*/ + +/* + Reads data from memory + Returns the value read from memory; Returns default-value in case an error occured + */ +template +inline T SlimMem::ReadPtr(std::uintptr_t ptrAddress, std::initializer_list ilOffsets) const { + static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + if (!this->HasProcessHandle()) + return 0x0; + for (auto it = ilOffsets.begin(); it != ilOffsets.end(); it++) { + if ((std::uintptr_t*)(it + 1) == ilOffsets.end()) { + //Read value + //std::cout << "yee: " << std::hex << ptrAddress << ":" << std::hex << *it << std::endl; + return this->Read(ptrAddress + *it); + } else { + //Read offset + //std::cout << "yee: " << std::hex << ptrAddress << ":" << std::hex << *it << std::endl; + ptrAddress = this->Read(ptrAddress + *it); + } + } + return T(); +} + +/* + Writes data to memory + Returns whether the operation was successful or not! + */ +template +inline bool SlimMem::Write(std::uintptr_t ptrAddress, T value) const { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + //if (!this->HasProcessHandle()) + //return false; + *reinterpret_cast(ptrAddress) = value; + return true; + //return WriteProcessMemory(this->m_hProc, (LPVOID)ptrAddress, &value, sizeof(T), NULL); +} + +/*inline bool SlimMem::WriteRaw(std::uintptr_t ptrAddress, uint8_t value[], size_t size) const + { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + if (!this->HasProcessHandle()) + return false; + return WriteProcessMemory(this->m_hProc, (LPVOID)ptrAddress, value, size, NULL); + } + + inline bool SlimMem::WriteRawChar(std::uintptr_t ptrAddress, char value[], size_t size) const + { + //static_assert(std::is_trivially_copyable::value, "Invalid RPM/WPM type"); + + if (!this->HasProcessHandle()) + return false; + return WriteProcessMemory(this->m_hProc, (LPVOID)ptrAddress, value, size, NULL); + }*/ +#pragma endregion +} // namespace SlimUtils diff --git a/README.md b/README.md new file mode 100644 index 0000000..f1febcb --- /dev/null +++ b/README.md @@ -0,0 +1,29 @@ +
+
+

+ Horion +

+
+

+ Download Injector + Discord server + Build Status + License +

+

+ Horion is a Minecraft: Bedrock Edition utility mod designed to enhance gameplay. We do not take responsibility in anything done with this utility mod. +If you want to contribute to this project, feel free to fork this repository and submit a pull request. +

+
+ +## Contributing +To contribute, simply **fork the repository**, edit the code, and **submit a pull request**. +We will then check your pull request and accept/deny it. +If you are clueless about what you could start with, [we collected some issues for you](https://github.com/horionclient/Horion/contribute). +More Information on setting everything up can be found in the **[wiki](https://github.com/horionclient/Horion/wiki "wiki")**! +If you need any help with understanding our code, join the [official Discord server](https://horion.download/discord) + +## Licensing +This work is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc/4.0/ or send a letter to Creative Commons, PO Box 1866, Mountain View, CA 94042, USA. +You are allowed to fork the project and distribute it, if you give credit. You may not sell any code protected by the license. +Not all source files are protected by this license - Some third party libraries (Chakra, DX11) may be under different copyright. diff --git a/SDK/CBlockLegacy.cpp b/SDK/CBlockLegacy.cpp new file mode 100644 index 0000000..d5fdeea --- /dev/null +++ b/SDK/CBlockLegacy.cpp @@ -0,0 +1,37 @@ +#include "CBlockLegacy.h" + +#include "../Memory/GameData.h" +#include "../Utils/Utils.h" +#include "../Utils/Logger.h" +C_Block* C_BlockSource::getBlock(const vec3_ti& block) { + using getBlock_t = C_Block*(__fastcall*)(C_BlockSource*, const vec3_ti&); + static getBlock_t getBlock = reinterpret_cast(FindSignature("48 89 5C 24 ? 57 48 83 EC ? 48 8B F9 48 8B DA 8B 4A")); + return getBlock(this, block); +} +C_BlockActor* C_BlockSource::getBlockEntity(const vec3_ti& block) { + using getBlockEntity_t = C_BlockActor*(__fastcall*)(C_BlockSource*, const vec3_ti&); + static getBlockEntity_t getBlockEntity = reinterpret_cast(FindSignature("40 55 56 57 48 83 EC ?? 8B 02")); + return getBlockEntity(this, block); +} +C_Block* C_BlockSource::getLiquidBlock(const vec3_ti& block) { + using getLiquidBlock_t = C_Block*(__fastcall*)(C_BlockSource*, const vec3_ti&); + static getLiquidBlock_t getLiquidBlock = Utils::FuncFromSigOffset(FindSignature("E8 ? ? ? ? 48 8B C8 48 8B 47 ?"), 1); + return getLiquidBlock(this, block); +} +bool C_BlockLegacy::getCollisionShape(AABB* collShapeOut, C_Block* block, C_BlockSource* blockSource, const vec3_ti* pos, C_Entity* actor) { + return Utils::CallVFunc<5, bool, AABB*, C_Block*, C_BlockSource*, const vec3_ti*, C_Entity*>(this, collShapeOut, block, blockSource, pos, actor); +} +void C_BlockLegacy::liquidGetFlow(vec3_t* flowOut, C_BlockSource* reg, const vec3_ti* pos) { + using liquid_getFlow_t = int(__fastcall*)(C_BlockLegacy*, vec3_t*, C_BlockSource*, const vec3_ti*); + static liquid_getFlow_t liquid_getDepth = Utils::FuncFromSigOffset(FindSignature("E8 ? ? ? ? 48 8B 4C 24 ? F3 0F 10 01"), 1); + + liquid_getDepth(this, flowOut, reg, pos); +} +bool C_BlockLegacy::hasWater(C_BlockSource* reg, const vec3_ti& pos) { + if(this->material->isLiquid){ + return !this->material->isSuperHot; + } + + auto liquidBlock = reg->getLiquidBlock(pos)->toLegacy(); + return this != liquidBlock && liquidBlock->material->isLiquid && !liquidBlock->material->isSuperHot; +} diff --git a/SDK/CBlockLegacy.h b/SDK/CBlockLegacy.h new file mode 100644 index 0000000..0c76fad --- /dev/null +++ b/SDK/CBlockLegacy.h @@ -0,0 +1,87 @@ +#pragma once + +#include "../Utils/HMath.h" +#include "TextHolder.h" +//#include "Tag.h" + +class C_Material { +public: + int type; // 5 for water, 6 for lava + bool isFlammable; + bool isNeverBuildable; + bool isAlwaysDestroyable; + bool isReplaceable; + bool isLiquid; // 0x0008 +private: + char pad2[0x3]; // 0x009 +public: + float translucency; // 0x00C + bool isBlockingMotion; + bool isBlockingPrecipitation; + bool isSolid; + bool isSuperHot; + float color[4]; +}; + +class C_Entity; +class C_Block; +class C_BlockSource; + +class C_BlockLegacy { +public: + uintptr_t** Vtable; //0x0000 + class TextHolder tileName; //0x0008 +private: + char pad_0028[8]; //0x0028 +public: + class TextHolder name; //0x0030 +private: + char pad_0050[136]; //0x0050 +public: + class C_Material* material; //0x00D8 +private: + char pad_00E0[108]; //0x00E0 +public: + short blockId; //0x014C + + int liquidGetDepth(C_BlockSource*, const vec3_ti* pos); + void liquidGetFlow(vec3_t* flowOut, C_BlockSource*, const vec3_ti* pos); + bool getCollisionShape(AABB* collShapeOut, C_Block* block, C_BlockSource* blockSource, const vec3_ti* pos, C_Entity* actor); + bool hasWater(C_BlockSource*, const vec3_ti& pos); +}; + +class C_Block { +public: + uint8_t data; // 0x8 + +private: + char pad[0x7]; + +public: + C_BlockLegacy* blockLegacy; // 0x10 + + inline C_BlockLegacy* toLegacy() { return blockLegacy; } + + virtual ~C_Block(); + virtual int getRenderLayer(); +}; + +class CompoundTag; + +class C_BlockActor { +private: + virtual void destructor(); + virtual __int64 load(__int64&, CompoundTag*, __int64&); + +public: + virtual bool save(CompoundTag*); +}; + +class C_BlockSource { +public: + C_Block* getBlock(const vec3_ti& block);; + + C_BlockActor* getBlockEntity(const vec3_ti& block); + + C_Block* getLiquidBlock(const vec3_ti& block); +}; diff --git a/SDK/CCamera.cpp b/SDK/CCamera.cpp new file mode 100644 index 0000000..aa50021 --- /dev/null +++ b/SDK/CCamera.cpp @@ -0,0 +1,46 @@ +#include "CCamera.h" + +#include "../Utils/Utils.h" + +void C_Camera::getEulerAngles(vec3_t* vec) { + using cam_getEuler_t = void(__fastcall*)(C_Camera*, vec3_t*); + static auto cam_getEuler = reinterpret_cast(FindSignature("48 8B C4 53 48 81 EC ?? ?? ?? ?? 0F 29 70 ?? 48 8B DA 0F 29 78 ?? F3")); + cam_getEuler(this, vec); +} +void C_Camera::setOrientation(float pitch, float yaw, float roll) { + using cam_setOrientation_t = void(__fastcall*)(C_Camera*, float, float, float); + static auto cam_setOrientation = reinterpret_cast(FindSignature("40 53 48 81 EC ?? ?? ?? ?? 0F 29 74 24 ?? 0F 57")); + cam_setOrientation(this, pitch, yaw, roll); +} +void C_Camera::getPlayerRotation(vec2_t* angOut) { + vec3_t angles; + this->getEulerAngles(&angles); + + float v4; + if ( this->facesPlayerFront ) + v4 = -1.0; + else + v4 = 1.0; + + angOut->y = (float)(angles.y * 57.295776) + *(float *)(reinterpret_cast<__int64>(this) + 272); + angOut->x = (float)((float)(angles.x * 57.295776) + *(float *)(reinterpret_cast<__int64>(this) + 268)) * v4; + angOut->normAngles(); +} +void C_Camera::getForwardVector(vec3_t* forward) { + vec3_t eulerAngles; + this->getEulerAngles(&eulerAngles); + + float calcYaw = eulerAngles.y - (90 * (PI / 180)); + float calcPitch = -eulerAngles.x; + + forward->x = cos(calcYaw) * cos(calcPitch); + forward->y = sin(calcPitch); + forward->z = sin(calcYaw) * cos(calcPitch); +} + +C_Camera* C_CameraManager::getCameraOrDebugCamera() { + /*using camerManager_getCameraOrDebugCamera_t = C_Camera*(__fastcall*)(C_CameraManager*); + static auto camerManager_getCameraOrDebugCamera = reinterpret_cast(FindSignature("40 53 48 83 EC ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 80 39 00 48 8B D9 74 ?? 48")); + return camerManager_getCameraOrDebugCamera(this);*/ + return reinterpret_cast(reinterpret_cast<__int64>(this) + 0x40); +} diff --git a/SDK/CCamera.h b/SDK/CCamera.h new file mode 100644 index 0000000..f4df6f0 --- /dev/null +++ b/SDK/CCamera.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../Utils/HMath.h" + +class C_Camera { +private: + char padding[0x78]; // 0x0 +public: + bool renderPlayerModel; // 0x078 + bool renderFirstPersonObjects; // 0x079 probably hand and item +private: + char autoAlignPadding[2]; // 0x07A + char padding7C[0x18]; // 0x07C +public: + float fieldOfView; // 0x094 + float nearClippingPlane; // 0x098 usually 0.025 + float farClippingPlane; // 0x09C usually 2500 +private: + char paddingA0[0x68]; // 0x0A0 +public: + bool facesPlayerFront; // 0x108 + + void getForwardVector(vec3_t*); + void getEulerAngles(vec3_t*); + void getPlayerRotation(vec2_t*); + void setOrientation(float pitch, float yaw, float roll); + void setOrientationDeg(float pitch, float yaw, float roll) { + setOrientation((-yaw - 180) * RAD_DEG, -pitch * RAD_DEG, roll * RAD_DEG); + } +}; + +class C_CameraManager { +public: + C_Camera* getCameraOrDebugCamera(); +}; \ No newline at end of file diff --git a/SDK/CChestBlockActor.cpp b/SDK/CChestBlockActor.cpp new file mode 100644 index 0000000..e49a041 --- /dev/null +++ b/SDK/CChestBlockActor.cpp @@ -0,0 +1,21 @@ +#include "CChestBlockActor.h" + +#include "../Utils/Utils.h" + +bool C_ChestBlockActor::isBarrelBlock() { + GamerTextHolder alloc; + Utils::CallVFunc<25, void, GamerTextHolder*, __int64>(this, &alloc, 0); + return strcmp(alloc.getText(), "container.barrel") == 0; +} +bool C_ChestBlockActor::isShulkerBlock() { + GamerTextHolder alloc; + Utils::CallVFunc<25, void, GamerTextHolder*, __int64>(this, &alloc, 0); + return strcmp(alloc.getText(), "container.shulker") == 0; +} +AABB C_ChestBlockActor::getObstructionAABB() { + void* coolPtr = malloc(sizeof(AABB) + 4); + Utils::CallVFunc<40, void, void*>(this, coolPtr); + AABB ret = *reinterpret_cast(coolPtr); + free(coolPtr); + return ret; +} diff --git a/SDK/CChestBlockActor.h b/SDK/CChestBlockActor.h new file mode 100644 index 0000000..57cc765 --- /dev/null +++ b/SDK/CChestBlockActor.h @@ -0,0 +1,51 @@ +#pragma once + +#include "../Utils/HMath.h" +#include "CEntityList.h" +#include "TextHolder.h" + +class C_ChestBlockActor { +public: + uintptr_t** vTable; //0x0000 +private: + char pad_0x0008[0x8]; //0x0008 +public: + uintptr_t* block; //0x0010 +private: + char pad_0x0018[0x14]; //0x0018 +public: + vec3_ti posI; //0x002C + AABB aabb; + + bool isPaired() { + return *reinterpret_cast<__int64*>(reinterpret_cast<__int64>(this) + 0x228) != 0; //ptr to paired chest block actor + } + + vec3_ti* getPairedPos() { + return reinterpret_cast(reinterpret_cast<__int64>(this) + 0x230); + } + + bool isMainSubchest() { + return *reinterpret_cast(reinterpret_cast<__int64>(this) + 0x204) & 1; //in paired chest, is it the main one + } + + AABB getFullAABB() { + if (!isPaired()) { + if (isBarrelBlock() || isShulkerBlock()) + return AABB(this->posI.toVec3t(), this->posI.toVec3t().add(1)); + return AABB(this->posI.toVec3t().add(0.0625, 0, 0.0625), this->posI.toVec3t().add(1 - 0.0625, 1 - 1.f / 8, 1 - 0.0625)); + } + vec3_ti first = this->posI; + vec3_ti second = *getPairedPos(); + + if (first.x > second.x || first.z > second.z) + std::swap(first, second); + + return AABB(first.toVec3t().add(0.0625, 0, 0.0625), second.toVec3t().add(1 - 0.0625, 1 - 1.f / 8, 1 - 0.0625)); + } + + bool isBarrelBlock(); + bool isShulkerBlock(); + + AABB getObstructionAABB(); +}; diff --git a/SDK/CClientInstance.cpp b/SDK/CClientInstance.cpp new file mode 100644 index 0000000..dd23083 --- /dev/null +++ b/SDK/CClientInstance.cpp @@ -0,0 +1,74 @@ +#include "CClientInstance.h" +#include "../Utils/Utils.h" +#include "../Utils/Logger.h" +#include + +__int64 MinecraftGame::getServerEntries() { + return Utils::CallVFunc<30, __int64>(this); +} +void C_GuiData::displayClientMessage(std::string *a2) { + using displayClientMessage = void(__thiscall*)(void*, TextHolder&); + static displayClientMessage displayMessageFunc = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 54 41 56 41 57 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 30 4C 8B F1")); + + TextHolder text = TextHolder(*a2); + + if (displayMessageFunc != nullptr) + displayMessageFunc(this, text); +} +void C_GuiData::displayClientMessageF(const char *fmt, ...) { + va_list arg; + va_start(arg, fmt); + displayClientMessageVA(fmt, arg, true); + va_end(arg); +} +void C_GuiData::displayClientMessageVA(const char *fmt, va_list lis, bool sendToInjector) { + auto lengthNeeded = _vscprintf(fmt, lis) + 1; + if(lengthNeeded >= 300) { + logF("A message that was %i characters long could not be fitted into the buffer", lengthNeeded); + return; + } + + char message[300]; + vsprintf_s(message, 300, fmt, lis); + std::string msg(message); + if(sendToInjector) + Logger::SendToConsoleF(message); + displayClientMessage(&msg); + +} +void C_GuiData::displayClientMessageNoSendF(const char *fmt, ...) { + va_list arg; + va_start(arg, fmt); + displayClientMessageVA(fmt, arg, false); + va_end(arg); +} + +mce::MaterialPtr::MaterialPtr(const std::string &materialName) { + + using materialPtrConst_t = void(__fastcall*)(mce::MaterialPtr *, __int64, const HashedString&); + static materialPtrConst_t materialPtrConst = reinterpret_cast(FindSignature("48 89 4C 24 ?? 57 48 83 EC ?? 48 C7 44 24 ?? FE FF FF FF 48 89 5C 24 ?? 48 89 74 24 ?? 4C 8B CA")); + + static __int64 renderGroupBase = 0; + if (renderGroupBase == 0){ + auto sig = FindSignature("48 8D 15 ?? ?? ?? ?? 48 8D 4C 24 ?? E8 ?? ?? ?? ?? 48 8D 54 24 ?? 49 8D 8F") + 3; + auto off = *reinterpret_cast(sig); + renderGroupBase = sig + 4 + off; + } + + HashedString hashedStr(materialName); + materialPtrConst(this, renderGroupBase, hashedStr); +} + +void mce::Mesh::renderMesh(__int64 screenContext, mce::MaterialPtr *material, size_t numTextures, __int64 **textureArray) { + struct TextureData { + size_t numTextures; + __int64 **texturePtr; + } data; + using renderMesh_t = __int64 (*)(mce::Mesh*, __int64, mce::MaterialPtr *, TextureData *); + static renderMesh_t renderMesh = reinterpret_cast(FindSignature("40 53 55 56 57 41 54 41 55 41 56 41 57 48 81 EC ?? ?? ?? ?? 48 C7 44 24 ?? ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ?? 49 8B F1 4D 8B E0 4C")); + + data.numTextures = numTextures; + data.texturePtr = textureArray; + + renderMesh(this, screenContext + 0x10, material, &data); +} diff --git a/SDK/CClientInstance.h b/SDK/CClientInstance.h new file mode 100644 index 0000000..dc7cdcc --- /dev/null +++ b/SDK/CClientInstance.h @@ -0,0 +1,847 @@ +#pragma once + +#include "CEntity.h" +#include "CGameSettingsInput.h" +#include "CLoopbackPacketSender.h" +#include "CMinecraftUIRenderContext.h" +#include "TextHolder.h" + +class Minecraft { +private: + char pad_0x0000[0xD0]; //0x0000 +public: + float* timer; //0x00B0 +}; + +class Tessellator; +class C_Block; + +class BlockTessellator; +class ResourceLocation { +private: + char pad[0x28]; + __int64 hashCode; // 0x28 + char pad2[8]; +}; + +class HashedString { +private: + unsigned __int64 hash; + TextHolder text; // 0x0008 + +public: + HashedString(const std::string& text) { + this->text.setText(text); + + this->computeHash(); + } + + void computeHash() { + hash = 0xCBF29CE484222325i64; + if (this->text.getTextLength() <= 0) + return; + char* textP = this->text.getText(); + auto c = *textP; + + do { + hash = c ^ 0x100000001B3i64 * hash; + c = *++textP; + } while (*textP); + } + + unsigned __int64 getHash() { + return this->hash; + } +}; + +namespace mce { + class TextureGroup; + class MaterialPtr; + class Mesh { + public: + void renderMesh(__int64 screenContext, mce::MaterialPtr* material, size_t numTextures, __int64** textureArray); + + template + void renderMesh(__int64 screenContext, mce::MaterialPtr* material, std::array<__int64*, numTextures> textures) { + this->renderMesh(screenContext, material, numTextures, &textures[0]); + } + }; + class TexturePtr { + private: + __int64* clientTexture; + char pad[0x8]; + ResourceLocation resourceLocation; // 0x10 + + public: + __int64* getClientTexture() { + return this->clientTexture; + } + }; + class MaterialPtr { + private: + std::shared_ptr materialPtr; + + public: + MaterialPtr(const std::string& materialName); + }; + } + + +class LevelRenderer { +private: + char pad_0x0000[0x58]; //0x0000 +public: + mce::TextureGroup* textureGroup; // 0x0058 +private: + char pad_0x0060[0xE0]; //0x0060 +public: + mce::TexturePtr atlasTexture; // 0x140 +private: + char pad_0x0188[0x150]; //0x0188 +public: + BlockTessellator* blockTessellator; // 0x02D8 +private: + char pad_0x02F0[0x568]; //0x02E0 +public: + vec3_t origin; //0x0890 + + __int64 getLevelRendererPlayer(){ + return reinterpret_cast<__int64>(this) + 0x310; + } +}; +class HitDetectSystem; + +struct C_FontRepository_FontList_FontEntry { +public: + C_Font* font; + +private: + void* sharedFontPtr; +}; + +struct C_FontRepository_FontList { +public: + C_FontRepository_FontList_FontEntry fontEntries[9]; +}; + +struct C_FontRepository { +private: + uintptr_t* font_repository_vtable; // 0x0000 + __int64 pad; // 0x0008 + void* ptrToSelf; // 0x0010 + void* ptrToSelfSharedPtr; // 0x0018 + __int64 pad2; // 0x0020 +public: + C_FontRepository_FontList* fontList; //0x0028 + //C_FontRepository_FontList* fontList1; //0x0040 +}; + +class MinecraftGame { +private: + char filler[256]; //0x0000 +public: + C_FontRepository* fontRepository; //0xF8 +private: + char pad_0x128[0x1F0]; //0x100 +public: + bool canUseKeys; //0x2F0 + // 0x2F0 + + C_Font* getTheGoodFontThankYou() { + return fontRepository->fontList->fontEntries[7].font; + }; + + C_Font* getOldFont() { + return fontRepository->fontList->fontEntries[7].font; + }; + + C_Font* getTheBetterFontYes() { + return fontRepository->fontList->fontEntries[3].font; + } + + const bool canUseKeybinds() { + return canUseKeys; + }; + + __int64 getServerEntries(); +}; + +class C_GuiData { +private: + char pad_0x0000[0x18]; //0x0000 +public: + union { + struct { + float widthReal; //0x0018 + float heightReal; //0x001C + }; + vec2_t windowSizeReal; //0x0018 + }; + + float widthReal2; //0x0020 + float heightReal2; //0x0024 + union { + struct { + float widthGame; //0x0028 + float heightGame; //0x002C + }; + vec2_t windowSize; //0x0028 + }; + + void displayClientMessageVA(const char* fmt, va_list lis, bool sendToInjector = true); + + void displayClientMessageF(const char* fmt, ...); + void displayClientMessageNoSendF(const char* fmt, ...); + void displayClientMessage(std::string* a2); +}; + +struct PtrToGameSettings3 { +private: + char pad_0x0000[0x18]; //0x0000 +public: + C_GameSettingsInput* settingsInput; +}; + +struct PtrToGameSettings2 { +private: + char pad_0x0000[0x148]; //0x0000 +public: + PtrToGameSettings3* ptr; +}; + +struct PtrToGameSettings1 { +private: + char pad_0x0000[0x18]; //0x0000 +public: + PtrToGameSettings2* ptr; +}; + +class C_MoveInputHandler; +class C_CameraManager; + +class C_ClientInstance { +private: + char firstPad[0x90]; //0x0008 +public: + MinecraftGame* minecraftGame; //0x0098 +private: + MinecraftGame* N0000080C; //0x00A0 +public: + MinecraftGame* N0000080D; //0x00A8 +public: + Minecraft* minecraft; //0x00B0 +private: + char pad_0x0068[0x8]; //0x00B8 +public: + LevelRenderer* levelRenderer; //0x00C0 +private: + char pad_0x0078[0x8]; //0x00C8 +public: + C_LoopbackPacketSender* loopbackPacketSender; //0x00D0 +private: + char pad_0x0088[0x18]; //0x00D8 +public: + PtrToGameSettings1* ptr; //0x00F0 +private: + char pad_0x00B0[0x8]; //0x00F8 +public: + HitDetectSystem* hitDetectSystem; //0x0100 +private: + char pad_0x00B8[0x30]; //0x0108 +public: + C_LocalPlayer* localPlayer; //0x0138 +private: + char pad[0x388]; // 0x0140 +public: + struct { + char pad[0x238]; + struct { + __int64 materialPtr; + size_t refCount; + } entityLineMaterial; + } *itemInHandRenderer; // 0x04C8 + +private: + virtual __int64 destructorClientInstance(); + // Duplicate destructor + virtual __int64 onInitMinecraftGame(void); + virtual __int64 onDestroyMinecraftGame(void); + virtual __int64 init(__int64*, __int64&, __int64&, __int64&, __int64&, int); + virtual __int64 initSceneFactory(__int64*); + virtual __int64 initGraphics(void); + virtual __int64 stop(void); + virtual __int64 teardown(void); + virtual __int64 preShutDown(void); + virtual __int64 requestLeaveGame(bool, bool); + virtual __int64 stopPlayScreen(void); + +public: + virtual bool isLeaveGameDone(void) const; + virtual void setupPlayScreenForLeaveGame(void); + +private: + virtual __int64 resetPrimaryClient(void); + virtual __int64 resetGameSession(void); + virtual __int64 tick(void); + virtual __int64 frameUpdate(__int64&); + virtual __int64 update(bool); + virtual __int64 endFrame(void); + virtual __int64 startSubClientLateJoin(bool); + +public: + virtual void setupClientGame(__int64&&, bool); + +private: + virtual __int64 sub_1400C5D00(void) const; + virtual __int64 getLocalC_Player(void); + virtual __int64 getLocalC_Player(void) const; + virtual __int64 getCameraEntity(void) const; + +public: + virtual void setCameraEntity(C_Entity*); + +private: + virtual __int64 getCameraTargetEntity(void) const; + +public: + virtual void setCameraTargetEntity(C_Entity*); + virtual bool isLeavingGame(void) const; + virtual bool isDestroyingGame(void) const; + +private: + virtual __int64 sub_1400C98E0(void) const; + virtual __int64 useLowFrequencyUIRender(void) const; + +public: + virtual bool isSplitScreenActive(void) const; + virtual bool isVRClient(void) const; + virtual bool isARClient(void) const; + virtual bool isARVRClient(void) const; + virtual bool isHoloviewerMode(void) const; + virtual bool isHoloscreenMode(void) const; + virtual bool isLivingroomMode(void) const; + virtual bool isExitingLevel(void) const; + virtual bool isNotVLRMode(void) const; + virtual bool isHoloRealityMode(void) const; + virtual bool isRealityFullVRMode(void) const; + virtual bool isInBedScreen(void) const; + virtual bool isKeyboardEnabled(void) const; + virtual bool isVRTransitioning(void) const; + virtual bool hasCommands(void) const; + virtual bool isScriptingEnabled(void) const; + +private: + virtual __int64 getHoloviewerScale(void) const; + virtual __int64 getSplitScreenCount(void) const; + +public: + virtual bool isStereoRendering(void) const; + virtual bool isPlatformNX(void) const; + virtual bool isLocalSplitscreenWith(__int64 const&) const; + virtual bool isValidCrossPlatformSkin(void) const; + virtual __int64 sub_1400C9B70(void); + +private: + virtual __int64 getSplitScreenInfo(void) const; + virtual __int64 getCurrentMaxGUIScaleIndex(void) const; + virtual __int64 getRealityModeFrameFactor(void) const; + +public: + virtual void setRealityModeFrameFactor(float const&); + +private: + virtual __int64 getRealityModeToggleTriggered(void) const; + +public: + virtual void setRealityModeToggleTriggered(bool); + +private: + virtual bool sub_1400C9C50(void); + +public: + virtual void setOpenControllerDisconnectScreen(bool); + +private: + virtual __int64 getClientPlayMode(void) const; + +public: + virtual void setClientPlayMode(__int64 const&); + +private: + virtual __int64 getLivingRoomForCredits(void) const; + +public: + virtual void setLivingRoomForCredits(bool); + +private: + virtual __int64 getCreditsCallback(void); + +public: + virtual void setCreditsCallback(__int64); + virtual void setupTransitionForCredits(__int64); + +private: + virtual __int64 refreshScreenSizeData(void); + virtual __int64 onScreenSizeChanged(int, int, float); + virtual __int64 onGuiScaleOffsetChanged(void); + virtual __int64 onSafeZoneChanged(void); + virtual __int64 quit(std::string const&, std::string const&); + +public: + virtual __int64 getMinecraftGame(void) const; + +private: + virtual __int64 getAutomationClient(void) const; + virtual __int64 getScreenshotStreamer(void) const; + virtual __int64 getEventing(void) const; + virtual __int64 sub_1400CA2E0(__int64 a1); + virtual __int64 sub_1400CA2E8(__int64 a1); + virtual __int64 sub_1400CA2F0(__int64 a1); + virtual C_Font* getFont(void) const; + virtual C_Font* getRuneFont(void) const; + virtual C_Font* getUnicodeFont(void) const; + virtual __int64 getGeometryGroup(void) const; + virtual __int64 getMultiplayerServiceManager(void) const; + virtual __int64 getLocalServerLevel(void); + virtual __int64 getResourcePackRepository(void) const; + virtual __int64 getResourcePackManager(void) const; + virtual __int64 getSkinRepository(void) const; + virtual __int64 getSkinRepositoryClientInterface(void) const; + virtual __int64 sub_140630650(void) const; + virtual void test0(); + virtual void test1(); + virtual __int64 sub_1400CA400(void) const; + virtual __int64 getTextures(void) const; + virtual __int64 getStoreCacheTextures(void) const; + virtual __int64 getMinecraftGraphics(void) const; + virtual __int64 getUIRepository(void) const; + virtual __int64 getUserManager(void) const; + virtual __int64 wantToQuit(void) const; + +public: + virtual bool isPrimaryLevelCrossPlatformMultiplayer(void) const; + virtual bool isPrimaryLevelMultiplayer(void) const; + virtual bool isAdhocEnabled(void) const; + +private: + virtual char sub_1406A1620(void) const; + virtual __int64 linkToOffer(std::string const&, bool, std::string const&, __int64); + virtual __int64 linkToAllOffers(std::string const&, std::string const&, bool, std::string const&, bool); + virtual __int64 navigateToBrazeScreen(std::string const&, std::string const&, std::string const&, std::string const&, std::string const&, std::string const&, std::string const&); + virtual __int64 navigateToStoreHomeScreen(void); + virtual __int64 navigateToCoinPurchaseScreen(int, __int64); + virtual __int64 navigateToPurchaseOfferScreen(__int64, bool); + virtual __int64 navigateToOfferCollectionScreen(__int64&); + virtual __int64 navigateToStoreSeeAllByCreatorScreen(std::string const&, bool); + virtual __int64 navigateToServersScreen(bool); + virtual __int64 navigateToHowToPlayScreen(std::string const&); + virtual __int64 tryPushLeaveGameScreen(void); + virtual char sub_1400D16A0(void) const; + +public: + virtual bool isReadyToRender(void) const; + +private: + virtual __int64 onDimensionChanged(void); + virtual __int64 onGameEventNotification(__int64); + +public: + virtual TextHolder getTopScreenName(void) const; + virtual void setLeaveGameInProgressAsReadyToContinue(void); + +private: + virtual __int64 stopDestroying(void); + virtual __int64 onClientCreatedLevel(__int64); + virtual __int64 getClientRandomId(void) const; + virtual __int64 getUserAuthentication(void); + virtual __int64 sub_1400CAC50(__int64* a2); + virtual __int64 registerToUserManager(__int64&, int); + virtual __int64 resumeWithUserManager(__int64&, int); + virtual __int64 createUserAuthentication(std::string); + virtual __int64 createUserAuthentication(unsigned long long, std::string const&); + virtual __int64 getPlatformId(void) const; + virtual __int64 getPlatformOnlineId(void) const; + +public: + virtual bool isHoloCursorNeeded(void) const; + +private: + virtual __int64 useController(void) const; + virtual __int64 useTouchscreen(void) const; + +public: + virtual bool getMouseGrabbed(void) const; + +private: + virtual __int64 currentInputModeIsGamePadOrMotionController(void) const; + virtual __int64 currentInputModeIsMouseAndKeyboard(void) const; + virtual __int64 getForceMonoscopic(void) const; + virtual __int64 allowPicking(void) const; + +public: + virtual bool isShowingMenu(void) const; + virtual bool isShowingProgressScreen(void) const; + virtual bool isShowingWorldProgressScreen(void) const; + virtual bool isShowingDeathScreen(void) const; + virtual bool isScreenReplaceable(void) const; + virtual bool isInGame(void) const; + virtual bool sub_14070D6F0(void) const; + virtual bool isInRealm(void); + +private: + virtual __int64 readyForShutdown(void) const; + +public: + virtual bool isPrimaryClient(void) const; + virtual bool isEduMode(void) const; + virtual bool isGamepadCursorEnabled(void) const; + +private: + virtual Minecraft* getServerData(void); + virtual Minecraft* getServerData(void) const; + +public: + virtual PointingStruct* getLevel(void); + virtual PointingStruct* getLevel(void) const; + virtual bool isPreGame(void) const; + virtual bool isInMultiplayerGame(void) const; + virtual bool isMultiC_PlayerClient(void) const; + virtual __int64 sub_14012F590() const; + virtual __int64 sub_14012F4D0() const; + virtual __int64 getOptions(void); + virtual __int64 getOptions(void) const; + //virtual __int64 getOptionsPtr(void); + virtual __int64 getUser(void); + virtual __int64 getUser(void) const; + virtual __int64 getGameRenderer(void) const; + virtual __int64 getHolosceneRenderer(void) const; + virtual __int64 getLevelRenderer(void) const; + virtual __int64 getLevelRendererCameraProxy(void) const; +public: + virtual C_CameraManager* getCameraManager(void) const; +private: + virtual __int64 sub_1400CCC08(void) const; + +public: + virtual __int64 getLightTexture(void); + +public: + virtual void setupLevelRendering(__int64&, C_Entity&); + +private: + virtual __int64 getViewportInfo(void) const; + +public: + virtual void setViewportInfo(__int64 const&); + +private: + virtual __int64 getNormalizedViewportSize(void) const; + virtual __int64 updateChunkRadius(void); + +public: + virtual void setUITexture(__int64*); + +private: + virtual __int64 getUITexture(void); + +public: + virtual void setLevelTexture(__int64*); + +private: + virtual __int64 getLevelTexture(void); + +public: + virtual void setUICursorTexture(__int64); + + virtual __int64 getUICursorTexture(void) const; + virtual __int64 getCamera(void); + virtual __int64 getShaderColor(void); + virtual __int64 getDarkShaderColor(void); + virtual __int64 clearGraphicsCache(void); + virtual __int64 getNormalizedUICursorTransform(__int64&, float); + virtual __int64 shouldRenderUICursor(void) const; + virtual bool sub_1400CD3B0(void); + virtual bool sub_1400CD3B1(void); + virtual __int64 getGuiScale(void) const; + virtual __int64 getGuiScaleOption(void) const; + virtual __int64 getGuiScaleOffset(void) const; + +public: + virtual void setGuiScaleOffset(int); + +private: + virtual __int64 renderEditorGui(__int64&, bool); + +public: + virtual C_GuiData* getGuiData(void); + virtual C_GuiData* getGuiData(void) const; + +private: + virtual __int64 getGuidedFlowManager(void); + virtual __int64 getDpadScale(void) const; + virtual __int64 getDateManager(void) const; + virtual __int64 addOverrideHoursToDateTime(unsigned int); + virtual __int64 getToastManager(void); + virtual __int64 getTopScene(void); + virtual __int64 getTopScene(void) const; + virtual __int64 getActiveScene(void); + virtual __int64 getActiveScene(void) const; + virtual __int64 getSceneFactory(void) const; + virtual __int64 getClientSceneStack(void) const; + virtual __int64 getClientSceneStack(void); + virtual __int64 sub_140634B30(void) const; + virtual __int64 getMainSceneStack(void); + virtual __int64 getMainSceneStack(void) const; + virtual __int64 getCurrentSceneStack(void) const; + virtual __int64 getCurrentSceneStack(void); + virtual __int64 getCurrentUIRouter(void); + virtual __int64 getCurrentUIRouter(void) const; + virtual __int64 sub_14012BAB0(void) const; + virtual __int64 prepareSceneFor(__int64); + virtual __int64 getCachedScenes(void); + +public: + virtual TextHolder getScreenName(void) const; + +private: + virtual __int64 getScreenTelemetry(void) const; + virtual __int64 getTopSceneType(void) const; + virtual __int64 getMobEffectsLayout(void); + virtual __int64 newFunc2(__int64 a2, __int64 a3, char a4); + virtual __int64 newFunc3(__int64 a2, __int64 a3); + virtual __int64 onMobEffectsChange(void); + +public: + virtual void setUISizeAndScale(int, int, float); + +private: + virtual __int64 forEachVisibleScreen(__int64, bool); + virtual __int64 forEachScreen(__int64, bool); + virtual __int64 forEachScreenConst(__int64, bool) const; + virtual __int64 updateSceneStack(void); + virtual __int64 forEachAlwaysAcceptInputScreen(__int64); + virtual __int64 forEachAlwaysAcceptInputScreenWithTop(__int64); + virtual __int64 showC_PlayerProfile(std::string const&, __int64); + virtual __int64 getCurrentInputMode(void) const; + +public: + virtual bool isTouchGameplayAllowed(void) const; + +private: + virtual __int64 getMinecraftInput(void) const; + +public: + virtual void setHoloInput(__int64); + +private: + virtual __int64 getHoloInput(void) const; + virtual __int64 getVoiceSystem(void) const; + virtual __int64 getKeyboardManager(void); + +public: + virtual void setVoiceSystem(__int64); + virtual void setLastPointerLocation(float, float, float); + +private: + virtual __int64 getLastPointerLocation(void); + virtual __int64 shouldUseLastPointerLocationOnFocusChange(void); + virtual __int64 adjustGazeCursorByMouse(float, float); + virtual __int64 currentScreenShouldStealMouse(void); + virtual __int64 getInProgressBAI(void) const; + virtual __int64 newDictationDataAvailable(void) const; + virtual __int64 clearDictationDataAvailable(void); + virtual __int64 getDictationText(void) const; + virtual __int64 getPacketSender(void); + virtual __int64 getClientNetworkSystem(void); + virtual __int64 getClientNetworkSystem(void) const; + +public: + virtual void setMoveTurnInput(__int64); + virtual C_MoveInputHandler* getMoveTurnInput(void); + +public: + virtual void setupPersistentControls(__int64); + +private: + virtual __int64 resetC_PlayerMovement(void); + virtual __int64 onClientInputInitComplete(void); + +public: + virtual void setClientInputHandler(__int64); + +private: + virtual __int64 getInput(void) const; + virtual __int64 getControllerId(void) const; + +public: + virtual bool hasConnectedController(void) const; + +private: + virtual __int64 getClientSubId(void) const; + +public: + virtual void setSuspendInput(bool); + virtual void setDisableInput(bool); + +private: + virtual void subFunction(void) const; + +public: + virtual void grabMouse(void); + virtual void releaseMouse(void); + virtual void refocusMouse(void); + +private: + virtual __int64 resetBai(int); + virtual __int64 clearInProgressBAI(void); + virtual __int64 tickBuildAction(void); + virtual __int64 getSoundEngine(void) const; + virtual __int64 play(std::string const&, vec3_t const&, float, float); + virtual __int64 playUI(std::string const&, float, float); + virtual __int64 muteAudio(void); + virtual __int64 unMuteAudio(void); + virtual __int64 fadeOutMusic(void) const; + virtual __int64 getTaskGroup(void); + virtual __int64 onFullVanillaPackOnStack(void); + +public: + virtual bool isFullVanillaPackOnStack(void) const; + +private: + virtual __int64 onPlayerLoaded(C_Player&); + +public: + virtual void setClientGameMode(__int64); + +private: + virtual __int64 resetToDefaultGameMode(void); + virtual __int64 connectToThirdParyServer(std::string const&, std::string const&, int); + virtual __int64 startExternalNetworkWorld(__int64, std::string const&, bool); + virtual __int64 checkForPiracy(void); + virtual __int64 updateChatFilterStatus(void); + virtual void sub_1400D2A20(void); + +public: + virtual void setBehaviorCommandCallback(__int64); + virtual void setBehaviorCommandStatus(std::string, __int64); + +private: + virtual __int64 requestScreenshot(__int64&); + virtual void sub_1400BE0A0(char a2); + virtual __int64 getDevConsoleLogger(void) const; + virtual __int64 requestImageFromUrl(std::string const&, __int64); + virtual __int64 initializeRenderResources(void); + virtual __int64 postInitRenderResources(void); + virtual __int64 onAppSuspended(void); + virtual __int64 onActiveResourcePacksChanged(__int64 const&); + virtual __int64 reloadEntityRenderers(__int64 const&); + virtual __int64 getBlockTessellator(void); + virtual __int64 getBlockEntityRenderDispatcher(void); + virtual __int64 getEntityRenderDispatcher(void); + virtual __int64 getEntityBlockRenderer(void); + virtual __int64 getItemInHandRenderer(void); + virtual __int64 getItemRenderer(void); + virtual __int64 getSentMessageHistory(void); + virtual __int64 getUIProfanityContext(void) const; + virtual __int64 initTTSClient(__int64&); + virtual __int64 getTTSClient(void); + virtual __int64 getTTSClient(void) const; + virtual __int64 getTTSEventManager(void); + virtual __int64 addTTSMessage(std::string const&, __int64, bool, bool, bool); + virtual __int64 initCommands(void); + virtual __int64 getUserId(void) const; + virtual __int64 getServerConnectionTime(void) const; + virtual __int64 getHMDState(void); + virtual __int64 getHMDState(void) const; + +public: + virtual void setServerPingTime(unsigned int); + +private: + virtual __int64 getServerPingTime(void) const; + +public: + virtual void setDefaultPlayscreenTab(__int64); + virtual void setClientInstanceState(__int64 const&); + virtual void setUIEventCoordinator(__int64&&); + +private: + virtual __int64 getUIEventCoordinator(void); + virtual __int64 getEventCoordinator(void); + virtual __int64 computeScreenCoordsFromScreenNormCoords(float, float, short&, short&); + virtual __int64 getNoBlockBreakUntil(void); + +public: + virtual void setNoBlockBreakUntil(__int64); + virtual void setDictation(std::string const&); + virtual void setNewDictationString(bool); + virtual void setGameModule(__int64); + +private: + virtual __int64 getGameModule(void); + virtual __int64 getGameCallbacks(void); + virtual __int64 getStorageAreaStateListener(void); + virtual __int64 getScriptEngine(void); + virtual __int64 sendClientEnteredLevel(void); + virtual __int64 getHitDetectSystem(void); + +public: + virtual bool isPlaying(void) const; + +private: + virtual __int64 getLatencyGraphDisplay(void) const; + virtual __int64 createSkin(void); + virtual __int64 onExtendDiskSpace(bool, __int64&, unsigned long long const&, __int64); + virtual __int64 onLowDiskSpace(bool); + virtual __int64 onOutOfDiskSpace(bool); + virtual __int64 onCriticalDiskError(bool, __int64 const&); + virtual __int64 onLevelCorrupt(void); + virtual __int64 onGameModeChanged(void); + virtual __int64 onTick(int, int); + virtual __int64 onInternetUpdate(void); + virtual __int64 onGameSessionReset(void); + virtual __int64 onLevelExit(void); + virtual __int64 updateScreens(void); + +public: + C_LocalPlayer* getLocalPlayerDONTUSEPLS() { + return localPlayer; + }; + + PointingStruct* getPointerStruct() { + return this->getLevel(); + } + + glmatrixf* getRefDef() { + uintptr_t _this = reinterpret_cast(this); + //logF("refderf %llX", _this + 0x258); + return reinterpret_cast(_this + 0x2E0); + }; + + vec2_t* getMousePos() { + uintptr_t _this = reinterpret_cast(this); + return reinterpret_cast(_this + 0x448); + } + + vec2_t getFov() { + uintptr_t _this = reinterpret_cast(this); + vec2_t fov; + fov.x = *reinterpret_cast(_this + 0x660); + fov.y = *reinterpret_cast(_this + 0x674); + return fov; + } + + C_Font* _getFont() { + return this->getFont(); + } + + C_Font* _getRuneFont() { + return this->getRuneFont(); + } + + C_Font* _getUnicodeFont() { + return this->getUnicodeFont(); + } + + inline C_GameSettingsInput* getGameSettingsInput() { return this->ptr->ptr->ptr->settingsInput; }; +}; diff --git a/SDK/CClientInstanceScreenModel.h b/SDK/CClientInstanceScreenModel.h new file mode 100644 index 0000000..579bc71 --- /dev/null +++ b/SDK/CClientInstanceScreenModel.h @@ -0,0 +1,14 @@ +#pragma once + +#include "../Utils/Utils.h" + +class C_ClientInstanceScreenModel { +public: + void sendChatMessage(char* message) { + using sendChatMessage = void(__fastcall*)(void*, char*); + static sendChatMessage sendChatMessageFunc = reinterpret_cast(FindSignature("56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 C7 45 D8 ?? ?? ?? ?? 48 89 9C 24 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 48 89 54 24 ??") - 2); + + if (sendChatMessageFunc != 0x0) + sendChatMessageFunc(this, (char*)std::string(message).c_str()); + } +}; diff --git a/SDK/CComplexInventoryTransaction.cpp b/SDK/CComplexInventoryTransaction.cpp new file mode 100644 index 0000000..e2e591d --- /dev/null +++ b/SDK/CComplexInventoryTransaction.cpp @@ -0,0 +1,72 @@ +#include "CComplexInventoryTransaction.h" +#include "../Utils/Utils.h" +C_ComplexInventoryTransaction::C_ComplexInventoryTransaction(C_InventoryTransaction& transac) { + static uintptr_t** ComplexInventoryTransactionVtable = 0x0; + if (ComplexInventoryTransactionVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 03 89 73 08 48"); + int offset = *reinterpret_cast(sigOffset + 3); + ComplexInventoryTransactionVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (ComplexInventoryTransactionVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_ComplexInventoryTransaction)); // Avoid overwriting vtable + vTable = ComplexInventoryTransactionVtable; + uintptr_t boi = reinterpret_cast(this); + using constructor_t = void(__fastcall*)(uintptr_t, C_InventoryTransaction&); + static constructor_t constructor = reinterpret_cast(FindSignature("48 89 4C 24 ?? 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 ?? 48 89 74 24 ?? 48 8B DA 48 8B F9 48 89 4C 24 ?? 8B 02 89 01 33 F6 48 89 71 ??")); + if (constructor != 0) + constructor(boi + 0x10, transac); + this->actionType = 0; +} +C_ComplexInventoryTransaction::C_ComplexInventoryTransaction() { + memset(this, 0, sizeof(C_ComplexInventoryTransaction)); + static uintptr_t** ComplexInventoryTransactionVtable = 0x0; + if (ComplexInventoryTransactionVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 03 89 73 08 48"); + int offset = *reinterpret_cast(sigOffset + 3); + ComplexInventoryTransactionVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (ComplexInventoryTransactionVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + vTable = ComplexInventoryTransactionVtable; +} +C_ItemUseInventoryTransaction::C_ItemUseInventoryTransaction() { + memset(this, 0x0, sizeof(C_ItemUseInventoryTransaction)); + using ItemUseInventoryTransactionContructor = void(__fastcall*)(C_ItemUseInventoryTransaction*); + static ItemUseInventoryTransactionContructor constructor = reinterpret_cast(FindSignature("48 89 4C 24 08 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 50 48 89 74 24 58 48 8B F9 48 8D 05 ?? ?? ?? ?? 48 89 01 C7 41 ?? ?? ?? ?? ?? 48 8D 59 ?? 48 89 5C 24 ?? 48 8B CB E8 ?? ?? ?? ?? 33 F6 48 89 73 ?? 48 89 73 ?? 48 89 73 ?? 48 8D 05 ?? ?? ?? ?? 48 89 07 48 89 77 ?? 48 89 77 ?? 89 77 ?? 40 88 77 ?? 89")); + if (constructor != 0) + constructor(this); +} +C_ItemUseInventoryTransaction::C_ItemUseInventoryTransaction(int slot, const C_ItemStack* item, const vec3_t pos, int blockSide, int runtimeBlockId) { + memset(this, 0x0, sizeof(C_ItemUseInventoryTransaction)); + using ItemUseInventoryTransactionContructor = void(__fastcall*)(C_ItemUseInventoryTransaction*); + static ItemUseInventoryTransactionContructor constructor = reinterpret_cast(FindSignature("48 89 4C 24 08 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 50 48 89 74 24 58 48 8B F9 48 8D 05 ?? ?? ?? ?? 48 89 01 C7 41 ?? ?? ?? ?? ?? 48 8D 59 ?? 48 89 5C 24 ?? 48 8B CB E8 ?? ?? ?? ?? 33 F6 48 89 73 ?? 48 89 73 ?? 48 89 73 ?? 48 8D 05 ?? ?? ?? ?? 48 89 07 48 89 77 ?? 48 89 77 ?? 89 77 ?? 40 88 77 ?? 89")); + if (constructor != 0) + constructor(this); + this->slot = slot; + this->item = *item; + this->pos = pos; + this->runtimeBlockId = runtimeBlockId; + this->blockSide = blockSide; +} +C_ItemReleaseInventoryTransaction::C_ItemReleaseInventoryTransaction() { + memset(this, 0x0, sizeof(C_ItemReleaseInventoryTransaction)); + using ItemReleaseInventoryTransactionContructor = void(__fastcall*)(C_ItemReleaseInventoryTransaction*); + static ItemReleaseInventoryTransactionContructor constructor = reinterpret_cast(FindSignature("48 89 4C 24 ?? 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 ?? 48 89 74 24 ?? 48 8B F9 48 8D 05 ?? ?? ?? ?? 48 89 01 C7 41 ?? ?? ?? ?? ?? 48 8D 59 ?? 48 89 5C 24 ?? 48 8B CB")); + if (constructor != 0) + constructor(this); +} +C_ItemReleaseInventoryTransaction::C_ItemReleaseInventoryTransaction(int slot, const C_ItemStack* item, const vec3_t pos) { + memset(this, 0x0, sizeof(C_ItemReleaseInventoryTransaction)); + using ItemReleaseInventoryTransactionContructor = void(__fastcall*)(C_ItemReleaseInventoryTransaction*); + static ItemReleaseInventoryTransactionContructor constructor = reinterpret_cast(FindSignature("48 89 4C 24 ?? 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 ?? 48 89 74 24 ?? 48 8B F9 48 8D 05 ?? ?? ?? ?? 48 89 01 C7 41 ?? ?? ?? ?? ?? 48 8D 59 ?? 48 89 5C 24 ?? 48 8B CB")); + if (constructor != 0) + constructor(this); + this->slot = slot; + this->item = *item; + this->pos = pos; +} diff --git a/SDK/CComplexInventoryTransaction.h b/SDK/CComplexInventoryTransaction.h new file mode 100644 index 0000000..b4de306 --- /dev/null +++ b/SDK/CComplexInventoryTransaction.h @@ -0,0 +1,48 @@ +#pragma once +#include "../Utils/HMath.h" +#include "CInventory.h" +#include "CInventoryTransaction.h" + +class C_ComplexInventoryTransaction { +public: + C_ComplexInventoryTransaction(); + C_ComplexInventoryTransaction(C_InventoryTransaction& transac); + uintptr_t** vTable; //0x0000 + int actionType; //0x8 + int unknown; //0xC + C_InventoryTransaction transac; //0x10 +}; + +class C_ItemUseInventoryTransaction : public C_ComplexInventoryTransaction { +public: + C_ItemUseInventoryTransaction(); + C_ItemUseInventoryTransaction(int slot, C_ItemStack const* item, vec3_t const pos, int blockSide = 255, int runtimeBlockId = 0); + +private: + char pad_0x68[0x4]; //0x68 +public: + vec3_ti blockPos; //0x6C + int runtimeBlockId; //0x78 + int blockSide; //0x7C + int slot; //0x80 +private: + char pad_0x84[0x4]; //0x84 +public: + C_ItemStack item; //0x88 + vec3_t pos; //0x110 + vec3_t clickPos; //0x11C +}; + +class C_ItemReleaseInventoryTransaction : public C_ComplexInventoryTransaction { +public: + C_ItemReleaseInventoryTransaction(); + C_ItemReleaseInventoryTransaction(int slot, C_ItemStack const* item, vec3_t const pos); + +private: + char pad_0x68[0x4]; //0x68 +public: + int slot; //0x6C + C_ItemStack item; //0x70 + vec3_t pos; //0xF8 + int unknown; //0x104 +}; diff --git a/SDK/CEntity.cpp b/SDK/CEntity.cpp new file mode 100644 index 0000000..e1c94cf --- /dev/null +++ b/SDK/CEntity.cpp @@ -0,0 +1,52 @@ +#include "CEntity.h" +#include "../Utils/Utils.h" +#include "../Memory/GameData.h" +C_InventoryTransactionManager *C_Entity::getTransactionManager() { + static unsigned int offset = 0; + if (offset == 0) { + // EnchantCommand::execute + //offset = *reinterpret_cast(FindSignature("48 8D 8B ?? ?? ?? ?? E8 ?? ?? ?? ?? 90 48 8D 8D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8D 8D ?? ?? ?? ?? E8 ?? ?? ?? ?? 48 8B ?? ?? ?? 8B") + 3); + offset = *reinterpret_cast(FindSignature("48 8D 8F ? ? ? ? E8 ? ? ? ? 90 48 8D 4D ? E8 ? ? ? ? 48 8B 8D ? ? ? ? 8B 81 ? ? ? ?") + 3); + } + return reinterpret_cast(reinterpret_cast<__int64>(this) + offset); +} +C_PlayerInventoryProxy *C_Player::getSupplies() { + static unsigned int offset = 0xC88; + /*if (offset == 0) { + offset = *reinterpret_cast(FindSignature("48 8B 51 ?? 4C 8B 82 ?? ?? ?? ?? 48 8B B2 ?? ?? ?? ?? 41 80 B8") + 7); // GameMode::startDestroyBlock -> GameMode::_canDestroy -> getSupplies + }*/ + return *reinterpret_cast(reinterpret_cast<__int64>(this) + offset); +} +void C_LocalPlayer::unlockAchievments() { // MinecraftEventing::fireEventAwardAchievement + using fireEventAward = void(__fastcall *)(void *, int); + static fireEventAward fireEventAwardFunc = reinterpret_cast(FindSignature("48 85 C9 0F 84 ?? ?? ?? ?? 55 56 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 C7 44 24 ?? FE FF FF FF 48 89 9C 24 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 8B")); + for (int i = 0; i < 100; i++) + fireEventAwardFunc(this, i); +} +void C_LocalPlayer::applyTurnDelta(vec2_t *viewAngleDelta) { + using applyTurnDelta = void(__thiscall *)(void *, vec2_t *); + static applyTurnDelta TurnDelta = reinterpret_cast(FindSignature("48 89 5C 24 ?? 57 48 83 EC ?? 48 8B D9 0F 29 74 24 ?? 48 8B 89 ?? ?? ?? ?? 48 8B ?? 0F 29 7C 24 ?? 44 0F")); + TurnDelta(this, viewAngleDelta); +} +void C_LocalPlayer::setGameModeType(int gma) { + // Player::setPlayerGameType + //using setGameMode = void(__thiscall *)(void *, int); + //static setGameMode Game_Mode = reinterpret_cast(FindSignature("48 8B C4 56 57 41 56 48 81 EC ? ? ? ? 48 C7 44 24 ? ? ? ? ? 48 89 58 ? 48 89 68 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 84 24 ? ? ? ? 8B EA 48 8B D9 44 8B B1 ? ? ? ? 83 FA ? 75 2D")); + this->setC_PlayerGameType(gma); +} + +bool PointingStruct::hasEntity() { + return rayHitType == 1; +} + +C_Entity *PointingStruct::getEntity() { + if (rayHitType != 1) return nullptr; + C_Entity *retval = nullptr; + g_Data.forEachEntity([this, &retval](C_Entity *ent, bool b) { + if (*(__int64 *)((__int64)ent + 0x10) == GamingEntityFinder) { + retval = ent; + return; + } + }); + return retval; +} diff --git a/SDK/CEntity.h b/SDK/CEntity.h new file mode 100644 index 0000000..d956c5c --- /dev/null +++ b/SDK/CEntity.h @@ -0,0 +1,898 @@ +#pragma once + +#include "../Utils/HMath.h" +#include "CBlockLegacy.h" +#include "CEntityList.h" +#include "CInventory.h" +#include "CInventoryTransaction.h" +#include "TextHolder.h" +#include "../Utils/Utils.h" + +class C_GameMode; + +class PointingStruct { + char pad_0x0000[0x980]; //0x0000 +public: + int rayHitType; //0x08E0 + int blockSide; //0x08E4 + vec3_ti block; //0x08E8 + vec3_t rayHitVec; //0x08F4 +private: + C_Entity *entityPtr; //0x0900 + C_Entity *entityPtr2; //0x0908 + uint64_t GamingEntityFinder; //0x0910 + +public: + bool hasEntity(); //to not go trough the entity list twice + C_Entity *getEntity(); //returns the entity that the player is looking at +}; + +class C_Player; + +#pragma pack(push, 4) +class C_Entity { +public: + uintptr_t *ptrToPtrToEntList; //0x0008 +private: + char pad_0010[0x130]; //0x0010 +public: + union { + struct { + float pitch; //0x0120 + float yaw; //0x0124 + }; + vec2_t viewAngles; + }; + union { + struct { + float pitch2; + float yaw2; + }; + vec2_t viewAngles2; // 0x128 + }; + +private: + char pad_0100[0x10]; //0x0130 +public: + vec3_t eyePos0; //0x0140 +private: + char pad_0x11C[0x70]; //0x14C +public: + float fallDistance; //0x1BC + bool onGround; //0x01C0 +private: + char pad_0x179[0x5F]; //0x1C1 +public: + float stepHeight; //0x220 +private: + char pad_0x228[0x10]; //0x224 +public: + vec3_t slowdownFactor; + +private: + char pad_0x23C[0x5]; //0x0238 +public: + bool didEnterWaterBool; //0x0245 +private: + char pad_023E[0x4A]; //0x0246 +public: + int ticksAlive; //0x0294 +private: + char pad_0290[0xB4]; //0x0298 +public: + C_BlockSource *region; //0x348 +private: + char pad_0x340[0x160]; //0x350 +public: + AABB aabb; //0x0498 + float width; //0x04B4 + float height; //0x04B8 + vec3_t currentPos; //0x04BC + vec3_t oldPos; //0x04C8 + vec3_t velocity; //0x04D4 +private: + char pad_0x0478[0x58]; //0x4E0 +public: + __int64 entityRuntimeId; //0x538 +private: + char pad_0478[0x1A8]; //0x0540 +public: + float bodyYaw; //0x0688 + float oldBodyYaw; //0x068C + float yawUnused1; //0x0690 + float yawUnused2; //0x0694 + int damageTime; //0x0698 +private: + char pad_0824[0x8C]; //0x069C +public: + int timeSinceDeath; //0x0728 +private: + char pad_08B0[0x15C]; //0x072C +public: + TextHolder playerName; + +private: + char pad_08B8[0x8C]; + +public: + bool canFly; //0x092C +private: + char pad_0x0A95[0x6C3]; //0x092D +public: + int16_t itemData; //0x0FF0 + int16_t itemId; //0x0FF2 +private: + char pad_10CC[0x1FC]; //0x0FF4 +public: + C_InventoryTransactionManager transac; //0x11F0 +private: + char pad_0x1324[0xAA4]; //0x1258 +public: + int gamemode; //0x1CFC +private: + char pad_1DA4[0x260]; //0x1D00 +public: + TextHolder uuid; //0x1F60 + +private: + virtual __int64 reloadHardcoded(__int64, __int64 const &); + virtual __int64 reloadHardcodedClient(__int64, __int64 const &); + virtual __int64 initializeComponents(__int64, __int64 const &); + virtual __int64 reloadComponents(__int64, __int64 const &); + virtual __int64 _serverInitItemStackIds(); + virtual __int64 _doInitialMove(); + virtual bool hasComponent(__int64 const &) const; + +private: + virtual void destructor(); + // Duplicate destructor + virtual __int64 reset(void); + virtual __int64 getOnDeathExperience(void); + virtual __int64 getOwnerEntityType(void); + virtual __int64 remove(void); + +public: + virtual void setPos(vec3_t const &); + virtual bool isRuntimePredictedMovementEnabled(void); + virtual vec3_t *getPredictedMovementValues(void) const; + virtual vec3_t *getPos(void) const; // getStateVectorComponent + virtual vec3_t *getPosOld(void) const; + virtual vec3_t *getPosExtrapolated(float) const; + +private: + virtual __int64 getAttachPos(__int64, float) const; + virtual __int64 getFiringPos(void) const; + +public: + virtual void setRot(vec2_t const &); + virtual void move(class IActorMovementProxy &, vec3_t const &); + virtual void move(vec3_t const &); + virtual __int64 getInterpolatedRidingPosition(float) const; + virtual __int64 getInterpolatedBodyRot(float) const; + virtual __int64 getInterpolatedHeadRot(float) const; + virtual __int64 getInterpolatedBodyYaw(float) const; + virtual __int64 getYawSpeedInDegreesPerSecond(void) const; + virtual __int64 getInterpolatedWalkAnimSpeed(float) const; + virtual __int64 getWorldPosition(); + virtual void checkBlockCollisions(AABB const &); + virtual void updateEntityInside(); + virtual void updateEntityInside(AABB const &); + virtual bool isFireImmune(); + virtual bool breaksFallingBlocks(void) const; + virtual bool blockedByShield(__int64 const &, C_Entity &); + virtual void teleportTo(vec3_t const &, bool, int, int); + virtual void tryTeleportTo(vec3_t const &, bool, bool, int, int); + virtual void chorusFruitTeleport(vec3_t &); + virtual __int64 lerpTo(vec3_t const &, vec2_t const &, int); + virtual void lerpMotion(vec3_t const &); + +private: + virtual __int64 getAddPacket(void); + virtual __int64 normalTick(void); + virtual __int64 baseTick(void); + virtual __int64 rideTick(void); + virtual __int64 positionRider(C_Entity &, float); + virtual __int64 getRidingHeight(void); + virtual __int64 startRiding(C_Entity &); + virtual __int64 addRider(C_Entity &); + virtual __int64 flagRiderToRemove(C_Entity &); + virtual __int64 getExitTip(std::string const &, __int64) const; + virtual __int64 intersects(vec3_t const &, vec3_t const &) const; + +public: + virtual bool isFree(vec3_t const &, float); + virtual bool isFree(vec3_t const &); + virtual bool isInWall(void) const; + virtual bool isInvisible(void) const; + virtual bool canShowNameTag(void) const; + virtual bool canExistInPeaceful(void) const; + virtual void setNameTagVisible(bool); + virtual TextHolder *getNameTag(void) const; + +private: + virtual __int64 getNameTagAsHash(void) const; + +public: + virtual TextHolder *getFormattedNameTag(void) const; + +private: + virtual __int64 filterFormattedNameTag(__int64 const &); + +public: + virtual void setNameTag(std::string const &); + +private: + virtual __int64 getAlwaysShowNameTag(void) const; + +public: + virtual void setScoreTag(std::string const &); + virtual TextHolder *getScoreTag(void) const; + +public: + virtual bool isInWater(void) const; + virtual bool hasEnteredWater(void) const; + virtual bool isImmersedInWater(void) const; + virtual bool isInLava(void) const; + virtual bool isUnderLiquid(__int64) const; + virtual bool isOverWater(void) const; + +private: + virtual __int64 setBlockMovementSlowdownMultiplier(vec3_t const &); + virtual __int64 resetBlockMovementSlowdownMultiplier(); + virtual __int64 getCameraOffset(void) const; + virtual __int64 getShadowHeightOffs(void); + virtual __int64 getShadowRadius(void) const; + virtual __int64 getHeadLookVector(float); + +public: + virtual bool canSeeInvisible(void) const; + virtual bool canSee(vec3_t const &) const; + virtual bool canSee(C_Entity const &) const; + virtual bool isSkyLit(float); + +private: + virtual __int64 getBrightness(float) const; + virtual __int64 interactPreventDefault(void); + virtual __int64 playerTouch(C_Player &); + virtual __int64 onAboveBubbleColumn(bool); + virtual __int64 onInsideBubbleColumn(bool); + +public: + virtual bool isImmobile(void) const; + virtual bool isSilent(void); + virtual bool isPickable(void); + virtual bool isFishable(void) const; + virtual bool isSleeping(); + virtual bool isPushable(void) const; + virtual void setSneaking(bool); + virtual bool isBlocking(void) const; + virtual bool isDamageBlocked(__int64 const &) const; + virtual bool isAlive(void) const; + virtual bool isOnFire(void) const; + virtual bool isOnHotBlock(void) const; + virtual bool isCreativeModeAllowed(void); + virtual bool isSurfaceMob(void) const; + virtual bool isTargetable(void) const; + virtual bool isLocalPlayer(void); + virtual bool isPlayer(void); + virtual bool isAffectedByWaterBottle(void) const; + virtual bool canAttack(C_Entity *, bool) const; + virtual void setTarget(C_Entity *); + +private: + virtual __int64 findAttackTarget(void); + +public: + virtual bool isValidTarget(C_Entity *) const; + +private: + virtual __int64 attack(C_Entity &); + virtual void performRangedAttack(C_Entity &, float); + virtual __int64 adjustDamageAmount(int &) const; + virtual __int64 getEquipmentCount(void) const; + +public: + virtual void setOwner(__int64); + virtual void setSitting(bool); + +private: + virtual __int64 onTame(void); + virtual __int64 onFailedTame(void); + virtual __int64 getInventorySize(void) const; + virtual __int64 getEquipSlots(void) const; + virtual __int64 getChestSlots(void) const; + +public: + virtual void setStanding(bool); + virtual bool canPowerJump(void) const; + virtual void setCanPowerJump(bool); + virtual bool isJumping(void) const; + virtual bool isEnchanted(void) const; + +private: + virtual __int64 rideJumped(void); + virtual __int64 rideLanded(vec3_t const &, vec3_t const &); + virtual __int64 shouldRender(void) const; + +public: + virtual bool isInvulnerableTo(__int64 const &) const; + +private: + virtual __int64 getBlockDamageCause(); + virtual void actuallyHurt(int, __int64 const *, bool); + virtual __int64 animateHurt(void); + virtual __int64 doFireHurt(int); + virtual __int64 onLightningHit(void); + virtual __int64 onBounceStarted(vec3_ti const &, __int64 const &); + virtual __int64 feed(int); + virtual __int64 handleEntityEvent(__int64, int); + virtual __int64 getPickRadius(void); + virtual const class HashedString *getActorRendererId(void); + virtual __int64 spawnAtLocation(int, int); + virtual __int64 spawnAtLocation(int, int, float); + virtual __int64 spawnAtLocation(__int64 const &, int); + virtual __int64 spawnAtLocation(__int64 const &, int, float); + virtual __int64 spawnAtLocation(__int64 const &, float); + virtual __int64 despawn(void); + virtual __int64 killed(C_Entity &); + virtual __int64 awardKillScore(C_Entity &, int); + +public: + virtual void setArmor(int, C_ItemStack const &); + virtual C_ItemStack *getArmor(int) const; + +private: + virtual __int64 getArmorMaterialTypeInSlot(__int64) const; + virtual __int64 getArmorMaterialTextureTypeInSlot(__int64) const; + virtual __int64 getArmorColorInSlot(__int64, int) const; + +public: + virtual void getEquippedSlot(__int64); + virtual void setEquippedSlot(__int64, __int64 const &); + +private: + virtual __int64 getCarriedItem(void) const; + +public: + virtual void setCarriedItem(__int64 const &); + virtual void setOffhandSlot(C_ItemStack *); + virtual C_ItemStack *getEquippedTotem(void) const; + virtual __int64 consumeTotem(void); + +public: + virtual __int64 save(CompoundTag *); + virtual __int64 saveWithoutId(CompoundTag *); + +private: + virtual __int64 load(__int64 const &, __int64 &); + virtual __int64 loadLinks(__int64 const &, __int64); + +public: + virtual uint8_t getEntityTypeId(void) const; + +private: + virtual __int64 queryEntityRenderer(void) const; + virtual __int64 getSourceUniqueID(void) const; + +public: + virtual void setOnFire(int); + + virtual __int64 extinguishFire(void); + virtual __int64 thawFreezeEffect(void); + virtual bool canFreeze(void); + virtual bool isWearingLeatherArmor(void); + +private: + virtual __int64 getHandleWaterAABB(void) const; + virtual __int64 handleInsidePortal(vec3_ti const &); + virtual __int64 getPortalCooldown(void) const; + virtual __int64 getPortalWaitTime(void) const; + +public: + virtual int *getDimensionId(int *dimOut) const; + + virtual bool canChangeDimensions(void) const; + +private: + virtual __int64 changeDimension(__int64, bool); + virtual __int64 changeDimension(__int64 const &); + virtual __int64 getControllingPlayer(void) const; // getSourceUniqueID2 + virtual __int64 checkFallDamage(float, bool); + +public: + virtual void causeFallDamage(float); + virtual void handleFallDistanceOnServer(float, bool); + +private: + virtual __int64 playSynchronizedSound(__int64, vec3_t const &, __int64 const &, bool); + virtual __int64 playSynchronizedSound(__int64, vec3_t const &, int, bool); + virtual __int64 onSynchedDataUpdate(int); + +public: + virtual bool canAddRider(C_Entity &) const; + virtual bool canBePulledIntoVehicle(void) const; + +private: + virtual bool returnTrue(void) const; + virtual __int64 inCaravan(void) const; + +public: + virtual bool isLeashableType(void); + +private: + virtual __int64 tickLeash(void); + virtual __int64 sendMotionPacketIfNeeded(void); + +public: + virtual bool canSynchronizeNewEntity(void) const; + +private: + virtual __int64 stopRiding(bool, bool, bool); + +public: + virtual void startSwimming(void); + virtual void stopSwimming(void); + +private: + virtual __int64 buildDebugInfo(std::string &) const; + virtual __int64 getCommandPermissionLevel(void) const; + virtual bool isClientSide(void); + virtual __int64 getMutableAttribute(__int64 const &); + +public: + virtual __int64 getAttribute(int *) const; + virtual __int64 getDeathTime(void) const; + virtual __int64 heal(int); + virtual bool isInvertedHealAndHarm(void) const; + virtual bool canBeAffected(__int64 const &) const; + virtual bool canBeAffected(int) const; + virtual bool canBeAffectedByArrow(__int64 const &) const; + +private: + virtual __int64 onEffectAdded(__int64 &); + virtual __int64 onEffectUpdated(__int64 const &); + virtual __int64 onEffectRemoved(__int64 &); + virtual __int64 getAnimationComponent(void); + virtual __int64 openContainerComponent(C_Player &); + +public: + virtual __int64 swing(void); + +private: + virtual __int64 useItem(__int64 &, __int64, bool); + +public: + virtual bool hasOutputSignal(unsigned char) const; + +private: + virtual __int64 getOutputSignal(void) const; + virtual __int64 getDebugText(__int64 &); + virtual __int64 getMapDecorationRotation(void) const; + virtual __int64 getRiderYRotation(C_Entity const &) const; + virtual __int64 getYHeadRot(void) const; + +public: + virtual bool isWorldBuilder(void); + virtual bool isCreative(void) const; + virtual bool isAdventure(void) const; + +private: + virtual __int64 add(__int64 &); + virtual __int64 drop(__int64 const &, bool); + virtual __int64 getInteraction(C_Player &, __int64 &, vec3_t const &); + +public: + virtual bool canDestroyBlock(__int64 const &) const; + virtual void setAuxValue(int); + virtual void setSize(float, float); + +private: + virtual __int64 getLifeSpan(void) const; + virtual __int64 onOrphan(void); + virtual __int64 wobble(void); + virtual __int64 wasHurt(void); + +public: + virtual __int64 startSpinAttack(void); + virtual __int64 stopSpinAttack(void); + +public: + virtual void setDamageNearbyMobs(bool); + +private: + virtual __int64 renderDebugServerState(__int64 const &); + virtual __int64 reloadLootTable(void); + virtual __int64 reloadLootTable(__int64 const *); + virtual __int64 getLootTable(void) const; + virtual __int64 getDefaultLootTable(void); + virtual __int64 getDeletionDelayTimeSeconds(void); + virtual __int64 kill(void); + virtual __int64 die(__int64 const &); + virtual __int64 shouldTick(void) const; + virtual __int64 createMovementProxy(void); + virtual __int64 getMovementProxy(void); + virtual __int64 getNextStep(float) const; + virtual __int64 updateEntitySpecificMolangVariables(__int64 &); + +public: + virtual bool shouldTryMakeStepSound(void) const; + +private: + virtual bool canMakeStepSound(void) const; + virtual __int64 outOfWorld(void); + virtual __int64 _hurt(__int64 const &, int, bool, bool); + virtual __int64 markHurt(void); + virtual __int64 _getAnimationComponent(std::shared_ptr<__int64> &, __int64); + virtual __int64 readAdditionalSaveData(__int64 const &, __int64 &); + virtual __int64 addAdditionalSaveData(__int64 &); + virtual __int64 _playStepSound(vec3_ti const &, __int64 const &); + virtual __int64 _playFlySound(vec3_ti const &, __int64 const &); + virtual __int64 _makeFlySound(void) const; + virtual __int64 checkInsideBlocks(float); + virtual __int64 pushOutOfBlocks(vec3_t const &); + virtual __int64 updateWaterState(void); + +public: + virtual __int64 doWaterSplashEffect(void); + +private: + virtual __int64 spawnTrailBubbles(void); + virtual __int64 updateInsideBlock(void); + virtual __int64 _removeRider(__int64 const &, bool, bool); + virtual __int64 _onSizeUpdated(void); + virtual __int64 _doAutoAttackOnTouch(C_Entity &); + + // Mob only functions + + virtual __int64 knockback(C_Entity *, int, float, float, float, float, float); + virtual __int64 resolveDeathLoot(int, __int64 const &); + virtual __int64 spawnAnim(void); + +public: + virtual void setSleeping(bool); + virtual void setSprinting(bool); + +private: + virtual __int64 playAmbientSound(void); + virtual __int64 getAmbientSound(void); + virtual __int64 getHurtSound(void); + virtual __int64 getDeathSound(void); + virtual __int64 getAmbientSoundPostponeTicks(void); + virtual __int64 getAmbientSoundPostponeTicksRange(void); + virtual __int64 getItemInHandIcon(__int64 const &, int); + +public: + virtual __int64 getSpeed(void) const; + virtual void setSpeed(float); + +private: + virtual __int64 getJumpPower(void) const; + virtual __int64 hurtEffects(__int64 const &, int, bool, bool); + virtual __int64 getMeleeWeaponDamageBonus(__int64 *); + virtual __int64 getMeleeKnockbackBonus(void); + virtual __int64 travel(__int64, float, float, float); + virtual __int64 travel(float, float, float); + virtual __int64 applyFinalFriction(float, bool); + virtual __int64 updateWalkAnim(void); + virtual __int64 aiStep(__int64); + virtual __int64 aiStep(void); + virtual __int64 pushActors(void); + virtual __int64 lookAt(C_Entity *, float, float); + +public: + virtual bool isLookingAtAnEntity(void); + +private: + virtual __int64 checkSpawnRules(bool); + virtual __int64 checkSpawnObstruction(void) const; + virtual __int64 getAttackAnim(float); + virtual __int64 getItemUseDuration(void); + virtual __int64 getItemUseStartupProgress(void); + virtual __int64 getItemUseIntervalProgress(void); + virtual __int64 getItemuseIntervalAxis(void); + virtual __int64 getTimeAlongSwing(void); + virtual __int64 ate(void); + virtual __int64 getMaxHeadXRot(void); + virtual __int64 getLastHurtByMob(void); + +public: + virtual void setLastHurtByMob(__int64 *); + +private: + virtual __int64 getLastHurtByPlayer(void); + +public: + virtual void setLastHurtByPlayer(C_Player *); + +private: + virtual __int64 getLastHurtMob(void); + +public: + virtual void setLastHurtMob(C_Entity *); + virtual bool isAlliedTo(C_Entity *); + +private: + virtual __int64 doHurtTarget(C_Entity *); + +public: + virtual bool canBeControlledByRider(void); + +private: + virtual __int64 leaveCaravan(void); + virtual __int64 joinCaravan(__int64 *); + +public: + virtual bool hasCaravanTail(void) const; + +private: + virtual __int64 getCaravanHead(void) const; + virtual __int64 getArmorValue(void); + virtual __int64 getArmorCoverPercentage(void) const; + virtual __int64 hurtArmor(int); + virtual __int64 hurtArmor(int, __int64); + virtual __int64 hurtArmorSlot(int, __int64); + virtual __int64 setDamagedArmor(); + virtual __int64 idk3(); + virtual __int64 sendArmor(void); + virtual __int64 containerChanged(int); + virtual __int64 updateEquipment(void); + virtual __int64 clearEquipment(void); + virtual __int64 getAllArmor(void) const; + virtual __int64 getAllArmorID(void) const; + virtual __int64 getAllHand(void) const; + virtual __int64 getAllEquipment(void) const; + virtual __int64 getArmorTypeHash(void); + virtual __int64 dropEquipmentOnDeath(void); + virtual __int64 dropEquipmentOnDeath(__int64 const &, int); + virtual __int64 clearVanishEnchantedItems(void); + virtual __int64 sendInventory(bool); + virtual __int64 getDamageAfterMagicAbsorb(__int64 const &, int); + virtual __int64 createAIGoals(void); + virtual __int64 onBorn(C_Entity &, C_Entity &); + virtual void setItemSlot(__int64, __int64 const &); + +public: + virtual void setTransitioningSitting(bool); + +private: + virtual __int64 attackAnimation(C_Entity *, float); + virtual __int64 getAttackTime(void); + virtual __int64 _getWalkTargetValue(vec3_ti const &); + +public: + virtual bool canExistWhenDisallowMob(void) const; + +private: + virtual __int64 useNewAi(void); + virtual __int64 ascendLadder(void); + virtual __int64 ascendBlockByJumping(void); // 0x161 + virtual __int64 descendBlockByCrouching(void); // 0x162 + virtual __int64 dropContainer(void); + virtual __int64 initBodyControl(void); + +public: + virtual __int64 jumpFromGround0(__int64); + virtual __int64 jumpFromGround(void); + +private: + virtual __int64 updateAi(void); + virtual __int64 newServerAiStep(void); + virtual __int64 _serverAiMobStep(void); + virtual __int64 getDamageAfterEnchantReduction(__int64 const &, int); + virtual __int64 getDamageAfterArmorAbsorb(__int64 const &, int); + virtual __int64 dropBags(void); + virtual __int64 tickDeath(void); + virtual __int64 updateGliding(void); + virtual __int64 _allowAscendingScaffolding(void) const; + +public: + C_InventoryTransactionManager *getTransactionManager(); + + AABB *getAABB() { + return &this->aabb; + } + + __int64 *getUniqueId() { + uintptr_t _this = reinterpret_cast(this); + __int64 *result; // rax + __int64 v2; // rcx + + result = (__int64 *)(_this + 0xE8); + if (*result == -1i64) { + v2 = *(__int64 *)(_this + 0x330); + *result = ++*(__int64 *)(v2 + 0x1A0); + } + return result; + } + + int getTicksUsingItem() { + return *reinterpret_cast(reinterpret_cast<__int64>(this) + 0xF60); + } + + bool isSneaking() { + return false; // TODO + } + + bool isSprinting() { + return false; // TODO + } +}; + +#pragma pack(pop) + +class C_ServerPlayer; + +class C_Player : public C_Entity { +public: + C_PlayerInventoryProxy *getSupplies(); + ; + + C_ItemStack *getSelectedItem() { + auto supplies = this->getSupplies(); + return supplies->inventory->getItemStack(supplies->selectedHotbarSlot); + } + + int getSelectedItemId() { + auto item = getSelectedItem(); + if (item == nullptr || item->item == nullptr) + return 0; + if (item->getItem() == nullptr) + return 0; + return item->getItem()->itemId; + } + +private: + virtual __int64 prepareRegion(__int64 &); + virtual __int64 destroyRegion(void); + virtual __int64 suspendRegion(void); + virtual void resendAllChunks(void); + virtual __int64 _fireWillChangeDimension(void); + virtual __int64 _fireDimensionChanged(void); + virtual __int64 changeDimensionWithCredits(__int64); + virtual __int64 tickWorld(__int64 const &); + + virtual __int64 frameUpdate(__int64 &); + virtual __int64 getTickingOffsets(void) const; + virtual __int64 moveView(void); + +public: + virtual void setName(std::string const &); + +private: + virtual __int64 checkMovementStats(vec3_t const &); + virtual __int64 getCurrentStructureFeature(void); + virtual __int64 isAutoJumpEnabled(void); + virtual __int64 respawn(void); + virtual __int64 resetRot(void); + virtual __int64 resetPos(bool); + +public: + virtual bool isInTrialMode(void); + virtual bool hasResource(int); + +private: + virtual __int64 completeUsingItem(void); + +public: + virtual void setPermissions(int); + + virtual __int64 startDestroying(void); + virtual __int64 stopDestroying(void); + +public: + virtual bool returnFalse0() const; + virtual bool returnFalse1() const; + + virtual __int64 openTrading(__int64 const &, bool); + +public: + virtual bool canOpenContainerScreen(void); + +private: + virtual bool returnFalse_0() const; + virtual bool returnFalse_1() const; + +public: + virtual __int64 openInventory(void); + +private: + virtual bool returnFalse_2() const; + virtual bool returnFalse_3() const; + virtual __int64 displayTextObjectMessage(__int64 const &, std::string const &, std::string const &); + virtual __int64 displayTextObjectMessageWhisperMessage(__int64 const &, std::string const &, std::string const &); + virtual __int64 displayWhisperMessage(std::string const &, std::string const &, std::string const &, std::string const &); + virtual __int64 startSleepInBed(vec3_ti const &); + virtual __int64 stopSleepInBed(bool, bool); + +public: + virtual bool canStartSleepInBed(void); + +private: + virtual __int64 getSleepTimer(void) const; + virtual __int64 getPreviousTickSleepTimer(void) const; + virtual bool returnFalse_4() const; + virtual bool returnFalse_5() const; + +public: + virtual bool isHostingC_Player(void) const; + virtual bool isLoading(void) const; + virtual bool isC_PlayerInitialized(void) const; + +private: + virtual bool returnFalse_7() const; + virtual __int64 registerTrackedBoss(__int64); + virtual __int64 unRegisterTrackedBoss(__int64); + +public: + virtual void setC_PlayerGameType(int); + virtual __int64 initHUDContainerManager(void); + virtual __int64 _crit(C_Entity *); + +private: + virtual __int64 getEventing(void) const; + +public: + virtual __int64 getUserId(void) const; + +private: + virtual __int64 sendEventPacket(__int64 &) const; + +public: + virtual void addExperience(int); + virtual void addLevels(int); + virtual void setContainerData(__int64 &, int, int); + +private: + virtual __int64 slotChanged(__int64 &, int, C_ItemStack const &, C_ItemStack const &, bool); + virtual __int64 inventoryChanged(__int64 &, int, C_ItemStack const &, C_ItemStack const &); + virtual __int64 refreshContainer(__int64 &); + virtual __int64 deleteContainerManager(void); + +public: + virtual void setFieldOfViewModifier(float); + virtual bool isPositionRelevant(__int64, int, vec3_ti const &); // is2DPositionRelevant((__int64, BlockPos&); + virtual bool isEntityRelevant(C_Entity const &); + virtual bool isTeacher(void) const; + +private: + virtual __int64 onSuspension(void); + virtual __int64 onLinkedSlotsChanged(void); + virtual __int64 startCooldown(C_Item const *); + virtual __int64 getItemCooldownLeft(int) const; + +public: + virtual bool isItemInCooldown(int) const; + virtual __int64 sendInventoryTransaction(__int64 const &) const; + virtual __int64 sendComplexInventoryTransaction(__int64, __int64) const; + +private: + virtual __int64 sendNetworkPacket(__int64 &) const; + virtual __int64 getC_PlayerEventCoordinator(void); + virtual __int64 getMoveInputHandler(void); + virtual __int64 getInputMode(void); + virtual __int64 getPlayMode(void); + virtual void **reportMovementTelemetry(__int64 *); + virtual __int64 onMoveC_PlayerPacketNormal(vec3_t const &, vec2_t const &, float); +}; + +class C_ServerPlayer : public C_Player { +}; + +class C_LocalPlayer : public C_Player { +public: + void unlockAchievments(); + + void swingArm() { + //using SwingArm = void(__thiscall*)(void*); + //static SwingArm swingFunc = reinterpret_cast(FindSignature("40 57 48 83 EC ?? 48 C7 44 24 ?? FE FF FF FF 48 89 5C 24 ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 48 8B D9 80 B9")); + //swingFunc(this); + this->swing(); + } + void localPlayerTurn(vec2_t* viewAngles) { + using Turn = void(__thiscall*)(void*, vec2_t*); + static Turn TurnFunc = reinterpret_cast(FindSignature("48 8B 58 68 48 ?? ?? ?? ?? ?? ?? ?? 48 ?? ?? ?? ?? ?? ?? 89 ?? ?? ?? ?? ?? ?? ?? 48 8B 03 48 8B CB FF 50 08 90 48 85 DB ?? 09 48 8B ?? 48 8B CB ?? ?? ?? ?? ?? ?? ?? 48 8B D3 48 8B CE E8 0D BB 1D FF 90 48 85 DB 74 09 48 8B 03 48 8B ?? ?? ?? ?? 48 83 C7 10")); + TurnFunc(this, viewAngles); + } + void applyTurnDelta(vec2_t *viewAngleDelta); + void setGameModeType(int gma); +}; diff --git a/SDK/CEntityList.h b/SDK/CEntityList.h new file mode 100644 index 0000000..d0497a0 --- /dev/null +++ b/SDK/CEntityList.h @@ -0,0 +1,51 @@ +#pragma once + +#include "../Utils/HMath.h" +class C_Entity; + +class C_EntityList { +private: + char pad_0x0000[0x70]; //0x0000 +public: + uintptr_t firstEntity; //0x0050 + uintptr_t lastEntity; //0x0058 + uintptr_t endAddr; //0x0060 + + inline size_t getListSize() { + return (lastEntity - firstEntity) / sizeof(uintptr_t); + } + + inline C_Entity* get(size_t idx) { + if (idx >= getListSize()) + return 0; + return *reinterpret_cast(firstEntity + (idx * sizeof(uintptr_t))); + } + + C_Entity* operator[](size_t idx) { + return get(idx); + } +}; //Size=0x0050 + +class C_MobEntityList { +public: +private: + char pad_0x0000[0x38]; //0x0000 +public: + uintptr_t firstEntity; //0x0038 + uintptr_t lastEntity; //0x0040 + uintptr_t endAddr; //0x0048 + + inline size_t getListSize() { + return (lastEntity - firstEntity) / sizeof(uintptr_t); + } + + inline C_Entity* get(size_t idx) { + if (idx >= getListSize()) + return 0; + return *reinterpret_cast(firstEntity + (idx * sizeof(uintptr_t))); + } + + C_Entity* operator[](size_t idx) { + return get(idx); + } +}; //Size=0x0050 diff --git a/SDK/CGameMode.cpp b/SDK/CGameMode.cpp new file mode 100644 index 0000000..4b3a719 --- /dev/null +++ b/SDK/CGameMode.cpp @@ -0,0 +1,25 @@ +#include "CGameMode.h" +#include "../Memory/GameData.h" + +void C_GameMode::survivalDestroyBlockHack(vec3_ti const &block, int face, bool &isDestroyedOut, bool isFirst) { + auto p = this->player; + p->swing(); + if (isFirst) + this->startDestroyBlock(block, face, isDestroyedOut); + else { + *reinterpret_cast(reinterpret_cast<__int64>(p) + 0x1c5a) = 1; + this->continueDestroyBlock(block, face, isDestroyedOut); + } + + p->startDestroying(); + + // prevents regular code from aborting block-break + *reinterpret_cast(reinterpret_cast<__int64>(p) + 0x1c5a) = 0; + + C_PlayerActionPacket action; + action.action = 18; + action.blockPosition = vec3_ti(block.x, block.y, block.z); + action.face = face; + action.entityRuntimeId = p->entityRuntimeId; + g_Data.getClientInstance()->loopbackPacketSender->sendToServer(&action); +} diff --git a/SDK/CGameMode.h b/SDK/CGameMode.h new file mode 100644 index 0000000..75cb45f --- /dev/null +++ b/SDK/CGameMode.h @@ -0,0 +1,47 @@ +#pragma once + +#include + +#include "../Utils/HMath.h" +#include "CClientInstance.h" +#include "CEntity.h" + +class C_GameMode { +private: + virtual __int64 destructorGameMode(); + // Duplicate destructor +public: + virtual __int64 startDestroyBlock(vec3_ti const & pos, unsigned char blockSide, bool & isDestroyedOut); + virtual __int64 destroyBlock(vec3_ti *, unsigned char); + virtual __int64 continueDestroyBlock(vec3_ti const &, unsigned char blockSide, bool & isDestroyedOut); + virtual __int64 stopDestroyBlock(vec3_ti const &); + virtual __int64 startBuildBlock(vec3_ti const &, unsigned char); + virtual __int64 buildBlock(vec3_ti *, unsigned char); + virtual __int64 continueBuildBlock(vec3_ti const &, unsigned char); + virtual __int64 stopBuildBlock(void); + virtual __int64 tick(void); + +private: + virtual __int64 getPickRange(__int64 const &, bool); + virtual __int64 useItem(__int64 &); + virtual __int64 useItemOn(__int64 &, vec3_ti const &, unsigned char, vec3_t const &, __int64 const *); + virtual __int64 interact(C_Entity &, vec3_t const &); + +public: + virtual __int64 attack(C_Entity *); + +private: + virtual __int64 releaseUsingItem(void); + +public: + virtual void setTrialMode(bool); + virtual bool isInTrialMode(void); + +private: + virtual __int64 registerUpsellScreenCallback(__int64); + +public: + C_Player *player; + + void survivalDestroyBlockHack(vec3_ti const &block, int face, bool &isDestroyedOut, bool isFirst); +}; diff --git a/SDK/CGameSettingsInput.h b/SDK/CGameSettingsInput.h new file mode 100644 index 0000000..7cf5cd5 --- /dev/null +++ b/SDK/CGameSettingsInput.h @@ -0,0 +1,28 @@ +#pragma once + +class C_GameSettingsInput { +private: + char pad_0x0000[0x3E0]; //0x0000 +public: + int* spaceBarKey; //0x3E0 +private: + char pad_0x370[0x38]; //0x3E8 +public: + int* sneakKey; //0x420 +private: + char pad_0x0428[0x78]; //0x0428 +public: + int* leftKey; //0x4A0 +private: + char pad_0x418[0x38]; //0x4A8 +public: + int* rightKey; //0x4E0 +private: + char pad_0x450[0x38]; //0x4E8 +public: + int* backKey; //0x520 +private: + char pad_0x488[0x38]; //0x528 +public: + int* forwardKey; //0x560 +}; diff --git a/SDK/CHIDController.h b/SDK/CHIDController.h new file mode 100644 index 0000000..d9750bb --- /dev/null +++ b/SDK/CHIDController.h @@ -0,0 +1,17 @@ +#pragma once + +class C_HIDController { +private: + char pad_0x0000[0x50]; //0x0000 +public: + union { + struct { + bool leftClickDown; //0x0050 + bool rightClickDown; //0x0051 + bool wheelDown; //0x0052 + bool mouse4Down; //0x0053 + bool mouse5Down; //0x0054 + }; + bool clickMap[5]; + }; +}; diff --git a/SDK/CImageBuffer.h b/SDK/CImageBuffer.h new file mode 100644 index 0000000..fc07583 --- /dev/null +++ b/SDK/CImageBuffer.h @@ -0,0 +1,7 @@ +#pragma once + +class CBlob { +public: + void* data; + size_t size; +}; \ No newline at end of file diff --git a/SDK/CInventory.cpp b/SDK/CInventory.cpp new file mode 100644 index 0000000..26c8f97 --- /dev/null +++ b/SDK/CInventory.cpp @@ -0,0 +1,85 @@ +#include "CInventory.h" +#include "../Utils/Utils.h" +#include "../Memory/GameData.h" +void C_Inventory::dropSlot(int slot) { + // FillingContainer::dropSlot + using drop_t = void(__fastcall*)(C_Inventory*, int, char); + static drop_t func = reinterpret_cast(FindSignature("85 D2 0F 88 ?? ?? ?? ?? 48 89 5C 24 ?? 55")); + if (func != 0) + func(this, slot, 0); +} +void C_Inventory::dropAll(int slot) { + // FillingContainer::dropAll + using dropAll_t = void(__fastcall*)(C_Inventory*, int, int, char); + static dropAll_t func = reinterpret_cast(FindSignature("48 89 5C 24 ?? 48 89 6C 24 ?? 48 89 74 24 ?? 48 89 7C 24 ?? 41 56 48 83 EC ?? 48 8B 01 41 0F")); + if (func != 0) + func(this, slot, 0, 0); +} +bool C_Inventory::isFull() { + int fullslots = 0; + for (int i = 0; i < 36; i++) { + if (this->getItemStack(i)->item != nullptr) + fullslots++; + } + if (fullslots == 36) return true; + return false; +} + +void C_ContainerScreenController::handleAutoPlace(uintptr_t a1, std::string name, int slot) { + using ContainerScreenController__autoPlace = __int64(__fastcall*)(C_ContainerScreenController*, uintptr_t, TextHolder, int); + static ContainerScreenController__autoPlace autoPlaceFunc = reinterpret_cast(FindSignature("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D 6C 24 ?? 48 81 EC ?? ?? ?? ?? 48 8B 05 30 ?? ?? ?? ?? ?? C4 48 89 45 ?? 45 8B E1 49 8B F0 44 8B EA 89 54 24 30 4C 8B F1")); + + TextHolder txt = TextHolder(name); + + if (autoPlaceFunc != 0x0) + autoPlaceFunc(this, a1, txt, slot); +} + +void C_Inventory::moveItem(int from, int to = -1) { + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + + uintptr_t sigOffset = FindSignature("48 8D 3D ? ? ? ? 80 B8 ? ? ? ? ? 75 19 48 8B 88 ? ? ? ? 48 8B 11 4C 8B 42 28 8B 50 10"); + int offset = *reinterpret_cast(sigOffset + 3); + C_ItemStack* emptyItemStack = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + + if (to < 0) to = getFirstEmptySlot(); + C_ItemStack* item1 = getItemStack(from); + C_ItemStack* item2 = getItemStack(to); + + if (item1->item == NULL) return; + if (item2->item == NULL) { + C_InventoryAction first(from, item1, nullptr); + C_InventoryAction second(to, nullptr, item1); + manager->addInventoryAction(first); + manager->addInventoryAction(second); + *item2 = *item1; + *item1 = *emptyItemStack; + } else { + C_InventoryAction first(from, item1, nullptr); + C_InventoryAction second(to, item2, item1); + C_InventoryAction third(from, nullptr, item2); + manager->addInventoryAction(first); + manager->addInventoryAction(second); + manager->addInventoryAction(third); + C_ItemStack a = *item2; + *item2 = *item1; + *item1 = a; + } +} + +void C_Inventory::swapSlots(int from, int to) { + C_InventoryTransactionManager* manager = g_Data.getLocalPlayer()->getTransactionManager(); + + C_ItemStack* i1 = getItemStack(from); + C_ItemStack* i2 = getItemStack(to); + + C_InventoryAction first(from, i1, nullptr); + C_InventoryAction second(to, i2, i1); + C_InventoryAction third(from, nullptr, i2); + manager->addInventoryAction(first); + manager->addInventoryAction(second); + manager->addInventoryAction(third); + C_ItemStack a = *i2; + *i2 = *i1; + *i1 = a; +} diff --git a/SDK/CInventory.h b/SDK/CInventory.h new file mode 100644 index 0000000..63f1a28 --- /dev/null +++ b/SDK/CInventory.h @@ -0,0 +1,168 @@ +#pragma once +#include "CItem.h" + +class C_ItemStack; +class C_Inventory; +class C_Player; + +class C_Inventory { +private: + virtual ~C_Inventory(); + +public: + bool isFull(); + void dropSlot(int slot); + + // DROPS WHOLE INVENTORY doesnt work tho + void dropAll(int slot); + + virtual __int64 init(); + virtual bool serverInitItemStackIds(signed int a2, int a3, __int64 a4); + virtual __int64 addContentChangeListener(__int64 a2); + virtual __int64 removeContentChangeListener(__int64 a2); + virtual C_ItemStack* getItemStack(int slot); + virtual bool hasRoomForItem(C_ItemStack*); + virtual __int64 addItem(C_ItemStack*); + virtual __int64 addItemToFirstEmptySlot(C_ItemStack*); + virtual __int64 setItem(int slot, const C_ItemStack&); + virtual __int64 setItemWithForceBalance(int, const C_ItemStack&, bool); + virtual __int64 removeItem(int, int); + virtual __int64 removeAllItems(); + virtual __int64 dropContents(C_BlockSource&, const vec3_t&, bool); + virtual __int64 getContainerSize(); + virtual __int64 getMaxStackSize(); + virtual __int64 startOpen(C_Player&); + virtual __int64 stopOpen(C_Player&); + virtual __int64 getSlotCopies(); + virtual __int64 getSlots(); + virtual __int64 getItemCount(const C_ItemStack&); + virtual __int64 findFirstSlotForItem(const C_ItemStack&); + virtual __int64 canPushInItem(); // BlockSource &,int,int,ItemInstance const& + virtual __int64 canPullOutItem(); // BlockSource &,int,int,ItemInstance const& + virtual __int64 setContainerChanged(int); + virtual __int64 setContainerMoved(); + virtual __int64 setCustomName(const TextHolder&); + virtual __int64 hasCustomName(); + virtual __int64 readAdditionalSaveData(); // CompoundTag const& + virtual __int64 addAdditionalSaveData(); // CompoundTag & + virtual __int64 createTransactionContext(); // std::function, std::function + virtual __int64 initializeContainerContents(C_BlockSource&); + virtual char isEmpty(); + virtual __int64 add(C_ItemStack&); + virtual __int64 canAdd(const C_ItemStack&); + //virtual void unknown(); + virtual __int64 clearSlot(int); + virtual __int64 clearInventory(int); + virtual __int64 load(); // ListTag const&,SemVersion const&,Level & + //virtual void unknown2(); + virtual __int64 getEmptySlotsCount(); + virtual int getFirstEmptySlot(); + virtual __int64 setContainerSize(); + + void moveItem(int from, int to); + void swapSlots(int from, int to); +}; + +class C_PlayerInventoryProxy { +private: + char pad_0x0000[0x10]; //0x0000 +public: + int selectedHotbarSlot; //0x0010 +private: + char pad_0x0014[0x9C]; //0x0014 +public: + C_Inventory* inventory; //0x00B0 +}; + +//Im not sure exactly where these unknown's go but the funcs we use work. +class C_ContainerScreenController { +private: + virtual __int64 destructor(); + virtual __int64 tick(void); + virtual __int64 handleEvent(__int64&); + virtual __int64 getRoute(void); + virtual __int64 setScreenState(__int64, std::string const&); + virtual __int64 onOpen(void); + virtual __int64 onTerminate(void); + virtual __int64 onInit(void); + virtual __int64 onDelete(void); + virtual __int64 unknown1(); + +public: + virtual bool canExit(void); + virtual __int64 tryExit(void); + +private: + virtual __int64 areControllerTabsEnabled(void); + virtual __int64 onCreation(void); + virtual __int64 logCreationTime(std::string const&, double, double, unsigned char); + virtual __int64 unknown2(); + virtual __int64 unknown3(); + +public: + virtual __int64 onLeave(void); + virtual __int64 leaveScreen(void); + +private: + virtual __int64 handleGameEventNotification(__int64); + virtual __int64 bind(std::string const&, unsigned int, int, std::string const&, unsigned int, std::string const&, __int64&); + virtual __int64 bind(std::string const&, unsigned int, std::string const&, __int64&); + virtual __int64 handleLicenseChanged(void); + virtual __int64 onDictationEvent(std::string const&); + +public: + virtual void setAssociatedBlockPos(vec3_ti const&); + virtual void setAssociatedEntityUniqueID(__int64); + virtual void setSuspendInput(bool); + +private: + virtual __int64 getCallbackInterval(void); + virtual __int64 onRender(void); + virtual __int64 addStaticScreenVars(__int64&); + virtual __int64 getAdditionalScreenInfo(void); + virtual __int64 getTelemetryOverride(void); + virtual __int64 addEventProperties(__int64) const; + virtual __int64 getSceneType(void); + virtual __int64 getScreenVersion(void); + virtual __int64 screenHandlesGamepadMenuButton(void); + virtual __int64 getProxy(void); + virtual __int64 onEntered(void); + virtual __int64 getNameId(std::string const&); + virtual __int64 _doesScreenHaveExitBehavior(void); + virtual __int64 _isStillValid(void); + virtual __int64 _getGamepadHelperVisible(void); + virtual __int64 _getMixedHelperVisible(void); + virtual __int64 _getKeyboardHelperVisible(void); + virtual __int64 _getButtonADescription(void); + virtual __int64 _getButtonBDescription(void); + virtual __int64 _getButtonXDescription(void); + virtual __int64 _getButtonYDescription(void); + virtual __int64 _getButtonKeyboardDescription(void); + +public: + virtual __int64 _handlePlaceAll(std::string const&, int); + virtual __int64 _handlePlaceOne(std::string const&, int); + virtual __int64 _handleSelectSlot(std::string const&, int); + virtual __int64 _getSelectedSlotInfo(void); + virtual C_ItemStack* _getItemStack(TextHolder, int) const; + +private: + virtual __int64 _getVisualItemStack(std::string const&, int); + virtual __int64 _getTakeableItemStackBase(std::string const&, int); + virtual __int64 _onContainerSlotHovered(std::string const&, int); + virtual __int64 _onContainerSlotSelected(std::string const&, int); + virtual __int64 _onContainerSlotPressed(std::string const&, int); + virtual __int64 _shouldSwap(std::string const&, int, std::string const&, int); + virtual __int64 _getCollectionName(__int64*); + virtual __int64 _canSplit(std::string const&, int); + virtual __int64 _sendFlyingItem(__int64 const&, std::string const&, int, std::string const&, int); + +public: + void handleAutoPlace(uintptr_t a1, std::string name, int slot); +}; + +class C_CraftingScreenController : public C_ContainerScreenController { +}; + +class C_ChestScreenController : public C_ContainerScreenController { +}; \ No newline at end of file diff --git a/SDK/CInventoryTransaction.cpp b/SDK/CInventoryTransaction.cpp new file mode 100644 index 0000000..58510db --- /dev/null +++ b/SDK/CInventoryTransaction.cpp @@ -0,0 +1,9 @@ +#include "CInventoryTransaction.h" +#include "../Utils/Utils.h" +void C_InventoryTransactionManager::addInventoryAction(const C_InventoryAction& action,bool idk) { + using InventoryTransactionManager__addAction_t = void(__fastcall*)(C_InventoryTransactionManager*, C_InventoryAction const&,bool); + //static auto InventoryTransactionManager__addAction = reinterpret_cast(FindSignature("40 55 56 57 41 56 41 57 48 83 EC 30 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 ?? 48 8B EA 4C 8B F1 4C 8B C2 48 8B 51 ?? 48 8B 49 ?? E8")); + static auto InventoryTransactionManager__addAction = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 41 56 41 57 48 83 EC 30 45 0F B6 F8 4C 8B F2 48 8B F1 48 8B 01 48 8B 88 ? ? ? ? 48 85 C9")); + if (InventoryTransactionManager__addAction != 0) + InventoryTransactionManager__addAction(this, action,idk); +} diff --git a/SDK/CInventoryTransaction.h b/SDK/CInventoryTransaction.h new file mode 100644 index 0000000..0669faf --- /dev/null +++ b/SDK/CInventoryTransaction.h @@ -0,0 +1,85 @@ +#pragma once +#include "../Utils/HMath.h" +#include "CItem.h" +#include "CInventory.h" + +class C_InventoryAction { +public: + C_InventoryAction() = default; + C_InventoryAction(int slot, C_ItemStack* sourceItem, C_ItemStack* targetItem, int sourceType = 0, int type = 0) { + memset(this, 0x0, sizeof(C_InventoryAction)); + this->slot = slot; + if (sourceItem != nullptr) + this->sourceItem = *sourceItem; + if (targetItem != nullptr) + this->targetItem = *targetItem; + this->sourceType = sourceType; + this->type = type; + } + + C_InventoryAction(int slot,ItemDescriptor* source ,ItemDescriptor* target ,C_ItemStack* sourceItem, C_ItemStack* targetItem, int count, int sourceType = 0, int type = 0) { + memset(this, 0x0, sizeof(C_InventoryAction)); + this->slot = slot; + + if (source != nullptr) { + this->sourceItemDescriptor = *source; + this->s_count = count; + } + + if (target != nullptr) { + this->targetItemDescriptor = *target; + this->t_count = count; + } + + + if (sourceItem != nullptr) + this->sourceItem = *sourceItem; + if (targetItem != nullptr) + this->targetItem = *targetItem; + + + this->sourceType = sourceType; + this->type = type; + } + +public: + int type; //0x0 // named sourceType in nukkit + int sourceType; //0x4 // sometimes windowId +private: + int unknown; //0x8 +public: + int slot; //0xC + ItemDescriptor sourceItemDescriptor; //0x10 + int s_count; //0x58 +private: + char pad_0x0058[0x34];//0x005C +public: + ItemDescriptor targetItemDescriptor; //0x90 + int t_count; //0xD8 + +private: + char pad_0x00DC[0x34]; //0x00DC +public: + C_ItemStack sourceItem; //0x110 + C_ItemStack targetItem; //0x1A0 +}; + +class C_InventoryTransaction { +private: + char pad_0x0[8]; +public: + __int64 ptr; // 0x008 +private: + char pad_0x10[0x58 - 16]; //0x10 +}; + +class C_InventoryTransactionManager { +public: + uintptr_t* player; //0x0 + C_InventoryTransaction transac; //0x8 +private: + int unknown; //0x60 + // Total size: 0x68 +public: + void addInventoryAction(C_InventoryAction const& action , bool idk = false); +}; diff --git a/SDK/CItem.cpp b/SDK/CItem.cpp new file mode 100644 index 0000000..16aa009 --- /dev/null +++ b/SDK/CItem.cpp @@ -0,0 +1,92 @@ +#include "CItem.h" + +#include "../Utils/Utils.h" +#include "Tag.h" +#include "../Memory/GameData.h" + +C_BaseActorRenderContext::C_BaseActorRenderContext(C_ScreenContext *ScreenCtx, C_ClientInstance *client, MinecraftGame *game) { + memset(this, 0, sizeof(C_BaseActorRenderContext)); + using BaseActorRenderContext_t = __int64(__fastcall *)(C_BaseActorRenderContext *, C_ScreenContext *, C_ClientInstance *, MinecraftGame *); + static BaseActorRenderContext_t BaseActorRenderContext_constructor = reinterpret_cast(FindSignature("48 89 5C 24 ?? 48 89 74 24 ?? 48 89 4C 24 08 57 48 83 EC ?? ?? ?? ?? 48 8B F9 48 8D 05 ?? ?? ?? ?? 48 89 ?? 33 F6 48 89 71 08")); + BaseActorRenderContext_constructor(this, ScreenCtx, client, game); +} +void C_ItemRenderer::renderGuiItemNew(C_BaseActorRenderContext *BaseActorRenderCtx, C_ItemStack *item, MinecraftGame *game, float x, float y, float opacity, float scale, bool isEnchanted) { + using renderGuiItemNew_t = void(__fastcall *)(C_ItemRenderer *, C_BaseActorRenderContext *, C_ItemStack *, MinecraftGame *, float, float, float, float, float, bool); + static renderGuiItemNew_t renderGuiItemNew = reinterpret_cast(FindSignature("48 8B C4 48 89 58 20 55 56 57 41 54 41 55 41 56 41 57 48 81 EC 00 01 00 00 0F 29 70 B8 ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 84 24 ?? ?? ?? ??")); + item->setShowPickUp(false); + renderGuiItemNew(this, BaseActorRenderCtx, item, game, x, y, 1, opacity, scale, isEnchanted); +} + +void C_ItemRenderer::renderGuiItemInChunk(C_BaseActorRenderContext* BaseActorRenderCtx, C_ItemStack* item, float x, float y, float opacity, float scale, bool isEnchanted, int mode) { + using renderGuiItemInChunk_t = void(__fastcall *)(C_ItemRenderer *, C_BaseActorRenderContext *, __int64, C_ItemStack *, float, float, float, float, float, int); + static renderGuiItemInChunk_t renderGuiItem = reinterpret_cast(FindSignature("48 8B C4 48 89 58 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D A8 ? ? ? ? 48 81 EC ? ? ? ? 0F 29 70 B8 0F 29 78 A8 44 0F 29 40 ? 44 0F 29 48 ? 44 0F 29 90 ? ? ? ? 44 0F 29 98 ? ? ? ? 44 0F 29 A0 ? ? ? ? 44 0F 29 A8 ? ? ? ? 48 8B 05 ? ? ? ?")); + //item->setShowPickUp(false); + + renderGuiItem(this, BaseActorRenderCtx, 2, item, x, y, 1, 1, scale, 0); +} + +C_ItemStack::C_ItemStack(const C_ItemStack &src) { + memset(this, 0x0, sizeof(C_ItemStack)); + using ItemStackCopyConstructor_t = void(__fastcall *)(C_ItemStack &, C_ItemStack const &); + static ItemStackCopyConstructor_t ItemStackCopyConstructor = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 83 EC 40 4C 8B F2 48 8B F1 48 89 4C 24 ? 33 ED 89 6C 24 20 48 8D")); + ItemStackCopyConstructor(*this, src); + this->setVtable(); +} +C_ItemStack::C_ItemStack(const Tag &tag) { + memset(this, 0x0, sizeof(C_ItemStack)); + this->setVtable(); + fromTag(tag); + /*using ItemStackBase__loadItemF = void(__fastcall*)(C_ItemStack*,Tag const&); + static ItemStackBase__loadItemF ItemStackBase__loadItem = reinterpret_cast(FindSignature("48 8B C4 55 57 41 56 48 8D 68 A1 48 81 EC ? ? ? ? 48 C7 45 ? ? ? ? ? 48 89 58 ? 48 89 70 ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 ? 48 8B DA 48 8B F9 48 89 4D ? 33 D2 41 B8 ? ? ? ? 48 8D 4D A7 E8 ? ? ? ? 48 8D 05 ? ? ? ?")); + ItemStackBase__loadItem(this, tag);*/ +} +void C_ItemStack::fromTag(const Tag &tag) { + using ItemStackBase__loadItemF = void(__fastcall *)(C_ItemStack *, Tag const &); + static ItemStackBase__loadItemF fromTag = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 74 24 ? 55 57 41 56 48 8D 6C 24 ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 45 37 48 8B DA 48 8B F9 48 89 4D 97 0F 57 C0 0F 11 45 A7 0F 11 45 B7 0F 11 45 C7 0F 11 45 D7 0F 11 45 E7 0F 11 45 F7 0F 11 45 07")); + fromTag(this, tag); +} +void C_ItemStack::save(CompoundTag **tag) { + using ItemStackBase__saveF = void(__fastcall *)(C_ItemStack *, CompoundTag **); + ItemStackBase__saveF save = reinterpret_cast(FindSignature("48 89 5C 24 ?? 55 56 57 41 56 41 57 48 8D 6C 24 C9 48 81 EC ?? ?? ?? ?? 48 8B FA 48 8B F1 48 89 55 0F 45 33 ?? 44 89 7D 97 33 C0")); + return save(this, tag); +} +void C_ItemStack::setUserData(std::unique_ptr tag) { + using setUserData_t = void(__fastcall *)(C_ItemStack *, std::unique_ptr); + setUserData_t setUserData = reinterpret_cast(FindSignature("48 89 5C 24 18 55 56 57 48 81 EC ? ? ? ? 48 8B 05 8A ? ? ? 48 33 C4 48 89 84 24 ? ? ? ? 48 8B FA")); + setUserData(this, std::move(tag)); +} +void C_ItemStack::reinit(C_BlockLegacy &legacy, int count) { + this->setVtable(); + Utils::CallVFunc<2, void>(this, &legacy, count); +} +void C_ItemStack::reinit(C_Item &item, int count, int itemData) { + this->setVtable(); + Utils::CallVFunc<3, void>(this, &item, count, itemData); +} +int C_ItemStack::getEnchantValue(int enchantId) { + using getEnchantsLevel_t = int(__fastcall *)(int, C_ItemStack *); + static getEnchantsLevel_t getEnchantsLevel = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B F2 0F B6 D9 33 FF 48 8B CA E8 ? ? ? ?")); + return getEnchantsLevel(enchantId, this); +} +void C_ItemStack::setVtable(void) { + static uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? C7 05 ? ? ? ? ? ? ? ? 48 8D 0D ? ? ? ? 48 89 05 ? ? ? ? C6 05 ? ? ? ? ? 48 83 C4"); + int offset = *reinterpret_cast(sigOffset + 3); + this->vTable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +} +C_Item ***ItemRegistry::getItemFromId(void *ptr, int itemId) { + using getItemFromId_t = C_Item ***(__fastcall *)(void *, int); + static getItemFromId_t getItemFromId = reinterpret_cast(FindSignature("40 53 48 83 EC ? 8D 42 ? 48 8B D9 66 83 F8 ? 0F 86 ? ? ? ? 44 0F BF C2 49 B9 ? ? ? ? ? ? ? ? 41 8B C0")); + return getItemFromId(ptr, itemId); +} + +C_Item ***ItemRegistry::lookUpByName(void *a1, void *a2, TextHolder &text) { + using ItemRegistry__lookupByName_t = C_Item ***(__fastcall *)(void *, void *, TextHolder &); + static ItemRegistry__lookupByName_t ItemRegistry__lookupByNameF = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ? ? ? ? 48 81 EC ? ? ? ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 85 ? ? ? ? 4C 8B EA 48 89 54 24 ? 48 89 4C 24 ? 48 89 4D")); + return ItemRegistry__lookupByNameF(a1, a2, text); +} + +ItemDescriptor::ItemDescriptor(int id, int16_t itemData) { + using ItemDescriptor__ItemDescriptor_t = ItemDescriptor*(__fastcall *)(ItemDescriptor*,int,int16_t); + static ItemDescriptor__ItemDescriptor_t func = reinterpret_cast(FindSignature("48 89 5C 24 ? 55 56 57 48 83 EC ? 33 ED 48 8B D9 48 89 29 41 8B F8 48 89 69 ? 8B F2 48 89 69 ? 66 89 69 ? C6 41")); + func(this, id, itemData); +} diff --git a/SDK/CItem.h b/SDK/CItem.h new file mode 100644 index 0000000..2890248 --- /dev/null +++ b/SDK/CItem.h @@ -0,0 +1,385 @@ +#pragma once +//#include "Tag.h" +#include +#include "TextHolder.h" +#include "../Utils/HMath.h" + +class CompoundTag; +class Tag; +class C_BlockLegacy; +class C_BlockSource; +class C_Block; +class C_Entity; +class C_ItemStack; +class C_ScreenContext; +class C_ItemRenderer; +class C_ClientInstance; +class MinecraftGame; + +class C_BaseActorRenderContext { +private: + char pad_0x0[0x60]; //0x0000 +public: + C_ItemRenderer* renderer; //0x0058 +private: + char pad_0x50[0x238]; //0x60 +public: + C_BaseActorRenderContext(C_ScreenContext* ScreenCtx, C_ClientInstance* client, MinecraftGame* game); +}; + +class C_ItemRenderer { +public: + void renderGuiItemNew(C_BaseActorRenderContext* BaseActorRenderCtx, C_ItemStack* item, MinecraftGame* game, float x, float y, float opacity, float scale, bool isEnchanted); + void renderGuiItemInChunk(C_BaseActorRenderContext* BaseActorRenderCtx, C_ItemStack* item, float x, float y, float opacity, float scale, bool isEnchanted, int mode); +}; + +class C_Item { + + +private: + char pad_0008[0x70]; //0x0008 +public: + int16_t maxStackSize; //0x0090 + int16_t itemId; //0x0092 +private: + char pad_0094[4]; //0x0094 +public: + TextHolder tileName; //0x0098 +private: + char pad_00B8[8]; //0x00B8 +public: + TextHolder name; //0x00C0 +private: + char pad_00E0[8]; //0x00E0 +public: + TextHolder isFrom; //0x00E8 +private: + char pad_0108[80]; //0x0108 +public: + int16_t duration; //0x0158 + +/* +private: + char pad_0x0008[0x62]; //0x8 +public: + uint16_t itemId; //0x6A +private: + char pad_0x00072[0x4]; //0x6C +public: + TextHolder tileName; //0x70 + TextHolder name; //0x90 +private: + char pad_0x0B8[0x4C]; //0xB0 +public: + int duration; //0xFC*/ +private: + virtual __int64 destructor(); // 0x0 + virtual __int64 initServer(int &); // 0x1 + virtual __int64 tearDown(void); // 0x2 + virtual __int64 getMaxUseDuration(__int64 const *) const; // 0x3 + virtual __int64 getMaxUseDuration(C_ItemStack const *); // 0x4 +public: + virtual bool isMusicDisk(void); // 0x5 +private: + virtual __int64 executeEvent(C_ItemStack &, std::string, char const &, int &); // 0x6 + virtual __int64 isComponentBased(void); // 0x7 +public: + virtual bool isArmor(void); // 0x8 + virtual bool isBlockPlanterItem(void); // 0x9 + virtual bool isBucket(void); // 0xA + virtual bool isCamera(void); // 0xB + virtual bool isCandle(void); // 0xC + virtual bool isDamageable(void); // 0xD + virtual bool isDyeable(void); // 0xE + virtual bool isDye(void); // 0xF +private: + virtual __int64 getItemColor(void); // 0x10 +public: + virtual bool isFertilizer(void); // 0x11 + virtual bool isFood(void); // 0x12 + virtual bool isThrowable(void); // 0x13 + virtual bool isUseable(void); // 0x14 +private: + virtual __int64 getCamera(void); // 0x15 + virtual __int64 getFood(void); // 0x16 + virtual __int64 getFuel(void); // 0x17 +public: + virtual __int64 setMaxStackSize(int); // 0x18 + virtual __int64 setStackedByData(bool); // 0x19 + virtual __int64 setMaxDamage(int); // 0x1A + virtual __int64 setHandEquipped(void); // 0x1B + virtual __int64 setUseAnimation(int); // 0x1C + virtual __int64 setMaxUseDuration(int); // 0x1D + virtual __int64 setRequiresWorldBuilder(bool); // 0x1E + virtual __int64 setExplodable(bool); // 0x1F + virtual __int64 setFireResistant(bool); // 0x20 + virtual __int64 setIsGlint(bool); // 0x21 + virtual __int64 setShouldDespawn(bool); // 0x22 +private: + virtual __int64 getC_BlockShape(void) const; // 0x23 +public: + virtual bool canBeDepleted(void) const; // 0x24 + virtual bool canDestroySpecial(C_Block const &) const; // 0x25 +private: + virtual __int64 getLevelDataForAuxValue(int); // 0x26 +public: + virtual bool isStackedByData(void); // 0x27 + virtual __int64 getMaxDamage(void); // 0x28 + virtual __int64 getAttackDamage(void); // 0x29 + virtual bool isHandEquipped(void); // 0x2A + virtual bool isGlint(C_ItemStack const &); // 0x2B + virtual bool isPattern(void); // 0x2C +private: + virtual __int64 getPatternIndex(void); // 0x2D +public: + virtual bool showsDurabilityInCreative(void); // 0x2E + virtual bool isWearableThroughLootTable(CompoundTag const *); // 0x2F + virtual bool canDestroyInCreative(void); // 0x30 + virtual bool isDestructive(int); // 0x31 +private: + virtual bool isLiquidClipItem(int); // 0x32 + virtual bool shouldInteractionWithBlockBypassLiquid(C_Block const &); // 0x33 + virtual bool requiresInteract(void); // 0x34 + virtual __int64 appendFormattedHovertext(C_ItemStack const &, __int64 &, std::string &, bool) const; // 0x35 +public: + virtual bool isValidRepairItem(C_ItemStack const &, C_ItemStack const &) const; // 0x36 +public: + virtual __int64 getEnchantSlot(void); // 0x37 + virtual __int64 getEnchantValue(void); // 0x38 + virtual __int64 getArmorValue(void); // 0x39 +private: + virtual bool isComplex(void); // 0x3A + virtual bool isValidAuxValue(int); // 0x3B +public: + virtual __int64 getDamageChance(int); // 0x3C + virtual __int64 getViewDamping(void); // 0x3D + virtual __int64 uniqueAuxValues(void); // 0x3E +private: + virtual __int64 isActorPlacerItem(void); // 0x3F +public: + virtual bool isMultiColorTinted(C_ItemStack const &) const; // 0x40 +private: + virtual __int64 getColor(CompoundTag const *, C_ItemStack const &); // 0x41 + virtual __int64 hasCustomColor(C_ItemStack const &); // 0x42 + virtual __int64 hasCustomColor(CompoundTag const *); // 0x43 + virtual __int64 clearColor(C_ItemStack &); // 0x44 + virtual __int64 clearColor(CompoundTag *); // 0x45 + virtual __int64 setColor(C_ItemStack &, int const &); // 0x46 + virtual __int64 getBaseColor(C_ItemStack const &); // 0x47 + virtual __int64 getSecondaryColor(C_ItemStack const &); // 0x48 + virtual __int64 getActorIdentifier(C_ItemStack const &); // 0x49 + virtual __int64 saveAdditionalData(C_ItemStack const &, CompoundTag &); // 0x4A + virtual __int64 readAdditionalData(C_ItemStack &, CompoundTag const &); // 0x4B + virtual __int64 buildIdAux(short, const CompoundTag *); // 0x4C + virtual __int64 use(C_ItemStack &, C_Entity &); // 0x4D + virtual __int64 dispense(C_Block &, __int64 &, int, vec3_t const &, char); // 0x4E + virtual __int64 useTimeDepleted(C_ItemStack &, __int64 *, C_Entity *); // 0x4F + virtual __int64 releaseUsing(C_ItemStack &, C_Entity *, int); // 0x50 + virtual __int64 getDestroySpeed(C_ItemStack const &, C_Block const &); // 0x51 + virtual __int64 hurtActor(C_ItemStack &, C_Entity &, C_Entity &); // 0x52 + virtual __int64 hitActor(C_ItemStack &, C_Entity &, C_Entity &); // 0x53 + virtual __int64 hitBlock(C_ItemStack &, C_Block const &, vec3_t const &, C_Entity &); // 0x54 + virtual __int64 mineBlock(__int64 &&, C_Block const &, int, int, int, C_Entity *); // 0x55 + virtual __int64 mineBlock(C_ItemStack &, C_Block const &, int, int, int, C_Entity *); // 0x56 + virtual __int64 buildDescriptionName(C_ItemStack const &); // 0x57 + virtual __int64 buildDescriptionId(C_ItemStack const &) const; // 0x58 + virtual __int64 buildEffectDescriptionName(C_ItemStack const &); // 0x59 + virtual __int64 buildCategoryDescriptionName(void); // 0x5A + virtual __int64 readUserData(C_ItemStack &, __int64 &, __int64 &) const; // 0x5B + virtual __int64 writeUserData(C_ItemStack const &, __int64 &) const; // 0x5C +public: + virtual int getMaxStackSize(void *itemDescriptor) const; // 0x5D +private: + virtual __int64 inventoryTick(C_ItemStack &, __int64 &, C_Entity &, int, bool) const; // 0x5E + virtual __int64 refreshedInContainer(C_ItemStack &, __int64 &) const; // 0x5F + virtual __int64 getCooldownType(void); // 0x60 + virtual __int64 getCooldownTime(void); // 0x61 + virtual __int64 fixupCommon(C_ItemStack &); // 0x62 + virtual __int64 fixupCommon(C_ItemStack &, __int64 &&); // 0x63 + virtual __int64 getDamageValue(C_ItemStack const &) const; // 0x64 +public: + virtual __int64 setDamageValue(C_ItemStack &, short); // 0x65 +private: + virtual __int64 getInHandUpdateType(C_Entity const &, __int64 const &, __int64 const &, bool, bool) const; // 0x66 + virtual __int64 getInHandUpdateType(C_Entity const &, C_ItemStack const &, C_ItemStack const &, bool, bool) const; // 0x67 + virtual __int64 validFishInteraction(int); // 0x68 +public: + virtual bool isSameItem(C_ItemStack const &, C_ItemStack const &) const; // 0x69 +private: + virtual __int64 initClient(__int64 &); // 0x6A + virtual __int64 getInteractText(C_Entity const &); // 0x6B + virtual __int64 getAnimationFrameFor(C_Entity *, bool, C_ItemStack const *, bool); // 0x6C +public: + virtual bool isEmissive(int); // 0x6D + virtual __int64 getLightEmission(int); // 0x6E +private: + virtual __int64 getIcon(int, int, bool) const; // 0x6F + virtual __int64 getIconYOffset(void) const; // 0x70 +public: + virtual void setIcon(std::string const &, int); // 0x71 + virtual void setIcon(__int64 const &); // 0x72 + virtual void setIconAtlas(__int64 const &); // 0x73 + virtual bool canBeCharged(void) const; // 0x74 +private: + virtual __int64 playSoundIncrementally(__int64 const &, __int64 &) const; // 0x75 + virtual __int64 playSoundIncrementally(C_ItemStack const &, __int64 &) const; // 0x76 + virtual __int64 getFurnaceBurnIntervalMultipler(C_ItemStack const &); // 0x77 + virtual __int64 getFurnaceXPmultiplier(C_ItemStack const &); // 0x78 + virtual __int64 getAuxValuesDescription(void); // 0x79 + virtual __int64 _checkUseOnPermissions(C_Entity &, C_ItemStack &, unsigned char const &, vec3_ti const &) const; // 0x7A + virtual __int64 _calculatePlacePos(C_ItemStack &, C_Entity &, unsigned char &, vec3_ti &) const; // 0x7B + +public: + bool isTool(void) { + if (getAttackDamage() > 0) return true; // Does Attack Damage + if (itemId == 300 || itemId == 301) return true; // Bow + if (itemId == 299) return true; // Flint n Steel + return false; + } + bool isWeapon(void) { + if (itemId == 308) return true; //Wooden Sword + if (itemId == 312) return true; //Stone Sword + if (itemId == 322) return true; //Gold Sword + if (itemId == 307) return true; //Iron Sword + if (itemId == 316) return true; //Diamond Sword + if (itemId == 602) return true; //Netherite Sword + if (itemId == 311) return true; //Wooden Axe + if (itemId == 315) return true; //Stone Axe + if (itemId == 325) return true; //Gold Axe + if (itemId == 298) return true; //Iron Axe + if (itemId == 319) return true; //Diamond Axe + if (itemId == 605) return true; //Netherite Axe + return false; + } + bool isBlock(void) { + auto val = *reinterpret_cast<__int64***>(reinterpret_cast<__int64>(this) + 0x1A0); + return val != nullptr && *val != nullptr; + } +}; + + +class ItemDescriptor { +private: + char pad_0x0[0x48]; //0x0000 +public: + ItemDescriptor() { + memset(this, 0x0, sizeof(ItemDescriptor)); + } + ItemDescriptor(int id, int16_t itemData); +}; + +class C_ItemStack { +private: + uintptr_t** vTable; //0x0000 +public: + C_Item** item; //0x08 + CompoundTag* tag; //0x10 +private: + char pad_0x18[0xA]; //0x18 +public: + char count; //0x22 +private: + char pad_0x1B[0x6D]; //0x23 +public: + C_ItemStack() { + memset(this, 0x0, sizeof(C_ItemStack)); + } + + C_ItemStack(C_BlockLegacy& legacy, int count) { + memset(this, 0x0, sizeof(C_ItemStack)); + reinit(legacy, count); + } + + C_ItemStack(C_Item& item, int count, int itemData) { + memset(this, 0x0, sizeof(C_ItemStack)); + reinit(item, count, itemData); + } + + C_ItemStack(C_ItemStack const& src); + + C_ItemStack(Tag const& tag); + + void fromTag(Tag const& tag); + + void save(CompoundTag** tag); + + void setUserData(std::unique_ptr tag); + + bool isValid() { + return this->item != nullptr && *this->item != nullptr; + } + + inline C_Item* getItem() { + return *this->item; + } + + void reinit(C_BlockLegacy& legacy, int count); + + void reinit(C_Item& item, int count, int itemData); + + int getEnchantValue(int enchantId); + + bool isEnchanted() { + int enchantValue = 0; + for (int i = 0; i < 40; i++) { + enchantValue = this->getEnchantValue(i); + } + if (enchantValue != 0) + return true; + else + return false; + } + + float getArmorValueWithEnchants() { + if (!this->item || !(*this->item)->isArmor()) + return 0; + + return (float)(((*this->item)->getArmorValue() + ((this->getEnchantValue(0) * 1.5f // Protection + + this->getEnchantValue(5) * 0.4f // Thorns + + this->getEnchantValue(3) * 0.4f // Blast Protection + + this->getEnchantValue(1) * 0.4f // Fire Protection + + this->getEnchantValue(4) * 0.4f // Projectile Protection + )))); + } + + float getAttackingDamageWithEnchants() { + if (!this->item) + return 0; + int sharpnessValue = this->getEnchantValue(9); + return (*this->item)->getAttackDamage() + 1.25f * sharpnessValue; + } + + void setShowPickUp(bool b) { + *(bool*)(reinterpret_cast<__int64>(this)+ 0x30) = b; + } + +private: + inline void setVtable(void); +}; + +class C_ArmorItem : public C_Item { +private: + char pad_0x108[0x228 - sizeof(C_Item)]; //0x100 +public: + int ArmorSlot; //0x1B8 + + bool isHelmet() { + return ArmorSlot == 0; + } + bool isChestplate() { + return ArmorSlot == 1; + } + bool isLeggings() { + return ArmorSlot == 2; + } + bool isBoots() { + return ArmorSlot == 3; + } +}; + + +class ItemRegistry { +public: + static C_Item*** getItemFromId(void* ptr, int itemId); + static C_Item*** lookUpByName(void*, void*, TextHolder&); +}; diff --git a/SDK/CLoopbackPacketSender.h b/SDK/CLoopbackPacketSender.h new file mode 100644 index 0000000..d203ede --- /dev/null +++ b/SDK/CLoopbackPacketSender.h @@ -0,0 +1,16 @@ +#pragma once + +#include "CPacket.h" + +class C_LoopbackPacketSender { +public: + virtual ~C_LoopbackPacketSender(); + //Duplicate contructor + virtual __int64 send(C_Packet* packet); + virtual __int64 sendToServer(C_Packet* packet); + virtual __int64 sendToClient(const void* networkIdentifier, const C_Packet* packet, int a4); + virtual __int64 sendToClients(const void* networkIdentifier, const C_Packet* packet); + virtual __int64 sendBroadcast(const C_Packet* packet); + virtual __int64 sendBroadcast(const void* networkIdentifier, int a3, const C_Packet* packet); + virtual __int64 flush(void* networkIdentifier, int a3); +}; diff --git a/SDK/CMinecraftUIRenderContext.cpp b/SDK/CMinecraftUIRenderContext.cpp new file mode 100644 index 0000000..869df7e --- /dev/null +++ b/SDK/CMinecraftUIRenderContext.cpp @@ -0,0 +1,9 @@ +#include "CMinecraftUIRenderContext.h" +#include "../Utils/Utils.h" +#include "../Utils/HMath.h" + +C_TexturePtr* C_MinecraftUIRenderContext::getTexture(C_TexturePtr* ptr, C_FilePath& path) { + using getTexture_t = C_TexturePtr*(__fastcall*)(C_MinecraftUIRenderContext*,C_TexturePtr*,C_FilePath&,int); + getTexture_t getTextureF = reinterpret_cast(FindSignature("48 89 54 24 ?? 53 48 83 EC ?? 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 8B DA 49 83 78 ?? ?? 75 1C 33 C0 48 89 02 48 89 42 ?? 48 8D 4A ?? E8")); + return getTextureF(this, ptr, path, 0); +} diff --git a/SDK/CMinecraftUIRenderContext.h b/SDK/CMinecraftUIRenderContext.h new file mode 100644 index 0000000..b3ba0d2 --- /dev/null +++ b/SDK/CMinecraftUIRenderContext.h @@ -0,0 +1,70 @@ +#pragma once + +#include "TextHolder.h" +#include "../Utils/HMath.h" + +struct MC_Color; + +class C_FilePath { +private: + char pad_0x0[0x8]; //0x0000 + TextHolder filePath; //0x0008 +public: + C_FilePath(std::string filePath) { + memset(this, 0, sizeof(C_FilePath)); + this->filePath.setText(filePath); + }; +}; + +class C_TexturePtr { +private: + char pad_0x0[0x18]; //0x0000 +public: + TextHolder filePath; //0x0018 +private: + char pad_0x0038[0x20]; //0x0038 +}; + +class C_Font { +private: + virtual void destructorFont(); + virtual void unk1(); + virtual void unk2(); + virtual void unk3(); + virtual void unk4(); + virtual void unk5(); + +public: + virtual float getLineLength(TextHolder* str, float textSize, bool unknown); + virtual float getLineHeight(); +}; + +struct TextMeasureData { + float textSize; + int idk; + bool bool1; + bool bool2; +}; + +class C_MinecraftUIRenderContext { +private: + float _[140]; + +public: + C_TexturePtr* getTexture(C_TexturePtr* ptr, C_FilePath& path); + virtual ~C_MinecraftUIRenderContext(); + virtual float getLineLength(C_Font* font, TextHolder* str, float textSize, bool unknown); + virtual float getTextAlpha(); + virtual void setTextAlpha(float alpha); + virtual __int64 drawDebugText(const float* pos, TextHolder* text, float* color, float alpha, unsigned int textAlignment, const float* textMeasureData, const void* caretMeasureData); + virtual __int64 drawText(C_Font* font, const float* pos, TextHolder* text, const float* color, float alpha, unsigned int textAlignment, const TextMeasureData* textMeasureData, const uintptr_t* caretMeasureData); + virtual void flushText(float timeSinceLastFlush); // time used for ticking the obfuscated text + virtual __int64 drawImage(C_TexturePtr* texturePtr, vec2_t& ImagePos, vec2_t& ImageDimension,__int64& a4,vec2_t& idk); // didnt bother putting in the parameters + virtual __int64 drawNinesliceNOTIMPLEMENTED(); + virtual __int64 flushImages(MC_Color& color, __int64 flushImageAddr, __int64 hashedString); + virtual __int64 beginSharedMeshBatchNOTIMPLEMENTED(); + virtual __int64 endSharedMeshBatchNOTIMPLEMENTED(); + virtual void drawRectangle(const float* pos, const float* color, float alpha, int lineWidth); // line width is guessed + virtual void fillRectangle(const float* pos, const float* color, float alpha); + // There are a few more functions but didnt bother +}; diff --git a/SDK/CMoveInputHandler.cpp b/SDK/CMoveInputHandler.cpp new file mode 100644 index 0000000..8f6b3ca --- /dev/null +++ b/SDK/CMoveInputHandler.cpp @@ -0,0 +1,6 @@ +#include "CMoveInputHandler.h" +#include "../Utils/Utils.h" + +__int64 C_MoveInputHandler::clearMovementState() { + return Utils::CallVFunc<4, __int64>(this); +} diff --git a/SDK/CMoveInputHandler.h b/SDK/CMoveInputHandler.h new file mode 100644 index 0000000..521fc50 --- /dev/null +++ b/SDK/CMoveInputHandler.h @@ -0,0 +1,30 @@ +#pragma once + +class C_MoveInputHandler { +private: + char pad_0x0000[0x8]; //0x0000 +public: + float sideMovement; //0x0008 + float forwardMovement; //0x000C +private: + char pad_0x0010[0x39]; //0x0010 +public: + unsigned char isSneakDown; //0x0049 +private: + char pad_0x004A[0x5]; //0x004A +public: + unsigned char isJumping; //0x004F + unsigned char autoJumpInWater; // 50 + +private: + char pad_0x0051[0xE]; //0x0051 +public: + bool forward; //0x005F + bool backward; //0x0060 + bool left; //0x0061 + bool right; //0x0062 +private: + char pad_0x0063[0x2D]; //0x0063 +public: + __int64 clearMovementState();; +}; diff --git a/SDK/CPacket.cpp b/SDK/CPacket.cpp new file mode 100644 index 0000000..1b3fbe0 --- /dev/null +++ b/SDK/CPacket.cpp @@ -0,0 +1,169 @@ +#include "CPacket.h" +#include "../Utils/Utils.h" + +TextHolder* C_Packet::getName() { + return Utils::CallVFunc<2, TextHolder*>(this, new TextHolder()); +} +LevelSoundEventPacket::LevelSoundEventPacket() { + static uintptr_t** LevelSoundEventPacketVtable = 0x0; + if (LevelSoundEventPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ? ? ? ? 48 89 4D ? C7 45 ? ? ? ? ? F2 0F 10 00 F2 0F 11 45 ? 8B 40"); + int offset = *reinterpret_cast(sigOffset + 3); + LevelSoundEventPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (LevelSoundEventPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(LevelSoundEventPacket)); // Avoid overwriting vtable + vTable = LevelSoundEventPacketVtable; + this->entityType.setText("minecraft:player"); +} +PlayerAuthInputPacket::PlayerAuthInputPacket() { + static uintptr_t** PlayerAuthInputPacketVtable = 0x0; + if (PlayerAuthInputPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 01 F2 0F 10 42 ?? F2 0F 11 41 ?? F2 0F 10 42"); + int offset = *reinterpret_cast(sigOffset + 3); + PlayerAuthInputPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (PlayerAuthInputPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(PlayerAuthInputPacket)); // Avoid overwriting vtable + vTable = PlayerAuthInputPacketVtable; +} +PlayerAuthInputPacket::PlayerAuthInputPacket(__int64 entityRuntimeId, vec3_t pos, float pitch, float yaw, float yawUnused) { + static uintptr_t** PlayerAuthInputPacketVtable = 0x0; + if (PlayerAuthInputPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 89 01 F2 0F 10 42 ?? F2 0F 11 41 ?? F2 0F 10 42"); + int offset = *reinterpret_cast(sigOffset + 3); + PlayerAuthInputPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (PlayerAuthInputPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(PlayerAuthInputPacket)); // Avoid overwriting vtable + vTable = PlayerAuthInputPacketVtable; + this->pos = pos; + this->pitch = pitch; + this->yaw = yaw; + this->yawUnused = yawUnused; + this->entityRuntimeId = entityRuntimeId; +} +/*C_ActorFallPacket::C_ActorFallPacket() { + static uintptr_t** ActorFallPacketVtable = 0x0; + if (ActorFallPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D ? ? ? ? ? 48 89 ? E7 48 89 45 0F F3 0F 11 75 ?"); + int offset = *reinterpret_cast(sigOffset + 3); + ActorFallPacketVtable = reinterpret_cast(sigOffset + offset + 7); +#ifdef _DEBUG + if (ActorFallPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_ActorFallPacket)); // Avoid overwriting vtable + vTable = ActorFallPacketVtable; +}*/ +C_MobEquipmentPacket::C_MobEquipmentPacket() { + static uintptr_t** MobEquipmentPacketVtable = 0x0; + if (MobEquipmentPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ? ? ? ? 48 89 4D 90 48 89 45 B8 48 8D 97 ? ? ? ?"); + int offset = *reinterpret_cast(sigOffset + 3); + MobEquipmentPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (MobEquipmentPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_MobEquipmentPacket)); // Avoid overwriting vtable + vTable = MobEquipmentPacketVtable; +} +C_MobEquipmentPacket::C_MobEquipmentPacket(__int64 entityRuntimeId, C_ItemStack& item, int hotbarSlot, int inventorySlot) { + memset(this, 0x0, sizeof(C_MobEquipmentPacket)); + using MobEquimentPacketConstructor_t = void(__fastcall*)(C_MobEquipmentPacket*, __int64, C_ItemStack&, int, int, char); + static MobEquimentPacketConstructor_t MobEquimentPacketConstructor = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 4C 24 ? 57 48 83 EC ? 41 8B D9 48 8B F9 C7 41 ? ? ? ? ? C7 41")); + + if (MobEquimentPacketConstructor != 0) + MobEquimentPacketConstructor(this, entityRuntimeId, item, hotbarSlot, inventorySlot, 0); +} +C_InventoryTransactionPacket::C_InventoryTransactionPacket() { + static uintptr_t** InventoryTransactionPacketVtable = 0x0; + if (InventoryTransactionPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 15 ? ? ? ? 48 89 54 24 ? 44 89 75"); + int offset = *reinterpret_cast(sigOffset + 3); + InventoryTransactionPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (InventoryTransactionPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_InventoryTransactionPacket)); // Avoid overwriting vtable + vTable = InventoryTransactionPacketVtable; +} +C_TextPacket::C_TextPacket() { + static uintptr_t** textPacketVtable = 0x0; + if (textPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ?? ?? ?? ?? 48 8B F9 48 89 01 48 83 C1 ?? E8 ?? ?? ?? ?? 48 8D 8F"); + int offset = *reinterpret_cast(sigOffset + 3); + textPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (textPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_TextPacket)); // Avoid overwriting vtable + vTable = textPacketVtable; + + messageType = 1; // TYPE_CHAT +} +C_MovePlayerPacket::C_MovePlayerPacket() { + static uintptr_t** movePlayerPacketVtable = 0x0; + if (movePlayerPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 01 48 8B 82 70 ? ? ? 48 89 41 ? 48 8B 02 48 8B CA"); + int offset = *reinterpret_cast(sigOffset + 3); + movePlayerPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (movePlayerPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_MovePlayerPacket)); // Avoid overwriting vtable + vTable = movePlayerPacketVtable; +} +C_MovePlayerPacket::C_MovePlayerPacket(C_LocalPlayer* player, vec3_t pos) { + static uintptr_t** movePlayerPacketVtable = 0x0; + if (movePlayerPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 01 48 8B 82 70 ? ? ? 48 89 41 ? 48 8B 02 48 8B CA"); + int offset = *reinterpret_cast(sigOffset + 3); + movePlayerPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (movePlayerPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_MovePlayerPacket)); // Avoid overwriting vtable + vTable = movePlayerPacketVtable; + entityRuntimeID = player->entityRuntimeId; + Position = pos; + pitch = player->pitch; + yaw = player->yaw; + headYaw = player->yaw; + onGround = true; + mode = 0; +} +C_PlayerActionPacket::C_PlayerActionPacket() { + static uintptr_t** playerActionPacketVtable = 0x0; + if (playerActionPacketVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ?? ?? ?? ?? 48 89 4C 24 30 F3 0F 11 44 24 60 F3"); + int offset = *reinterpret_cast(sigOffset + 3); + playerActionPacketVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); +#ifdef _DEBUG + if (playerActionPacketVtable == 0x0 || sigOffset == 0x0) + __debugbreak(); +#endif + } + memset(this, 0, sizeof(C_PlayerActionPacket)); // Avoid overwriting vtable + vTable = playerActionPacketVtable; +} \ No newline at end of file diff --git a/SDK/CPacket.h b/SDK/CPacket.h new file mode 100644 index 0000000..41ee35e --- /dev/null +++ b/SDK/CPacket.h @@ -0,0 +1,155 @@ +#pragma once +#include "../Utils/HMath.h" +#include "CEntity.h" +#include "CComplexInventoryTransaction.h" +#include "TextHolder.h" + +class C_Packet { +public: + uintptr_t** vTable; //0x0000 + TextHolder* getName(); + template + bool isInstanceOf() { + T packet; + if (packet.vTable == this->vTable) + return true; + else + return false; + } +}; + +class LevelSoundEventPacket : public C_Packet { +private: + char pad_[0x20]; //0x8 +public: + int sound; //0x28 + vec3_t pos; //0x2C + int extraData = -1; //0x38 +private: + int unknown = 0; //0x3C +public: + TextHolder entityType; //0x40 + bool isBabyMod = false; //0x60 + bool disableRelativeVolume = false; //0x61 + LevelSoundEventPacket(); +}; + +class PlayerAuthInputPacket : public C_Packet { +private: + char pad_0x0000[0x18]; //0x0008 +public: + __int64 entityRuntimeId; //0x0020 + float pitch; //0x0028 + float yaw; //0x002C + vec3_t pos; //0x0030 + float yawUnused; //0x003C +private: + char pad_0x0040[0x20]; //0x0040 +public: + PlayerAuthInputPacket(); + PlayerAuthInputPacket(__int64 entityRuntimeId, vec3_t pos, float pitch, float yaw, float yawUnused); +}; + +/*class C_ActorFallPacket : public C_Packet { +private: + char pad_0x8[0x20]; //0x8 +public: + C_ActorFallPacket(); + __int64 runtimeId; // 0x28 + float fallDistance; + bool isInVoid; +};*/ + +class C_PlayerActionPacket : public C_Packet { +public: + C_PlayerActionPacket(); + char pad_0x8[0x28]; //0x8 + vec3_ti blockPosition; // 0x28 + int face; // 0x34 + int action; // 0x38 + __int64 entityRuntimeId; // 0x40 +}; + + +class C_MobEquipmentPacket : public C_Packet { +public: + C_MobEquipmentPacket(); + C_MobEquipmentPacket(__int64 entityRuntimeId, C_ItemStack& item, int hotbarSlot, int inventorySlot); + +private: + char pad_0x8[0x28]; //0x0 +public: + __int64 entityRuntimeId; //0x28 + C_ItemStack item; //0x30 + int inventorySlot; // 0xB8 DONT USE FOR PACKET SENDING + int hotbarSlot; // 0xBC DONT USE FOR PACKET SENDING + char windowId; //0xC0 DONT USE FOR PACKET SENDING + char windowId1; //0xC1 DONT USE FOR PACKET SENDING + char inventorySlot1; //0xC2 + char hotbarSlot1; //0xC3 + char windowId2; //0xC4 ALL OF THIS IS PROBABLY BROKEN, DONT USE +private: + char unknown1; +}; + +class C_InventoryTransactionPacket : public C_Packet { +public: + C_InventoryTransactionPacket(); + C_InventoryTransactionPacket(C_ComplexInventoryTransaction* transac) : C_InventoryTransactionPacket() { + this->complexTransaction = transac; + } + +private: + char pad_0x8[0x28]; //0x8 +public: + int unknown = 0;//0x28 + __int64* unknownStart = 0; //0x30 + __int64* unknownEnd = 0; //0x38 + __int64 filler = 0; // 0x40 + C_ComplexInventoryTransaction* complexTransaction; // 0x48 + unsigned char numTransactions; // 0x50 +}; + +class C_TextPacket : public C_Packet { +public: + C_TextPacket(); + + unsigned char gap0[0x28]; + unsigned __int8 messageType; // 0x28 + + unsigned char gap[7]; + + TextHolder sourceName; // 0x30 + TextHolder message; // 0x50 + unsigned char field_24222[24]; // 0x70 + bool translationNeeded = false; // 0x88 + + unsigned char ga2p[7]; // 0x89 + TextHolder xboxUserId; + TextHolder platformChatId; +}; + +#pragma pack(push, 8) + +__declspec(align(8)) class C_MovePlayerPacket : public C_Packet { +public: + C_MovePlayerPacket(); + C_MovePlayerPacket(C_LocalPlayer* player, vec3_t pos); + + //uintptr_t** vTable; // 0x0 +private: + char filler[0x28]; // 0x8 +public: + __int64 entityRuntimeID; //0x28 + vec3_t Position; //0x30 + float pitch; //0x3c + float yaw; //0x40 + float headYaw; //0x44 + uint8_t mode; //0x48 + bool onGround; + __int64 ridingEid; + int int1; + int int2; +}; + +#pragma pack(pop) diff --git a/SDK/CRakNetInstance.h b/SDK/CRakNetInstance.h new file mode 100644 index 0000000..7e0fbf1 --- /dev/null +++ b/SDK/CRakNetInstance.h @@ -0,0 +1,48 @@ +#pragma once + +class C_RakNetInstance { + char pad_0000[856]; //0x0000 +public: + TextHolder numericalIp; //0x0360 + TextHolder serverIp; //0x0380 + uint32_t serverPort; //0x03A0 + + private: + virtual ~C_RakNetInstance(); + virtual __int64 onAppResumed(void); + virtual __int64 onAppSuspended(void); + +public: + virtual TextHolder* getLocalIps(TextHolder*); + virtual TextHolder* getLocalIp(TextHolder*); + +public: + virtual unsigned int getPort(void) const; + +private: + virtual __int64 getRefinedLocalIps(void) const; + virtual __int64 getConnectedGameInfo(void) const; + +public: + virtual void setupNatPunch(bool); + +private: + virtual __int64 getNatPunchInfo(void) const; + virtual __int64 startNatPunchingClient(__int64); + virtual __int64 addConnectionStateListener(__int64); + virtual __int64 removeConnectionStateListener(__int64); + +public: + virtual bool isIPv4Supported(void) const; + virtual bool isIPv6Supported(void) const; + +private: + virtual __int64 getIPv4Port(void) const; + virtual __int64 getIPv6Port(void) const; + virtual __int64 getGUID(void) const; + +public: + bool isonaServer() { return !(serverIp.textLength == 0); } + +}; //Size: 0x0848 + diff --git a/SDK/CUIScene.h b/SDK/CUIScene.h new file mode 100644 index 0000000..8d3bd98 --- /dev/null +++ b/SDK/CUIScene.h @@ -0,0 +1,168 @@ +#pragma once + +#include "TextHolder.h" + +class C_UIScene { + /* +private: + virtual ~C_UIScene(); + // Duplicate destructor + virtual __int64 init(__int64 const &); + +public: + virtual void setSize(__int64 const &); + +private: + virtual void unknown(); + virtual __int64 onSetKeyboardHeight(float); + virtual __int64 onInternetUpdate(void); + virtual __int64 getInputAreas(void) const; + virtual __int64 onFocusGained(void); + virtual __int64 onFocusLost(void); + virtual __int64 terminate(void); + virtual __int64 onCreation(void); + virtual __int64 onLeave(void); + virtual __int64 onGameEventNotification(__int64); + virtual __int64 _handleDirtyVisualTree(bool); + virtual __int64 leaveScreen(void); + virtual __int64 tick(int, int); + virtual __int64 updateEvents(void); + virtual __int64 applyInput(float); + virtual __int64 update(double); + virtual __int64 preRenderUpdate(__int64 &); + virtual __int64 prepareFrame(__int64 &); + virtual __int64 render(__int64 &, __int64 const &); + virtual __int64 postRenderUpdate(__int64 &); + +public: + virtual void setupAndRender(__int64 &); + +private: + virtual __int64 handleInputModeChanged(__int64); + virtual __int64 handleHoloInputModeChanged(__int64); + virtual __int64 handleButtonPress(unsigned int, __int64); + virtual __int64 handleButtonRelease(unsigned int, __int64); + virtual __int64 handleRawInputEvent(int, __int64, __int64, bool); + virtual __int64 handlePointerLocation(__int64 const &, __int64); + virtual __int64 handlePointerPressed(bool); + virtual __int64 handleDirection(__int64, float, float, __int64); + virtual __int64 handleBackEvent(bool); + virtual __int64 handleTextChar(__int64 const &, bool, __int64); + virtual __int64 handleCaretLocation(int, __int64); + virtual __int64 unk(); +public: + virtual void setTextboxText(__int64 const &); + +private: + virtual __int64 onKeyboardDismissed(void); + virtual __int64 handleLicenseChanged(void); + virtual __int64 handleIdentityGained(void); + virtual __int64 handleIdentityLost(void); + virtual __int64 handleGazeGestureInput(short, float, float, float, __int64); + virtual __int64 handleDictationEvent(__int64 const &); + virtual __int64 handleCommandEvent(__int64 const &); + virtual __int64 renderGameBehind(void) const; + virtual __int64 absorbsInput(void) const; + virtual __int64 closeOnPlayerHurt(void) const; + +public: + virtual bool isModal(void) const; + virtual bool isShowingMenu(void) const; + +private: + virtual __int64 shouldStealMouse(void) const; + virtual __int64 screenIsNotFlushable(void) const; + virtual __int64 alwaysAcceptsInput(void) const; + virtual __int64 screenDrawsLast(void) const; + +public: + virtual bool isPlayScreen(void) const; + +private: + virtual __int64 renderOnlyWhenTopMost(void) const; + virtual __int64 lowFreqRendering(void) const; + virtual __int64 ignoreAsTop(void) const; + virtual __int64 screenHandlesGamepadMenuButton(void) const; + virtual __int64 getWidth(void); + virtual __int64 getHeight(void); + virtual __int64 reload(void); + virtual __int64 getRenderingAABB(void); + virtual __int64 getEyeRenderingMode(void) const; + virtual __int64 getSceneType(void) const; + +public: + virtual TextHolder *getScreenName(TextHolder *text) const; + +private: + virtual __int64 getScreenTelemetryName(void) const; + virtual __int64 getScreenNameW(void) const; + virtual __int64 addEventProperties(__int64 const &) const; + virtual __int64 getScreenVersion(void) const; + virtual __int64 processBufferedTextCharEvents(__int64 const &); + virtual __int64 getShouldSendEvents(void); + +public: + virtual void setShouldSendEvents(bool); + +private: + virtual __int64 getWantsTextOnly(void); + +public: + virtual void setWantsTextOnly(bool); + +private: + virtual __int64 onDelete(__int64 &, __int64 &); + +public: + virtual bool isGamepadCursorEnabled(void) const; + +private: + virtual __int64 getGamepadCursorPosition(void) const; + virtual __int64 cleanInputComponents(void); + virtual __int64 getProxy(void); + +public: + virtual bool canBePushed(void) const; + virtual bool canBePopped(void) const; + virtual bool canBeTransitioned(void) const; + +private: + virtual __int64 onScreenExit(bool, bool); + virtual __int64 onScreenEntrance(bool, bool); + +public: + virtual bool isEntering(void) const; + virtual bool isExiting(void) const; + +private: + virtual __int64 schedulePop(void); + +public: + virtual bool isTerminating(void) const; + +private: + virtual __int64 loadScreenImmediately(void) const; + virtual __int64 forceUpdateActiveSceneStackWhenPushed(void) const; + +public: + virtual bool hasFinishedLoading(void) const; + +private: + virtual __int64 sendScreenEvent(__int64 const &, __int64 const &); + +public: + virtual void setDebugFeature(__int64, bool) const; + virtual void setupForRendering(__int64 &); + +private: + virtual __int64 cleanupForRendering(__int64 &);*/ + +public: + bool isPlayScreen() { + return Utils::CallVFunc<55, bool>(this); + } + + void getScreenName(TextHolder* txt) { + Utils::CallVFunc<67, void, TextHolder*>(this, txt); + } +}; diff --git a/SDK/MatrixStack.cpp b/SDK/MatrixStack.cpp new file mode 100644 index 0000000..2a9cad1 --- /dev/null +++ b/SDK/MatrixStack.cpp @@ -0,0 +1,5 @@ +#include "MatrixStack.h" + +MatrixStackRef::~MatrixStackRef() { + this->stack->pop(); +} diff --git a/SDK/MatrixStack.h b/SDK/MatrixStack.h new file mode 100644 index 0000000..a2827ab --- /dev/null +++ b/SDK/MatrixStack.h @@ -0,0 +1,46 @@ +#pragma once + +#include +#include + +class MatrixStack; + +class MatrixStackRef { +private: + MatrixStack* stack; + glm::mat4x4& myPtr; + +public: + MatrixStackRef(MatrixStack* st, glm::mat4x4& top) : stack(st), myPtr(top){}; + ~MatrixStackRef(); + + auto& operator->() { + return myPtr; + } + auto& operator*() { + return myPtr; + } +}; + +class MatrixStack { +private: + std::deque stack; + bool isDirty; + +public: + MatrixStackRef push() { + this->isDirty = 1; + const auto latestAndGreatest = this->stack.back(); + this->stack.push_back(latestAndGreatest); + return MatrixStackRef(this, this->stack.back()); + } + + void pop() { + this->isDirty = 1; + this->stack.pop_back(); + } + + glm::mat4x4& top() { + return this->stack.back(); + } +}; \ No newline at end of file diff --git a/SDK/MojangsonToken.h b/SDK/MojangsonToken.h new file mode 100644 index 0000000..a0c82e8 --- /dev/null +++ b/SDK/MojangsonToken.h @@ -0,0 +1,77 @@ +#pragma once + +#include + +enum class TagType{ + END, + BYTE, + SHORT, + INT, + LONG, + FLOAT, + DOUBLE, + BYTE_ARRAY, + STRING, + LIST, + COMPOUND, + INT_ARRAY +}; + +class MojangsonToken { +public: + static MojangsonToken COMPOUND_START; + static MojangsonToken COMPOUND_END; + static MojangsonToken ELEMENT_SEPERATOR; + static MojangsonToken ARRAY_START; + static MojangsonToken ARRAY_END; + static MojangsonToken ELEMENT_PAIR_SEPERATOR; + static MojangsonToken STRING_QUOTES; + static MojangsonToken DOUBLE_SUFFIX; + static MojangsonToken BYTE_SUFFIX; + static MojangsonToken FLOAT_SUFFIX; + static MojangsonToken SHORT_SUFFIX; + static MojangsonToken LONG_SUFFIX; + static MojangsonToken WHITE_SPACE; +private: + int id; + std::string name; + char symbol; +public: + MojangsonToken(int id,std::string name, char symbol) { + this->id = id; + this->name = name; + this->symbol = symbol; + } + + int getId() { + return id; + } + + std::string getName() { + return name; + } + + char getSymbol() { + return symbol; + } + + + std::string toString() { + return ""; + //return String.valueOf(symbol); + } +}; + +__declspec(selectany) MojangsonToken MojangsonToken::COMPOUND_START(0, "Compound_Start", '{'); +__declspec(selectany) MojangsonToken MojangsonToken::COMPOUND_END(1, "Compound_End", '}'); +__declspec(selectany) MojangsonToken MojangsonToken::ELEMENT_SEPERATOR(2, "Element_Seperator", ','); +__declspec(selectany) MojangsonToken MojangsonToken::ARRAY_START(3, "Array_Start", '['); +__declspec(selectany) MojangsonToken MojangsonToken::ARRAY_END(4, "Array_End", ']'); +__declspec(selectany) MojangsonToken MojangsonToken::ELEMENT_PAIR_SEPERATOR(5, "Pair_Seperator", ':'); +__declspec(selectany) MojangsonToken MojangsonToken::STRING_QUOTES(6, "String_Quotes", '\"'); +__declspec(selectany) MojangsonToken MojangsonToken::DOUBLE_SUFFIX(8, "Double_Suffix", 'd'); +__declspec(selectany) MojangsonToken MojangsonToken::BYTE_SUFFIX(9, "Byte_Suffix", 'b'); +__declspec(selectany) MojangsonToken MojangsonToken::FLOAT_SUFFIX(10, "Float_Suffix", 'f'); +__declspec(selectany) MojangsonToken MojangsonToken::SHORT_SUFFIX(11, "Short_Suffix", 's'); +__declspec(selectany) MojangsonToken MojangsonToken::LONG_SUFFIX(12, "Long_Suffix", 'l'); +__declspec(selectany) MojangsonToken MojangsonToken::WHITE_SPACE(13, "WhiteSpace", ' '); diff --git a/SDK/Tag.cpp b/SDK/Tag.cpp new file mode 100644 index 0000000..f167c13 --- /dev/null +++ b/SDK/Tag.cpp @@ -0,0 +1,313 @@ +#include "Tag.h" + +#include "../Utils/Utils.h" +#include "../Utils/Logger.h" +#include "../Memory/GameData.h" +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include + +Int64Tag::Int64Tag(__int64 value) { + static uintptr_t** Int64TagVtable = 0x0; + if (Int64TagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 47 40 48 89 77 48 C6 47 68 04 48 8B CD E8 ? ? ? ?"); + int offset = *reinterpret_cast(sigOffset + 3); + Int64TagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (Int64TagVtable == 0x0 || sigOffset == 0x0) + logF("Int64TagVtable signature not working!!!"); + } + memset(this, 0, sizeof(Int64Tag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)Int64TagVtable; + this->value = value; +} +void Int64Tag::read(std::string& string) //throws MojangsonParseException +{ + std::transform(string.begin(), string.end(), string.begin(), ::tolower); + char lastChar = string.at(string.length() - 1); + if (lastChar == MojangsonToken::LONG_SUFFIX.getSymbol()) { + string = string.substr(0, string.length() - 1); + } + + try { + value = std::stoull(string); + } catch (...) { + logF(" Unhandled exception for Int64Tag : %s", string.c_str()); + } +} +IntTag::IntTag(int value) { + static uintptr_t** IntTagVtable = 0x0; + if (IntTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 15 ? ? ? ? 48 89 10 89 48 08 48 89 03 48 8B C3 48 8B 5C 24 ?"); + int offset = *reinterpret_cast(sigOffset + 3); + IntTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (IntTagVtable == 0x0 || sigOffset == 0x0) + logF("IntTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(IntTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)IntTagVtable; + this->value = value; +} +void IntTag::read(std::string& string) //throws MojangsonParseException +{ + try { + value = static_cast(std::stoi(string)); + } catch (...) { + logF(" Unhandled exception for IntTag : %s", string.c_str()); + } +} +StringTag::StringTag(std::string value) { + static uintptr_t** StringTagVtable = 0x0; + if (StringTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 03 0F 10 44 24 ? 0F 11 43 ? 0F 10 4C 24 ? 0F 11 4B"); + int offset = *reinterpret_cast(sigOffset + 3); + StringTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (StringTagVtable == 0x0 || sigOffset == 0x0) + logF("StringTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(StringTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)StringTagVtable; + this->value = value; +} +ShortTag::ShortTag(short value) { + static uintptr_t** ShortTagVtable = 0x0; + if (ShortTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 15 ? ? ? ? 48 89 10 66 89 48 ? 48 89 03 48 8B C3 48 8B 5C 24 ?"); + int offset = *reinterpret_cast(sigOffset + 3); + ShortTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (ShortTagVtable == 0x0 || sigOffset == 0x0) + logF("ShortTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(ShortTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)ShortTagVtable; + this->value = value; +} +void ShortTag::read(std::string& string) //throws MojangsonParseException +{ + std::transform(string.begin(), string.end(), string.begin(), ::tolower); + char lastChar = string.at(string.length() - 1); + if (lastChar == MojangsonToken::SHORT_SUFFIX.getSymbol()) { + string = string.substr(0, string.length() - 1); + } + + try { + value = static_cast(std::stoi(string)); + } catch (...) { + logF(" Unhandled exception for ShortTag : %s", string.c_str()); + } +} +FloatTag::FloatTag(float value) { + static uintptr_t** FloatTagVtable = 0x0; + if (FloatTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 05 ? ? ? ? 48 89 06 8B 47 08 89 46 08 48 8B 03 C6 40 28 05"); + int offset = *reinterpret_cast(sigOffset + 3); + FloatTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (FloatTagVtable == 0x0 || sigOffset == 0x0) + logF("FloatTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(FloatTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)FloatTagVtable; + this->value = value; +} +void FloatTag::read(std::string& string) // MojangsonParseException +{ + std::transform(string.begin(), string.end(), string.begin(), ::tolower); + char lastChar = string.at(string.length() - 1); + if (lastChar == MojangsonToken::FLOAT_SUFFIX.getSymbol()) { + string = string.substr(0, string.length() - 1); + } + + try { + value = static_cast(std::stof(string)); + } catch (...) { + logF(" Unhandled exception for FloatTag : %s", string.c_str()); + } +} +DoubleTag::DoubleTag(double value) { + static uintptr_t** DoubleTagVtable = 0x0; + if (DoubleTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ? ? ? ? F2 0F 11 40 ? 48 89 08 48 89 03 48 8B C3 48 8B 5C 24 ? 48 83 C4 30"); + int offset = *reinterpret_cast(sigOffset + 3); + DoubleTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (DoubleTagVtable == 0x0 || sigOffset == 0x0) + logF("DoubleTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(DoubleTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)DoubleTagVtable; + this->value = value; +} +void DoubleTag::read(std::string& string) //throws MojangsonParseException +{ + char lastChar = string.at(string.length() - 1); + if (lastChar == MojangsonToken::DOUBLE_SUFFIX.getSymbol()) { + string = string.substr(0, string.length() - 1); + } + + try { + value = static_cast(std::stod(string)); + } catch (...) { + logF(" Unhandled exception for DoubleTag : %s", string.c_str()); + } +} +ByteTag::ByteTag(char value) { + static uintptr_t** ByteTagVtable = 0x0; + if (ByteTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 15 ? ? ? ? 48 89 10 88 48 ? 48 89 03 48 8B C3 48 8B 5C 24 ?"); + int offset = *reinterpret_cast(sigOffset + 3); + ByteTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (ByteTagVtable == 0x0 || sigOffset == 0x0) + logF("ByteTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(ByteTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)ByteTagVtable; + this->value = value; +} +void ByteTag::read(std::string& string) //throws MojangsonParseException +{ + std::transform(string.begin(), string.end(), string.begin(), ::tolower); + char lastChar = string.at(string.length() - 1); + if (lastChar == MojangsonToken::BYTE_SUFFIX.getSymbol()) { + string = string.substr(0, string.length() - 1); + } + + try { + value = static_cast(std::stoi(string)); + } catch (...) { + logF(" Unhandled exception for ByteTag : %s", string.c_str()); + } +} +ListTag::ListTag() { + static uintptr_t** ListTagVtable = 0x0; + if (ListTagVtable == 0x0) { + uintptr_t sigOffset = FindSignature("48 8D 0D ? ? ? ? 48 89 08 33 C9 48 89 48 08 48 89 48 10 48 89 48 18 88 48 20 48 89 03"); + int offset = *reinterpret_cast(sigOffset + 3); + ListTagVtable = reinterpret_cast(sigOffset + offset + /*length of instruction*/ 7); + if (ListTagVtable == 0x0 || sigOffset == 0x0) + logF("ListTagVtable signature not working!!!"); + } + memset(this, 0, sizeof(ListTag)); // Avoid overwriting vtable + uintptr_t* _this = reinterpret_cast(this); + *_this = (uintptr_t)ListTagVtable; +} +void ListTag::add(std::unique_ptr tag) { + using ListTag__add_t = void(__fastcall*)(ListTag*, std::unique_ptr); + static ListTag__add_t func = reinterpret_cast(FindSignature("48 89 5C 24 ? 57 48 83 EC 30 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 ? 48 8B FA 48 8B D9 48 89 54 24 ? 48 8B 0A 48 8B 01")); + func(this, std::move(tag)); +} +void CompoundTag::write(std::stringstream& builder) { + builder << MojangsonToken::COMPOUND_START.getSymbol(); + bool start = true; + + class CompoundTagVariant { + private: + char pad_0x0[0x20]; //0x0000 + + public: + TextHolder keyName; //0x0020 + Tag tag; //0x0040 + }; + + __int64* v10 = *(__int64**)(uintptr_t(this) + 0x8); + __int64* v11 = (__int64*)*v10; + __int64 i = 0; + if ((__int64*)*v10 != v10) { + do { + if (start) { + start = false; + } else { + builder << MojangsonToken::ELEMENT_SEPERATOR.getSymbol(); + } + CompoundTagVariant* variant = reinterpret_cast(v11); + + if (variant) { + builder << variant->keyName.getText() << MojangsonToken::ELEMENT_PAIR_SEPERATOR.getSymbol(); + Handler::handleWrite(&variant->tag, builder); + } + + + __int64** v17 = (__int64**)v11[2]; + if (*((BYTE*)v17 + 0x19)) { + for (i = v11[1]; !*(BYTE*)(i + 0x19); i = *(__int64*)(i + 8)) { + if (v11 != *(__int64**)(i + 0x10)) + break; + v11 = (__int64*)i; + } + v11 = (__int64*)i; + } else { + v11 = (__int64*)v11[2]; + for (__int64* j = *v17; !*((BYTE*)j + 25); j = (__int64*)*j) + v11 = j; + } + + } while (v11 != *(__int64**)(uintptr_t(this) + 0x8)); + } + + /*for (std::map::iterator it = this->map.begin(); it != this->map.end(); it++) { + if (start) { + start = false; + } else { + builder << MojangsonToken::ELEMENT_SEPERATOR.getSymbol(); + } + + builder << it->first << MojangsonToken::ELEMENT_PAIR_SEPERATOR.getSymbol(); + yeet::handleWrite(&it->second, builder); + }*/ + builder << MojangsonToken::COMPOUND_END.getSymbol(); +} +CompoundTag::CompoundTag() { + memset(this, 0, sizeof(CompoundTag)); + using constructor_t = void(__fastcall*)(CompoundTag*); + static constructor_t func = reinterpret_cast(FindSignature("48 89 5C 24 ? 48 89 4C 24 ? 57 48 83 EC ? 48 8B F9 48 8D 05 ? ? ? ? 48 89 01 48 8D 59 ? 48 89 5C 24 ? 33 C0 48 89 03 48 89 43")); + func(this); +} +void CompoundTag::put(TextHolder& tag, std::unique_ptr value) { + using CompoundTag__putF = void(__fastcall*)(CompoundTag*, TextHolder&, std::unique_ptr); + static CompoundTag__putF func = reinterpret_cast(FindSignature("40 53 56 57 48 83 EC ? 48 8B 05 ? ? ? ? 48 33 C4 48 89 44 24 ? 49 8B F8 48 8B DA 48 89 54 24 ? 4C 89 44 24 ? 4D 8B")); + func(this, tag, std::move(value)); +} +void Handler::handleWrite(Tag* value, std::stringstream& builder) { + switch (static_cast(value->getId())) { + case TagType::BYTE: + reinterpret_cast(value)->write(builder); + break; + case TagType::COMPOUND: + reinterpret_cast(value)->write(builder); + break; + case TagType::DOUBLE: + reinterpret_cast(value)->write(builder); + break; + case TagType::FLOAT: + reinterpret_cast(value)->write(builder); + break; + case TagType::INT: + reinterpret_cast(value)->write(builder); + break; + case TagType::LIST: + reinterpret_cast(value)->write(builder); + break; + case TagType::LONG: + reinterpret_cast(value)->write(builder); + break; + case TagType::SHORT: + reinterpret_cast(value)->write(builder); + break; + case TagType::STRING: + reinterpret_cast(value)->write(builder); + break; + case TagType::BYTE_ARRAY: + logF("BYTE ARRAY CANNOT HANDLE"); + break; + case TagType::INT_ARRAY: + logF("INT ARRAY CANNOT HANDLE"); + break; + default: + break; + } +} \ No newline at end of file diff --git a/SDK/Tag.h b/SDK/Tag.h new file mode 100644 index 0000000..038d235 --- /dev/null +++ b/SDK/Tag.h @@ -0,0 +1,500 @@ +#pragma once +#include "MojangsonToken.h" +#include "TextHolder.h" +#include +#include + +class Tag { +public: + virtual ~Tag() {} + + virtual void deleteChildren() {} + + virtual void write(__int64&) {} + + virtual void load(__int64&) {} + + virtual std::string toString() { + return this->toString(); + } + + virtual char getId() { + return this->getId(); + } + + virtual bool equals(Tag& tag) { + return this->equals(tag); + } + + virtual void print(std::string, __int64&) {} + + virtual void print(__int64&) {} + + virtual std::unique_ptr copy(std::unique_ptr tag) { + return this->copy(std::move(tag)); + } + + virtual __int64 hash() { + return this->hash(); + } + + /** + * Writes the value to a StringBuilder buffer. + * @param builder The buffer to write to + */ + void write(std::stringstream& builder); + + /** + * Parses and updates the current value to the given string representation + * @param string The string representation of the value + * @throws MojangsonParseException if the given value cannot be parsed + */ + void read(std::string& string); // throw MojangsonParseException; +}; + +class Mojangson { +public: + static inline std::unique_ptr parseTag(std::string& mojangson); +}; + +class Handler { +public: + static void handleWrite(Tag* value, std::stringstream& builder); +}; + +class Int64Tag : public Tag { +private: + __int64 value; + +public: + Int64Tag(__int64 value); + + __int64 getValue() { + return value; + } + + void setValue(__int64 value) { + this->value = value; + } + + //@Override + //public Class getValueClass() { + // return long.class; + //} + + void write(std::stringstream& builder) { + builder << value << MojangsonToken::LONG_SUFFIX.getSymbol(); + } + + void read(std::string& string); +}; + +class IntTag : public Tag { +private: + int value; + +public: + IntTag(int value); + + int getValue() { + return value; + } + + void setValue(int value) { + this->value = value; + } + + // public Class getValueClass() { + // return int.class; + //} + + void write(std::stringstream& builder) { + builder << value; + } + + void read(std::string& string); +}; + +class StringTag : public Tag { +private: + TextHolder value; + +public: + StringTag(std::string value); + + std::string getValue() { + return value.getText(); + } + + void setValue(std::string value) { + this->value.setText(value); + } + + void write(std::stringstream& builder) { + builder << MojangsonToken::STRING_QUOTES.getSymbol() << value.getText() << MojangsonToken::STRING_QUOTES.getSymbol(); + } + + // public Class getValueClass() { + // return String.class; + // } + + void read(std::string& string) //throws MojangsonParseException + { + char lastChar = string.at(string.length() - 1); + char firstChar = string.at(0); + + if (firstChar == MojangsonToken::STRING_QUOTES.getSymbol() && lastChar == MojangsonToken::STRING_QUOTES.getSymbol()) { + value.setText(string.substr(1, string.length() - 2)); + } else { + value.setText(string); + } + } +}; + +class ShortTag : public Tag { +private: + short value; + +public: + ShortTag(short value); + + short getValue() { + return value; + } + + void setValue(short value) { + this->value = value; + } + + // public Class getValueClass() { + // return short.class; + //} + + void write(std::stringstream& builder) { + builder << value << MojangsonToken::SHORT_SUFFIX.getSymbol(); + } + + void read(std::string& string); +}; + +class FloatTag : public Tag { +private: + float value; + +public: + FloatTag(float value); + + float getValue() { + return value; + } + + void setValue(float value) { + this->value = value; + } + + //typeid getValueClass() { + // return typeid(value); + //} + + void write(std::stringstream& builder) { + builder << value << MojangsonToken::FLOAT_SUFFIX.getSymbol(); + } + + void read(std::string& string); +}; + +class DoubleTag : public Tag { +private: + double value; + +public: + DoubleTag(double value); + + double getValue() { + return value; + } + + void setValue(double value) { + this->value = value; + } + + //public Class getValueClass() { + // return double.class; + //} + + void write(std::stringstream& builder) { + builder << value << MojangsonToken::DOUBLE_SUFFIX.getSymbol(); + } + + void read(std::string& string); +}; + +class ByteTag : public Tag { +private: + char value; + +public: + ByteTag(char value); + + char getValue() { + return value; + } + + void setValue(char value) { + this->value = value; + } + + // public Class getValueClass() { + // return byte.class; + //} + + void write(std::stringstream& builder) { + builder << (int)value << MojangsonToken::BYTE_SUFFIX.getSymbol(); + } + + void read(std::string& string); +}; + +class ListTag : public Tag { +private: + uintptr_t firstTag; //0x0008 + uintptr_t lastTag; //0x0010 + uintptr_t endAddr; //0x0018 + size_t id; //0x20 +public: + inline size_t getListSize() { + return (lastTag - firstTag) / sizeof(uintptr_t); + } + + inline Tag* get(std::size_t idx) { + if (idx >= getListSize()) + return 0; + return *reinterpret_cast(firstTag + (idx * sizeof(uintptr_t))); + } + + Tag* operator[](std::size_t idx) { + return get(idx); + } + +public: + ListTag(); + + void add(std::unique_ptr tag); + + void write(std::stringstream& builder) { + builder << MojangsonToken::ARRAY_START.getSymbol(); + bool start = true; + + for (size_t i = 0; i < this->getListSize(); i++) { + if (start) { + start = false; + } else { + builder << MojangsonToken::ELEMENT_SEPERATOR.getSymbol(); + } + Tag* value = this->get(i); + Handler::handleWrite(value, builder); + } + builder << MojangsonToken::ARRAY_END.getSymbol(); + } + + void read(std::string& string) { + static constexpr int C_ARRAY_START = 0; // Parsing context + static constexpr int C_ARRAY_ELEMENT = 1; // Parsing context + int context = C_ARRAY_START; + std::string tmpval = ""; + int scope = 0; + bool inString = false; + + for (size_t index = 0; index < string.size(); index++) { + char character = string.at(index); + + if (character == MojangsonToken::STRING_QUOTES.getSymbol()) { + inString = !inString; + } + if (character == MojangsonToken::WHITE_SPACE.getSymbol()) { + if (!inString) + continue; + } + if ((character == MojangsonToken::COMPOUND_START.getSymbol() || character == MojangsonToken::ARRAY_START.getSymbol()) && !inString) { + scope++; + } + if ((character == MojangsonToken::COMPOUND_END.getSymbol() || character == MojangsonToken::ARRAY_END.getSymbol()) && !inString) { + scope--; + } + if (context == C_ARRAY_START) { + if (character != MojangsonToken::ARRAY_START.getSymbol()) { + //parseException(index, character); + return; + } + context++; + continue; + } + if (context == C_ARRAY_ELEMENT) { + if ((character == MojangsonToken::ELEMENT_SEPERATOR.getSymbol() || character == MojangsonToken::ARRAY_END.getSymbol()) && scope <= 1 && !inString) { + if (tmpval.length() == 0) { + continue; + } + std::unique_ptr val = std::move(Mojangson::parseTag(tmpval)); + + this->add(std::move(val)); + tmpval = ""; + continue; + } + tmpval += character; + } + } + } + + // private void parseException(int index, char symbol) throws MojangsonParseException { + // throw new MojangsonParseException("Index: " + index + ", symbol: \'" + symbol + "\'", MojangsonParseException.ParseExceptionReason.UNEXPECTED_SYMBOL); + // }*/ +}; + +class CompoundTag : public Tag { +private: + //std::map map;//Don't use or Crash + __int64* map; //0x0008 + size_t entries; //0x0010 + +public: + CompoundTag(); + + void put(TextHolder& tag, std::unique_ptr value); + + /*void putCompound(TextHolder& text, std::unique_ptr tag) { + using putCompound_t = void(__fastcall*)(CompoundTag*, TextHolder&, std::unique_ptr); + static putCompound_t func = reinterpret_cast(FindSignature("40 53 56 57 48 83 EC ?? 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 44 24 ?? 49 8B D8 48 8B FA 48 89 54 24 ?? 48 89 5C ?? 40 49 83 38 ?? 74 4A")); + func(this, text, std::move(tag)); + } + + std::unique_ptr clone(CompoundTag** tag) { + using clone_t = std::unique_ptr(__fastcall*)(CompoundTag*, CompoundTag**); + static clone_t func = reinterpret_cast(FindSignature("48 89 54 24 ?? 57 48 83 EC ?? 48 ?? ?? ?? ?? ?? ?? ?? ?? 48 89 5C 24 ?? 48 8B FA 48 8B D9 C7 44 ?? ?? ?? ?? ?? ?? 33 C0 48 89 02 48 8B CA")); + return func(this, std::move(tag)); + }*/ + + /*CompoundTag(std::map& map) { + this->map = map; + }*/ + + void write(std::stringstream& builder); + + void read(std::string& string) { + static constexpr int C_COMPOUND_START = 0; // Parsing context + static constexpr int C_COMPOUND_PAIR_KEY = 1; // Parsing context + static constexpr int C_COMPOUND_PAIR_VALUE = 2; // Parsing context + + int context = C_COMPOUND_START; + std::string tmp_key = "", tmp_val = ""; + int scope = 0; + bool inString = false; + + for (int index = 0; index < string.length(); index++) { + char character = string.at(index); + + if (character == MojangsonToken::STRING_QUOTES.getSymbol()) { + inString = !inString; + } + if (character == MojangsonToken::WHITE_SPACE.getSymbol()) { + if (!inString) + continue; + } + if ((character == MojangsonToken::COMPOUND_START.getSymbol() || character == MojangsonToken::ARRAY_START.getSymbol()) && !inString) { + scope++; + } + if ((character == MojangsonToken::COMPOUND_END.getSymbol() || character == MojangsonToken::ARRAY_END.getSymbol()) && !inString) { + scope--; + } + if (context == C_COMPOUND_START) { + if (character != MojangsonToken::COMPOUND_START.getSymbol()) { + //parseException(index, character); + return; + } + context++; + continue; + } + if (context == C_COMPOUND_PAIR_KEY) { + if (character == MojangsonToken::ELEMENT_PAIR_SEPERATOR.getSymbol() && scope <= 1) { + context++; + continue; + } + tmp_key += character; + continue; + } + if (context == C_COMPOUND_PAIR_VALUE) { + if ((character == MojangsonToken::ELEMENT_SEPERATOR.getSymbol() || character == MojangsonToken::COMPOUND_END.getSymbol()) && scope <= 1 && !inString) { + context = C_COMPOUND_PAIR_KEY; + TextHolder t(tmp_key); + this->put(t, std::move(Mojangson::parseTag(tmp_val))); + tmp_key = tmp_val = ""; + continue; + } + tmp_val += character; + } + } + } + + // private void parseException(int index, char symbol) throws MojangsonParseException { + // throw new MojangsonParseException("Index: " + index + ", symbol: \'" + symbol + "\'", MojangsonParseException.ParseExceptionReason.UNEXPECTED_SYMBOL); + //} +}; + +/** + * Detects the Tag type of the Mojangson string, and parses it. Convenience method for other + * parse methods. + * + *

This method will fall back to an IntTag if it could not find an appropriate Tag type, and + * to String if the value could not be parsed as an Integer either. + * + * @param mojangson The Mojangson string + * @return The parsed NBT Tag + * @throws MojangsonParseException if the given Mojangson string could not be parsed. + */ +std::unique_ptr Mojangson::parseTag(std::string& mojangson) { + if (mojangson.front() == MojangsonToken::COMPOUND_START.getSymbol() && mojangson.back() != MojangsonToken::COMPOUND_END.getSymbol()) { + mojangson += '}'; + } + if (mojangson.front() == MojangsonToken::STRING_QUOTES.getSymbol() && mojangson.back() == MojangsonToken::STRING_QUOTES.getSymbol()) { + std::unique_ptr val = std::make_unique(""); + val->read(mojangson); + return val; + } + if (mojangson.front() == MojangsonToken::ARRAY_START.getSymbol() && mojangson.back() == MojangsonToken::ARRAY_END.getSymbol()) { + std::unique_ptr val = std::make_unique(); + val->read(mojangson); + return val; + } + if (mojangson.front() == MojangsonToken::COMPOUND_START.getSymbol() && mojangson.back() == MojangsonToken::COMPOUND_END.getSymbol()) { + std::unique_ptr val = std::make_unique(); + val->read(mojangson); + return val; + } + if (mojangson.back() == MojangsonToken::BYTE_SUFFIX.getSymbol()) { + std::unique_ptr val = std::make_unique(0); + val->read(mojangson); + return val; + } + if (mojangson.back() == MojangsonToken::DOUBLE_SUFFIX.getSymbol() /*|| mojangson.contains(".")*/) { + std::unique_ptr val = std::make_unique(0); + val->read(mojangson); + return val; + } + if (mojangson.back() == MojangsonToken::LONG_SUFFIX.getSymbol()) { + std::unique_ptr val = std::make_unique(0); + val->read(mojangson); + return val; + } + if (mojangson.back() == MojangsonToken::FLOAT_SUFFIX.getSymbol()) { + std::unique_ptr val = std::make_unique(0.f); + val->read(mojangson); + return val; + } + if (mojangson.back() == MojangsonToken::SHORT_SUFFIX.getSymbol()) { + std::unique_ptr val = std::make_unique(0); + val->read(mojangson); + return val; + } + std::unique_ptr val = std::make_unique(0); + val->read(mojangson); + return val; +} diff --git a/SDK/Tessellator.cpp b/SDK/Tessellator.cpp new file mode 100644 index 0000000..dcf7a3a --- /dev/null +++ b/SDK/Tessellator.cpp @@ -0,0 +1,16 @@ +#include "Tessellator.h" + +#include "../Utils/Utils.h" +#include "CBlockLegacy.h" +#include "CClientInstance.h" + +void Tessellator::addPostTransformOffset(float x, float y, float z) { + this->transformOffset = this->transformOffset.add(x, y, z); +} + +mce::Mesh* BlockTessellator::getMeshForBlockInWorld(Tessellator *t, C_Block *block, vec3_ti &pos) { + using BT_getMeshForBlockInWorld_t = mce::Mesh* (*)(BlockTessellator *, Tessellator *, C_Block *, vec3_ti &, int, __int64); + static BT_getMeshForBlockInWorld_t getMeshForBlock = reinterpret_cast(FindSignature("40 55 53 56 57 41 54 41 55 41 56 41 57 48 8D AC 24 ?? ?? ?? ?? 48 81 EC ?? ?? ?? ?? 48 C7 44 24 ?? FE FF FF FF 48 8B 05 ?? ?? ?? ?? 48 33 C4 48 89 85 ?? ?? ?? ?? 4D 8B F1 4D 8B F8 48")); + + return getMeshForBlock(this, t, block, pos, block->getRenderLayer(), 0); +} diff --git a/SDK/Tessellator.h b/SDK/Tessellator.h new file mode 100644 index 0000000..0d0e86b --- /dev/null +++ b/SDK/Tessellator.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../Utils/HMath.h" + +class Tessellator { +private: + char pad_0000[0x128]; + vec3_t transformOffset; // 0x128 + +public: + void addPostTransformOffset(int x, int y, int z) { + addPostTransformOffset((float)x, (float)y, (float)z); + } + void addPostTransformOffset(float x, float y, float z); +}; + +class C_Block; + +namespace mce { +class Mesh; +} + +class BlockTessellator { +public: + mce::Mesh* getMeshForBlockInWorld(Tessellator * t, C_Block * block, vec3_ti & pos); +}; \ No newline at end of file diff --git a/SDK/TextHolder.cpp b/SDK/TextHolder.cpp new file mode 100644 index 0000000..4c03222 --- /dev/null +++ b/SDK/TextHolder.cpp @@ -0,0 +1,45 @@ +#include "TextHolder.h" + +#include + +void GamerTextHolder::copyFrom(TextHolder *copy) { + typedef void*(__cdecl * _malloctype)(size_t); + + static auto _malloc = reinterpret_cast<_malloctype>(GetProcAddress(GetModuleHandleA("api-ms-win-crt-heap-l1-1-0"), "malloc")); + + deleteText(); + memset(this, 0, sizeof(TextHolder)); + textLength = copy->textLength; + alignedTextLength = copy->alignedTextLength; + if (copy->textLength < 16) { + memcpy(inlineText, copy->inlineText, 16); + }else { + size_t size = copy->textLength; + + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(_malloc(size + 1)); + + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + pText += 8; + } + + if (pText != 0x0 && copy->pText != 0x0) { + memcpy(pText, copy->pText, textLength); + pText[textLength] = 0; + } + } +} +void GamerTextHolder::deleteText() { + typedef void(__cdecl * _freetype)(void*); + static auto _free = reinterpret_cast<_freetype>(GetProcAddress(GetModuleHandleA("api-ms-win-crt-heap-l1-1-0"), "free")); + + if (textLength >= 16 && pText != nullptr) { + if (textLength + 1 >= 0x1000) { + pText = *reinterpret_cast(reinterpret_cast<__int64>(pText) - 8); + } + _free(pText); + } +} diff --git a/SDK/TextHolder.h b/SDK/TextHolder.h new file mode 100644 index 0000000..3976d5d --- /dev/null +++ b/SDK/TextHolder.h @@ -0,0 +1,215 @@ +#pragma once + +#include + +class TextHolder { +public: + union { + char inlineText[16]; //0x0000 + char* pText; //0x0000 + }; + + size_t textLength; //0x0010 + size_t alignedTextLength; //0x0018 + + TextHolder() { + memset(this, 0, sizeof(TextHolder)); + } + + TextHolder(TextHolder const& copy) { + memset(this, 0, sizeof(TextHolder)); + textLength = copy.textLength; + alignedTextLength = copy.alignedTextLength; + if (copy.textLength < 16) + memcpy(inlineText, copy.inlineText, 16); + else { + size_t size = textLength + 1; + + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(malloc(size + 1)); + alignedTextLength = size; + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + pText += 8; + } + + if (pText != 0x0 && copy.pText != 0x0) { + memcpy(pText, copy.pText, size); + pText[size] = 0; + } + } + } + + TextHolder& operator=(TextHolder const& copy) { + deleteText(); + memset(this, 0, sizeof(TextHolder)); + textLength = copy.textLength; + alignedTextLength = copy.alignedTextLength; + if (copy.textLength < 16) + memcpy(inlineText, copy.inlineText, 16); + else { + size_t size = textLength + 1; + + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(malloc(size + 1)); + alignedTextLength = size; + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + pText += 8; + } + + if (pText != 0x0 && copy.pText != 0x0) { + memcpy(pText, copy.pText, textLength); + pText[textLength] = 0; + } + } + return *this; + } + + TextHolder(std::string str) { + memset(this, 0, sizeof(TextHolder)); + textLength = str.size(); + alignedTextLength = textLength | 0xF; + if (str.size() < 16) { + memcpy(inlineText, str.c_str(), str.size()); + if (str.size() < 15) + inlineText[str.size()] = 0; + } else { + size_t size = str.size(); + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(malloc(size + 1)); + alignedTextLength = size; + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + pText += 8; + } + + if (pText != 0x0) { + memcpy(pText, str.c_str(), str.size()); + pText[str.size()] = 0; + } + } + } + + TextHolder(size_t allocSize) { + memset(this, 0, sizeof(TextHolder)); + textLength = 0; + alignedTextLength = allocSize | 0xF; + if (alignedTextLength < 16) { + memset(&inlineText, 0, 16); + } else { + size_t size = alignedTextLength; + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(malloc(size + 1)); + alignedTextLength = size; + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + + pText += 8; + memset(pText, 0, alignedTextLength - 8); + }else + memset(pText, 0, alignedTextLength); + } + } + + TextHolder(void* ptr, size_t sizeOfData) { + memset(this, 0, sizeof(TextHolder)); + textLength = sizeOfData; + alignedTextLength = sizeOfData; + if (alignedTextLength < 16) + memcpy(inlineText, ptr, sizeOfData); + else + pText = reinterpret_cast(ptr); + } + + void deleteText() { + if (alignedTextLength >= 16 && pText != nullptr) { + if (alignedTextLength + 1 >= 0x1000) { + pText = *reinterpret_cast(reinterpret_cast<__int64>(pText) - 8); + } + free(pText); + } + } + + ~TextHolder() { + this->deleteText(); + } + + char* getText() { + if (alignedTextLength < 16) + return this->inlineText; + else + return this->pText; + } + + size_t getTextLength() { + return textLength; + } + + void setText(std::string str) { + this->deleteText(); + memset(this, 0, sizeof(TextHolder)); + textLength = str.size(); + alignedTextLength = textLength | 0xF; + if (str.size() < 16) { + memcpy(inlineText, str.c_str(), str.size()); + if (str.size() < 15) + inlineText[str.size()] = 0; + } else { + size_t size = str.size(); + if (size + 1 >= 0x1000) + size += 8; + + pText = reinterpret_cast(malloc(size + 1)); + alignedTextLength = size; + if (size + 1 >= 0x1000) { + *reinterpret_cast(pText) = pText; + pText += 8; + } + + if (pText != 0x0) { + memcpy(pText, str.c_str(), str.size()); + pText[str.size()] = 0; + } + } + } + + void resetWithoutDelete() { + *getText() = 0; + textLength = 0; + } +}; + +class GamerTextHolder { +public: + union { + char inlineText[16]; //0x0000 + char* pText; //0x0000 + }; + + size_t textLength; //0x0010 + size_t alignedTextLength; //0x0018 + + GamerTextHolder() { + memset(this, 0, sizeof(GamerTextHolder)); + } + + char* getText() { + if (alignedTextLength < 16) + return this->inlineText; + else + return this->pText; + } + + void copyFrom(TextHolder* copy); + + void deleteText(); +}; \ No newline at end of file diff --git a/Utils/ChakraHelper.h b/Utils/ChakraHelper.h new file mode 100644 index 0000000..1b25371 --- /dev/null +++ b/Utils/ChakraHelper.h @@ -0,0 +1,267 @@ +#pragma once +#include + +#include "../include/chakra/ChakraCore.h" +#include "DllHelper.h" +#include + +#ifndef DECL_API +#define DECL_API(f) decltype(f)* f##_ = _dll[#f] +#endif + +class ChakraApi { + DllHelper _dll{"Chakra.dll"}; + +public: + DECL_API(JsCreateRuntime); + DECL_API(JsCreateContext); + DECL_API(JsSetCurrentContext); + DECL_API(JsDisposeRuntime); + DECL_API(JsRunScript); + DECL_API(JsConvertValueToString); + DECL_API(JsStringToPointer); + DECL_API(JsSetRuntimeMemoryLimit); + DECL_API(JsCreateObject); + DECL_API(JsGetGlobalObject); + DECL_API(JsGetPropertyIdFromName); + DECL_API(JsPointerToString); + DECL_API(JsSetProperty); + DECL_API(JsCreateFunction); + DECL_API(JsCreateString); + DECL_API(JsHasException); + DECL_API(JsGetAndClearException); + DECL_API(JsCollectGarbage); + DECL_API(JsAddRef); + DECL_API(JsRelease); + DECL_API(JsGetNullValue); + DECL_API(JsCreateExternalObject); + DECL_API(JsGetCurrentContext); + DECL_API(JsGetExternalData); + DECL_API(JsGetUndefinedValue); + DECL_API(JsStrictEquals); + DECL_API(JsGetValueType); + DECL_API(JsHasExternalData); + DECL_API(JsBoolToBoolean); + DECL_API(JsCreateError); + DECL_API(JsSetException); + DECL_API(JsCreateTypeError); + DECL_API(JsDefineProperty); + DECL_API(JsGetTrueValue); + DECL_API(JsGetFalseValue); + DECL_API(JsDoubleToNumber); + DECL_API(JsNumberToDouble); + DECL_API(JsSetPrototype); + DECL_API(JsGetProperty); + DECL_API(JsBooleanToBool); + DECL_API(JsCallFunction); + DECL_API(JsDisableRuntimeExecution); + DECL_API(JsCreateArray); + DECL_API(JsIntToNumber); + DECL_API(JsSetIndexedProperty); + DECL_API(JsNumberToInt); + DECL_API(JsGetIndexedProperty); + + std::wstring exceptionToString(JsValueRef ref) { + JsValueRef stack; + this->getProperty(ref, L"stack", &stack); + if (this->isNullOrUndefined(stack)) + return this->valueToString(ref); + else + return this->valueToString(stack); + } + + void throwException(std::wstring error) { + JsValueRef errorValue; + JsValueRef errorObject; + this->JsPointerToString_(error.c_str(), error.length(), &errorValue); + this->JsCreateError_(errorValue, &errorObject); + this->JsSetException_(errorObject); + } + + void throwTypeException(std::wstring error) { + JsValueRef errorValue; + JsValueRef errorObject; + this->JsPointerToString_(error.c_str(), error.length(), &errorValue); + this->JsCreateTypeError_(errorValue, &errorObject); + this->JsSetException_(errorObject); + } + + JsValueRef toBoolean(bool boolVal) { + JsValueRef ref = JS_INVALID_REFERENCE; + this->JsBoolToBoolean_(boolVal, &ref); + return ref; + } + + JsValueRef toNumber(double doubleVal) { + JsValueRef ref = JS_INVALID_REFERENCE; + this->JsDoubleToNumber_(doubleVal, &ref); + return ref; + } + + JsValueRef trueValue() { + JsValueRef ref = JS_INVALID_REFERENCE; + this->JsGetTrueValue_(&ref); + return ref; + } + + JsValueRef falseValue() { + JsValueRef ref = JS_INVALID_REFERENCE; + this->JsGetFalseValue_(&ref); + return ref; + } + + JsValueRef nullValue() { + JsValueRef ref = JS_INVALID_REFERENCE; + this->JsGetNullValue_(&ref); + return ref; + } + + std::optional tryGetFunctionFromArgs(JsValueRef arg, int argumentCount) { + if (argumentCount < 1) + return std::optional (); + + JsValueType type = JsUndefined; + this->JsGetValueType_(arg, &type); + + if (type != JsFunction) + return std::optional(); + + return arg; + } + + std::optional tryGetStringFromArgs(JsValueRef args, int argumentCount) { + if (argumentCount < 1) + return std::optional(); + + const wchar_t* ref = 0; + size_t length = 0; + auto err = this->JsStringToPointer_(args, &ref, &length); + if (err != JsNoError) + return std::optional(); + return std::optional(std::wstring(ref, length)); + } + + std::optional tryGetBoolFromArgs(JsValueRef* args, int argumentCount) { + if (argumentCount < 1) + return std::optional(); + + bool ref = false; + auto err = this->JsBooleanToBool_(args[0], &ref); + if (err != JsNoError) + return std::optional(); + return ref; + } + + JsValueRef defineFunction(JsValueRef object, const wchar_t* callbackName, JsNativeFunction function, void* callbackState = nullptr) { + JsPropertyIdRef propertyId; + this->JsGetPropertyIdFromName_(callbackName, &propertyId); + + JsValueRef functionRef; + this->JsCreateFunction_(function, callbackState, &functionRef); + + this->JsSetProperty_(object, propertyId, functionRef, true); + + return functionRef; + } + + void addPropertyToObj(JsValueRef obj, const wchar_t* name, JsValueRef prop) { + JsPropertyIdRef propertyId; + this->JsGetPropertyIdFromName_(name, &propertyId); + this->JsSetProperty_(obj, propertyId, prop, true); + } + + bool defineValueProp(JsValueRef object, const wchar_t* name, JsValueRef value, bool changeable) { + JsPropertyIdRef namePropertyId; + this->JsGetPropertyIdFromName_(name, &namePropertyId); + + JsValueRef propertyDesc; + this->JsCreateObject_(&propertyDesc); + + JsValueRef jsTrue; + this->JsGetTrueValue_(&jsTrue); + JsValueRef jsFalse; + this->JsGetFalseValue_(&jsFalse); + + addPropertyToObj(propertyDesc, L"value", value); + addPropertyToObj(propertyDesc, L"writable", jsFalse); + addPropertyToObj(propertyDesc, L"enumerable", jsTrue); + addPropertyToObj(propertyDesc, L"configurable", jsFalse); + + bool result; + this->JsDefineProperty_(object, namePropertyId, propertyDesc, &result); + return result; + } + + bool defineProp(JsValueRef object, const wchar_t* name, JsNativeFunction getter, JsNativeFunction setter) { + JsPropertyIdRef namePropertyId; + this->JsGetPropertyIdFromName_(name, &namePropertyId); + + JsValueRef propertyDesc; + this->JsCreateObject_(&propertyDesc); + + JsValueRef get = NULL, set = NULL; + if (getter != nullptr) + this->JsCreateFunction_(getter, 0, &get); + if (setter != nullptr) + this->JsCreateFunction_(setter, 0, &set); + + JsValueRef jsTrue; + this->JsGetTrueValue_(&jsTrue); + JsValueRef jsFalse; + this->JsGetFalseValue_(&jsFalse); + + if (getter != nullptr) + addPropertyToObj(propertyDesc, L"get", get); + if (setter != nullptr) + addPropertyToObj(propertyDesc, L"set", set); + addPropertyToObj(propertyDesc, L"enumerable", jsTrue); + addPropertyToObj(propertyDesc, L"configurable", jsFalse); + + bool result; + this->JsDefineProperty_(object, namePropertyId, propertyDesc, &result); + return result; + } + + void getProperty(JsValueRef obj, const wchar_t* str, JsValueRef* prop) { + JsPropertyIdRef namePropertyId; + this->JsGetPropertyIdFromName_(str, &namePropertyId); + this->JsGetProperty_(obj, namePropertyId, prop); + } + + bool isNullOrUndefined(JsValueRef ref) { + JsValueType type = JsUndefined; + this->JsGetValueType_(ref, &type); + return type == JsUndefined || type == JsNull; + } + + std::wstring valueToString(JsValueRef value) { + if (value == JS_INVALID_REFERENCE) + return L"INVALID_REFERENCE"; + JsValueRef resultJSString; + auto err = JsConvertValueToString_(value, &resultJSString); + if (err == JsNoError) { + const wchar_t* resultWC; + size_t stringLength; + err = JsStringToPointer_(resultJSString, &resultWC, &stringLength); + + if (err == JsNoError) + return std::wstring(resultWC, stringLength); + else + return std::wstring(L"error1#") + std::to_wstring(err); + } else + return std::wstring(L"error2#") + std::to_wstring(err); + } + + JsValueRef arrayGet(JsValueRef arr, int index) { + JsValueRef indexNum, result; + this->JsIntToNumber_(index, &indexNum); + this->JsGetIndexedProperty_(arr, indexNum, &result); + return result; + } + + void arraySet(JsValueRef arr, int index, JsValueRef value) { + JsValueRef indexNum; + this->JsIntToNumber_(index, &indexNum); + JsSetIndexedProperty_(arr, indexNum, value); + } +}; \ No newline at end of file diff --git a/Utils/DllHelper.h b/Utils/DllHelper.h new file mode 100644 index 0000000..31a553e --- /dev/null +++ b/Utils/DllHelper.h @@ -0,0 +1,36 @@ +#pragma once + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include +#include + +class ProcPtr { +public: + explicit ProcPtr(FARPROC ptr) : _ptr(ptr) {} + + template >> + operator T*() const { + return reinterpret_cast(_ptr); + } + +private: + FARPROC _ptr; +}; + +class DllHelper { +private: + HMODULE _module; + +public: + static HMODULE _parent_module; + + explicit DllHelper(LPCSTR filename) : _module(GetModuleHandleA(filename)) {} + + ~DllHelper() {} + + ProcPtr operator[](LPCSTR proc_name) const { + return ProcPtr(GetProcAddress(_module, proc_name)); + } +}; \ No newline at end of file diff --git a/Utils/HMath.h b/Utils/HMath.h new file mode 100644 index 0000000..17f2ae0 --- /dev/null +++ b/Utils/HMath.h @@ -0,0 +1,587 @@ +#pragma once +#define PI (3.1415927f) + +#include + +static constexpr float DEG_RAD2 = PI / 360.0f; +static constexpr float DEG_RAD = 180.0f / PI; +static constexpr float RAD_DEG = PI / 180.f; + +inline float lerp(float a, float b, float t) { + return a + t * (b - a); +} + +struct vec2_t { + + union { + struct { + float x, y; + }; + float floatArr[2]; + }; + vec2_t() { x = y = 0; } + vec2_t(float a, float b) : x(a), y(b) {} + vec2_t(int a, int b) : x((float)a), y((float)b) {} + vec2_t &operator=(const vec2_t ©) { + x = copy.x; + y = copy.y; + return *this; + } + + static vec2_t fromAngle(float angle){ + return vec2_t((float)-sin(angle), (float)cos(angle)); + } + + bool operator==(const vec2_t &o) const { return x == o.x && y == o.y; } + bool operator!=(const vec2_t &o) const { return x != o.x || y != o.y; } + + vec2_t sub(float f) { + return vec2_t(x - f, y - f); + } + vec2_t sub(float ox, float oy) { + return vec2_t(x - ox, y - oy); + } + vec2_t div(float f) { + return vec2_t(x / f, y / f); + } + + vec2_t div(const vec2_t &o) { + return vec2_t(x / o.x, y / o.y); + } + vec2_t mul(const vec2_t &o) { + return vec2_t(x * o.x, y * o.y); + } + vec2_t mul(float f) { + return vec2_t(x * f, y * f); + } + vec2_t sub(const vec2_t &o) { + return vec2_t(x - o.x, y - o.y); + } + vec2_t add(const vec2_t &o) { + return vec2_t(x + o.x, y + o.y); + } + vec2_t add(float o) { + return vec2_t(x + o, y + o); + } + vec2_t add(float ox, float oy) { + return vec2_t(x + ox, y + oy); + } + + vec2_t normalized() { + return div(magnitude()); + } + + vec2_t cross(){ + return vec2_t(-y, x); + } + + float dot(float ox, float oy) const { return x * ox + y * oy; } + + + float dot(const vec2_t &o) const { return x * o.x + y * o.y; } + + vec2_t normAngles() { + float x = this->x; + float y = this->y; + while (x > 90.f) + x -= 180.0f; + while (x < -90.f) + x += 180.0f; + + while (y > 180.0f) + y -= 360.0f; + while (y < -180.0f) + y += 360.0f; + return vec2_t(x, y); + } + + float squaredlen() const { return x * x + y * y; } + float magnitude() const { return sqrtf(squaredlen()); } +}; + +struct vec3_t { + union { + struct { + float x, y, z; + }; + float floatArr[3]; + }; + + vec3_t() { x = y = z = 0; } + vec3_t(int a, int b, int c) : x((float)a), y((float)b), z((float)c) {} + vec3_t(double a, double b, double c) : x((float)a), y((float)b), z((float)c) {} + vec3_t(float a, float b, float c) : x(a), y(b), z(c) {} + vec3_t(float a, float b) : x(a), y(b), z(0) {} + vec3_t(const vec2_t ©, float zP) { + x = copy.x; + y = copy.y; + z = zP; + } + vec3_t(const vec3_t ©) { + x = copy.x; + y = copy.y; + z = copy.z; + } + + vec3_t &operator=(const vec3_t ©) { + x = copy.x; + y = copy.y; + z = copy.z; + + return *this; + } + + vec3_t(float *v) : x(v[0]), y(v[1]), z(v[2]) {} + + bool iszero() const { return x == 0 && y == 0 && z == 0; } + + inline bool operator==(const vec3_t &o) const { return x == o.x && y == o.y && z == o.z; }; + bool operator!=(const vec3_t &o) const { return x != o.x || y != o.y || z != o.z; }; + vec3_t operator-() const { return vec3_t(-x, -y, -z); }; + + vec3_t mul(const vec3_t &o) const { + return vec3_t(x * o.x, y * o.y, z * o.z); + }; + vec3_t mul(float f) const { + return vec3_t(x * f, y * f, z * f); + }; + vec3_t mul(float x1, float y1, float z1) const { + return vec3_t(x * x1, y * y1, z * z1); + }; + vec3_t div(float f) const { + return vec3_t(x / f, y / f, z / f); + }; + vec3_t div(float x1, float y1, float z1) const { + return vec3_t(x / x1, y / y1, z / z1); + }; + vec3_t div(const vec3_t &o) const { + return vec3_t(x / o.x, y / o.y, z / o.z); + }; + vec3_t add(float f) const { + return vec3_t(x + f, y + f, z + f); + }; + vec3_t add(float x1, float y1, float z1) const { + return vec3_t(x + x1, y + y1, z + z1); + }; + vec3_t sub(float f) const { + return vec3_t(x - f, y - f, z - f); + }; + + vec3_t sub(float x1, float y1, float z1) const { + return vec3_t(x - x1, y - y1, z - z1); + }; + + vec3_t floor() const { + return vec3_t(floorf(x), floorf(y), floorf(z)); + }; + + vec3_t add(const vec3_t &o) const { + return vec3_t(x + o.x, y + o.y, z + o.z); + } + vec3_t sub(const vec3_t &o) const { + return vec3_t(x - o.x, y - o.y, z - o.z); + } + + float squaredlen() const { return x * x + y * y + z * z; } + float squaredxzlen() const { return x * x + z * z; } + + vec3_t lerp(const vec3_t& other, float tx, float ty, float tz) const { + vec3_t ne; + ne.x = x + tx * (other.x - x); + ne.y = y + ty * (other.y - y); + ne.z = z + tz * (other.z - z); + return ne; + } + + vec3_t lerp(const vec3_t other, float val) const { + vec3_t ne; + ne.x = x + val * (other.x - x); + ne.y = y + val * (other.y - y); + ne.z = z + val * (other.z - z); + return ne; + } + + vec3_t lerp(const vec3_t *other, float val) const { + vec3_t ne; + ne.x = x + val * (other->x - x); + ne.y = y + val * (other->y - y); + ne.z = z + val * (other->z - z); + return ne; + } + + vec2_t flatten() const { + return vec2_t(x, y); + } + + float sqrxy() const { return x * x + y * y; } + + float dot(const vec3_t &o) const { return x * o.x + y * o.y + z * o.z; } + float dotxy(const vec3_t &o) const { return x * o.x + y * o.y; } + + float magnitude() const { return sqrtf(squaredlen()); } + + vec3_t normalize() { + return div(magnitude()); + } + + float dist(const vec3_t &e) const { + return sub(e).magnitude(); + } + + float Get2DDist(const vec3_t &e) const { + float dx = e.x - x, dy = e.y - y; + return sqrtf(dx * dx + dy * dy); + } + + float magnitudexy() const { return sqrtf(x * x + y * y); } + float magnitudexz() const { return sqrtf(x * x + z * z); } + + vec3_t cross(const vec3_t &b) { + return vec3_t(y * b.z - z * b.y, z * b.x - x * b.z, x * b.y - y * b.x); + } + float cxy(const vec3_t &a) { return x * a.y - y * a.x; } + + vec2_t CalcAngle(vec3_t dst) { + vec3_t diff = dst.sub(*this); + + diff.y = diff.y / diff.magnitude(); + vec2_t angles; + angles.x = asinf(diff.y) * -DEG_RAD; + angles.y = (float)-atan2f(diff.x, diff.z) * DEG_RAD; + + return angles; + } +}; + +struct vec3_ti { + int x, y, z; + + vec3_ti() { x = y = z = 0; } + vec3_ti(int a, int b, int c) : x(a), y(b), z(c) {} + vec3_ti(int a, int b) : x(a), y(b), z(0) {} + vec3_ti(const vec3_ti ©) { + x = copy.x; + y = copy.y; + z = copy.z; + } + + vec3_ti(const vec3_t ©) { + x = (int)copy.x; + y = (int)copy.y; + z = (int)copy.z; + } + + vec3_ti &operator=(const vec3_ti ©) { + x = copy.x; + y = copy.y; + z = copy.z; + + return *this; + } + + vec3_ti *operator=(const vec3_ti *copy) { + x = copy->x; + y = copy->y; + z = copy->z; + + return this; + } + + vec3_ti(int *v) : x(v[0]), y(v[1]), z(v[2]) {} + + vec3_t toVec3t() const { + return vec3_t(x, y, z); + } + + bool iszero() const { return x == 0 && y == 0 && z == 0; } + + bool operator==(const vec3_ti &o) const { return x == o.x && y == o.y && z == o.z; } + bool operator!=(const vec3_ti &o) const { return x != o.x || y != o.y || z != o.z; } + + vec3_ti add(vec3_ti o) const { + return vec3_ti(x + o.x, y + o.y, z + o.z); + } + + vec3_ti add(int f) const { + return vec3_ti(x + f, y + f, z + f); + } + + vec3_ti add(int a, int b, int c) const { + return vec3_ti(x + a, y + b, z + c); + }; + + vec3_ti sub(int ox, int oy, int oz) const { + return vec3_ti(x - ox, y - oy, z - oz); + } + + vec3_ti sub(const vec3_ti& o) const { + return vec3_ti(x - o.x, y - o.y, z - o.z); + } + + void set(vec3_ti *o) { + x = o->x; + y = o->y; + z = o->z; + }; + + vec3_t toFloatVector() const { + vec3_t vec; + vec.x = (float)x; + vec.y = (float)y; + vec.z = (float)z; + return vec; + } +}; +struct vec4_t { + union { + struct { + float x, y, z, w; + }; + float v[4]; + }; + vec4_t() { x = 0, y = 0, z = 0, w = 0; } + explicit vec4_t(const vec3_t &p, float w = 0) : x(p.x), y(p.y), z(p.z), w(w){}; + vec4_t(float x, float y, float z, float w) : x(x), y(y), z(z), w(w){}; + float &operator[](int i) { return v[i]; }; + float operator[](int i) const { return v[i]; }; + + __forceinline bool contains(vec2_t *point) { + if (point->x <= x || point->y <= y) + return false; + + if (point->x >= z || point->y >= w) + return false; + return true; + }; +}; + +struct glmatrixf { + union { + float v[16]; + float v_nested[4][4]; + }; + + __forceinline float operator[](int i) const { return v[i]; } + __forceinline float &operator[](int i) { return v[i]; } + +#define MULMAT(row, col) v[col + row] = x[row] * y[col] + x[row + 4] * y[col + 1] + x[row + 8] * y[col + 2] + x[row + 12] * y[col + 3]; + + template + void mul(const XT x[16], const YT y[16]) { + MULMAT(0, 0); + MULMAT(1, 0); + MULMAT(2, 0); + MULMAT(3, 0); + MULMAT(0, 4); + MULMAT(1, 4); + MULMAT(2, 4); + MULMAT(3, 4); + MULMAT(0, 8); + MULMAT(1, 8); + MULMAT(2, 8); + MULMAT(3, 8); + MULMAT(0, 12); + MULMAT(1, 12); + MULMAT(2, 12); + MULMAT(3, 12); + } + +#undef MULMAT + + glmatrixf *correct() { + glmatrixf *newMatPtr = new glmatrixf; + + for (int i = 0; i < 4; i++) { + newMatPtr->v[i * 4 + 0] = v[0 + i]; + newMatPtr->v[i * 4 + 1] = v[4 + i]; + newMatPtr->v[i * 4 + 2] = v[8 + i]; + newMatPtr->v[i * 4 + 3] = v[12 + i]; + } + return newMatPtr; + }; + + inline bool OWorldToScreen(vec3_t origin, vec3_t pos, vec2_t &screen, vec2_t fov, vec2_t displaySize) { + pos = pos.sub(origin); + + float x = transformx(pos); + float y = transformy(pos); + float z = transformz(pos); + + if (z > 0) + return false; + + float mX = (float)displaySize.x / 2.0F; + float mY = (float)displaySize.y / 2.0F; + + screen.x = mX + (mX * x / -z * fov.x); + screen.y = mY - (mY * y / -z * fov.y); + + return true; + } + + inline void mul(const glmatrixf &x, const glmatrixf &y) { + mul(x.v, y.v); + } + + inline void translate(float x, float y, float z) { + v[12] += x; + v[13] += y; + v[14] += z; + } + + inline void translate(const vec3_t &o) { + translate(o.x, o.y, o.z); + } + + inline void scale(float x, float y, float z) { + v[0] *= x; + v[1] *= x; + v[2] *= x; + v[3] *= x; + v[4] *= y; + v[5] *= y; + v[6] *= y; + v[7] *= y; + v[8] *= z; + v[9] *= z; + v[10] *= z; + v[11] *= z; + } + + inline void invertnormal(vec3_t &dir) const { + vec3_t n(dir); + dir.x = n.x * v[0] + n.y * v[1] + n.z * v[2]; + dir.y = n.x * v[4] + n.y * v[5] + n.z * v[6]; + dir.z = n.x * v[8] + n.y * v[9] + n.z * v[10]; + } + + inline void invertvertex(vec3_t &pos) const { + vec3_t p(pos); + p.x -= v[12]; + p.y -= v[13]; + p.z -= v[14]; + pos.x = p.x * v[0] + p.y * v[1] + p.z * v[2]; + pos.y = p.x * v[4] + p.y * v[5] + p.z * v[6]; + pos.z = p.x * v[8] + p.y * v[9] + p.z * v[10]; + } + + inline void transform(const vec3_t &in, vec4_t &out) const { + out.x = transformx(in); + out.y = transformy(in); + out.z = transformz(in); + out.w = transformw(in); + } + + __forceinline float transformx(const vec3_t &p) const { + return p.x * v[0] + p.y * v[4] + p.z * v[8] + v[12]; + } + + __forceinline float transformy(const vec3_t &p) const { + return p.x * v[1] + p.y * v[5] + p.z * v[9] + v[13]; + } + + __forceinline float transformz(const vec3_t &p) const { + return p.x * v[2] + p.y * v[6] + p.z * v[10] + v[14]; + } + + __forceinline float transformw(const vec3_t &p) const { + return p.x * v[3] + p.y * v[7] + p.z * v[11] + v[15]; + } + + __forceinline vec3_t gettranslation() const { + return vec3_t(v[12], v[13], v[14]); + } + + //assault cube world2screen + vec3_t transform(glmatrixf *matrix, vec3_t &totransform) { + return vec3_t(matrix->transformx(totransform), + matrix->transformy(totransform), + matrix->transformz(totransform)) + .div(matrix->transformw(totransform)); + } + + ///pos should be the exact center of the enemy model for scaling to work properly + vec3_t WorldToScreen(vec3_t pos, int width, int height) { + //Matrix-vector Product, multiplying world(eye) coordinates by projection matrix = clipCoords + vec4_t clipCoords; + clipCoords.x = pos.x * v[0] + pos.y * v[4] + pos.z * v[8] + v[12]; + clipCoords.y = pos.x * v[1] + pos.y * v[5] + pos.z * v[9] + v[13]; + clipCoords.z = pos.x * v[2] + pos.y * v[6] + pos.z * v[10] + v[14]; + clipCoords.w = pos.x * v[3] + pos.y * v[7] + pos.z * v[11] + v[15]; + + //perspective division, dividing by clip.W = Normalized Device Coordinates + vec3_t NDC; + NDC.x = clipCoords.x / clipCoords.w; + NDC.y = clipCoords.y / clipCoords.w; + NDC.z = clipCoords.z / clipCoords.w; + + //viewport tranform to screenCooords + + vec3_t playerscreen; + playerscreen.x = (width / 2 * NDC.x) + (NDC.x + width / 2); + playerscreen.y = -(height / 2 * NDC.y) + (NDC.y + height / 2); + + return playerscreen; + } +}; + +struct AABB { + vec3_t lower; + vec3_t upper; + bool isZero = false; + char padding[3]; + AABB() {} + AABB(vec3_t l, vec3_t h) : lower(l), upper(h){}; + AABB(const AABB &aabb) { + lower = vec3_t(aabb.lower); + upper = vec3_t(aabb.upper); + } + AABB(vec3_t lower, float width, float height, float eyeHeight) { + lower = lower.sub(vec3_t(width, eyeHeight * 2, width).div(2)); + this->lower = lower; + this->upper = {lower.x + width, lower.y + height, lower.z + width}; + } + + inline bool operator==(const AABB &rhs) const { + return lower == rhs.lower && upper == rhs.upper; + } + + bool isFullBlock(){ + auto diff = lower.sub(upper); + return fabsf(diff.y) == 1 && fabsf(diff.x) == 1 && fabsf(diff.z) == 1; + } + + AABB expanded(float amount) { + return AABB(lower.sub(amount), upper.add(amount)); + } + + AABB expandedXZ(float amount) { + return AABB(lower.sub(amount, 0.f, amount), upper.add(amount, 0.f, amount)); + } + + vec3_t centerPoint() { + vec3_t diff = upper.sub(lower); + return lower.add(diff.mul(0.5f)); + } + + bool intersects(AABB aabb) { + return aabb.upper.x > lower.x && upper.x > aabb.lower.x && + aabb.upper.y > lower.y && upper.y > aabb.lower.y && + aabb.upper.z > lower.z && upper.z > aabb.lower.z; + } + + bool intersectsXZ(AABB aabb) { + return aabb.upper.x > lower.x && upper.x > aabb.lower.x && + aabb.upper.z > lower.z && upper.z > aabb.lower.z; + } +}; + +/* +inline int random(int start, int end) { + return rand() % (end - start + 1) + start; +} + +inline float randomf(int start, int end) { + return (float)random(start, end); +} +*/ \ No newline at end of file diff --git a/Utils/Json.hpp b/Utils/Json.hpp new file mode 100644 index 0000000..d80ceb6 --- /dev/null +++ b/Utils/Json.hpp @@ -0,0 +1,22874 @@ +/* + __ _____ _____ _____ + __| | __| | | | JSON for Modern C++ +| | |__ | | | | | | version 3.7.3 +|_____|_____|_____|_|___| https://github.com/nlohmann/json + +Licensed under the MIT License . +SPDX-License-Identifier: MIT +Copyright (c) 2013-2019 Niels Lohmann . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ + +#ifndef INCLUDE_NLOHMANN_JSON_HPP_ +#define INCLUDE_NLOHMANN_JSON_HPP_ + +#define NLOHMANN_JSON_VERSION_MAJOR 3 +#define NLOHMANN_JSON_VERSION_MINOR 7 +#define NLOHMANN_JSON_VERSION_PATCH 3 + +#include // all_of, find, for_each +#include // assert +#include // and, not, or +#include // nullptr_t, ptrdiff_t, size_t +#include // hash, less +#include // initializer_list +#include // istream, ostream +#include // random_access_iterator_tag +#include // unique_ptr +#include // accumulate +#include // string, stoi, to_string +#include // declval, forward, move, pair, swap +#include // vector + +// #include + + +#include + +// #include + + +#include // transform +#include // array +#include // and, not +#include // forward_list +#include // inserter, front_inserter, end +#include // map +#include // string +#include // tuple, make_tuple +#include // is_arithmetic, is_same, is_enum, underlying_type, is_convertible +#include // unordered_map +#include // pair, declval +#include // valarray + +// #include + + +#include // exception +#include // runtime_error +#include // to_string + +// #include + + +#include // size_t + +namespace nlohmann +{ + namespace detail + { + /// struct to capture the start position of the current token + struct position_t + { + /// the total number of characters read + std::size_t chars_read_total = 0; + /// the number of characters read in the current line + std::size_t chars_read_current_line = 0; + /// the number of lines read + std::size_t lines_read = 0; + + /// conversion to size_t to preserve SAX interface + constexpr operator size_t() const + { + return chars_read_total; + } + }; + + } // namespace detail +} // namespace nlohmann + +// #include + + +#include // pair +// #include +/* Hedley - https://nemequ.github.io/hedley + * Created by Evan Nemerson + * + * To the extent possible under law, the author(s) have dedicated all + * copyright and related and neighboring rights to this software to + * the public domain worldwide. This software is distributed without + * any warranty. + * + * For details, see . + * SPDX-License-Identifier: CC0-1.0 + */ + +#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 11) +#if defined(JSON_HEDLEY_VERSION) +#undef JSON_HEDLEY_VERSION +#endif +#define JSON_HEDLEY_VERSION 11 + +#if defined(JSON_HEDLEY_STRINGIFY_EX) +#undef JSON_HEDLEY_STRINGIFY_EX +#endif +#define JSON_HEDLEY_STRINGIFY_EX(x) #x + +#if defined(JSON_HEDLEY_STRINGIFY) +#undef JSON_HEDLEY_STRINGIFY +#endif +#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x) + +#if defined(JSON_HEDLEY_CONCAT_EX) +#undef JSON_HEDLEY_CONCAT_EX +#endif +#define JSON_HEDLEY_CONCAT_EX(a,b) a##b + +#if defined(JSON_HEDLEY_CONCAT) +#undef JSON_HEDLEY_CONCAT +#endif +#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b) + +#if defined(JSON_HEDLEY_VERSION_ENCODE) +#undef JSON_HEDLEY_VERSION_ENCODE +#endif +#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision)) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR) +#undef JSON_HEDLEY_VERSION_DECODE_MAJOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR) +#undef JSON_HEDLEY_VERSION_DECODE_MINOR +#endif +#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000) + +#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION) +#undef JSON_HEDLEY_VERSION_DECODE_REVISION +#endif +#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000) + +#if defined(JSON_HEDLEY_GNUC_VERSION) +#undef JSON_HEDLEY_GNUC_VERSION +#endif +#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__) +#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) +#elif defined(__GNUC__) +#define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0) +#endif + +#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK) +#undef JSON_HEDLEY_GNUC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GNUC_VERSION) +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION) +#undef JSON_HEDLEY_MSVC_VERSION +#endif +#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100) +#elif defined(_MSC_FULL_VER) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10) +#elif defined(_MSC_VER) +#define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK) +#undef JSON_HEDLEY_MSVC_VERSION_CHECK +#endif +#if !defined(_MSC_VER) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0) +#elif defined(_MSC_VER) && (_MSC_VER >= 1400) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch))) +#elif defined(_MSC_VER) && (_MSC_VER >= 1200) +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch))) +#else +#define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor))) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION) +#undef JSON_HEDLEY_INTEL_VERSION +#endif +#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) +#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE) +#elif defined(__INTEL_COMPILER) +#define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0) +#endif + +#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK) +#undef JSON_HEDLEY_INTEL_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_INTEL_VERSION) +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION) +#undef JSON_HEDLEY_PGI_VERSION +#endif +#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__) +#define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__) +#endif + +#if defined(JSON_HEDLEY_PGI_VERSION_CHECK) +#undef JSON_HEDLEY_PGI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PGI_VERSION) +#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION) +#undef JSON_HEDLEY_SUNPRO_VERSION +#endif +#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10) +#elif defined(__SUNPRO_C) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf) +#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10) +#elif defined(__SUNPRO_CC) +#define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf) +#endif + +#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK) +#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_SUNPRO_VERSION) +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION +#endif +#if defined(__EMSCRIPTEN__) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__) +#endif + +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK) +#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION) +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION) +#undef JSON_HEDLEY_ARM_VERSION +#endif +#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION) +#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100) +#elif defined(__CC_ARM) && defined(__ARMCC_VERSION) +#define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100) +#endif + +#if defined(JSON_HEDLEY_ARM_VERSION_CHECK) +#undef JSON_HEDLEY_ARM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_ARM_VERSION) +#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION) +#undef JSON_HEDLEY_IBM_VERSION +#endif +#if defined(__ibmxl__) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__) +#elif defined(__xlC__) && defined(__xlC_ver__) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff) +#elif defined(__xlC__) +#define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0) +#endif + +#if defined(JSON_HEDLEY_IBM_VERSION_CHECK) +#undef JSON_HEDLEY_IBM_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IBM_VERSION) +#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION) +#undef JSON_HEDLEY_TI_VERSION +#endif +#if defined(__TI_COMPILER_VERSION__) +#define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000)) +#endif + +#if defined(JSON_HEDLEY_TI_VERSION_CHECK) +#undef JSON_HEDLEY_TI_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TI_VERSION) +#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION) +#undef JSON_HEDLEY_CRAY_VERSION +#endif +#if defined(_CRAYC) +#if defined(_RELEASE_PATCHLEVEL) +#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL) +#else +#define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0) +#endif +#endif + +#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK) +#undef JSON_HEDLEY_CRAY_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_CRAY_VERSION) +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION) +#undef JSON_HEDLEY_IAR_VERSION +#endif +#if defined(__IAR_SYSTEMS_ICC__) +#if __VER__ > 1000 +#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000)) +#else +#define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(VER / 100, __VER__ % 100, 0) +#endif +#endif + +#if defined(JSON_HEDLEY_IAR_VERSION_CHECK) +#undef JSON_HEDLEY_IAR_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_IAR_VERSION) +#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION) +#undef JSON_HEDLEY_TINYC_VERSION +#endif +#if defined(__TINYC__) +#define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100) +#endif + +#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK) +#undef JSON_HEDLEY_TINYC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_TINYC_VERSION) +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION) +#undef JSON_HEDLEY_DMC_VERSION +#endif +#if defined(__DMC__) +#define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf) +#endif + +#if defined(JSON_HEDLEY_DMC_VERSION_CHECK) +#undef JSON_HEDLEY_DMC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_DMC_VERSION) +#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION) +#undef JSON_HEDLEY_COMPCERT_VERSION +#endif +#if defined(__COMPCERT_VERSION__) +#define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100) +#endif + +#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK) +#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_COMPCERT_VERSION) +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION) +#undef JSON_HEDLEY_PELLES_VERSION +#endif +#if defined(__POCC__) +#define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0) +#endif + +#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK) +#undef JSON_HEDLEY_PELLES_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_PELLES_VERSION) +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION) +#undef JSON_HEDLEY_GCC_VERSION +#endif +#if \ + defined(JSON_HEDLEY_GNUC_VERSION) && \ + !defined(__clang__) && \ + !defined(JSON_HEDLEY_INTEL_VERSION) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_ARM_VERSION) && \ + !defined(JSON_HEDLEY_TI_VERSION) && \ + !defined(__COMPCERT__) +#define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION +#endif + +#if defined(JSON_HEDLEY_GCC_VERSION_CHECK) +#undef JSON_HEDLEY_GCC_VERSION_CHECK +#endif +#if defined(JSON_HEDLEY_GCC_VERSION) +#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch)) +#else +#define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE +#endif +#if defined(__has_attribute) +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) __has_attribute(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE +#endif +#if \ + defined(__has_cpp_attribute) && \ + defined(__cplusplus) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS) +#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS +#endif +#if !defined(__cplusplus) || !defined(__has_cpp_attribute) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#elif \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \ + (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0)) +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute) +#else +#define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE +#endif +#if defined(__has_cpp_attribute) && defined(__cplusplus) +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_BUILTIN) +#undef JSON_HEDLEY_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin) +#else +#define JSON_HEDLEY_HAS_BUILTIN(builtin) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN) +#undef JSON_HEDLEY_GNUC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else +#define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN) +#undef JSON_HEDLEY_GCC_HAS_BUILTIN +#endif +#if defined(__has_builtin) +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin) +#else +#define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_FEATURE) +#undef JSON_HEDLEY_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature) +#else +#define JSON_HEDLEY_HAS_FEATURE(feature) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE) +#undef JSON_HEDLEY_GNUC_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else +#define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_FEATURE) +#undef JSON_HEDLEY_GCC_HAS_FEATURE +#endif +#if defined(__has_feature) +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature) +#else +#define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_EXTENSION) +#undef JSON_HEDLEY_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension) +#else +#define JSON_HEDLEY_HAS_EXTENSION(extension) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION) +#undef JSON_HEDLEY_GNUC_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else +#define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION) +#undef JSON_HEDLEY_GCC_HAS_EXTENSION +#endif +#if defined(__has_extension) +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension) +#else +#define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE +#endif +#if defined(__has_declspec_attribute) +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute) +#else +#define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_HAS_WARNING) +#undef JSON_HEDLEY_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning) +#else +#define JSON_HEDLEY_HAS_WARNING(warning) (0) +#endif + +#if defined(JSON_HEDLEY_GNUC_HAS_WARNING) +#undef JSON_HEDLEY_GNUC_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else +#define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_GCC_HAS_WARNING) +#undef JSON_HEDLEY_GCC_HAS_WARNING +#endif +#if defined(__has_warning) +#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning) +#else +#define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + + /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ +#endif +#if defined(__cplusplus) && JSON_HEDLEY_HAS_WARNING("-Wc++98-compat") +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \ + xpr \ + JSON_HEDLEY_DIAGNOSTIC_POP +#else +# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x +#endif + +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + defined(__clang__) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR)) +#define JSON_HEDLEY_PRAGMA(value) _Pragma(#value) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#define JSON_HEDLEY_PRAGMA(value) __pragma(value) +#else +#define JSON_HEDLEY_PRAGMA(value) +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH) +#undef JSON_HEDLEY_DIAGNOSTIC_PUSH +#endif +#if defined(JSON_HEDLEY_DIAGNOSTIC_POP) +#undef JSON_HEDLEY_DIAGNOSTIC_POP +#endif +#if defined(__clang__) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push)) +#define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop)) +#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,1,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) +#define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)") +#define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)") +#else +#define JSON_HEDLEY_DIAGNOSTIC_PUSH +#define JSON_HEDLEY_DIAGNOSTIC_POP +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215") +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)") +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068)) +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030)) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097") +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)") +#elif JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES +#endif + +#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL) +#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual") +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"") +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)") +#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"") +#else +#define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL +#endif + +#if defined(JSON_HEDLEY_DEPRECATED) +#undef JSON_HEDLEY_DEPRECATED +#endif +#if defined(JSON_HEDLEY_DEPRECATED_FOR) +#undef JSON_HEDLEY_DEPRECATED_FOR +#endif +#if defined(__cplusplus) && (__cplusplus >= 201402L) +#define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]]) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]]) +#elif \ + JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,3,0) +#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since))) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__)) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) +#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since)) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) +#define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated") +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated") +#else +#define JSON_HEDLEY_DEPRECATED(since) +#define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) +#endif + +#if defined(JSON_HEDLEY_UNAVAILABLE) +#undef JSON_HEDLEY_UNAVAILABLE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since))) +#else +#define JSON_HEDLEY_UNAVAILABLE(available_since) +#endif + +#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT) +#undef JSON_HEDLEY_WARN_UNUSED_RESULT +#endif +#if defined(__cplusplus) && (__cplusplus >= 201703L) +#define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__)) +#elif defined(_Check_return_) /* SAL */ +#define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_ +#else +#define JSON_HEDLEY_WARN_UNUSED_RESULT +#endif + +#if defined(JSON_HEDLEY_SENTINEL) +#undef JSON_HEDLEY_SENTINEL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) +#define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position))) +#else +#define JSON_HEDLEY_SENTINEL(position) +#endif + +#if defined(JSON_HEDLEY_NO_RETURN) +#undef JSON_HEDLEY_NO_RETURN +#endif +#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_NO_RETURN __noreturn +#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L +#define JSON_HEDLEY_NO_RETURN _Noreturn +#elif defined(__cplusplus) && (__cplusplus >= 201103L) +#define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]]) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(18,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(17,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +#define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) +#define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) +#define JSON_HEDLEY_NO_RETURN __attribute((noreturn)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) +#define JSON_HEDLEY_NO_RETURN __declspec(noreturn) +#else +#define JSON_HEDLEY_NO_RETURN +#endif + +#if defined(JSON_HEDLEY_NO_ESCAPE) +#undef JSON_HEDLEY_NO_ESCAPE +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape) +#define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__)) +#else +#define JSON_HEDLEY_NO_ESCAPE +#endif + +#if defined(JSON_HEDLEY_UNREACHABLE) +#undef JSON_HEDLEY_UNREACHABLE +#endif +#if defined(JSON_HEDLEY_UNREACHABLE_RETURN) +#undef JSON_HEDLEY_UNREACHABLE_RETURN +#endif +#if \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) +#define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable() +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#define JSON_HEDLEY_UNREACHABLE() __assume(0) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) +#if defined(__cplusplus) +#define JSON_HEDLEY_UNREACHABLE() std::_nassert(0) +#else +#define JSON_HEDLEY_UNREACHABLE() _nassert(0) +#endif +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#elif defined(EXIT_FAILURE) +#define JSON_HEDLEY_UNREACHABLE() abort() +#else +#define JSON_HEDLEY_UNREACHABLE() +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) return value +#endif +#if !defined(JSON_HEDLEY_UNREACHABLE_RETURN) +#define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE() +#endif + +#if defined(JSON_HEDLEY_ASSUME) +#undef JSON_HEDLEY_ASSUME +#endif +#if \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_ASSUME(expr) __assume(expr) +#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume) +#define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr) +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) +#if defined(__cplusplus) +#define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr) +#else +#define JSON_HEDLEY_ASSUME(expr) _nassert(expr) +#endif +#elif \ + (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && !defined(JSON_HEDLEY_ARM_VERSION)) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) +#define JSON_HEDLEY_ASSUME(expr) ((void) ((expr) ? 1 : (__builtin_unreachable(), 1))) +#else +#define JSON_HEDLEY_ASSUME(expr) ((void) (expr)) +#endif + +JSON_HEDLEY_DIAGNOSTIC_PUSH +#if JSON_HEDLEY_HAS_WARNING("-Wpedantic") +#pragma clang diagnostic ignored "-Wpedantic" +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus) +#pragma clang diagnostic ignored "-Wc++98-compat-pedantic" +#endif +#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0) +#if defined(__clang__) +#pragma clang diagnostic ignored "-Wvariadic-macros" +#elif defined(JSON_HEDLEY_GCC_VERSION) +#pragma GCC diagnostic ignored "-Wvariadic-macros" +#endif +#endif +#if defined(JSON_HEDLEY_NON_NULL) +#undef JSON_HEDLEY_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) +#define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__))) +#else +#define JSON_HEDLEY_NON_NULL(...) +#endif +JSON_HEDLEY_DIAGNOSTIC_POP + +#if defined(JSON_HEDLEY_PRINTF_FORMAT) +#undef JSON_HEDLEY_PRINTF_FORMAT +#endif +#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check))) +#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check))) +#elif \ + JSON_HEDLEY_HAS_ATTRIBUTE(format) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check))) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0) +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check)) +#else +#define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) +#endif + +#if defined(JSON_HEDLEY_CONSTEXPR) +#undef JSON_HEDLEY_CONSTEXPR +#endif +#if defined(__cplusplus) +#if __cplusplus >= 201103L +#define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr) +#endif +#endif +#if !defined(JSON_HEDLEY_CONSTEXPR) +#define JSON_HEDLEY_CONSTEXPR +#endif + +#if defined(JSON_HEDLEY_PREDICT) +#undef JSON_HEDLEY_PREDICT +#endif +#if defined(JSON_HEDLEY_LIKELY) +#undef JSON_HEDLEY_LIKELY +#endif +#if defined(JSON_HEDLEY_UNLIKELY) +#undef JSON_HEDLEY_UNLIKELY +#endif +#if defined(JSON_HEDLEY_UNPREDICTABLE) +#undef JSON_HEDLEY_UNPREDICTABLE +#endif +#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable) +#define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable(!!(expr)) +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) +# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(expr, value, probability) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1, probability) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0, probability) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#if !defined(JSON_HEDLEY_BUILTIN_UNPREDICTABLE) +#define JSON_HEDLEY_BUILTIN_UNPREDICTABLE(expr) __builtin_expect_with_probability(!!(expr), 1, 0.5) +#endif +#elif \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) +# define JSON_HEDLEY_PREDICT(expr, expected, probability) \ + (((probability) >= 0.9) ? __builtin_expect(!!(expr), (expected)) : (((void) (expected)), !!(expr))) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \ + })) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \ + (__extension__ ({ \ + JSON_HEDLEY_CONSTEXPR double hedley_probability_ = (probability); \ + ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \ + })) +# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1) +# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0) +#else +# define JSON_HEDLEY_PREDICT(expr, expected, probability) (((void) (expected)), !!(expr)) +# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr)) +# define JSON_HEDLEY_LIKELY(expr) (!!(expr)) +# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr)) +#endif +#if !defined(JSON_HEDLEY_UNPREDICTABLE) +#define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5) +#endif + +#if defined(JSON_HEDLEY_MALLOC) +#undef JSON_HEDLEY_MALLOC +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_MALLOC __attribute__((__malloc__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +#define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory") +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(14, 0, 0) +#define JSON_HEDLEY_MALLOC __declspec(restrict) +#else +#define JSON_HEDLEY_MALLOC +#endif + +#if defined(JSON_HEDLEY_PURE) +#undef JSON_HEDLEY_PURE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_PURE __attribute__((__pure__)) +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +#define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) +#define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;") +#else +#define JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_CONST) +#undef JSON_HEDLEY_CONST +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(const) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) +#define JSON_HEDLEY_CONST __attribute__((__const__)) +#elif \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) +#define JSON_HEDLEY_CONST _Pragma("no_side_effect") +#else +#define JSON_HEDLEY_CONST JSON_HEDLEY_PURE +#endif + +#if defined(JSON_HEDLEY_RESTRICT) +#undef JSON_HEDLEY_RESTRICT +#endif +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus) +#define JSON_HEDLEY_RESTRICT restrict +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \ + JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \ + defined(__clang__) +#define JSON_HEDLEY_RESTRICT __restrict +#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus) +#define JSON_HEDLEY_RESTRICT _Restrict +#else +#define JSON_HEDLEY_RESTRICT +#endif + +#if defined(JSON_HEDLEY_INLINE) +#undef JSON_HEDLEY_INLINE +#endif +#if \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \ + (defined(__cplusplus) && (__cplusplus >= 199711L)) +#define JSON_HEDLEY_INLINE inline +#elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0) +#define JSON_HEDLEY_INLINE __inline__ +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_INLINE __inline +#else +#define JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_ALWAYS_INLINE) +#undef JSON_HEDLEY_ALWAYS_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) +#define JSON_HEDLEY_ALWAYS_INLINE __forceinline +#elif JSON_HEDLEY_TI_VERSION_CHECK(7,0,0) && defined(__cplusplus) +#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced") +#else +#define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE +#endif + +#if defined(JSON_HEDLEY_NEVER_INLINE) +#undef JSON_HEDLEY_NEVER_INLINE +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__)) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) +#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline") +#elif JSON_HEDLEY_TI_VERSION_CHECK(6,0,0) && defined(__cplusplus) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;") +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +#define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never") +#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0) +#define JSON_HEDLEY_NEVER_INLINE __attribute((noinline)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0) +#define JSON_HEDLEY_NEVER_INLINE __declspec(noinline) +#else +#define JSON_HEDLEY_NEVER_INLINE +#endif + +#if defined(JSON_HEDLEY_PRIVATE) +#undef JSON_HEDLEY_PRIVATE +#endif +#if defined(JSON_HEDLEY_PUBLIC) +#undef JSON_HEDLEY_PUBLIC +#endif +#if defined(JSON_HEDLEY_IMPORT) +#undef JSON_HEDLEY_IMPORT +#endif +#if defined(_WIN32) || defined(__CYGWIN__) +#define JSON_HEDLEY_PRIVATE +#define JSON_HEDLEY_PUBLIC __declspec(dllexport) +#define JSON_HEDLEY_IMPORT __declspec(dllimport) +#else +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(8,0,0) || \ + (JSON_HEDLEY_TI_VERSION_CHECK(7,3,0) && defined(__TI_EABI__) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) +#define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden"))) +#define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default"))) +#else +#define JSON_HEDLEY_PRIVATE +#define JSON_HEDLEY_PUBLIC +#endif +#define JSON_HEDLEY_IMPORT extern +#endif + +#if defined(JSON_HEDLEY_NO_THROW) +#undef JSON_HEDLEY_NO_THROW +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +#define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__)) +#elif \ + JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) +#define JSON_HEDLEY_NO_THROW __declspec(nothrow) +#else +#define JSON_HEDLEY_NO_THROW +#endif + +#if defined(JSON_HEDLEY_FALL_THROUGH) +#undef JSON_HEDLEY_FALL_THROUGH +#endif +#if JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(fallthrough,7,0,0) && !defined(JSON_HEDLEY_PGI_VERSION) +#define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__)) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough) +#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]]) +#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough) +#define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]]) +#elif defined(__fallthrough) /* SAL */ +#define JSON_HEDLEY_FALL_THROUGH __fallthrough +#else +#define JSON_HEDLEY_FALL_THROUGH +#endif + +#if defined(JSON_HEDLEY_RETURNS_NON_NULL) +#undef JSON_HEDLEY_RETURNS_NON_NULL +#endif +#if \ + JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) +#define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__)) +#elif defined(_Ret_notnull_) /* SAL */ +#define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_ +#else +#define JSON_HEDLEY_RETURNS_NON_NULL +#endif + +#if defined(JSON_HEDLEY_ARRAY_PARAM) +#undef JSON_HEDLEY_ARRAY_PARAM +#endif +#if \ + defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \ + !defined(__STDC_NO_VLA__) && \ + !defined(__cplusplus) && \ + !defined(JSON_HEDLEY_PGI_VERSION) && \ + !defined(JSON_HEDLEY_TINYC_VERSION) +#define JSON_HEDLEY_ARRAY_PARAM(name) (name) +#else +#define JSON_HEDLEY_ARRAY_PARAM(name) +#endif + +#if defined(JSON_HEDLEY_IS_CONSTANT) +#undef JSON_HEDLEY_IS_CONSTANT +#endif +#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR) +#undef JSON_HEDLEY_REQUIRE_CONSTEXPR +#endif +/* JSON_HEDLEY_IS_CONSTEXPR_ is for + HEDLEY INTERNAL USE ONLY. API subject to change without notice. */ +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) +#undef JSON_HEDLEY_IS_CONSTEXPR_ +#endif +#if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_TI_VERSION_CHECK(6,1,0) || \ + (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) +#define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr) +#endif +#if !defined(__cplusplus) +# if \ + JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \ + JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \ + JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24) +#if defined(__INTPTR_TYPE__) +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*) +#else +#include +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*) +#endif +# elif \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(JSON_HEDLEY_SUNPRO_VERSION) && !defined(JSON_HEDLEY_PGI_VERSION)) || \ + JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \ + JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \ + JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0) +#if defined(__INTPTR_TYPE__) +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0) +#else +#include +#define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0) +#endif +# elif \ + defined(JSON_HEDLEY_GCC_VERSION) || \ + defined(JSON_HEDLEY_INTEL_VERSION) || \ + defined(JSON_HEDLEY_TINYC_VERSION) || \ + defined(JSON_HEDLEY_TI_VERSION) || \ + defined(__clang__) +# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \ + sizeof(void) != \ + sizeof(*( \ + 1 ? \ + ((void*) ((expr) * 0L) ) : \ +((struct { char v[sizeof(void) * 2]; } *) 1) \ + ) \ + ) \ + ) +# endif +#endif +#if defined(JSON_HEDLEY_IS_CONSTEXPR_) +#if !defined(JSON_HEDLEY_IS_CONSTANT) +#define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr) +#endif +#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1)) +#else +#if !defined(JSON_HEDLEY_IS_CONSTANT) +#define JSON_HEDLEY_IS_CONSTANT(expr) (0) +#endif +#define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr) +#endif + +#if defined(JSON_HEDLEY_BEGIN_C_DECLS) +#undef JSON_HEDLEY_BEGIN_C_DECLS +#endif +#if defined(JSON_HEDLEY_END_C_DECLS) +#undef JSON_HEDLEY_END_C_DECLS +#endif +#if defined(JSON_HEDLEY_C_DECL) +#undef JSON_HEDLEY_C_DECL +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_BEGIN_C_DECLS extern "C" { +#define JSON_HEDLEY_END_C_DECLS } +#define JSON_HEDLEY_C_DECL extern "C" +#else +#define JSON_HEDLEY_BEGIN_C_DECLS +#define JSON_HEDLEY_END_C_DECLS +#define JSON_HEDLEY_C_DECL +#endif + +#if defined(JSON_HEDLEY_STATIC_ASSERT) +#undef JSON_HEDLEY_STATIC_ASSERT +#endif +#if \ + !defined(__cplusplus) && ( \ + (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \ + JSON_HEDLEY_HAS_FEATURE(c_static_assert) || \ + JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \ + defined(_Static_assert) \ + ) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message) +#elif \ + (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ + JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \ + (defined(__cplusplus) && JSON_HEDLEY_TI_VERSION_CHECK(8,3,0)) +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message)) +#else +# define JSON_HEDLEY_STATIC_ASSERT(expr, message) +#endif + +#if defined(JSON_HEDLEY_CONST_CAST) +#undef JSON_HEDLEY_CONST_CAST +#endif +#if defined(__cplusplus) +# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast(expr)) +#elif \ + JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_REINTERPRET_CAST) +#undef JSON_HEDLEY_REINTERPRET_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast(expr)) +#else +#define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (*((T*) &(expr))) +#endif + +#if defined(JSON_HEDLEY_STATIC_CAST) +#undef JSON_HEDLEY_STATIC_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast(expr)) +#else +#define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr)) +#endif + +#if defined(JSON_HEDLEY_CPP_CAST) +#undef JSON_HEDLEY_CPP_CAST +#endif +#if defined(__cplusplus) +#define JSON_HEDLEY_CPP_CAST(T, expr) static_cast(expr) +#else +#define JSON_HEDLEY_CPP_CAST(T, expr) (expr) +#endif + +#if defined(JSON_HEDLEY_NULL) +#undef JSON_HEDLEY_NULL +#endif +#if defined(__cplusplus) +#if __cplusplus >= 201103L +#define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr) +#elif defined(NULL) +#define JSON_HEDLEY_NULL NULL +#else +#define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0) +#endif +#elif defined(NULL) +#define JSON_HEDLEY_NULL NULL +#else +#define JSON_HEDLEY_NULL ((void*) 0) +#endif + +#if defined(JSON_HEDLEY_MESSAGE) +#undef JSON_HEDLEY_MESSAGE +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_MESSAGE(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(message msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \ + JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg) +#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg) +#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0) +# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_WARNING) +#undef JSON_HEDLEY_WARNING +#endif +#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas") +# define JSON_HEDLEY_WARNING(msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \ + JSON_HEDLEY_PRAGMA(clang warning msg) \ + JSON_HEDLEY_DIAGNOSTIC_POP +#elif \ + JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \ + JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg) +#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg)) +#else +# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg) +#endif + +#if defined(JSON_HEDLEY_REQUIRE) +#undef JSON_HEDLEY_REQUIRE +#endif +#if defined(JSON_HEDLEY_REQUIRE_MSG) +#undef JSON_HEDLEY_REQUIRE_MSG +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if) +# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat") +# define JSON_HEDLEY_REQUIRE(expr) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), #expr, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \ + __attribute__((diagnose_if(!(expr), msg, "error"))) \ + JSON_HEDLEY_DIAGNOSTIC_POP +# else +# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error"))) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error"))) +# endif +#else +# define JSON_HEDLEY_REQUIRE(expr) +# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) +#endif + +#if defined(JSON_HEDLEY_FLAGS) +#undef JSON_HEDLEY_FLAGS +#endif +#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) +#define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__)) +#endif + +#if defined(JSON_HEDLEY_FLAGS_CAST) +#undef JSON_HEDLEY_FLAGS_CAST +#endif +#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0) +# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \ + JSON_HEDLEY_DIAGNOSTIC_PUSH \ + _Pragma("warning(disable:188)") \ + ((T) (expr)); \ + JSON_HEDLEY_DIAGNOSTIC_POP \ + })) +#else +# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr) +#endif + +#if defined(JSON_HEDLEY_EMPTY_BASES) +#undef JSON_HEDLEY_EMPTY_BASES +#endif +#if JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0) +#define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases) +#else +#define JSON_HEDLEY_EMPTY_BASES +#endif + + /* Remaining macros are deprecated. */ + +#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK) +#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK +#endif +#if defined(__clang__) +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0) +#else +#define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) +#endif + +#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN) +#undef JSON_HEDLEY_CLANG_HAS_BUILTIN +#endif +#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin) + +#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE) +#undef JSON_HEDLEY_CLANG_HAS_FEATURE +#endif +#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature) + +#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION) +#undef JSON_HEDLEY_CLANG_HAS_EXTENSION +#endif +#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension) + +#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE) +#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE +#endif +#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) + +#if defined(JSON_HEDLEY_CLANG_HAS_WARNING) +#undef JSON_HEDLEY_CLANG_HAS_WARNING +#endif +#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning) + +#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */ + + +// This file contains all internal macro definitions +// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them + +// exclude unsupported compilers +#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK) +#if defined(__clang__) +#if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400 +#error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers" +#endif +#elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER)) +#if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800 +#error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers" +#endif +#endif +#endif + +// C++ language standard detection +#if (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464 +#define JSON_HAS_CPP_17 +#define JSON_HAS_CPP_14 +#elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1) +#define JSON_HAS_CPP_14 +#endif + +// disable float-equal warnings on GCC/clang +#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + +// disable documentation warnings on clang +#if defined(__clang__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdocumentation" +#endif + +// allow to disable exceptions +#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION) +#define JSON_THROW(exception) throw exception +#define JSON_TRY try +#define JSON_CATCH(exception) catch(exception) +#define JSON_INTERNAL_CATCH(exception) catch(exception) +#else +#include +#define JSON_THROW(exception) std::abort() +#define JSON_TRY if(true) +#define JSON_CATCH(exception) if(false) +#define JSON_INTERNAL_CATCH(exception) if(false) +#endif + +// override exception macros +#if defined(JSON_THROW_USER) +#undef JSON_THROW +#define JSON_THROW JSON_THROW_USER +#endif +#if defined(JSON_TRY_USER) +#undef JSON_TRY +#define JSON_TRY JSON_TRY_USER +#endif +#if defined(JSON_CATCH_USER) +#undef JSON_CATCH +#define JSON_CATCH JSON_CATCH_USER +#undef JSON_INTERNAL_CATCH +#define JSON_INTERNAL_CATCH JSON_CATCH_USER +#endif +#if defined(JSON_INTERNAL_CATCH_USER) +#undef JSON_INTERNAL_CATCH +#define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER +#endif + +/*! +@brief macro to briefly define a mapping between an enum and JSON +@def NLOHMANN_JSON_SERIALIZE_ENUM +@since version 3.4.0 +*/ +#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \ + template \ + inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [e](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.first == e; \ + }); \ + j = ((it != std::end(m)) ? it : std::begin(m))->second; \ + } \ + template \ + inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \ + { \ + static_assert(std::is_enum::value, #ENUM_TYPE " must be an enum!"); \ + static const std::pair m[] = __VA_ARGS__; \ + auto it = std::find_if(std::begin(m), std::end(m), \ + [&j](const std::pair& ej_pair) -> bool \ + { \ + return ej_pair.second == j; \ + }); \ + e = ((it != std::end(m)) ? it : std::begin(m))->first; \ + } + +// Ugly macros to avoid uglier copy-paste when specializing basic_json. They +// may be removed in the future once the class is split. + +#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \ + template class ObjectType, \ + template class ArrayType, \ + class StringType, class BooleanType, class NumberIntegerType, \ + class NumberUnsignedType, class NumberFloatType, \ + template class AllocatorType, \ + template class JSONSerializer> + +#define NLOHMANN_BASIC_JSON_TPL \ + basic_json + + +namespace nlohmann +{ + namespace detail + { + //////////////// + // exceptions // + //////////////// + + /*! + @brief general exception of the @ref basic_json class + + This class is an extension of `std::exception` objects with a member @a id for + exception ids. It is used as the base class for all exceptions thrown by the + @ref basic_json class. This class can hence be used as "wildcard" to catch + exceptions. + + Subclasses: + - @ref parse_error for exceptions indicating a parse error + - @ref invalid_iterator for exceptions indicating errors with iterators + - @ref type_error for exceptions indicating executing a member function with + a wrong type + - @ref out_of_range for exceptions indicating access out of the defined range + - @ref other_error for exceptions indicating other library errors + + @internal + @note To have nothrow-copy-constructible exceptions, we internally use + `std::runtime_error` which can cope with arbitrary-length error messages. + Intermediate strings are built with static functions and then passed to + the actual constructor. + @endinternal + + @liveexample{The following code shows how arbitrary library exceptions can be + caught.,exception} + + @since version 3.0.0 + */ + class exception : public std::exception + { + public: + /// returns the explanatory string + JSON_HEDLEY_RETURNS_NON_NULL + const char* what() const noexcept override + { + return m.what(); + } + + /// the id of the exception + const int id; + + protected: + JSON_HEDLEY_NON_NULL(3) + exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} + + static std::string name(const std::string& ename, int id_) + { + return "[json.exception." + ename + "." + std::to_string(id_) + "] "; + } + + private: + /// an exception object as storage for error messages + std::runtime_error m; + }; + + /*! + @brief exception indicating a parse error + + This exception is thrown by the library when a parse error occurs. Parse errors + can occur during the deserialization of JSON text, CBOR, MessagePack, as well + as when using JSON Patch. + + Member @a byte holds the byte index of the last read character in the input + file. + + Exceptions have ids 1xx. + + name / id | example message | description + ------------------------------ | --------------- | ------------------------- + json.exception.parse_error.101 | parse error at 2: unexpected end of input; expected string literal | This error indicates a syntax error while deserializing a JSON text. The error message describes that an unexpected token (character) was encountered, and the member @a byte indicates the error position. + json.exception.parse_error.102 | parse error at 14: missing or wrong low surrogate | JSON uses the `\uxxxx` format to describe Unicode characters. Code points above above 0xFFFF are split into two `\uxxxx` entries ("surrogate pairs"). This error indicates that the surrogate pair is incomplete or contains an invalid code point. + json.exception.parse_error.103 | parse error: code points above 0x10FFFF are invalid | Unicode supports code points up to 0x10FFFF. Code points above 0x10FFFF are invalid. + json.exception.parse_error.104 | parse error: JSON patch must be an array of objects | [RFC 6902](https://tools.ietf.org/html/rfc6902) requires a JSON Patch document to be a JSON document that represents an array of objects. + json.exception.parse_error.105 | parse error: operation must have string member 'op' | An operation of a JSON Patch document must contain exactly one "op" member, whose value indicates the operation to perform. Its value must be one of "add", "remove", "replace", "move", "copy", or "test"; other values are errors. + json.exception.parse_error.106 | parse error: array index '01' must not begin with '0' | An array index in a JSON Pointer ([RFC 6901](https://tools.ietf.org/html/rfc6901)) may be `0` or any number without a leading `0`. + json.exception.parse_error.107 | parse error: JSON pointer must be empty or begin with '/' - was: 'foo' | A JSON Pointer must be a Unicode string containing a sequence of zero or more reference tokens, each prefixed by a `/` character. + json.exception.parse_error.108 | parse error: escape character '~' must be followed with '0' or '1' | In a JSON Pointer, only `~0` and `~1` are valid escape sequences. + json.exception.parse_error.109 | parse error: array index 'one' is not a number | A JSON Pointer array index must be a number. + json.exception.parse_error.110 | parse error at 1: cannot read 2 bytes from vector | When parsing CBOR or MessagePack, the byte vector ends before the complete value has been read. + json.exception.parse_error.112 | parse error at 1: error reading CBOR; last byte: 0xF8 | Not all types of CBOR or MessagePack are supported. This exception occurs if an unsupported byte was read. + json.exception.parse_error.113 | parse error at 2: expected a CBOR string; last byte: 0x98 | While parsing a map key, a value that is not a string has been read. + json.exception.parse_error.114 | parse error: Unsupported BSON record type 0x0F | The parsing of the corresponding BSON record type is not implemented (yet). + + @note For an input with n bytes, 1 is the index of the first character and n+1 + is the index of the terminating null byte or the end of file. This also + holds true when reading a byte vector (CBOR or MessagePack). + + @liveexample{The following code shows how a `parse_error` exception can be + caught.,parse_error} + + @sa - @ref exception for the base class of the library exceptions + @sa - @ref invalid_iterator for exceptions indicating errors with iterators + @sa - @ref type_error for exceptions indicating executing a member function with + a wrong type + @sa - @ref out_of_range for exceptions indicating access out of the defined range + @sa - @ref other_error for exceptions indicating other library errors + + @since version 3.0.0 + */ + class parse_error : public exception + { + public: + /*! + @brief create a parse error exception + @param[in] id_ the id of the exception + @param[in] pos the position where the error occurred (or with + chars_read_total=0 if the position cannot be + determined) + @param[in] what_arg the explanatory string + @return parse_error object + */ + static parse_error create(int id_, const position_t& pos, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + position_string(pos) + ": " + what_arg; + return parse_error(id_, pos.chars_read_total, w.c_str()); + } + + static parse_error create(int id_, std::size_t byte_, const std::string& what_arg) + { + std::string w = exception::name("parse_error", id_) + "parse error" + + (byte_ != 0 ? (" at byte " + std::to_string(byte_)) : "") + + ": " + what_arg; + return parse_error(id_, byte_, w.c_str()); + } + + /*! + @brief byte index of the parse error + + The byte index of the last read character in the input file. + + @note For an input with n bytes, 1 is the index of the first character and + n+1 is the index of the terminating null byte or the end of file. + This also holds true when reading a byte vector (CBOR or MessagePack). + */ + const std::size_t byte; + + private: + parse_error(int id_, std::size_t byte_, const char* what_arg) + : exception(id_, what_arg), byte(byte_) {} + + static std::string position_string(const position_t& pos) + { + return " at line " + std::to_string(pos.lines_read + 1) + + ", column " + std::to_string(pos.chars_read_current_line); + } + }; + + /*! + @brief exception indicating errors with iterators + + This exception is thrown if iterators passed to a library function do not match + the expected semantics. + + Exceptions have ids 2xx. + + name / id | example message | description + ----------------------------------- | --------------- | ------------------------- + json.exception.invalid_iterator.201 | iterators are not compatible | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. + json.exception.invalid_iterator.202 | iterator does not fit current value | In an erase or insert function, the passed iterator @a pos does not belong to the JSON value for which the function was called. It hence does not define a valid position for the deletion/insertion. + json.exception.invalid_iterator.203 | iterators do not fit current value | Either iterator passed to function @ref erase(IteratorType first, IteratorType last) does not belong to the JSON value from which values shall be erased. It hence does not define a valid range to delete values from. + json.exception.invalid_iterator.204 | iterators out of range | When an iterator range for a primitive type (number, boolean, or string) is passed to a constructor or an erase function, this range has to be exactly (@ref begin(), @ref end()), because this is the only way the single stored value is expressed. All other ranges are invalid. + json.exception.invalid_iterator.205 | iterator out of range | When an iterator for a primitive type (number, boolean, or string) is passed to an erase function, the iterator has to be the @ref begin() iterator, because it is the only way to address the stored value. All other iterators are invalid. + json.exception.invalid_iterator.206 | cannot construct with iterators from null | The iterators passed to constructor @ref basic_json(InputIT first, InputIT last) belong to a JSON null value and hence to not define a valid range. + json.exception.invalid_iterator.207 | cannot use key() for non-object iterators | The key() member function can only be used on iterators belonging to a JSON object, because other types do not have a concept of a key. + json.exception.invalid_iterator.208 | cannot use operator[] for object iterators | The operator[] to specify a concrete offset cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + json.exception.invalid_iterator.209 | cannot use offsets with object iterators | The offset operators (+, -, +=, -=) cannot be used on iterators belonging to a JSON object, because JSON objects are unordered. + json.exception.invalid_iterator.210 | iterators do not fit | The iterator range passed to the insert function are not compatible, meaning they do not belong to the same container. Therefore, the range (@a first, @a last) is invalid. + json.exception.invalid_iterator.211 | passed iterators may not belong to container | The iterator range passed to the insert function must not be a subrange of the container to insert to. + json.exception.invalid_iterator.212 | cannot compare iterators of different containers | When two iterators are compared, they must belong to the same container. + json.exception.invalid_iterator.213 | cannot compare order of object iterators | The order of object iterators cannot be compared, because JSON objects are unordered. + json.exception.invalid_iterator.214 | cannot get value | Cannot get value for iterator: Either the iterator belongs to a null value or it is an iterator to a primitive type (number, boolean, or string), but the iterator is different to @ref begin(). + + @liveexample{The following code shows how an `invalid_iterator` exception can be + caught.,invalid_iterator} + + @sa - @ref exception for the base class of the library exceptions + @sa - @ref parse_error for exceptions indicating a parse error + @sa - @ref type_error for exceptions indicating executing a member function with + a wrong type + @sa - @ref out_of_range for exceptions indicating access out of the defined range + @sa - @ref other_error for exceptions indicating other library errors + + @since version 3.0.0 + */ + class invalid_iterator : public exception + { + public: + static invalid_iterator create(int id_, const std::string& what_arg) + { + std::string w = exception::name("invalid_iterator", id_) + what_arg; + return invalid_iterator(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + invalid_iterator(int id_, const char* what_arg) + : exception(id_, what_arg) {} + }; + + /*! + @brief exception indicating executing a member function with a wrong type + + This exception is thrown in case of a type error; that is, a library function is + executed on a JSON value whose type does not match the expected semantics. + + Exceptions have ids 3xx. + + name / id | example message | description + ----------------------------- | --------------- | ------------------------- + json.exception.type_error.301 | cannot create object from initializer list | To create an object from an initializer list, the initializer list must consist only of a list of pairs whose first element is a string. When this constraint is violated, an array is created instead. + json.exception.type_error.302 | type must be object, but is array | During implicit or explicit value conversion, the JSON type must be compatible to the target type. For instance, a JSON string can only be converted into string types, but not into numbers or boolean types. + json.exception.type_error.303 | incompatible ReferenceType for get_ref, actual type is object | To retrieve a reference to a value stored in a @ref basic_json object with @ref get_ref, the type of the reference must match the value type. For instance, for a JSON array, the @a ReferenceType must be @ref array_t &. + json.exception.type_error.304 | cannot use at() with string | The @ref at() member functions can only be executed for certain JSON types. + json.exception.type_error.305 | cannot use operator[] with string | The @ref operator[] member functions can only be executed for certain JSON types. + json.exception.type_error.306 | cannot use value() with string | The @ref value() member functions can only be executed for certain JSON types. + json.exception.type_error.307 | cannot use erase() with string | The @ref erase() member functions can only be executed for certain JSON types. + json.exception.type_error.308 | cannot use push_back() with string | The @ref push_back() and @ref operator+= member functions can only be executed for certain JSON types. + json.exception.type_error.309 | cannot use insert() with | The @ref insert() member functions can only be executed for certain JSON types. + json.exception.type_error.310 | cannot use swap() with number | The @ref swap() member functions can only be executed for certain JSON types. + json.exception.type_error.311 | cannot use emplace_back() with string | The @ref emplace_back() member function can only be executed for certain JSON types. + json.exception.type_error.312 | cannot use update() with string | The @ref update() member functions can only be executed for certain JSON types. + json.exception.type_error.313 | invalid value to unflatten | The @ref unflatten function converts an object whose keys are JSON Pointers back into an arbitrary nested JSON value. The JSON Pointers must not overlap, because then the resulting value would not be well defined. + json.exception.type_error.314 | only objects can be unflattened | The @ref unflatten function only works for an object whose keys are JSON Pointers. + json.exception.type_error.315 | values in object must be primitive | The @ref unflatten function only works for an object whose keys are JSON Pointers and whose values are primitive. + json.exception.type_error.316 | invalid UTF-8 byte at index 10: 0x7E | The @ref dump function only works with UTF-8 encoded strings; that is, if you assign a `std::string` to a JSON value, make sure it is UTF-8 encoded. | + json.exception.type_error.317 | JSON value cannot be serialized to requested format | The dynamic type of the object cannot be represented in the requested serialization format (e.g. a raw `true` or `null` JSON object cannot be serialized to BSON) | + + @liveexample{The following code shows how a `type_error` exception can be + caught.,type_error} + + @sa - @ref exception for the base class of the library exceptions + @sa - @ref parse_error for exceptions indicating a parse error + @sa - @ref invalid_iterator for exceptions indicating errors with iterators + @sa - @ref out_of_range for exceptions indicating access out of the defined range + @sa - @ref other_error for exceptions indicating other library errors + + @since version 3.0.0 + */ + class type_error : public exception + { + public: + static type_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("type_error", id_) + what_arg; + return type_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + type_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + }; + + /*! + @brief exception indicating access out of the defined range + + This exception is thrown in case a library function is called on an input + parameter that exceeds the expected range, for instance in case of array + indices or nonexisting object keys. + + Exceptions have ids 4xx. + + name / id | example message | description + ------------------------------- | --------------- | ------------------------- + json.exception.out_of_range.401 | array index 3 is out of range | The provided array index @a i is larger than @a size-1. + json.exception.out_of_range.402 | array index '-' (3) is out of range | The special array index `-` in a JSON Pointer never describes a valid element of the array, but the index past the end. That is, it can only be used to add elements at this position, but not to read it. + json.exception.out_of_range.403 | key 'foo' not found | The provided key was not found in the JSON object. + json.exception.out_of_range.404 | unresolved reference token 'foo' | A reference token in a JSON Pointer could not be resolved. + json.exception.out_of_range.405 | JSON pointer has no parent | The JSON Patch operations 'remove' and 'add' can not be applied to the root element of the JSON value. + json.exception.out_of_range.406 | number overflow parsing '10E1000' | A parsed number could not be stored as without changing it to NaN or INF. + json.exception.out_of_range.407 | number overflow serializing '9223372036854775808' | UBJSON and BSON only support integer numbers up to 9223372036854775807. | + json.exception.out_of_range.408 | excessive array size: 8658170730974374167 | The size (following `#`) of an UBJSON array or object exceeds the maximal capacity. | + json.exception.out_of_range.409 | BSON key cannot contain code point U+0000 (at byte 2) | Key identifiers to be serialized to BSON cannot contain code point U+0000, since the key is stored as zero-terminated c-string | + + @liveexample{The following code shows how an `out_of_range` exception can be + caught.,out_of_range} + + @sa - @ref exception for the base class of the library exceptions + @sa - @ref parse_error for exceptions indicating a parse error + @sa - @ref invalid_iterator for exceptions indicating errors with iterators + @sa - @ref type_error for exceptions indicating executing a member function with + a wrong type + @sa - @ref other_error for exceptions indicating other library errors + + @since version 3.0.0 + */ + class out_of_range : public exception + { + public: + static out_of_range create(int id_, const std::string& what_arg) + { + std::string w = exception::name("out_of_range", id_) + what_arg; + return out_of_range(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {} + }; + + /*! + @brief exception indicating other library errors + + This exception is thrown in case of errors that cannot be classified with the + other exception types. + + Exceptions have ids 5xx. + + name / id | example message | description + ------------------------------ | --------------- | ------------------------- + json.exception.other_error.501 | unsuccessful: {"op":"test","path":"/baz", "value":"bar"} | A JSON Patch operation 'test' failed. The unsuccessful operation is also printed. + + @sa - @ref exception for the base class of the library exceptions + @sa - @ref parse_error for exceptions indicating a parse error + @sa - @ref invalid_iterator for exceptions indicating errors with iterators + @sa - @ref type_error for exceptions indicating executing a member function with + a wrong type + @sa - @ref out_of_range for exceptions indicating access out of the defined range + + @liveexample{The following code shows how an `other_error` exception can be + caught.,other_error} + + @since version 3.0.0 + */ + class other_error : public exception + { + public: + static other_error create(int id_, const std::string& what_arg) + { + std::string w = exception::name("other_error", id_) + what_arg; + return other_error(id_, w.c_str()); + } + + private: + JSON_HEDLEY_NON_NULL(3) + other_error(int id_, const char* what_arg) : exception(id_, what_arg) {} + }; + } // namespace detail +} // namespace nlohmann + +// #include + +// #include + + +#include // not +#include // size_t +#include // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type + +namespace nlohmann +{ + namespace detail + { + // alias templates to reduce boilerplate + template + using enable_if_t = typename std::enable_if::type; + + template + using uncvref_t = typename std::remove_cv::type>::type; + + // implementation of C++14 index_sequence and affiliates + // source: https://stackoverflow.com/a/32223343 + template + struct index_sequence + { + using type = index_sequence; + using value_type = std::size_t; + static constexpr std::size_t size() noexcept + { + return sizeof...(Ints); + } + }; + + template + struct merge_and_renumber; + + template + struct merge_and_renumber, index_sequence> + : index_sequence < I1..., (sizeof...(I1) + I2)... > {}; + + template + struct make_index_sequence + : merge_and_renumber < typename make_index_sequence < N / 2 >::type, + typename make_index_sequence < N - N / 2 >::type > {}; + + template<> struct make_index_sequence<0> : index_sequence<> {}; + template<> struct make_index_sequence<1> : index_sequence<0> {}; + + template + using index_sequence_for = make_index_sequence; + + // dispatch utility (taken from ranges-v3) + template struct priority_tag : priority_tag < N - 1 > {}; + template<> struct priority_tag<0> {}; + + // taken from ranges-v3 + template + struct static_const + { + static constexpr T value{}; + }; + + template + constexpr T static_const::value; + } // namespace detail +} // namespace nlohmann + +// #include + + +#include // not +#include // numeric_limits +#include // false_type, is_constructible, is_integral, is_same, true_type +#include // declval + +// #include + + +#include // random_access_iterator_tag + +// #include + + +namespace nlohmann +{ + namespace detail + { + template struct make_void + { + using type = void; + }; + template using void_t = typename make_void::type; + } // namespace detail +} // namespace nlohmann + +// #include + + +namespace nlohmann +{ + namespace detail + { + template + struct iterator_types {}; + + template + struct iterator_types < + It, + void_t> + { + using difference_type = typename It::difference_type; + using value_type = typename It::value_type; + using pointer = typename It::pointer; + using reference = typename It::reference; + using iterator_category = typename It::iterator_category; + }; + + // This is required as some compilers implement std::iterator_traits in a way that + // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341. + template + struct iterator_traits + { + }; + + template + struct iterator_traits < T, enable_if_t < !std::is_pointer::value >> + : iterator_types + { + }; + + template + struct iterator_traits::value>> + { + using iterator_category = std::random_access_iterator_tag; + using value_type = T; + using difference_type = ptrdiff_t; + using pointer = T*; + using reference = T&; + }; + } // namespace detail +} // namespace nlohmann + +// #include + +// #include + +// #include + + +#include + +// #include + + +// http://en.cppreference.com/w/cpp/experimental/is_detected +namespace nlohmann +{ + namespace detail + { + struct nonesuch + { + nonesuch() = delete; + ~nonesuch() = delete; + nonesuch(nonesuch const&) = delete; + nonesuch(nonesuch const&&) = delete; + void operator=(nonesuch const&) = delete; + void operator=(nonesuch&&) = delete; + }; + + template class Op, + class... Args> + struct detector + { + using value_t = std::false_type; + using type = Default; + }; + + template class Op, class... Args> + struct detector>, Op, Args...> + { + using value_t = std::true_type; + using type = Op; + }; + + template