Showing with 1,992 additions and 778 deletions.
  1. +28 −0 .editorconfig
  2. +2 −1 build.gradle
  3. +22 −0 buildSrc/build.gradle
  4. +1 −0 buildSrc/gradle.properties
  5. +41 −0 buildSrc/src/main/java/de/hysky/skyblocker/init/InitInjectingClassVisitor.java
  6. +112 −0 buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java
  7. +71 −0 buildSrc/src/main/java/de/hysky/skyblocker/init/InitReadingClassVisitor.java
  8. +2 −2 gradle.properties
  9. +17 −159 src/main/java/de/hysky/skyblocker/SkyblockerMod.java
  10. +2 −0 src/main/java/de/hysky/skyblocker/SkyblockerScreen.java
  11. +3 −2 src/main/java/de/hysky/skyblocker/UpdateNotifications.java
  12. +38 −0 src/main/java/de/hysky/skyblocker/annotations/Init.java
  13. +3 −0 src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
  14. +22 −16 src/main/java/de/hysky/skyblocker/config/SkyblockerConfigManager.java
  15. +39 −0 src/main/java/de/hysky/skyblocker/config/categories/DebugCategory.java
  16. +8 −0 src/main/java/de/hysky/skyblocker/config/categories/DungeonsCategory.java
  17. +19 −10 src/main/java/de/hysky/skyblocker/config/categories/HelperCategory.java
  18. +9 −0 src/main/java/de/hysky/skyblocker/config/categories/SlayersCategory.java
  19. +14 −0 src/main/java/de/hysky/skyblocker/config/configs/DebugConfig.java
  20. +3 −0 src/main/java/de/hysky/skyblocker/config/configs/DungeonsConfig.java
  21. +10 −2 src/main/java/de/hysky/skyblocker/config/configs/HelperConfig.java
  22. +3 −0 src/main/java/de/hysky/skyblocker/config/configs/SlayersConfig.java
  23. +15 −9 src/main/java/de/hysky/skyblocker/config/configs/UIAndVisualsConfig.java
  24. +57 −37 src/main/java/de/hysky/skyblocker/debug/Debug.java
  25. +42 −0 src/main/java/de/hysky/skyblocker/mixins/BossBarHudMixin.java
  26. +29 −0 src/main/java/de/hysky/skyblocker/mixins/EntityMixin.java
  27. +1 −3 src/main/java/de/hysky/skyblocker/mixins/EntityRenderDispatcherMixin.java
  28. +6 −10 src/main/java/de/hysky/skyblocker/mixins/HandledScreenMixin.java
  29. +0 −18 src/main/java/de/hysky/skyblocker/mixins/LivingEntityRendererMixin.java
  30. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/ChestValue.java
  31. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/FishingHelper.java
  32. +4 −4 src/main/java/de/hysky/skyblocker/skyblock/PetCache.java
  33. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/QuiverWarning.java
  34. +142 −102 src/main/java/de/hysky/skyblocker/skyblock/StatusBarTracker.java
  35. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/TeleportOverlay.java
  36. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/Tips.java
  37. +65 −0 src/main/java/de/hysky/skyblocker/skyblock/WardrobeKeybinds.java
  38. +3 −0 src/main/java/de/hysky/skyblocker/skyblock/WarpAutocomplete.java
  39. +1 −50 src/main/java/de/hysky/skyblocker/skyblock/bazaar/BazaarHelper.java
  40. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/calculators/CalculatorCommand.java
  41. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/chat/ChatRulesHandler.java
  42. +14 −8 src/main/java/de/hysky/skyblocker/skyblock/chat/SkyblockXpMessages.java
  43. +26 −0 src/main/java/de/hysky/skyblocker/skyblock/chat/chatcoords/ChatLocation.java
  44. +66 −0 src/main/java/de/hysky/skyblocker/skyblock/chat/chatcoords/ChatWaypointLocation.java
  45. +15 −33 src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/ChocolateFactorySolver.java
  46. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/EggFinder.java
  47. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/chocolatefactory/TimeTowerReminder.java
  48. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/crimson/dojo/DojoManager.java
  49. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/crimson/kuudra/Kuudra.java
  50. +1 −1 src/main/java/de/hysky/skyblocker/skyblock/crimson/slayer/AttunementColors.java
  51. +2 −4 src/main/java/de/hysky/skyblocker/skyblock/crimson/slayer/FirePillarAnnouncer.java
  52. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonMap.java
  53. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScore.java
  54. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonScoreHUD.java
  55. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/DungeonTextures.java
  56. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/FireFreezeStaffTimer.java
  57. +6 −4 src/main/java/de/hysky/skyblocker/skyblock/dungeon/GuardianHealth.java
  58. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/LividColor.java
  59. +1 −1 src/main/java/de/hysky/skyblocker/skyblock/dungeon/Reparty.java
  60. +52 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/SalvageHelper.java
  61. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/LightsOn.java
  62. +4 −2 src/main/java/de/hysky/skyblocker/skyblock/dungeon/device/SimonSays.java
  63. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/partyfinder/PartyFinderScreen.java
  64. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/CreeperBeams.java
  65. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/DungeonBlaze.java
  66. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/IceFill.java
  67. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Silverfish.java
  68. +4 −1 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/ThreeWeirdos.java
  69. +4 −2 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/TicTacToe.java
  70. +7 −4 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/Trivia.java
  71. +4 −1 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/boulder/Boulder.java
  72. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/puzzle/waterboard/Waterboard.java
  73. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonManager.java
  74. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretsTracker.java
  75. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/CommissionLabels.java
  76. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsChestHighlighter.java
  77. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsHud.java
  78. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/CrystalsLocationsManager.java
  79. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/DwarvenHud.java
  80. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/GlaciteColdOverlay.java
  81. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/dwarven/MetalDetector.java
  82. +31 −11 src/main/java/de/hysky/skyblocker/skyblock/dwarven/WishingCompassSolver.java
  83. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/end/BeaconHighlighter.java
  84. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/end/EnderNodes.java
  85. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/end/TheEnd.java
  86. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/entity/MobBoundingBoxes.java
  87. +5 −2 src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
  88. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/events/EventNotifications.java
  89. +2 −2 src/main/java/de/hysky/skyblocker/skyblock/events/EventToast.java
  90. +18 −8 src/main/java/de/hysky/skyblocker/skyblock/fancybars/FancyStatusBars.java
  91. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/garden/FarmingHud.java
  92. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/garden/LowerSensitivity.java
  93. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/garden/VisitorHelper.java
  94. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorAnimatedDyes.java
  95. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorDyeColors.java
  96. +2 −1 src/main/java/de/hysky/skyblocker/skyblock/item/CustomArmorTrims.java
  97. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/CustomItemNames.java
  98. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/HotbarSlotLock.java
  99. +54 −9 src/main/java/de/hysky/skyblocker/skyblock/item/ItemCooldowns.java
  100. +79 −0 src/main/java/de/hysky/skyblocker/skyblock/item/ItemPrice.java
  101. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/ItemProtection.java
  102. +7 −7 src/main/java/de/hysky/skyblocker/skyblock/item/ItemRarityBackgrounds.java
  103. +4 −3 src/main/java/de/hysky/skyblocker/skyblock/item/MuseumItemCache.java
  104. +2 −1 src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockInventoryScreen.java
  105. +5 −5 src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemData.java
  106. +10 −10 src/main/java/de/hysky/skyblocker/skyblock/item/SkyblockItemRarity.java
  107. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/WikiLookup.java
  108. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/slottext/SlotTextManager.java
  109. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/AccessoriesHelper.java
  110. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/BackpackPreview.java
  111. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/ItemTooltip.java
  112. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/TooltipManager.java
  113. +7 −6 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/AvgBinTooltip.java
  114. +8 −12 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/BazaarPriceTooltip.java
  115. +1 −1 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/EssenceShopPrice.java
  116. +3 −7 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/adders/LBinTooltip.java
  117. +0 −1 src/main/java/de/hysky/skyblocker/skyblock/item/tooltip/info/DataTooltipInfoType.java
  118. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemFixerUpper.java
  119. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemRepository.java
  120. +1 −1 src/main/java/de/hysky/skyblocker/skyblock/itemlist/ItemStackBuilder.java
  121. +3 −3 src/main/java/de/hysky/skyblocker/skyblock/itemlist/UpcomingEventsTab.java
  122. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/mayors/JerryTimer.java
  123. +41 −26 src/main/java/de/hysky/skyblocker/skyblock/profileviewer/ProfileViewerScreen.java
  124. +7 −2 src/main/java/de/hysky/skyblocker/skyblock/quicknav/QuickNavButton.java
  125. +3 −3 src/main/java/de/hysky/skyblocker/skyblock/rift/ManiaIndicator.java
  126. +2 −2 src/main/java/de/hysky/skyblocker/skyblock/rift/StakeIndicator.java
  127. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/rift/TheRift.java
  128. +3 −3 src/main/java/de/hysky/skyblocker/skyblock/rift/TwinClawsIndicator.java
  129. +3 −1 src/main/java/de/hysky/skyblocker/skyblock/searchoverlay/SearchOverManager.java
  130. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/shortcut/Shortcuts.java
  131. +102 −0 src/main/java/de/hysky/skyblocker/skyblock/slayers/SlayerBossBars.java
  132. +3 −1 src/main/java/de/hysky/skyblocker/skyblock/slayers/SlayerEntitiesGlow.java
  133. +8 −7 src/main/java/de/hysky/skyblocker/skyblock/special/DungeonsSpecialEffects.java
  134. +9 −9 src/main/java/de/hysky/skyblocker/skyblock/special/DyeSpecialEffects.java
  135. +0 −4 src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java
  136. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/tabhud/TabHud.java
  137. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/tabhud/screenbuilder/ScreenMaster.java
  138. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/waypoint/FairySouls.java
  139. +84 −0 src/main/java/de/hysky/skyblocker/skyblock/waypoint/IndividualWaypoint.java
  140. +134 −45 src/main/java/de/hysky/skyblocker/skyblock/waypoint/MythologicalRitual.java
  141. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/waypoint/OrderedWaypoints.java
  142. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/waypoint/Relics.java
  143. +2 −0 src/main/java/de/hysky/skyblocker/skyblock/waypoint/Waypoints.java
  144. +13 −13 src/main/java/de/hysky/skyblocker/utils/ApiAuthentication.java
  145. +2 −0 src/main/java/de/hysky/skyblocker/utils/ApiUtils.java
  146. +1 −1 src/main/java/de/hysky/skyblocker/utils/ItemUtils.java
  147. +2 −0 src/main/java/de/hysky/skyblocker/utils/NEURepoManager.java
  148. +18 −10 src/main/java/de/hysky/skyblocker/utils/RegexUtils.java
  149. +28 −0 src/main/java/de/hysky/skyblocker/utils/SkyblockTime.java
  150. +19 −8 src/main/java/de/hysky/skyblocker/utils/SlayerUtils.java
  151. +3 −19 src/main/java/de/hysky/skyblocker/utils/Utils.java
  152. +2 −0 src/main/java/de/hysky/skyblocker/utils/chat/ChatMessageListener.java
  153. +2 −2 src/main/java/de/hysky/skyblocker/utils/config/DurationController.java
  154. +7 −3 src/main/java/de/hysky/skyblocker/utils/container/ContainerSolverManager.java
  155. +1 −5 src/main/java/de/hysky/skyblocker/utils/container/RegexContainerMatcher.java
  156. +2 −0 src/main/java/de/hysky/skyblocker/utils/discord/DiscordRPCManager.java
  157. +2 −0 src/main/java/de/hysky/skyblocker/utils/mayor/MayorUtils.java
  158. +2 −0 src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java
  159. +3 −0 src/main/java/de/hysky/skyblocker/utils/render/culling/OcclusionCulling.java
  160. +2 −0 src/main/java/de/hysky/skyblocker/utils/render/title/TitleContainer.java
  161. +12 −7 src/main/java/de/hysky/skyblocker/utils/scheduler/MessageScheduler.java
  162. +3 −1 src/main/java/de/hysky/skyblocker/utils/waypoint/NamedWaypoint.java
  163. +10 −12 src/main/java/de/hysky/skyblocker/utils/ws/SkyblockerWebSocket.java
  164. +1 −1 src/main/java/de/hysky/skyblocker/utils/ws/WsMessageHandler.java
  165. +4 −2 src/main/java/de/hysky/skyblocker/utils/ws/WsStateManager.java
  166. +35 −13 src/main/resources/assets/skyblocker/lang/en_us.json
  167. BIN src/main/resources/assets/skyblocker/textures/gui/profile_viewer/vampire.png
  168. BIN src/main/resources/assets/skyblocker/textures/gui/sprites/bars/icons/speed.png
  169. +5 −1 src/main/resources/resourcepacks/recolored_dungeon_items/pack.mcmeta
  170. +2 −1 src/main/resources/skyblocker.mixins.json
  171. +4 −0 src/test/java/de/hysky/skyblocker/utils/ItemUtilsTest.java
28 changes: 28 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
tab_width = 4

[*.gradle]
indent_style = tab

[*.java]
indent_style = tab
max_line_length = off
ij_continuation_indent_size = 8 # IntelliJ default
# Wrapping and Braces
ij_java_keep_simple_blocks_in_one_line = true
ij_java_keep_simple_classes_in_one_line = true
ij_java_keep_simple_lambdas_in_one_line = true
ij_java_keep_simple_methods_in_one_line = true

[*.{json,properties}]
indent_style = space
indent_size = 2

[.editorconfig]
indent_style = space
indent_size = 4
3 changes: 2 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ plugins {
id 'fabric-loom' version '1.7-SNAPSHOT'
id 'maven-publish'
id "me.modmuss50.mod-publish-plugin" version "0.7.2"
id "de.hysky.skyblocker.annotation-processor"
}

version = "${project.mod_version}+${project.minecraft_version}"
Expand Down Expand Up @@ -226,7 +227,7 @@ java {

jar {
from("LICENSE") {
rename { "${it}_${base.archivesName.get()}"}
rename { "${it}_${base.archivesName.get()}" }
}
}

Expand Down
22 changes: 22 additions & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
plugins {
id 'java-gradle-plugin'
}

repositories {
mavenCentral()
}

dependencies {
implementation "org.ow2.asm:asm:${project.asm_version}"
implementation "org.ow2.asm:asm-tree:${project.asm_version}"
}

gradlePlugin {
plugins {
simplePlugin {
id = 'de.hysky.skyblocker.annotation-processor'
// The plugin entry point could be changed to a different class that then appropriately calls the different processors when there's more than one.
implementationClass = 'de.hysky.skyblocker.init.InitProcessor'
}
}
}
1 change: 1 addition & 0 deletions buildSrc/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
asm_version=9.7
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package de.hysky.skyblocker.init;

import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.MethodNode;

import java.util.List;

public class InitInjectingClassVisitor extends ClassVisitor {
private final List<InitProcessor.MethodReference> methodSignatures;

public InitInjectingClassVisitor(ClassVisitor classVisitor, List<InitProcessor.MethodReference> methodSignatures) {
super(Opcodes.ASM9, classVisitor);
this.methodSignatures = methodSignatures;
}

@Override
public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) {
MethodVisitor methodVisitor = super.visitMethod(access, name, descriptor, signature, exceptions);

// Limit replacing to the init method which is private, static, named init, has no args, and has a void return type
if ((access & Opcodes.ACC_PRIVATE) != 0 && (access & Opcodes.ACC_STATIC) != 0 && name.equals("init") && descriptor.equals("()V")) {
// Method node that we will overwrite the init method with
MethodNode methodNode = new MethodNode(Opcodes.ASM9, access, name, descriptor, signature, exceptions);

// Inject calls to each found @Init annotated method
for (InitProcessor.MethodReference methodCall : methodSignatures) {
methodNode.visitMethodInsn(Opcodes.INVOKESTATIC, methodCall.className(), methodCall.methodName(), methodCall.descriptor(), methodCall.itf());
}

// Return from the method
methodNode.visitInsn(Opcodes.RETURN);

// Apply our new method node to the visitor to replace the original one
methodNode.accept(methodVisitor);
}

return methodVisitor;
}
}
112 changes: 112 additions & 0 deletions buildSrc/src/main/java/de/hysky/skyblocker/init/InitProcessor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package de.hysky.skyblocker.init;

import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.tasks.compile.JavaCompile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.*;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

@SuppressWarnings("unused")
public abstract class InitProcessor implements Plugin<Project> {
@Override
public void apply(Project project) {
// https://docs.gradle.org/current/userguide/task_configuration_avoidance.html
// This only configures the `compileJava` task and not other `JavaCompile` tasks such as `compileTestJava`. https://stackoverflow.com/a/77047012
project.getTasks().withType(JavaCompile.class).named("compileJava").get().doLast(task -> {
long start = System.currentTimeMillis();
File classesDir = ((JavaCompile) task).getDestinationDirectory().get().getAsFile();
Map<MethodReference, Integer> methodSignatures = new HashMap<>();

//Find all methods with the @Init annotation
findInitMethods(classesDir, methodSignatures);

//Sort the methods by their priority. It's also converted to a list because the priority values are useless from here on
List<MethodReference> sortedMethodSignatures = methodSignatures.entrySet()
.stream()
.sorted(Map.Entry.<MethodReference, Integer>comparingByValue().thenComparing(entry -> entry.getKey().className()))
.map(Map.Entry::getKey)
.toList();

//Inject calls to the @Init annotated methods in the SkyblockerMod class
injectInitCalls(classesDir, sortedMethodSignatures);

System.out.println("Injecting init methods took: " + (System.currentTimeMillis() - start) + "ms");
});
}

public void findInitMethods(@NotNull File directory, Map<MethodReference, Integer> methodSignatures) {
try {
Files.walkFileTree(directory.toPath(), new SimpleFileVisitor<>() {
@Override
public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
if (!path.toString().endsWith(".class")) return FileVisitResult.CONTINUE;
try (InputStream inputStream = Files.newInputStream(path)) {
ClassReader classReader = new ClassReader(inputStream);
classReader.accept(new InitReadingClassVisitor(classReader, methodSignatures), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
} catch (IOException e) {
e.printStackTrace();
}

return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
}

public void injectInitCalls(File directory, List<MethodReference> methodSignatures) {
Path mainClassFile = Objects.requireNonNull(findMainClass(directory), "SkyblockerMod class wasn't found :(").toPath();

try (InputStream inputStream = Files.newInputStream(mainClassFile)) {
ClassReader classReader = new ClassReader(inputStream);
ClassWriter classWriter = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
classReader.accept(new InitInjectingClassVisitor(classWriter, methodSignatures), 0);
try (OutputStream outputStream = Files.newOutputStream(mainClassFile)) {
outputStream.write(classWriter.toByteArray());
}
} catch (Exception e) {
e.printStackTrace();
}
}

// Find the main SkyblockerMod class
@Nullable
public File findMainClass(@NotNull File directory) {
if (!directory.isDirectory()) throw new IllegalArgumentException("Not a directory");
for (File file : Objects.requireNonNull(directory.listFiles())) {
if (file.isDirectory()) {
File foundFile = findMainClass(file);

if (foundFile != null) return foundFile;
} else if (file.getName().equals("SkyblockerMod.class")) {
return file;
}
}

return null;
}

/**
* @param className the class name (e.g. de/hysky/skyblocker/skyblock/ChestValue)
* @param methodName the method's name (e.g. init)
* @param descriptor the method's descriptor (only ()V for now)
* @param itf whether the target class is an {@code interface} or not
*/
public record MethodReference(String className, String methodName, String descriptor, boolean itf) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package de.hysky.skyblocker.init;

import org.jetbrains.annotations.NotNull;
import org.objectweb.asm.*;

import java.util.Map;

public class InitReadingClassVisitor extends ClassVisitor {
private final Map<InitProcessor.MethodReference, Integer> methodSignatures;
private final ClassReader classReader;

public InitReadingClassVisitor(ClassReader classReader, Map<InitProcessor.MethodReference, Integer> methodSignatures) {
super(Opcodes.ASM9);
this.classReader = classReader;
this.methodSignatures = methodSignatures;
}

@Override
public MethodVisitor visitMethod(int access, String methodName, String descriptor, String signature, String[] exceptions) {
return new MethodVisitor(Opcodes.ASM9) {
@Override
public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
//This method visitor checks all methods and only acts upon those with the Init annotation.
//This lets us warn the user about invalid init methods and misuse of the annotation
if (!desc.equals("Lde/hysky/skyblocker/annotations/Init;")) return super.visitAnnotation(desc, visible);

//Delegates adding the method call to the map to the InitAnnotationVisitor since we don't have a value to put in the map here
return new InitAnnotationVisitor(methodSignatures, getMethodCall());
}

private @NotNull InitProcessor.MethodReference getMethodCall() {
String className = classReader.getClassName();
String methodCallString = className + "." + methodName;
if ((access & Opcodes.ACC_PUBLIC) == 0) throw new IllegalStateException(methodCallString + ": Initializer methods must be public");
if ((access & Opcodes.ACC_STATIC) == 0) throw new IllegalStateException(methodCallString + ": Initializer methods must be static");
if (!descriptor.equals("()V")) throw new IllegalStateException(methodCallString + ": Initializer methods must have no args and a void return type");

//Interface static methods need special handling, so we add a special marker for that
boolean itf = (classReader.getAccess() & Opcodes.ACC_INTERFACE) != 0;

return new InitProcessor.MethodReference(className, methodName, descriptor, itf);
}
};
}

static class InitAnnotationVisitor extends AnnotationVisitor {
private final Map<InitProcessor.MethodReference, Integer> methodSignatures;
private final InitProcessor.MethodReference methodCall;

protected InitAnnotationVisitor(Map<InitProcessor.MethodReference, Integer> methodSignatures, InitProcessor.MethodReference methodCall) {
super(Opcodes.ASM9);
this.methodSignatures = methodSignatures;
this.methodCall = methodCall;
}

@Override
public void visitEnd() {
//Annotations that use the default value for the priority field will not be called by the visit method, so we have to handle them here.
methodSignatures.putIfAbsent(methodCall, 0);
super.visitEnd();
}

@Override
public void visit(String name, Object value) {
if (name.equals("priority")) {
methodSignatures.put(methodCall, (int) value);
}
super.visit(name, value);
}
}
}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ occlusionculling_version = 0.0.8-SNAPSHOT
## neu repoparser (https://repo.nea.moe/#/releases/moe/nea/neurepoparser/)
repoparser_version = 1.6.0
## Networth Calculator (https://github.com/AzureAaron/networth-calculator)
networth_calculator_version = 1.0.2
networth_calculator_version = 1.0.5
## Legacy Item DFU (https://github.com/AzureAaron/legacy-item-dfu)
legacy_item_dfu_version = 1.0.0+1.21.1
legacy_item_dfu_version = 1.0.1+1.21.1

# Other Libraries
## JGit (https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit)
Expand Down
Loading