diff --git a/config/detekt/detekt.yml b/config/detekt/detekt.yml index 037b60d..0232507 100644 --- a/config/detekt/detekt.yml +++ b/config/detekt/detekt.yml @@ -54,7 +54,11 @@ style: active: true maxJumpCount: 3 WildcardImport: - active: false + active: true + excludeImports: + - 'org.lwjgl.vulkan.*' + - 'io.github.humbleui.skija.*' + - 'net.minecraft.world.level.block.*' ForbiddenComment: active: false UnusedPrivateProperty: diff --git a/src/main/java/org/cobalt/mixin/client/MinecraftMixin.java b/src/main/java/org/cobalt/mixin/client/MinecraftMixin.java index 81a44a8..4b379ad 100644 --- a/src/main/java/org/cobalt/mixin/client/MinecraftMixin.java +++ b/src/main/java/org/cobalt/mixin/client/MinecraftMixin.java @@ -11,7 +11,7 @@ import org.cobalt.event.impl.TickEvent; import org.cobalt.module.ModuleManager; import org.cobalt.util.config.SettingContainer; -import org.cobalt.util.helper.Multithreading; +import org.cobalt.util.scheduling.Multithreading; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; diff --git a/src/main/java/org/cobalt/mixin/client/MouseHandlerMixin.java b/src/main/java/org/cobalt/mixin/client/MouseHandlerMixin.java index a91fe3b..a293cb3 100644 --- a/src/main/java/org/cobalt/mixin/client/MouseHandlerMixin.java +++ b/src/main/java/org/cobalt/mixin/client/MouseHandlerMixin.java @@ -5,10 +5,10 @@ import org.cobalt.event.EventBus; import org.cobalt.event.impl.MouseEvent; import org.cobalt.event.impl.MouseScrollEvent; -import org.cobalt.util.MouseAction; -import org.cobalt.util.MouseButton; -import org.cobalt.util.MouseMode; -import org.cobalt.util.MouseUtils; +import org.cobalt.util.input.Mouse; +import org.cobalt.util.input.MouseAction; +import org.cobalt.util.input.MouseButton; +import org.cobalt.util.input.MouseMode; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; @@ -74,14 +74,14 @@ private void onMouseScroll(long handle, double xoffset, double yoffset, Callback @Inject(method = "turnPlayer", at = @At("HEAD"), cancellable = true) private void onUpdateMouse(CallbackInfo callbackInfo) { - if (MouseUtils.getMouseMode() == MouseMode.LOCK_MOUSE) { + if (Mouse.getMouseMode() == MouseMode.LOCK_MOUSE) { callbackInfo.cancel(); } } @Inject(method = "isMouseGrabbed", at = @At("HEAD"), cancellable = true) private void onIsCursorLocked(CallbackInfoReturnable callbackInfoReturnable) { - if (MouseUtils.getMouseMode() == MouseMode.UNGRAB_MOUSE) { + if (Mouse.getMouseMode() == MouseMode.UNGRAB_MOUSE) { if (this.mouseGrabbed) { this.releaseMouse(); } @@ -92,7 +92,7 @@ private void onIsCursorLocked(CallbackInfoReturnable callbackInfoReturn @Inject(method = "grabMouse", at = @At("HEAD"), cancellable = true) private void onLockCursor(CallbackInfo callbackInfo) { - if (MouseUtils.getMouseMode() == MouseMode.UNGRAB_MOUSE) { + if (Mouse.getMouseMode() == MouseMode.UNGRAB_MOUSE) { callbackInfo.cancel(); } } diff --git a/src/main/java/org/cobalt/mixin/gui/FontMixin.java b/src/main/java/org/cobalt/mixin/gui/FontMixin.java index 141c3cf..99316ac 100644 --- a/src/main/java/org/cobalt/mixin/gui/FontMixin.java +++ b/src/main/java/org/cobalt/mixin/gui/FontMixin.java @@ -8,7 +8,7 @@ import net.minecraft.network.chat.Style; import net.minecraft.util.FormattedCharSequence; import org.cobalt.module.impl.misc.NickHider; -import org.cobalt.util.PlayerUtils; +import org.cobalt.util.client.PlayerUtils; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; diff --git a/src/main/kotlin/org/cobalt/Cobalt.kt b/src/main/kotlin/org/cobalt/Cobalt.kt index b8865f2..91db2af 100644 --- a/src/main/kotlin/org/cobalt/Cobalt.kt +++ b/src/main/kotlin/org/cobalt/Cobalt.kt @@ -15,7 +15,7 @@ import org.cobalt.event.EventBus import org.cobalt.event.impl.WorldEvent import org.cobalt.module.ModuleManager import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.skia.SkiaPIP +import org.cobalt.util.render.skia.SkiaPIP import org.slf4j.LoggerFactory object Cobalt : ClientModInitializer { diff --git a/src/main/kotlin/org/cobalt/command/Command.kt b/src/main/kotlin/org/cobalt/command/Command.kt index c1451fd..765f538 100644 --- a/src/main/kotlin/org/cobalt/command/Command.kt +++ b/src/main/kotlin/org/cobalt/command/Command.kt @@ -1,6 +1,11 @@ package org.cobalt.command -import com.mojang.brigadier.arguments.* +import com.mojang.brigadier.arguments.ArgumentType +import com.mojang.brigadier.arguments.BoolArgumentType +import com.mojang.brigadier.arguments.DoubleArgumentType +import com.mojang.brigadier.arguments.FloatArgumentType +import com.mojang.brigadier.arguments.IntegerArgumentType +import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.builder.LiteralArgumentBuilder import com.mojang.brigadier.builder.RequiredArgumentBuilder import com.mojang.brigadier.context.CommandContext diff --git a/src/main/kotlin/org/cobalt/command/CommandManager.kt b/src/main/kotlin/org/cobalt/command/CommandManager.kt index d72607e..f6dc80a 100644 --- a/src/main/kotlin/org/cobalt/command/CommandManager.kt +++ b/src/main/kotlin/org/cobalt/command/CommandManager.kt @@ -5,7 +5,7 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException import net.minecraft.client.multiplayer.ClientSuggestionProvider import org.cobalt.Cobalt.minecraft import org.cobalt.command.impl.MainCommand -import org.cobalt.util.ChatUtils +import org.cobalt.util.chat.ChatUtils object CommandManager { diff --git a/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt b/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt index cf0be4c..570c428 100644 --- a/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt +++ b/src/main/kotlin/org/cobalt/command/impl/MainCommand.kt @@ -1,6 +1,5 @@ package org.cobalt.command.impl -import kotlin.time.Duration.Companion.milliseconds import org.cobalt.Cobalt.minecraft import org.cobalt.command.Command import org.cobalt.command.annotation.DefaultHandler @@ -9,11 +8,9 @@ import org.cobalt.pathfinder.PathConfig import org.cobalt.pathfinder.PathExecutor import org.cobalt.pathfinder.calculate.PathMode import org.cobalt.pathfinder.goal.GoalBlock -import org.cobalt.ui.notification.NotificationManager import org.cobalt.ui.screen.ConfigScreen import org.cobalt.ui.screen.HudEditorScreen -import org.cobalt.util.helper.Multithreading -import org.cobalt.util.helper.TickScheduler +import org.cobalt.util.scheduling.TickScheduler object MainCommand : Command(name = "cobalt", aliases = listOf("cb")) { @@ -33,31 +30,20 @@ object MainCommand : Command(name = "cobalt", aliases = listOf("cb")) { } } - @SubCommand - fun testNotif() { - Multithreading.runAsync { - - NotificationManager.queue("Hi", "", 2000.milliseconds) - Thread.sleep(750) - NotificationManager.queue("Hi", "Hello", 2000.milliseconds) - Thread.sleep(750) - NotificationManager.queue( - "Hi", - "HeASDASDHOUASHDOUASHDUOAHSDOUAHSDOUHASOUDHASDlloHeASDASDHOUASHDOUASHDUOAHSDOUAHSDOUHASOUDHASDlloHeASDASDHOUASHDOUASHDUOAHSDOUAHSDOUHASOUDHASDlloHeASDASDHOUASHDOUASHDUOAHSDOUAHSDOUHASOUDHASDlloHeASDASDHOUASHDOUASHDUOAHSDOUAHSDOUHASOUDHASDllo", - 2000.milliseconds - ) - } - } - @SubCommand fun goTo(x: Int, y: Int, z: Int, fly: Boolean) { - val mode = if (fly) PathMode.FLY else PathMode.WALK + val pathMode = if (fly) PathMode.FLY else PathMode.WALK val config = PathConfig( goal = GoalBlock(x, y, z), - movements = mode.movements + mode = pathMode ) PathExecutor.goTo(config) } + @SubCommand + fun stopPathfinder() { + PathExecutor.stop() + } + } diff --git a/src/main/kotlin/org/cobalt/dsl/Block.kt b/src/main/kotlin/org/cobalt/dsl/Block.kt deleted file mode 100644 index 152afad..0000000 --- a/src/main/kotlin/org/cobalt/dsl/Block.kt +++ /dev/null @@ -1,20 +0,0 @@ -package org.cobalt.dsl - -import net.minecraft.core.BlockPos -import net.minecraft.world.phys.AABB -import net.minecraft.world.phys.Vec3 - -fun BlockPos.centerVec(): Vec3 { - return Vec3(x + 0.5, y + 0.5, z + 0.5) -} - -fun Vec3.smallBox(): AABB { - return AABB( - x - 0.25, - y - 0.25, - z - 0.25, - x + 0.25, - y + 0.25, - z + 0.25 - ) -} diff --git a/src/main/kotlin/org/cobalt/event/impl/MouseEvent.kt b/src/main/kotlin/org/cobalt/event/impl/MouseEvent.kt index 34069b3..30505fe 100644 --- a/src/main/kotlin/org/cobalt/event/impl/MouseEvent.kt +++ b/src/main/kotlin/org/cobalt/event/impl/MouseEvent.kt @@ -1,8 +1,8 @@ package org.cobalt.event.impl import org.cobalt.event.Event -import org.cobalt.util.MouseAction -import org.cobalt.util.MouseButton +import org.cobalt.util.input.MouseAction +import org.cobalt.util.input.MouseButton class MouseEvent( val button: MouseButton, diff --git a/src/main/kotlin/org/cobalt/module/ModuleManager.kt b/src/main/kotlin/org/cobalt/module/ModuleManager.kt index 157619c..ac287b1 100644 --- a/src/main/kotlin/org/cobalt/module/ModuleManager.kt +++ b/src/main/kotlin/org/cobalt/module/ModuleManager.kt @@ -7,17 +7,22 @@ import org.cobalt.event.EventBus import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.RenderEvent import org.cobalt.module.impl.combat.AutoClicker -import org.cobalt.module.impl.misc.* +import org.cobalt.module.impl.misc.AutoHarp +import org.cobalt.module.impl.misc.AutoSprint +import org.cobalt.module.impl.misc.Debug +import org.cobalt.module.impl.misc.DiscordRPC +import org.cobalt.module.impl.misc.NickHider +import org.cobalt.module.impl.misc.Rotations import org.cobalt.module.impl.skills.Fishing import org.cobalt.module.impl.visual.PerformanceHUD import org.cobalt.module.type.RenderableModule import org.cobalt.module.type.Script import org.cobalt.ui.screen.HudEditorScreen -import org.cobalt.util.ChatUtils -import org.cobalt.util.WindowUtils.scaleX -import org.cobalt.util.WindowUtils.scaleY -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.SkiaPIP +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.client.WindowUtils.scaleX +import org.cobalt.util.client.WindowUtils.scaleY +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.SkiaPIP object ModuleManager { @@ -132,19 +137,19 @@ object ModuleManager { modules.filterIsInstance() .filter { module -> module.enabled } .forEach { module -> - Skia.push() + SkiaRenderer.push() val renderX = module.xPos * scaleX val renderY = module.yPos * scaleY val finalScale = module.scale * scaleY - Skia.translate(renderX, renderY) - Skia.scale(finalScale, finalScale) - Skia.translate(-module.xPos, -module.yPos) + SkiaRenderer.translate(renderX, renderY) + SkiaRenderer.scale(finalScale, finalScale) + SkiaRenderer.translate(-module.xPos, -module.yPos) module.renderComponent() - Skia.pop() + SkiaRenderer.pop() } } } diff --git a/src/main/kotlin/org/cobalt/module/impl/combat/AutoClicker.kt b/src/main/kotlin/org/cobalt/module/impl/combat/AutoClicker.kt index bf73e27..2cf583a 100644 --- a/src/main/kotlin/org/cobalt/module/impl/combat/AutoClicker.kt +++ b/src/main/kotlin/org/cobalt/module/impl/combat/AutoClicker.kt @@ -7,10 +7,14 @@ import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.WorldEvent import org.cobalt.module.Module import org.cobalt.module.ModuleCategory -import org.cobalt.ui.component.setting.impl.* -import org.cobalt.util.KeybindUtils -import org.cobalt.util.MouseUtils -import org.cobalt.util.helper.Clock +import org.cobalt.ui.component.setting.impl.CheckboxSetting +import org.cobalt.ui.component.setting.impl.KeyBindSetting +import org.cobalt.ui.component.setting.impl.ModeSetting +import org.cobalt.ui.component.setting.impl.SliderSetting +import org.cobalt.ui.component.setting.impl.TextSetting +import org.cobalt.util.input.Keyboard +import org.cobalt.util.input.Mouse +import org.cobalt.util.scheduling.Clock object AutoClicker : Module( name = "AutoClicker", @@ -80,18 +84,18 @@ object AutoClicker : Module( if ( leftClickDelay.passed() && - KeybindUtils.isKeyDown(leftClickKeybind) && + Keyboard.isKeyDown(leftClickKeybind) && canLeftClick() ) { - MouseUtils.leftClick() + Mouse.leftClick() leftClickDelay.schedule(nextDelay(leftClickCps)) } if ( rightClickDelay.passed() && - KeybindUtils.isKeyDown(rightClickKeybind) + Keyboard.isKeyDown(rightClickKeybind) ) { - KeybindUtils.press(minecraft.options.keyUse) + Keyboard.press(minecraft.options.keyUse) rightClickDelay.schedule(nextDelay(rightClickCps)) } } diff --git a/src/main/kotlin/org/cobalt/module/impl/misc/AutoHarp.kt b/src/main/kotlin/org/cobalt/module/impl/misc/AutoHarp.kt index da2a2a0..834f99b 100644 --- a/src/main/kotlin/org/cobalt/module/impl/misc/AutoHarp.kt +++ b/src/main/kotlin/org/cobalt/module/impl/misc/AutoHarp.kt @@ -8,8 +8,8 @@ import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.TickEvent import org.cobalt.module.Module import org.cobalt.module.ModuleCategory -import org.cobalt.util.InventoryUtils -import org.cobalt.util.MouseButton +import org.cobalt.util.input.MouseButton +import org.cobalt.util.inventory.InventoryUtils object AutoHarp : Module( name = "AutoHarp", diff --git a/src/main/kotlin/org/cobalt/module/impl/misc/Rotations.kt b/src/main/kotlin/org/cobalt/module/impl/misc/Rotations.kt index e1ae809..da85d62 100644 --- a/src/main/kotlin/org/cobalt/module/impl/misc/Rotations.kt +++ b/src/main/kotlin/org/cobalt/module/impl/misc/Rotations.kt @@ -10,12 +10,12 @@ import org.cobalt.event.impl.WorldEvent import org.cobalt.module.Module import org.cobalt.module.ModuleCategory import org.cobalt.ui.component.setting.impl.SliderSetting -import org.cobalt.util.MouseMode -import org.cobalt.util.MouseUtils -import org.cobalt.util.PlayerUtils -import org.cobalt.util.RotationUtils -import org.cobalt.util.rotation.Rotation -import org.cobalt.util.rotation.RotationTarget +import org.cobalt.util.client.PlayerUtils +import org.cobalt.util.input.Mouse +import org.cobalt.util.input.MouseMode +import org.cobalt.util.rotation.RotationMath +import org.cobalt.util.rotation.data.Rotation +import org.cobalt.util.rotation.data.RotationTarget object Rotations : Module( name = "Rotations", @@ -91,8 +91,8 @@ object Rotations : Module( lastFrameMs = System.currentTimeMillis() running = true - if (MouseUtils.mouseMode == MouseMode.DEFAULT) { - MouseUtils.mouseMode = MouseMode.LOCK_MOUSE + if (Mouse.mouseMode == MouseMode.DEFAULT) { + Mouse.mouseMode = MouseMode.LOCK_MOUSE returnMouseMode = true } } @@ -102,8 +102,8 @@ object Rotations : Module( target = rotationTarget running = true - if (MouseUtils.mouseMode == MouseMode.DEFAULT) { - MouseUtils.mouseMode = MouseMode.LOCK_MOUSE + if (Mouse.mouseMode == MouseMode.DEFAULT) { + Mouse.mouseMode = MouseMode.LOCK_MOUSE returnMouseMode = true } } @@ -113,7 +113,7 @@ object Rotations : Module( target = null if (returnMouseMode) { - MouseUtils.mouseMode = MouseMode.DEFAULT + Mouse.mouseMode = MouseMode.DEFAULT returnMouseMode = false } } @@ -140,7 +140,7 @@ object Rotations : Module( } private fun handleRotate(current: Rotation, target: Rotation, deltaTime: Float) { - if (RotationUtils.approximatelyEquals(current, target, endTolerance.toFloat())) { + if (RotationMath.approximatelyEquals(current, target, endTolerance.toFloat())) { stop() return } @@ -157,12 +157,12 @@ object Rotations : Module( } private fun handleTrack(current: Rotation, target: Rotation, deltaTime: Float) { - if (RotationUtils.approximatelyEquals(current, target, endTolerance.toFloat())) { + if (RotationMath.approximatelyEquals(current, target, endTolerance.toFloat())) { return } - var needYaw = RotationUtils.angleDifference(target.yaw, current.yaw) - var needPitch = RotationUtils.angleDifference(target.pitch, current.pitch) + var needYaw = RotationMath.angleDifference(target.yaw, current.yaw) + var needPitch = RotationMath.angleDifference(target.pitch, current.pitch) val distance = abs(needYaw) + abs(needPitch) val randomFactor = (0.8f + Random.nextFloat() * 0.4f) diff --git a/src/main/kotlin/org/cobalt/module/impl/skills/Fishing.kt b/src/main/kotlin/org/cobalt/module/impl/skills/Fishing.kt index 004b67c..202da34 100644 --- a/src/main/kotlin/org/cobalt/module/impl/skills/Fishing.kt +++ b/src/main/kotlin/org/cobalt/module/impl/skills/Fishing.kt @@ -13,8 +13,12 @@ import org.cobalt.module.impl.misc.Rotations import org.cobalt.module.type.Script import org.cobalt.ui.component.setting.impl.TextSetting import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.* -import org.cobalt.util.helper.Clock +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.input.Mouse +import org.cobalt.util.inventory.InventoryUtils +import org.cobalt.util.render.GizmoRenderer +import org.cobalt.util.rotation.RotationMath +import org.cobalt.util.scheduling.Clock object Fishing : Script( name = "Fishing", @@ -85,7 +89,7 @@ object Fishing : Script( State.CAST_ROD -> { if (minecraft.player?.fishing == null) { - MouseUtils.rightClick() + Mouse.rightClick() } state = State.WAIT_FOR_CATCH @@ -98,7 +102,7 @@ object Fishing : Script( Random.nextDouble(-0.25, 0.25), Random.nextDouble(-0.25, 0.25) )?.let { - Rotations.start(RotationUtils.getRotation(it)) + Rotations.start(RotationMath.getRotation(it)) } antiAfkDelay.schedule(Random.nextLong(10_000, 15_000)) @@ -113,7 +117,7 @@ object Fishing : Script( } State.REEL_IN -> { - MouseUtils.rightClick() + Mouse.rightClick() delayClock.schedule(Random.nextLong(100, 250)) state = State.CAST_ROD } @@ -127,7 +131,7 @@ object Fishing : Script( } lookPos?.let { - WorldRenderUtils.drawBox( + GizmoRenderer.drawBox( AABB( it.x - 0.25, it.y - 0.25, diff --git a/src/main/kotlin/org/cobalt/module/impl/visual/PerformanceHUD.kt b/src/main/kotlin/org/cobalt/module/impl/visual/PerformanceHUD.kt index 345488d..375bc66 100644 --- a/src/main/kotlin/org/cobalt/module/impl/visual/PerformanceHUD.kt +++ b/src/main/kotlin/org/cobalt/module/impl/visual/PerformanceHUD.kt @@ -3,8 +3,8 @@ package org.cobalt.module.impl.visual import kotlin.math.roundToInt import org.cobalt.module.ModuleCategory import org.cobalt.module.type.RenderableModule -import org.cobalt.util.ServerUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.server.ConnectionTracker object PerformanceHUD : RenderableModule( name = "PerformanceHUD", @@ -20,8 +20,8 @@ object PerformanceHUD : RenderableModule( width += PADDING + 2 * TEXT_SPACING } - width += Skia.textWidth(Skia.boldFont, stat.value, FONT_SIZE) + TEXT_SPACING - width += Skia.textWidth(Skia.boldFont, stat.unit, FONT_SIZE) + width += SkiaRenderer.textWidth(SkiaRenderer.boldFont, stat.value, FONT_SIZE) + TEXT_SPACING + width += SkiaRenderer.textWidth(SkiaRenderer.boldFont, stat.unit, FONT_SIZE) } return width @@ -31,7 +31,7 @@ object PerformanceHUD : RenderableModule( get() = 50f override fun renderComponent() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.backgroundPrimary ) @@ -45,7 +45,7 @@ object PerformanceHUD : RenderableModule( val dividerX = currentX + DIVIDER_GAP val midY = yPos + height / 2 - Skia.line( + SkiaRenderer.line( dividerX, midY - DIVIDER_HALF_HEIGHT, dividerX, midY + DIVIDER_HALF_HEIGHT, 2f, theme.border @@ -56,30 +56,30 @@ object PerformanceHUD : RenderableModule( var textX = currentX - Skia.text( - Skia.boldFont, + SkiaRenderer.text( + SkiaRenderer.boldFont, stat.value, textX, textY, FONT_SIZE, theme.textPrimary ) - textX += Skia.textWidth(Skia.boldFont, stat.value, FONT_SIZE) + TEXT_SPACING + textX += SkiaRenderer.textWidth(SkiaRenderer.boldFont, stat.value, FONT_SIZE) + TEXT_SPACING - Skia.text( - Skia.boldFont, + SkiaRenderer.text( + SkiaRenderer.boldFont, stat.unit, textX, textY, FONT_SIZE, theme.textDisabled ) - currentX = textX + Skia.textWidth(Skia.boldFont, stat.unit, FONT_SIZE) + currentX = textX + SkiaRenderer.textWidth(SkiaRenderer.boldFont, stat.unit, FONT_SIZE) } } private fun getStats() = listOf( Stat(minecraft.fps.toString(), "FPS"), - Stat(ServerUtils.averageTps.roundToInt().toString(), "TPS"), - Stat(ServerUtils.averagePing.toString(), "MS"), + Stat(ConnectionTracker.averageTps.roundToInt().toString(), "TPS"), + Stat(ConnectionTracker.averagePing.toString(), "MS"), ) private const val PADDING = 25f diff --git a/src/main/kotlin/org/cobalt/module/type/Script.kt b/src/main/kotlin/org/cobalt/module/type/Script.kt index d1540f4..9451e55 100644 --- a/src/main/kotlin/org/cobalt/module/type/Script.kt +++ b/src/main/kotlin/org/cobalt/module/type/Script.kt @@ -2,7 +2,7 @@ package org.cobalt.module.type import org.cobalt.module.Module import org.cobalt.module.ModuleCategory -import org.cobalt.util.ChatUtils +import org.cobalt.util.chat.ChatUtils abstract class Script( name: String, diff --git a/src/main/kotlin/org/cobalt/pathfinder/PathConfig.kt b/src/main/kotlin/org/cobalt/pathfinder/PathConfig.kt index de6a840..6319b04 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/PathConfig.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/PathConfig.kt @@ -2,18 +2,15 @@ package org.cobalt.pathfinder import org.cobalt.pathfinder.calculate.PathMode import org.cobalt.pathfinder.goal.Goal -import org.cobalt.pathfinder.movement.Movement class PathConfig( val goal: Goal, - val movements: Array = PathMode.WALK.movements, - val shouldSprint: Boolean = true, - val preferShifting: Boolean = false, + val mode: PathMode = PathMode.WALK, val returnBestNode: Boolean = false, + val maxCalculationTime: Long = 10_000_000_000L, ) { - val useFlyMovement = movements.any { - it.type == Movement.Type.FLY - } + val allowFly: Boolean = + mode == PathMode.FLY } diff --git a/src/main/kotlin/org/cobalt/pathfinder/PathExecutor.kt b/src/main/kotlin/org/cobalt/pathfinder/PathExecutor.kt index cdce036..f223be7 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/PathExecutor.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/PathExecutor.kt @@ -1,23 +1,18 @@ package org.cobalt.pathfinder -import java.awt.Color import net.minecraft.client.player.KeyboardInput import org.cobalt.Cobalt.minecraft -import org.cobalt.dsl.centerVec -import org.cobalt.dsl.smallBox import org.cobalt.event.EventBus import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.TickEvent import org.cobalt.event.impl.WorldEvent -import org.cobalt.module.impl.misc.Debug import org.cobalt.pathfinder.calculate.Path +import org.cobalt.pathfinder.helper.PlayerInput import org.cobalt.pathfinder.state.ExecutorState -import org.cobalt.pathfinder.state.impl.CalculatingState -import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.ChatUtils -import org.cobalt.util.MessageType -import org.cobalt.util.PlayerUtils -import org.cobalt.util.WorldRenderUtils +import org.cobalt.pathfinder.state.calculation.CalculatingState +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.chat.MessageType +import org.cobalt.util.client.PlayerUtils object PathExecutor { @@ -28,29 +23,38 @@ object PathExecutor { var pathIndex: Int = 0 var running = false - var pathInput = PathInput() + var playerInput = PlayerInput() init { EventBus.register(this) } fun goTo(config: PathConfig) { - stop() + val player = minecraft.player ?: run { + ChatUtils.sendSystemMessage( + "Tried running pathfinder, but minecraft.player is null!", + MessageType.DEBUG + ) - if (config.useFlyMovement && !PlayerUtils.canFly) { - ChatUtils.sendSystemMessage("Invalid path config, since player cannot fly!") return } + if (running) { + ChatUtils.sendSystemMessage( + "Stopping current pathfinder because a new one started.", + MessageType.DEBUG + ) - val player = minecraft.player + stop() + } - if (player != null) { - player.input = pathInput - } else { + if (config.allowFly && !PlayerUtils.canFly) { + ChatUtils.sendSystemMessage("Invalid path config, since player cannot fly!") return } + player.input = playerInput + this.config = config this.running = true @@ -64,11 +68,10 @@ object PathExecutor { minecraft.player?.let { it.input = KeyboardInput(minecraft.options) }.also { - pathInput.stopMovement() + playerInput.stopMovement() } running = false - config = null path = null pathIndex = 0 @@ -93,7 +96,7 @@ object PathExecutor { } if (minecraft.gui.screen() != null) { - pathInput.stopMovement() + playerInput.stopMovement() return } @@ -110,42 +113,11 @@ object PathExecutor { return } - state?.onRender() - - if (state is CalculatingState) { - return - } - - val theme = ThemeManager.activeTheme - val nodes = path?.nodes ?: return - val keyNodes = path?.keyNodes ?: return - - val targetNode = nodes[pathIndex].centerVec - val playerPos = PlayerUtils.position.centerVec() - - if (Debug.enabled) { - WorldRenderUtils.drawBox(playerPos.smallBox(), Color.GREEN) - WorldRenderUtils.drawBox(targetNode.smallBox(), Color.RED) + if (state !is CalculatingState) { + PathRenderer.render() } - for (index in keyNodes.indices) { - val node = keyNodes[index] - - WorldRenderUtils.drawBlockPos( - if (node.isFly) node.block else node.blockStandingOn, - color = theme.accentPrimary - ) - - if (index > 0) { - val prev = keyNodes[index - 1] - - WorldRenderUtils.drawLine( - if (prev.isFly) prev.centerVec else prev.topCenterVec, - if (node.isFly) node.centerVec else node.topCenterVec, - theme.accentSecondary - ) - } - } + state?.onRender() } } diff --git a/src/main/kotlin/org/cobalt/pathfinder/PathInput.kt b/src/main/kotlin/org/cobalt/pathfinder/PathInput.kt deleted file mode 100644 index 0a84a6b..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/PathInput.kt +++ /dev/null @@ -1,57 +0,0 @@ -package org.cobalt.pathfinder - -import net.minecraft.client.player.ClientInput -import net.minecraft.world.entity.player.Input -import net.minecraft.world.phys.Vec2 -import org.cobalt.Cobalt.minecraft -import org.cobalt.pathfinder.helper.PlayerInput - -class PathInput : ClientInput() { - - var forward = false - var backward = false - var left = false - var right = false - var jump = false - var shift = false - var sprint = false - - fun applyInput(input: PlayerInput) { - forward = input.forward - backward = input.backward - left = input.left - right = input.right - jump = input.jump - sprint = input.sprint - shift = input.sneak - } - - fun stopMovement() { - applyInput(PlayerInput()) - } - - override fun tick() { - this.keyPresses = Input( - forward, - backward, - left, - right, - jump, - shift, - sprint - ) - - val forwardImpulse = calculateImpulse(forward, backward) - val leftImpulse = calculateImpulse(left, right) - this.moveVector = Vec2(leftImpulse, forwardImpulse).normalized() - } - - private fun calculateImpulse(positive: Boolean, negative: Boolean): Float { - return when { - positive == negative -> 0.0f - positive -> 1.0f - else -> -1.0f - } - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/PathRenderer.kt b/src/main/kotlin/org/cobalt/pathfinder/PathRenderer.kt new file mode 100644 index 0000000..787271f --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/PathRenderer.kt @@ -0,0 +1,46 @@ +package org.cobalt.pathfinder + +import java.awt.Color +import org.cobalt.module.impl.misc.Debug +import org.cobalt.pathfinder.calculate.Path +import org.cobalt.ui.theme.Theme +import org.cobalt.ui.theme.ThemeManager +import org.cobalt.util.block.centerVec +import org.cobalt.util.block.smallBox +import org.cobalt.util.client.PlayerUtils +import org.cobalt.util.render.GizmoRenderer + +object PathRenderer { + + private inline val theme: Theme + get() = ThemeManager.activeTheme + + fun render() { + val path: Path = PathExecutor.path ?: return + + val nodes = path.nodes + val index = PathExecutor.pathIndex + + val targetNode = nodes[index].centerVec + val playerPos = PlayerUtils.position.centerVec() + + if (Debug.enabled) { + GizmoRenderer.drawBox(playerPos.smallBox(), Color.GREEN) + GizmoRenderer.drawBox(targetNode.smallBox(), Color.RED) + } + + for (index in nodes.indices) { + if (index <= 0) continue + + val prev = nodes[index - 1] + val curr = nodes[index + 1] + + GizmoRenderer.drawLine( + prev.centerVec, + curr.centerVec, + theme.accentSecondary + ) + } + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/calculate/Path.kt b/src/main/kotlin/org/cobalt/pathfinder/calculate/Path.kt index 90649c5..f6fe251 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/calculate/Path.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/calculate/Path.kt @@ -17,10 +17,10 @@ data class Path( } val keyNodes = mutableListOf(nodes.first()) - var lastDirection = direction(nodes[0], nodes[1]) + var lastDirection = Direction(nodes[0], nodes[1]) for (i in 2 until nodes.size) { - val currentDirection = direction(nodes[i - 1], nodes[i]) + val currentDirection = Direction(nodes[i - 1], nodes[i]) if (currentDirection != lastDirection) { keyNodes += nodes[i - 1] @@ -32,12 +32,11 @@ data class Path( return keyNodes } - private fun direction(a: PathNode, b: PathNode) = Direction( - (b.x - a.x).coerceIn(-1, 1), - (b.y - a.y).coerceIn(-1, 1), - (b.z - a.z).coerceIn(-1, 1) - ) - - private data class Direction(val dx: Int, val dy: Int, val dz: Int) - + private data class Direction(val dx: Int, val dy: Int, val dz: Int) { + constructor(a: PathNode, b: PathNode) : this( + (b.x - a.x).coerceIn(-1, 1), + (b.y - a.y).coerceIn(-1, 1), + (b.z - a.z).coerceIn(-1, 1) + ) + } } diff --git a/src/main/kotlin/org/cobalt/pathfinder/calculate/PathMode.kt b/src/main/kotlin/org/cobalt/pathfinder/calculate/PathMode.kt index 4fc16b9..49111f9 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/calculate/PathMode.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/calculate/PathMode.kt @@ -1,14 +1,14 @@ package org.cobalt.pathfinder.calculate import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.impl.fly.FlyAscendMovement -import org.cobalt.pathfinder.movement.impl.fly.FlyDescendMovement -import org.cobalt.pathfinder.movement.impl.fly.FlyDiagonalMovement -import org.cobalt.pathfinder.movement.impl.fly.FlyTraverseMovement -import org.cobalt.pathfinder.movement.impl.walk.AscendMovement -import org.cobalt.pathfinder.movement.impl.walk.DescendMovement -import org.cobalt.pathfinder.movement.impl.walk.DiagonalMovement -import org.cobalt.pathfinder.movement.impl.walk.TraverseMovement +import org.cobalt.pathfinder.movement.fly.FlyAscendMovement +import org.cobalt.pathfinder.movement.fly.FlyDescendMovement +import org.cobalt.pathfinder.movement.fly.FlyDiagonalMovement +import org.cobalt.pathfinder.movement.fly.FlyTraverseMovement +import org.cobalt.pathfinder.movement.walk.AscendMovement +import org.cobalt.pathfinder.movement.walk.DescendMovement +import org.cobalt.pathfinder.movement.walk.DiagonalMovement +import org.cobalt.pathfinder.movement.walk.TraverseMovement enum class PathMode(vararg val movements: Movement) { WALK( diff --git a/src/main/kotlin/org/cobalt/pathfinder/calculate/PathNode.kt b/src/main/kotlin/org/cobalt/pathfinder/calculate/PathNode.kt index 4bdb7d0..901013a 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/calculate/PathNode.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/calculate/PathNode.kt @@ -3,20 +3,21 @@ package org.cobalt.pathfinder.calculate import net.minecraft.core.BlockPos import net.minecraft.world.phys.Vec3 import org.cobalt.pathfinder.goal.Goal -import org.cobalt.pathfinder.movement.Movement +import org.cobalt.pathfinder.movement.MovementType data class PathNode( val x: Int, val y: Int, val z: Int, val goal: Goal, -) { +) : Comparable { var costSoFar = 1e6 val costToEnd = goal.heuristic(x, y, z) var totalCost = 1.0 var heapPosition = -1 - var type = Movement.Type.WALK + + var movementType = MovementType.WALK var parent: PathNode? = null val block: BlockPos = BlockPos(x, y, z) @@ -24,8 +25,17 @@ data class PathNode( val centerVec: Vec3 = Vec3(x + 0.5, y + 0.5, z + 0.5) val topCenterVec: Vec3 = Vec3(x + 0.5, y.toDouble(), z + 0.5) - val isFly: Boolean - get() = type == Movement.Type.FLY + val useMovementFly: Boolean + get() = movementType == MovementType.FLY + + override fun compareTo(other: PathNode): Int { + return compareValuesBy( + this, + other, + PathNode::costToEnd, + PathNode::costSoFar, + ) + } override fun equals(other: Any?): Boolean { if (this === other) { diff --git a/src/main/kotlin/org/cobalt/pathfinder/calculate/path/AStarPathfinder.kt b/src/main/kotlin/org/cobalt/pathfinder/calculate/path/AStarPathfinder.kt index 2261243..db6f174 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/calculate/path/AStarPathfinder.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/calculate/path/AStarPathfinder.kt @@ -1,32 +1,36 @@ package org.cobalt.pathfinder.calculate.path import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap -import kotlin.time.Duration.Companion.milliseconds +import kotlin.time.Duration.Companion.nanoseconds import org.cobalt.pathfinder.calculate.Path +import org.cobalt.pathfinder.calculate.PathMode import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.calculate.openset.BinaryHeapOpenSet import org.cobalt.pathfinder.goal.Goal import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.chat.MessageType class AStarPathfinder( - val startX: Int, - val startY: Int, - val startZ: Int, - val goal: Goal, - val movements: Array, - val returnBestNode: Boolean, + val startX: Int, + val startY: Int, + val startZ: Int, + val goal: Goal, + val mode: PathMode, + val returnBestNode: Boolean, + val maxCalculationTime: Long, ) { private val closedSet = Long2ObjectOpenHashMap() + private val movements = mode.movements private var startTime = 0L - @Suppress("CognitiveComplexMethod") fun findPath(): Path? { - val ctx = CalculationContext() + val calculationContext = CalculationContext() val openSet = BinaryHeapOpenSet() - val res = MovementResult() + val movementResult = MovementResult() val startNode = PathNode( startX, startY, startZ, goal @@ -36,22 +40,20 @@ class AStarPathfinder( } openSet.add(startNode) + startTime = System.nanoTime() - startTime = System.currentTimeMillis() var bestNode = startNode + val deadline = startTime + maxCalculationTime - while (!openSet.isEmpty()) { - if (System.currentTimeMillis() - startTime >= 5_000) { - break - } + ChatUtils.sendSystemMessage( + "Starting pathfinding from ${startNode.block}", + MessageType.DEBUG + ) + while (!openSet.isEmpty() && System.nanoTime() < deadline) { val currentNode = openSet.poll() - if ( - currentNode.costToEnd < bestNode.costToEnd || - (currentNode.costToEnd == bestNode.costToEnd && - currentNode.costSoFar < bestNode.costSoFar) - ) { + if (currentNode < bestNode) { bestNode = currentNode } @@ -59,33 +61,12 @@ class AStarPathfinder( return reconstruct(currentNode) } - for (move in movements) { - res.reset() - move.calculateCost(ctx, currentNode, res) - - if (res.cost >= ctx.infCost) { - continue - } - - val neighborCostSoFar = currentNode.costSoFar + res.cost - val neighborNode = getNode( - res.x, res.y, res.z, - PathNode.longHash(res.x, res.y, res.z) - ) - - if (neighborCostSoFar < neighborNode.costSoFar) { - neighborNode.parent = currentNode - neighborNode.costSoFar = neighborCostSoFar - neighborNode.totalCost = neighborCostSoFar + neighborNode.costToEnd - neighborNode.type = move.type - - if (neighborNode.heapPosition == -1) { - openSet.add(neighborNode) - } else { - openSet.relocate(neighborNode) - } - } - } + evaluateMovements( + calculationContext, + currentNode, + movementResult, + openSet + ) } return if (returnBestNode) { @@ -95,6 +76,50 @@ class AStarPathfinder( } } + private fun evaluateMovements( + calculationContext: CalculationContext, + currentNode: PathNode, + movementResult: MovementResult, + openSet: BinaryHeapOpenSet, + ) { + for (move in movements) { + movementResult.reset() + move.calculateCost(calculationContext, currentNode, movementResult) + + if (movementResult.cost < calculationContext.actionCosts.infCost) { + relaxNeighbor(currentNode, move, movementResult, openSet) + } + } + } + + private fun relaxNeighbor( + currentNode: PathNode, + movement: Movement, + movementResult: MovementResult, + openSet: BinaryHeapOpenSet, + ) { + val neighborCostSoFar = currentNode.costSoFar + movementResult.cost + val neighborNode = getNode( + movementResult.x, movementResult.y, movementResult.z, + PathNode.longHash(movementResult.x, movementResult.y, movementResult.z) + ) + + if (neighborCostSoFar >= neighborNode.costSoFar) { + return + } + + neighborNode.parent = currentNode + neighborNode.costSoFar = neighborCostSoFar + neighborNode.totalCost = neighborCostSoFar + neighborNode.costToEnd + neighborNode.movementType = movement.type + + if (neighborNode.heapPosition == -1) { + openSet.add(neighborNode) + } else { + openSet.relocate(neighborNode) + } + } + fun getNode(x: Int, y: Int, z: Int, hash: Long): PathNode { var node: PathNode? = closedSet.get(hash) @@ -117,7 +142,7 @@ class AStarPathfinder( return Path( nodes = path, - timeElapsed = (System.currentTimeMillis() - startTime).milliseconds, + timeElapsed = (System.nanoTime() - startTime).nanoseconds, goal = goal ) } diff --git a/src/main/kotlin/org/cobalt/pathfinder/cost/ActionCosts.kt b/src/main/kotlin/org/cobalt/pathfinder/cost/ActionCosts.kt new file mode 100644 index 0000000..05cc0a7 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/cost/ActionCosts.kt @@ -0,0 +1,7 @@ +package org.cobalt.pathfinder.cost + +class ActionCosts(speedAmplifier: Int, jumpAmplifier: Int) { + + val infCost = 1e4 + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/helper/BlockStateAccessor.kt b/src/main/kotlin/org/cobalt/pathfinder/helper/BlockStateAccessor.kt index 2a52fbf..6de5ae7 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/helper/BlockStateAccessor.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/helper/BlockStateAccessor.kt @@ -1,7 +1,6 @@ package org.cobalt.pathfinder.helper import net.minecraft.client.multiplayer.ClientLevel -import net.minecraft.core.BlockPos import net.minecraft.world.level.block.Blocks import net.minecraft.world.level.block.state.BlockState import net.minecraft.world.level.chunk.LevelChunk @@ -9,9 +8,6 @@ import net.minecraft.world.level.chunk.status.ChunkStatus class BlockStateAccessor(val level: ClientLevel) { - val mutablePos = BlockPos.MutableBlockPos() - val access = BlockViewWrapper(this) - private val provider = level.chunkSource private var prevChunk: LevelChunk? = null private val air = Blocks.AIR.defaultBlockState() diff --git a/src/main/kotlin/org/cobalt/pathfinder/helper/Input.kt b/src/main/kotlin/org/cobalt/pathfinder/helper/Input.kt new file mode 100644 index 0000000..4d32c36 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/helper/Input.kt @@ -0,0 +1,23 @@ +package org.cobalt.pathfinder.helper + +data class Input( + var forward: Boolean = false, + var backward: Boolean = false, + var left: Boolean = false, + var right: Boolean = false, + var jump: Boolean = false, + var sprint: Boolean = false, + var sneak: Boolean = false, +) { + + fun apply(other: Input) { + forward = forward || other.forward + backward = backward || other.backward + left = left || other.left + right = right || other.right + jump = jump || other.jump + sprint = sprint || other.sprint + sneak = sneak || other.sneak + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/helper/PlayerInput.kt b/src/main/kotlin/org/cobalt/pathfinder/helper/PlayerInput.kt index 6628b3b..0677e5c 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/helper/PlayerInput.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/helper/PlayerInput.kt @@ -1,23 +1,55 @@ package org.cobalt.pathfinder.helper -data class PlayerInput( - var forward: Boolean = false, - var backward: Boolean = false, - var left: Boolean = false, - var right: Boolean = false, - var jump: Boolean = false, - var sprint: Boolean = false, - var sneak: Boolean = false, -) { - - fun apply(other: PlayerInput) { - forward = forward || other.forward - backward = backward || other.backward - left = left || other.left - right = right || other.right - jump = jump || other.jump - sprint = sprint || other.sprint - sneak = sneak || other.sneak +import net.minecraft.client.player.ClientInput +import net.minecraft.world.entity.player.Input +import net.minecraft.world.phys.Vec2 + +class PlayerInput : ClientInput() { + + var forward = false + var backward = false + var left = false + var right = false + var jump = false + var shift = false + var sprint = false + + fun applyInput(input: org.cobalt.pathfinder.helper.Input) { + forward = input.forward + backward = input.backward + left = input.left + right = input.right + jump = input.jump + sprint = input.sprint + shift = input.sneak + } + + fun stopMovement() { + applyInput(Input()) + } + + override fun tick() { + this.keyPresses = Input( + forward, + backward, + left, + right, + jump, + shift, + sprint + ) + + val forwardImpulse = calculateImpulse(forward, backward) + val leftImpulse = calculateImpulse(left, right) + this.moveVector = Vec2(leftImpulse, forwardImpulse).normalized() + } + + private fun calculateImpulse(positive: Boolean, negative: Boolean): Float { + return when { + positive == negative -> 0.0f + positive -> 1.0f + else -> -1.0f + } } } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/CalculationContext.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/CalculationContext.kt index b8a13a3..8cbb409 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/CalculationContext.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/CalculationContext.kt @@ -2,20 +2,18 @@ package org.cobalt.pathfinder.movement import net.minecraft.world.effect.MobEffects import org.cobalt.Cobalt.minecraft +import org.cobalt.pathfinder.cost.ActionCosts import org.cobalt.pathfinder.helper.BlockStateAccessor -import org.cobalt.pathfinder.precompute.PrecomputedData class CalculationContext { - val infCost = 1e6 - val level = minecraft.level!! val player = minecraft.player!! val speedAmplifier = player.getEffect(MobEffects.SPEED)?.amplifier ?: -1 val jumpAmplifier = player.getEffect(MobEffects.JUMP_BOOST)?.amplifier ?: -1 - val bsa = BlockStateAccessor(level) - val precomputedData = PrecomputedData() + val actionCosts = ActionCosts(speedAmplifier, jumpAmplifier) + val blockStateAccessor = BlockStateAccessor(level) } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/Movement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/Movement.kt index 04fe1dc..fbf61f0 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/Movement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/Movement.kt @@ -4,13 +4,8 @@ import org.cobalt.pathfinder.calculate.PathNode // TODO: Implement costs in each movement type (to improve path quality) abstract class Movement( - val type: Type, + val type: MovementType, ) { abstract fun calculateCost(ctx: CalculationContext, currNode: PathNode, res: MovementResult) - - enum class Type { - WALK, FLY - } - } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/MovementHelper.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/MovementHelper.kt deleted file mode 100644 index 27410c1..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/MovementHelper.kt +++ /dev/null @@ -1,403 +0,0 @@ -@file:Suppress("TooManyFunctions") - -package org.cobalt.pathfinder.movement - -import net.minecraft.core.BlockPos -import net.minecraft.util.Mth -import net.minecraft.world.level.EmptyBlockGetter -import net.minecraft.world.level.block.* -import net.minecraft.world.level.block.piston.MovingPistonBlock -import net.minecraft.world.level.block.state.BlockState -import net.minecraft.world.level.block.state.properties.SlabType -import net.minecraft.world.level.material.FlowingFluid -import net.minecraft.world.level.material.Fluids -import net.minecraft.world.level.material.WaterFluid -import net.minecraft.world.level.pathfinder.PathComputationType -import net.minecraft.world.phys.Vec3 -import org.cobalt.pathfinder.calculate.PathNode -import org.cobalt.pathfinder.helper.BlockStateAccessor -import org.cobalt.pathfinder.helper.PlayerInput -import org.cobalt.pathfinder.precompute.Ternary -import org.cobalt.pathfinder.precompute.Ternary.* - -object MovementHelper { - - @JvmStatic - fun canWalkOn( - ctx: CalculationContext, - x: Int, y: Int, z: Int, - state: BlockState = ctx.bsa.get(x, y, z), - ): Boolean { - if (!canWalkThrough(ctx, x, y + 1, z)) { - return false - } - - return canStandOn(ctx, x, y, z, state) - } - - @JvmStatic - fun canWalkThrough( - ctx: CalculationContext, - x: Int, y: Int, z: Int, - state: BlockState = ctx.bsa.get(x, y, z), - ): Boolean { - return canPassThrough(ctx, x, y, z, state) && - canPassThrough(ctx, x, y + 1, z) - } - - @JvmStatic - fun canPassThrough( - ctx: CalculationContext, - x: Int, y: Int, z: Int, - state: BlockState = ctx.bsa.get(x, y, z), - ): Boolean { - return ctx.precomputedData.canPassThrough(ctx, x, y, z, state) - } - - @JvmStatic - fun canStandOn( - ctx: CalculationContext, - x: Int, y: Int, z: Int, - state: BlockState = ctx.bsa.get(x, y, z), - ): Boolean { - return ctx.precomputedData.canStandOn(ctx, x, y, z, state) - } - - @JvmStatic - fun canPassThrough( - bsa: BlockStateAccessor, - x: Int, y: Int, z: Int, - state: BlockState = bsa.get(x, y, z), - ): Boolean { - val result = canPassThroughState(state) - - if (result == YES) { - return true - } - - if (result == NO) { - return false - } - - return canPassThroughPosition(bsa, x, y, z, state) - } - - @JvmStatic - fun canStandOn( - bsa: BlockStateAccessor, - x: Int, y: Int, z: Int, - state: BlockState = bsa.get(x, y, z), - ): Boolean { - val result = canStandOnState(state) - - if (result == YES) { - return true - } - - if (result == NO) { - return false - } - - return canStandOnPosition(bsa, x, y, z, state) - } - - @JvmStatic - fun canPassThroughState(state: BlockState): Ternary { - val block = state.block - - return when { - block is AirBlock -> YES - - block is BaseFireBlock || - block == Blocks.COBWEB || - block == Blocks.END_PORTAL || - block == Blocks.COCOA || - block is AbstractSkullBlock || - block == Blocks.BUBBLE_COLUMN || - block is ShulkerBoxBlock || - block is SlabBlock || - block is TrapDoorBlock || - block == Blocks.HONEY_BLOCK || - block == Blocks.END_ROD || - block == Blocks.SWEET_BERRY_BUSH || - block == Blocks.POINTED_DRIPSTONE || - block is AmethystClusterBlock || - block is AzaleaBlock || - block == Blocks.BIG_DRIPLEAF || - block == Blocks.POWDER_SNOW -> NO - - block is DoorBlock || block is FenceGateBlock -> - if (block == Blocks.IRON_DOOR) NO else YES - - block is CarpetBlock || - block is SnowLayerBlock -> MAYBE - - !state.fluidState.isEmpty -> - if (state.fluidState.type.getAmount(state.fluidState) != 8) NO else MAYBE - - block is CauldronBlock -> NO - - else -> - if (state.isPathfindable(PathComputationType.LAND)) YES else NO - } - } - - @JvmStatic - fun canStandOnState(state: BlockState): Ternary { - val block = state.block - - return when { - isBlockNormalCube(state) && - block != Blocks.BUBBLE_COLUMN && - block != Blocks.HONEY_BLOCK -> YES - - block is AzaleaBlock || - block == Blocks.LADDER || - block == Blocks.VINE || - block == Blocks.FARMLAND || - block == Blocks.DIRT_PATH || - block == Blocks.SOUL_SAND || - block == Blocks.ENDER_CHEST || - block == Blocks.CHEST || - block == Blocks.TRAPPED_CHEST || - block == Blocks.GLASS || - block is StainedGlassBlock || - block is StairBlock || - block is SlabBlock -> YES - - isWater(state) -> MAYBE - isLava(state) -> MAYBE - - else -> NO - } - } - - private fun canPassThroughPosition(bsa: BlockStateAccessor, x: Int, y: Int, z: Int, state: BlockState): Boolean { - val block = state.block - - return when { - block is CarpetBlock -> { - canStandOn(bsa, x, y - 1, z) - } - - block is SnowLayerBlock -> { - if (!bsa.isLoaded(x, z)) { - true - } else if (state.getValue(SnowLayerBlock.LAYERS) >= 3) { - false - } else { - canStandOn(bsa, x, y - 1, z) - } - } - - !state.fluidState.isEmpty -> { - val fluidState = state.fluidState - - if (isFlowing(x, y, z, state, bsa)) { - false - } else { - val upState = bsa.get(x, y + 1, z) - - if (!upState.fluidState.isEmpty || upState.block is LilyPadBlock) { - false - } else { - fluidState.type is WaterFluid - } - } - } - - else -> state.isPathfindable(PathComputationType.LAND) - } - } - - private fun canStandOnPosition(bsa: BlockStateAccessor, x: Int, y: Int, z: Int, state: BlockState): Boolean { - if (isWater(state)) { - val upState = bsa.get(x, y + 1, z) - val upBlock = upState.block - - if (upBlock == Blocks.LILY_PAD || upBlock is CarpetBlock) { - return true - } - - if (isFlowing(x, y, z, state, bsa) || upState.fluidState.type == Fluids.FLOWING_WATER) { - return isWater(upState) - } - - return isWater(upState) xor false - } - - return false - } - - @JvmStatic - fun isLiquid(state: BlockState): Boolean { - return !state.fluidState.isEmpty - } - - @JvmStatic - fun isWater(state: BlockState): Boolean { - val fluid = state.fluidState.type - return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER - } - - @JvmStatic - fun isLava(state: BlockState): Boolean { - val fluid = state.fluidState.type - return fluid == Fluids.LAVA || fluid == Fluids.FLOWING_LAVA - } - - private fun possiblyFlowing(state: BlockState): Boolean { - val fluidState = state.fluidState - - return fluidState.type is FlowingFluid && - fluidState.type.getAmount(fluidState) != 8 - } - - @JvmStatic - private fun isFlowing(x: Int, y: Int, z: Int, state: BlockState, bsa: BlockStateAccessor): Boolean { - val fluidState = state.fluidState - - if (fluidState.type !is FlowingFluid) { - return false - } - - if (fluidState.type.getAmount(fluidState) != 8) { - return true - } - - return possiblyFlowing(bsa.get(x + 1, y, z)) - || possiblyFlowing(bsa.get(x - 1, y, z)) - || possiblyFlowing(bsa.get(x, y, z + 1)) - || possiblyFlowing(bsa.get(x, y, z - 1)) - } - - @JvmStatic - fun isBottomSlab(state: BlockState): Boolean { - return state.block is SlabBlock && - state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM - } - - @JvmStatic - fun isBlockNormalCube(state: BlockState): Boolean { - val block = state.block - - if ( - block is BambooStalkBlock || - block is MovingPistonBlock || - block is ScaffoldingBlock - ) { - return false - } - - if ( - block is ShulkerBoxBlock || - block is PointedDripstoneBlock || - block is AmethystClusterBlock - ) { - return false - } - - return try { - Block.isShapeFullBlock(state.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) - } catch (_: Exception) { - false - } - } - - @JvmStatic - fun getNeededKeys(playerYaw: Float, idealYaw: Float): PlayerInput { - val diff = Mth.wrapDegrees(idealYaw - playerYaw) - - return when { - diff >= -22.5f && diff < 22.5f -> PlayerInput(forward = true) - diff in 22.5f..<67.5f -> PlayerInput(forward = true, right = true) - diff in 67.5f..<112.5f -> PlayerInput(right = true) - diff in 112.5f..<157.5f -> PlayerInput(backward = true, right = true) - diff >= 157.5f || diff < -157.5f -> PlayerInput(backward = true) - diff >= -157.5f && diff < -112.5f -> PlayerInput(backward = true, left = true) - diff >= -112.5f && diff < -67.5f -> PlayerInput(left = true) - else -> PlayerInput(forward = true, left = true) - } - } - - @JvmStatic - fun getRotationTarget(playerEyePos: Vec3, nodes: List, currentIndex: Int, lookAhead: Double = 3.0): Vec3 { - val playerXZ = Vec3(playerEyePos.x, 0.0, playerEyePos.z) - - var bestDistSq = Double.MAX_VALUE - var bestSegIndex = currentIndex - var bestT = 0.0 - - val searchStart = (currentIndex - 1).coerceAtLeast(0) - val searchEnd = (currentIndex + 3).coerceAtMost(nodes.size - 1) - - for (i in searchStart until searchEnd) { - val from = nodes[i].centerVec - val to = nodes[i + 1].centerVec - val seg = Vec3(to.x - from.x, 0.0, to.z - from.z) - val segLenSq = seg.x * seg.x + seg.z * seg.z - - if (segLenSq <= 0.0) continue - - val t = ((playerXZ.x - from.x) * seg.x + (playerXZ.z - from.z) * seg.z) - .coerceIn(0.0, segLenSq) / segLenSq - - val px = from.x + seg.x * t - val pz = from.z + seg.z * t - val dx = playerXZ.x - px - val dz = playerXZ.z - pz - val distSq = dx * dx + dz * dz - - if (distSq < bestDistSq) { - bestDistSq = distSq - bestSegIndex = i - bestT = t - } - } - - var remaining = lookAhead - - val from = nodes[bestSegIndex].centerVec - val to = nodes[bestSegIndex + 1].centerVec - val seg = Vec3(to.x - from.x, 0.0, to.z - from.z) - val segLen = seg.length() - - if (segLen > 0.0) { - val remainingSeg = (1.0 - bestT) * segLen - if (remaining <= remainingSeg) { - val point = from.add(seg.scale(bestT + remaining / segLen)) - return Vec3(point.x, playerEyePos.y, point.z) - } - remaining -= remainingSeg - } - - for (i in (bestSegIndex + 1) until nodes.size - 1) { - val sFrom = nodes[i].centerVec - val sTo = nodes[i + 1].centerVec - val sSeg = Vec3(sTo.x - sFrom.x, 0.0, sTo.z - sFrom.z) - val sLen = sSeg.length() - - if (sLen <= 0.0) continue - - if (remaining <= sLen) { - val point = sFrom.add(sSeg.scale(remaining / sLen)) - return Vec3(point.x, playerEyePos.y, point.z) - } - - remaining -= sLen - } - - val last = nodes.last() - val prev = if (nodes.size > 1) nodes[nodes.size - 2] else last - val dir = Vec3((last.x - prev.x).toDouble(), 0.0, (last.z - prev.z).toDouble()) - val dirLen = dir.length() - val extrapolated = if (dirLen > 0.0) { - last.centerVec.add(dir.scale(remaining / dirLen)) - } else { - last.centerVec - } - - return Vec3(extrapolated.x, playerEyePos.y, extrapolated.z) - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/MovementType.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/MovementType.kt new file mode 100644 index 0000000..997b201 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/MovementType.kt @@ -0,0 +1,5 @@ +package org.cobalt.pathfinder.movement + +enum class MovementType { + WALK, FLY +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/MovementValidator.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/MovementValidator.kt new file mode 100644 index 0000000..5bc1f2d --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/MovementValidator.kt @@ -0,0 +1,23 @@ +package org.cobalt.pathfinder.movement + +import org.cobalt.pathfinder.movement.rules.PassthroughRules.canPassThrough +import org.cobalt.pathfinder.movement.rules.StandingRules.canStandOn + +object MovementValidator { + + @JvmStatic + fun canWalkOn(calculationContext: CalculationContext, x: Int, y: Int, z: Int): Boolean { + if (!canWalkThrough(calculationContext, x, y + 1, z)) { + return false + } + + return canStandOn(calculationContext.blockStateAccessor, x, y, z) + } + + @JvmStatic + fun canWalkThrough(calculationContext: CalculationContext, x: Int, y: Int, z: Int): Boolean { + return canPassThrough(calculationContext.blockStateAccessor, x, y, z) && + canPassThrough(calculationContext.blockStateAccessor, x, y + 1, z) + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyAscendMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyAscendMovement.kt similarity index 66% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyAscendMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyAscendMovement.kt index 0a11c74..d631853 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyAscendMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyAscendMovement.kt @@ -1,12 +1,13 @@ -package org.cobalt.pathfinder.movement.impl.fly +package org.cobalt.pathfinder.movement.fly import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator -class FlyAscendMovement : Movement(Type.FLY) { +class FlyAscendMovement : Movement(MovementType.FLY) { override fun calculateCost( ctx: CalculationContext, @@ -17,7 +18,7 @@ class FlyAscendMovement : Movement(Type.FLY) { val y = currNode.y + 1 val z = currNode.z - if (!MovementHelper.canWalkThrough(ctx, x, y, z)) { + if (!MovementValidator.canWalkThrough(ctx, x, y, z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDescendMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDescendMovement.kt similarity index 66% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDescendMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDescendMovement.kt index 1d4d8e6..0158e34 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDescendMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDescendMovement.kt @@ -1,12 +1,13 @@ -package org.cobalt.pathfinder.movement.impl.fly +package org.cobalt.pathfinder.movement.fly import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator -class FlyDescendMovement : Movement(Type.FLY) { +class FlyDescendMovement : Movement(MovementType.FLY) { override fun calculateCost( ctx: CalculationContext, @@ -17,7 +18,7 @@ class FlyDescendMovement : Movement(Type.FLY) { val y = currNode.y - 1 val z = currNode.z - if (!MovementHelper.canWalkThrough(ctx, x, y, z)) { + if (!MovementValidator.canWalkThrough(ctx, x, y, z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDiagonalMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDiagonalMovement.kt similarity index 65% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDiagonalMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDiagonalMovement.kt index 6fbe13d..58e63e3 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyDiagonalMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyDiagonalMovement.kt @@ -1,15 +1,16 @@ -package org.cobalt.pathfinder.movement.impl.fly +package org.cobalt.pathfinder.movement.fly import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator class FlyDiagonalMovement( val dx: Int, val dz: Int, -) : Movement(Type.FLY) { +) : Movement(MovementType.FLY) { override fun calculateCost( ctx: CalculationContext, @@ -20,15 +21,15 @@ class FlyDiagonalMovement( val y = currNode.y val z = currNode.z + dz - if (!MovementHelper.canWalkThrough(ctx, x, y, z)) { + if (!MovementValidator.canWalkThrough(ctx, x, y, z)) { return } - if (!MovementHelper.canWalkThrough(ctx, currNode.x + dx, y, currNode.z)) { + if (!MovementValidator.canWalkThrough(ctx, currNode.x + dx, y, currNode.z)) { return } - if (!MovementHelper.canWalkThrough(ctx, currNode.x, y, currNode.z + dz)) { + if (!MovementValidator.canWalkThrough(ctx, currNode.x, y, currNode.z + dz)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyTraverseMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyTraverseMovement.kt similarity index 74% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyTraverseMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyTraverseMovement.kt index 970fd6d..35d5145 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/fly/FlyTraverseMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/fly/FlyTraverseMovement.kt @@ -1,15 +1,16 @@ -package org.cobalt.pathfinder.movement.impl.fly +package org.cobalt.pathfinder.movement.fly import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator class FlyTraverseMovement( val dx: Int, val dz: Int, -) : Movement(Type.FLY) { +) : Movement(MovementType.FLY) { override fun calculateCost( ctx: CalculationContext, @@ -20,7 +21,7 @@ class FlyTraverseMovement( val y = currNode.y val z = currNode.z + dz - if (!MovementHelper.canWalkThrough(ctx, x, y, z)) { + if (!MovementValidator.canWalkThrough(ctx, x, y, z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/PassthroughRules.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/PassthroughRules.kt new file mode 100644 index 0000000..30ada3a --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/PassthroughRules.kt @@ -0,0 +1,157 @@ +package org.cobalt.pathfinder.movement.rules + +import net.minecraft.world.level.block.* +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.properties.BlockStateProperties +import net.minecraft.world.level.material.WaterFluid +import net.minecraft.world.level.pathfinder.PathComputationType +import org.cobalt.pathfinder.helper.BlockStateAccessor +import org.cobalt.pathfinder.movement.rules.StandingRules.canStandOn +import org.cobalt.pathfinder.movement.rules.data.BlockSetRule +import org.cobalt.pathfinder.movement.rules.data.BlockTypeRule +import org.cobalt.pathfinder.movement.rules.data.Ternary +import org.cobalt.util.block.BlockUtils + +object PassthroughRules { + + val PASS_THROUGH_RULES = listOf( + BlockTypeRule( + setOf(AirBlock::class.java), + Ternary.YES, + ), + + BlockSetRule( + setOf( + Blocks.COBWEB, + Blocks.END_PORTAL, + Blocks.COCOA, + Blocks.BUBBLE_COLUMN, + Blocks.HONEY_BLOCK, + Blocks.END_ROD, + Blocks.SWEET_BERRY_BUSH, + Blocks.POINTED_DRIPSTONE, + Blocks.BIG_DRIPLEAF, + Blocks.POWDER_SNOW, + ), + Ternary.NO, + ), + + BlockTypeRule( + setOf( + BaseFireBlock::class.java, + AbstractSkullBlock::class.java, + ShulkerBoxBlock::class.java, + SlabBlock::class.java, + AmethystClusterBlock::class.java, + AzaleaBlock::class.java, + ), + Ternary.NO, + ), + + BlockTypeRule( + setOf( + CarpetBlock::class.java, + SnowLayerBlock::class.java, + ), + Ternary.MAYBE, + ), + + BlockTypeRule( + setOf(CauldronBlock::class.java), + Ternary.NO, + ), + ) + + private val PRECOMPUTED = Array(Block.BLOCK_STATE_REGISTRY.size()) { + Ternary.NO + } + + init { + Block.BLOCK_STATE_REGISTRY.forEach { state -> + PRECOMPUTED[Block.BLOCK_STATE_REGISTRY.getId(state)] = compute(state) + } + } + + private fun compute(state: BlockState): Ternary { + PASS_THROUGH_RULES.firstOrNull { it.matches(state) } + ?.let { return it.result } + + val block = state.block + + if (block is DoorBlock || block is FenceGateBlock || block is TrapDoorBlock) { + return Ternary.MAYBE + } + + if (!state.fluidState.isEmpty) { + return if (state.fluidState.type.getAmount(state.fluidState) != 8) { + Ternary.NO + } else { + Ternary.MAYBE + } + } + + return if (state.isPathfindable(PathComputationType.LAND)) { + Ternary.YES + } else { + Ternary.NO + } + } + + fun canPassThrough(bsa: BlockStateAccessor, x: Int, y: Int, z: Int): Boolean { + val state = bsa.get(x, y, z) + val result = PRECOMPUTED[Block.BLOCK_STATE_REGISTRY.getId(state)] + + if (result == Ternary.YES) { + return true + } + + if (result == Ternary.NO) { + return false + } + + return resolveMaybe(bsa, x, y, z, state) + } + + private fun resolveMaybe(bsa: BlockStateAccessor, x: Int, y: Int, z: Int, state: BlockState): Boolean { + val block = state.block + + return when { + block is DoorBlock || block is FenceGateBlock || block is TrapDoorBlock -> { + state.getValue(BlockStateProperties.OPEN) + } + + block is CarpetBlock -> { + canStandOn(bsa, x, y - 1, z) + } + + block is SnowLayerBlock -> { + if (!bsa.isLoaded(x, z)) { + true + } else if (state.getValue(SnowLayerBlock.LAYERS) >= 3) { + false + } else { + canStandOn(bsa, x, y - 1, z) + } + } + + !state.fluidState.isEmpty -> { + val fluidState = state.fluidState + + if (BlockUtils.isFlowing(x, y, z, state, bsa)) { + false + } else { + val upState = bsa.get(x, y + 1, z) + + if (!upState.fluidState.isEmpty || upState.block is LilyPadBlock) { + false + } else { + fluidState.type is WaterFluid + } + } + } + + else -> state.isPathfindable(PathComputationType.LAND) + } + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/StandingRules.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/StandingRules.kt new file mode 100644 index 0000000..17d0b94 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/StandingRules.kt @@ -0,0 +1,105 @@ +package org.cobalt.pathfinder.movement.rules + +import net.minecraft.world.level.block.* +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.material.Fluids +import org.cobalt.pathfinder.helper.BlockStateAccessor +import org.cobalt.pathfinder.movement.rules.data.BlockSetRule +import org.cobalt.pathfinder.movement.rules.data.BlockTypeRule +import org.cobalt.pathfinder.movement.rules.data.Ternary +import org.cobalt.util.block.BlockUtils + +object StandingRules { + + val STANDING_RULES = listOf( + BlockSetRule( + setOf( + Blocks.LADDER, + Blocks.VINE, + Blocks.FARMLAND, + Blocks.DIRT_PATH, + Blocks.SOUL_SAND, + Blocks.ENDER_CHEST, + Blocks.CHEST, + Blocks.TRAPPED_CHEST, + Blocks.GLASS, + ), + Ternary.YES, + ), + + BlockTypeRule( + setOf( + StainedGlassBlock::class.java, + StairBlock::class.java, + SlabBlock::class.java, + AzaleaBlock::class.java, + ), + Ternary.YES, + ), + ) + + private val PRECOMPUTED = Array(Block.BLOCK_STATE_REGISTRY.size()) { + Ternary.NO + } + + init { + Block.BLOCK_STATE_REGISTRY.forEach { state -> + PRECOMPUTED[Block.BLOCK_STATE_REGISTRY.getId(state)] = compute(state) + } + } + + private fun compute(state: BlockState): Ternary { + val block = state.block + + if (BlockUtils.isBlockNormalCube(state) && + block != Blocks.BUBBLE_COLUMN && + block != Blocks.HONEY_BLOCK + ) { + return Ternary.YES + } + + STANDING_RULES.firstOrNull { it.matches(state) } + ?.let { return it.result } + + return when { + BlockUtils.isWater(state) -> Ternary.MAYBE + BlockUtils.isLava(state) -> Ternary.MAYBE + else -> Ternary.NO + } + } + + fun canStandOn(bsa: BlockStateAccessor, x: Int, y: Int, z: Int): Boolean { + val state = bsa.get(x, y, z) + val result = PRECOMPUTED[Block.BLOCK_STATE_REGISTRY.getId(state)] + + if (result == Ternary.YES) { + return true + } + + if (result == Ternary.NO) { + return false + } + + return resolveMaybe(bsa, x, y, z, state) + } + + private fun resolveMaybe(bsa: BlockStateAccessor, x: Int, y: Int, z: Int, state: BlockState): Boolean { + if (BlockUtils.isWater(state)) { + val upState = bsa.get(x, y + 1, z) + val upBlock = upState.block + + if (upBlock == Blocks.LILY_PAD || upBlock is CarpetBlock) { + return true + } + + if (BlockUtils.isFlowing(x, y, z, state, bsa) || upState.fluidState.type == Fluids.FLOWING_WATER) { + return BlockUtils.isWater(upState) + } + + return BlockUtils.isWater(upState) xor false + } + + return false + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockRule.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockRule.kt new file mode 100644 index 0000000..09fe992 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockRule.kt @@ -0,0 +1,11 @@ +package org.cobalt.pathfinder.movement.rules.data + +import net.minecraft.world.level.block.state.BlockState + +interface BlockRule { + + val result: Ternary + + fun matches(state: BlockState): Boolean + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockSetRule.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockSetRule.kt new file mode 100644 index 0000000..1a949f4 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockSetRule.kt @@ -0,0 +1,14 @@ +package org.cobalt.pathfinder.movement.rules.data + +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState + +class BlockSetRule( + private val blocks: Set, + override val result: Ternary, +) : BlockRule { + + override fun matches(state: BlockState): Boolean = + state.block in blocks + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockTypeRule.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockTypeRule.kt new file mode 100644 index 0000000..3d837a6 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/BlockTypeRule.kt @@ -0,0 +1,14 @@ +package org.cobalt.pathfinder.movement.rules.data + +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState + +class BlockTypeRule( + private val types: Set>, + override val result: Ternary, +) : BlockRule { + + override fun matches(state: BlockState): Boolean = + types.any { it.isInstance(state.block) } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/Ternary.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/Ternary.kt new file mode 100644 index 0000000..7dc30e4 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/rules/data/Ternary.kt @@ -0,0 +1,5 @@ +package org.cobalt.pathfinder.movement.rules.data + +enum class Ternary { + YES, MAYBE, NO +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/AscendMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/AscendMovement.kt similarity index 69% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/AscendMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/walk/AscendMovement.kt index 5143f9b..fd4459b 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/AscendMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/AscendMovement.kt @@ -1,16 +1,17 @@ -package org.cobalt.pathfinder.movement.impl.walk +package org.cobalt.pathfinder.movement.walk import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator // TODO: Handle ladder & vine climbing & jump boost class AscendMovement( val dx: Int, val dz: Int, -) : Movement(Type.WALK) { +) : Movement(MovementType.WALK) { override fun calculateCost( ctx: CalculationContext, @@ -21,11 +22,11 @@ class AscendMovement( val y = currNode.y + 1 val z = currNode.z + dz - if (!MovementHelper.canWalkOn(ctx, x, y - 1, z)) { + if (!MovementValidator.canWalkOn(ctx, x, y - 1, z)) { return } - if (!MovementHelper.canWalkThrough(ctx, currNode.x, currNode.y + 1, currNode.z)) { + if (!MovementValidator.canWalkThrough(ctx, currNode.x, currNode.y + 1, currNode.z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DescendMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/DescendMovement.kt similarity index 72% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DescendMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/walk/DescendMovement.kt index 873e9a4..cf33606 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DescendMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/DescendMovement.kt @@ -1,16 +1,17 @@ -package org.cobalt.pathfinder.movement.impl.walk +package org.cobalt.pathfinder.movement.walk import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator // TODO: Handle ladder & vine climbing downwards & falling down multiple blocks class DescendMovement( val dx: Int, val dz: Int, -) : Movement(Type.WALK) { +) : Movement(MovementType.WALK) { override fun calculateCost( ctx: CalculationContext, @@ -21,11 +22,11 @@ class DescendMovement( val y = currNode.y - 1 val z = currNode.z + dz - if (!MovementHelper.canWalkThrough(ctx, x, currNode.y, z)) { + if (!MovementValidator.canWalkThrough(ctx, x, currNode.y, z)) { return } - if (!MovementHelper.canWalkOn(ctx, x, y - 1, z)) { + if (!MovementValidator.canWalkOn(ctx, x, y - 1, z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DiagonalMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/DiagonalMovement.kt similarity index 65% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DiagonalMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/walk/DiagonalMovement.kt index c755311..182830e 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/DiagonalMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/DiagonalMovement.kt @@ -1,15 +1,16 @@ -package org.cobalt.pathfinder.movement.impl.walk +package org.cobalt.pathfinder.movement.walk import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator class DiagonalMovement( val dx: Int, val dz: Int, -) : Movement(Type.WALK) { +) : Movement(MovementType.WALK) { override fun calculateCost( ctx: CalculationContext, @@ -20,15 +21,15 @@ class DiagonalMovement( val y = currNode.y val z = currNode.z + dz - if (!MovementHelper.canWalkOn(ctx, x, y - 1, z)) { + if (!MovementValidator.canWalkOn(ctx, x, y - 1, z)) { return } - if (!MovementHelper.canWalkThrough(ctx, currNode.x + dx, y, currNode.z)) { + if (!MovementValidator.canWalkThrough(ctx, currNode.x + dx, y, currNode.z)) { return } - if (!MovementHelper.canWalkThrough(ctx, currNode.x, y, currNode.z + dz)) { + if (!MovementValidator.canWalkThrough(ctx, currNode.x, y, currNode.z + dz)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/TraverseMovement.kt b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/TraverseMovement.kt similarity index 74% rename from src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/TraverseMovement.kt rename to src/main/kotlin/org/cobalt/pathfinder/movement/walk/TraverseMovement.kt index f7c4150..3aef99b 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/movement/impl/walk/TraverseMovement.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/movement/walk/TraverseMovement.kt @@ -1,15 +1,16 @@ -package org.cobalt.pathfinder.movement.impl.walk +package org.cobalt.pathfinder.movement.walk import org.cobalt.pathfinder.calculate.PathNode import org.cobalt.pathfinder.movement.CalculationContext import org.cobalt.pathfinder.movement.Movement -import org.cobalt.pathfinder.movement.MovementHelper import org.cobalt.pathfinder.movement.MovementResult +import org.cobalt.pathfinder.movement.MovementType +import org.cobalt.pathfinder.movement.MovementValidator class TraverseMovement( val dx: Int, val dz: Int, -) : Movement(Type.WALK) { +) : Movement(MovementType.WALK) { override fun calculateCost( ctx: CalculationContext, @@ -20,7 +21,7 @@ class TraverseMovement( val y = currNode.y val z = currNode.z + dz - if (!MovementHelper.canWalkOn(ctx, x, y - 1, z)) { + if (!MovementValidator.canWalkOn(ctx, x, y - 1, z)) { return } diff --git a/src/main/kotlin/org/cobalt/pathfinder/precompute/PrecomputedData.kt b/src/main/kotlin/org/cobalt/pathfinder/precompute/PrecomputedData.kt deleted file mode 100644 index 48509fe..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/precompute/PrecomputedData.kt +++ /dev/null @@ -1,73 +0,0 @@ -package org.cobalt.pathfinder.precompute - -import net.minecraft.world.level.block.Block -import net.minecraft.world.level.block.state.BlockState -import org.cobalt.pathfinder.movement.CalculationContext -import org.cobalt.pathfinder.movement.MovementHelper - -class PrecomputedData { - - private val data = ByteArray(Block.BLOCK_STATE_REGISTRY.size()) - - companion object { - private const val COMPLETED_MASK = 1 shl 0 - private const val CAN_PASS_THROUGH_MAYBE_MASK = 1 shl 1 - private const val CAN_PASS_THROUGH_MASK = 1 shl 2 - private const val CAN_STAND_ON_MAYBE_MASK = 1 shl 3 - private const val CAN_STAND_ON_MASK = 1 shl 4 - } - - private fun fillData(id: Int, state: BlockState): Byte { - var blockData = 0 - - when (MovementHelper.canPassThroughState(state)) { - Ternary.YES -> blockData = 0 or CAN_PASS_THROUGH_MASK - Ternary.MAYBE -> blockData = 0 or CAN_PASS_THROUGH_MAYBE_MASK - Ternary.NO -> {} - } - - when (MovementHelper.canStandOnState(state)) { - Ternary.YES -> blockData = blockData or CAN_STAND_ON_MASK - Ternary.MAYBE -> blockData = blockData or CAN_STAND_ON_MAYBE_MASK - Ternary.NO -> {} - } - - blockData = blockData or COMPLETED_MASK - - val byteResult = blockData.toByte() - data[id] = byteResult - - return byteResult - } - - fun canPassThrough(ctx: CalculationContext, x: Int, y: Int, z: Int, state: BlockState): Boolean { - val id = Block.BLOCK_STATE_REGISTRY.getId(state) - var blockData = data[id].toInt() - - if ((blockData and COMPLETED_MASK) == 0) { - blockData = fillData(id, state).toInt() - } - - return if ((blockData and CAN_PASS_THROUGH_MAYBE_MASK) != 0) { - MovementHelper.canPassThrough(ctx.bsa, x, y, z, state) - } else { - (blockData and CAN_PASS_THROUGH_MASK) != 0 - } - } - - fun canStandOn(ctx: CalculationContext, x: Int, y: Int, z: Int, state: BlockState): Boolean { - val id = Block.BLOCK_STATE_REGISTRY.getId(state) - var blockData = data[id].toInt() - - if ((blockData and COMPLETED_MASK) == 0) { - blockData = fillData(id, state).toInt() - } - - return if ((blockData and CAN_STAND_ON_MAYBE_MASK) != 0) { - MovementHelper.canStandOn(ctx.bsa, x, y, z, state) - } else { - (blockData and CAN_STAND_ON_MASK) != 0 - } - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/precompute/Ternary.kt b/src/main/kotlin/org/cobalt/pathfinder/precompute/Ternary.kt deleted file mode 100644 index 9492e01..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/precompute/Ternary.kt +++ /dev/null @@ -1,5 +0,0 @@ -package org.cobalt.pathfinder.precompute - -enum class Ternary { - YES, MAYBE, NO -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/ExecutorState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/ExecutorState.kt index 7d6d22d..0b60899 100644 --- a/src/main/kotlin/org/cobalt/pathfinder/state/ExecutorState.kt +++ b/src/main/kotlin/org/cobalt/pathfinder/state/ExecutorState.kt @@ -1,12 +1,12 @@ package org.cobalt.pathfinder.state import org.cobalt.pathfinder.PathExecutor -import org.cobalt.pathfinder.PathInput +import org.cobalt.pathfinder.helper.PlayerInput abstract class ExecutorState { - protected val input: PathInput = - PathExecutor.pathInput + protected val playerInput: PlayerInput = + PathExecutor.playerInput open fun enter() {} open fun onTick() {} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/calculation/CalculatingState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/calculation/CalculatingState.kt new file mode 100644 index 0000000..9f4ada2 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/state/calculation/CalculatingState.kt @@ -0,0 +1,57 @@ +package org.cobalt.pathfinder.state.calculation + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job +import kotlinx.coroutines.isActive +import kotlinx.coroutines.launch +import org.cobalt.pathfinder.PathExecutor +import org.cobalt.pathfinder.calculate.path.AStarPathfinder +import org.cobalt.pathfinder.state.ExecutorState +import org.cobalt.pathfinder.state.pathing.PathingState +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.client.PlayerUtils + +class CalculatingState : ExecutorState() { + + private var calculationJob: Job? = null + + override fun enter() { + val config = PathExecutor.config ?: run { + ChatUtils.sendSystemMessage("Cannot calculate path, no path config set!") + PathExecutor.stop() + return + } + + val startPos = PlayerUtils.position + val goal = config.goal + + calculationJob = CoroutineScope(Dispatchers.Default).launch { + val path = AStarPathfinder( + startPos.x, startPos.y, startPos.z, + goal, config.mode, + config.returnBestNode, + config.maxCalculationTime + ).findPath() + + if (!isActive) { + return@launch + } + + if (path == null) { + ChatUtils.sendSystemMessage("Unable to find a path") + PathExecutor.stop() + return@launch + } + + PathExecutor.path = path + PathExecutor.changeState(PathingState()) + } + } + + override fun exit() { + calculationJob?.cancel() + calculationJob = null + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/fly/StartFlyState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/fly/StartFlyState.kt new file mode 100644 index 0000000..7443363 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/state/fly/StartFlyState.kt @@ -0,0 +1,67 @@ +package org.cobalt.pathfinder.state.fly + +import org.cobalt.pathfinder.PathExecutor +import org.cobalt.pathfinder.state.ExecutorState +import org.cobalt.pathfinder.state.pathing.PathingState +import org.cobalt.util.client.PlayerUtils + +class StartFlyState : ExecutorState() { + + private var flyStage = FlyStage.INITIAL_JUMP + + override fun enter() { + flyStage = FlyStage.INITIAL_JUMP + } + + override fun onTick() { + if (handleFlyStart()) { + return + } + + PathExecutor.changeState(PathingState()) + } + + private fun handleFlyStart(): Boolean { + if (PlayerUtils.isFlying) { + flyStage = FlyStage.INITIAL_JUMP + return false + } + + if (PlayerUtils.onGround) { + flyStage = FlyStage.INITIAL_JUMP + } + + playerInput.stopMovement() + + when (flyStage) { + FlyStage.INITIAL_JUMP -> { + playerInput.jump = true + flyStage = FlyStage.RELEASE_INITIAL_JUMP + } + + FlyStage.RELEASE_INITIAL_JUMP -> { + playerInput.jump = false + flyStage = FlyStage.SECOND_JUMP + } + + FlyStage.SECOND_JUMP -> { + playerInput.jump = true + flyStage = FlyStage.RELEASE_SECOND_JUMP + } + + FlyStage.RELEASE_SECOND_JUMP -> { + playerInput.jump = false + } + } + + return true + } + + private enum class FlyStage { + INITIAL_JUMP, + RELEASE_INITIAL_JUMP, + SECOND_JUMP, + RELEASE_SECOND_JUMP, + } + +} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/impl/CalculatingState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/impl/CalculatingState.kt deleted file mode 100644 index 2135381..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/state/impl/CalculatingState.kt +++ /dev/null @@ -1,42 +0,0 @@ -package org.cobalt.pathfinder.state.impl - -import org.cobalt.pathfinder.PathExecutor -import org.cobalt.pathfinder.calculate.path.AStarPathfinder -import org.cobalt.pathfinder.state.ExecutorState -import org.cobalt.util.ChatUtils -import org.cobalt.util.MessageType -import org.cobalt.util.PlayerUtils -import org.cobalt.util.helper.Multithreading - -class CalculatingState : ExecutorState() { - - override fun enter() { - val config = PathExecutor.config ?: return - val startPos = PlayerUtils.position - - val pathFinder = AStarPathfinder( - startPos.x, startPos.y, startPos.z, - config.goal, config.movements, - config.returnBestNode - ) - - Multithreading.runAsync { - val path = pathFinder.findPath() - - if (path == null) { - ChatUtils.sendSystemMessage("Unable to find a path") - PathExecutor.stop() - return@runAsync - } - - PathExecutor.path = path - PathExecutor.changeState(PathingState()) - - ChatUtils.sendSystemMessage( - "Found ${path.nodes.size} node path in ${path.timeElapsed.inWholeMilliseconds}ms", - MessageType.DEBUG - ) - } - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/impl/PathingState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/impl/PathingState.kt deleted file mode 100644 index 5dc591a..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/state/impl/PathingState.kt +++ /dev/null @@ -1,236 +0,0 @@ -package org.cobalt.pathfinder.state.impl - -import java.awt.Color -import kotlin.math.abs -import kotlin.random.Random -import net.minecraft.core.BlockPos -import net.minecraft.world.phys.AABB -import org.cobalt.Cobalt.minecraft -import org.cobalt.dsl.centerVec -import org.cobalt.module.impl.misc.Debug -import org.cobalt.module.impl.misc.Rotations -import org.cobalt.pathfinder.PathExecutor -import org.cobalt.pathfinder.calculate.PathNode -import org.cobalt.pathfinder.helper.PlayerInput -import org.cobalt.pathfinder.movement.MovementHelper -import org.cobalt.pathfinder.state.ExecutorState -import org.cobalt.util.PlayerUtils -import org.cobalt.util.RotationUtils -import org.cobalt.util.WorldRenderUtils -import org.cobalt.util.helper.Clock -import org.cobalt.util.rotation.RotationTarget - -class PathingState : ExecutorState() { - - private val path = PathExecutor.path - private val config = PathExecutor.config - private val jumpDelay = Clock() - - private inline val pathIndex: Int - get() = PathExecutor.pathIndex - - override fun exit() { - input.stopMovement() - Rotations.stop() - } - - override fun onTick() { - if (path == null || config == null) { - PathExecutor.stop() - return - } - - val player = PlayerUtils.player ?: return - val nodes = path.nodes - val node = nodes[pathIndex] - val playerPos = PlayerUtils.position - - if ( - advanceReachedNodes(playerPos, nodes) || - shouldStartFlying(node) - ) { - return - } - - val sameXZ = node.block.x == playerPos.x && node.block.z == playerPos.z - val movement = buildPlayerInput(playerPos, node, nodes, sameXZ) - val lookTarget = MovementHelper.getRotationTarget( - player.eyePosition, nodes, pathIndex - ) - - Rotations.track(RotationTarget(lookTarget)) - input.applyInput(movement) - } - - override fun onRender() { - if (path == null || config == null) { - PathExecutor.stop() - return - } - - if (!Debug.enabled) { - return - } - - val lookAhead = (PlayerUtils.velocity.length() * 6.0).coerceIn(5.0, 32.0) - val target = MovementHelper.getRotationTarget( - PlayerUtils.player!!.eyePosition, path.nodes, pathIndex, lookAhead - ) - - WorldRenderUtils.drawBox( - AABB( - target.x - 0.25, target.y - 0.25, target.z - 0.25, - target.x + 0.25, target.y + 0.25, target.z + 0.25 - ), Color.GREEN - ) - } - - private fun advanceReachedNodes(playerPos: BlockPos, nodes: List): Boolean { - if (!hasReached(playerPos, nodes, pathIndex)) { - return false - } - - while ( - pathIndex + 1 < nodes.size && - hasReached(playerPos, nodes, pathIndex) - ) { - PathExecutor.pathIndex++ - } - - if (pathIndex + 1 >= nodes.size) { - PathExecutor.stop() - } - - return true - } - - private fun shouldStartFlying(node: PathNode): Boolean { - if ( - !node.isFly || - !config!!.useFlyMovement || - !PlayerUtils.canFly || - PlayerUtils.isFlying - ) { - return false - } - - PathExecutor.changeState(StartFlyState()) - return true - } - - private fun buildPlayerInput( - playerPos: BlockPos, - node: PathNode, - nodes: List, - sameXZ: Boolean, - ): PlayerInput { - val index = pathIndex - val input = PlayerInput() - - if (!node.isFly || !sameXZ) { - val neededKeys = MovementHelper.getNeededKeys( - PlayerUtils.rotation.yaw, - RotationUtils.getRotation(node.centerVec).yaw - ) - - input.apply(neededKeys) - } - - if (!node.isFly) { - if (config!!.shouldSprint) input.sprint = true - if (shouldJump(playerPos, nodes, index)) input.jump = true - } - - if (node.isFly && sameXZ) { - val diffY = node.block.y - playerPos.y - when { - diffY > 0 -> input.jump = true - diffY < 0 -> input.sneak = true - } - } - - return input - } - - private fun hasReached( - playerPos: BlockPos, - nodes: List, - currentIndex: Int, - ): Boolean { - val level = minecraft.level ?: return false - val node = nodes[currentIndex] - - if (node.isFly) { - return false - } - - val nodeCenter = node.centerVec - val playerVec = playerPos.centerVec() - - if (playerVec.distanceToSqr(nodeCenter) < 0.3 * 0.3) { - return true - } - - if (currentIndex + 1 >= nodes.size) { - return false - } - - val isSlab = MovementHelper.isBottomSlab(level.getBlockState(node.blockStandingOn)) - - if (!isSlab && (node.block.y > playerPos.y || !PlayerUtils.onGround)) { - return false - } - - val segment = nodes[currentIndex + 1].centerVec.subtract(nodeCenter) - val toPlayer = playerVec.subtract(nodeCenter) - - if (toPlayer.dot(segment) < 0.0) { - return false - } - - val perpDistSq = toPlayer.cross(segment).lengthSqr() / segment.lengthSqr() - return perpDistSq < 1.0 - } - - private fun shouldJump( - playerPos: BlockPos, - nodes: List, - currentIndex: Int, - ): Boolean { - val level = minecraft.level ?: return false - - if (!PlayerUtils.onGround || !jumpDelay.passed()) { - return false - } - - val node = nodes[currentIndex] - - if (node.block.y - playerPos.y < 1) { - return false - } - - if (MovementHelper.isBottomSlab(level.getBlockState(node.blockStandingOn))) { - return false - } - - val nodeCenter = node.centerVec - val playerVec = playerPos.centerVec() - val dx = abs(nodeCenter.x - playerVec.x) - val dz = abs(nodeCenter.z - playerVec.z) - - if (dx + dz > 1.2) { - return false - } - - if (minOf(dx, dz) > 0.2) { - return false - } - - if (PlayerUtils.canFly) { - jumpDelay.schedule(Random.nextLong(350, 450)) - } - - return true - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/impl/StartFlyState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/impl/StartFlyState.kt deleted file mode 100644 index d24e6fe..0000000 --- a/src/main/kotlin/org/cobalt/pathfinder/state/impl/StartFlyState.kt +++ /dev/null @@ -1,60 +0,0 @@ -package org.cobalt.pathfinder.state.impl - -import org.cobalt.Cobalt.minecraft -import org.cobalt.pathfinder.PathExecutor -import org.cobalt.pathfinder.state.ExecutorState -import org.cobalt.util.PlayerUtils - -class StartFlyState : ExecutorState() { - - private var flyStage = 0 - - override fun enter() { - flyStage = 0 - } - - override fun onTick() { - if (handleFlyStart()) { - return - } - - PathExecutor.changeState(PathingState()) - } - - private fun handleFlyStart(): Boolean { - if (PlayerUtils.isFlying) { - flyStage = 0 - return false - } - - if (PlayerUtils.onGround) { - flyStage = 0 - } - - input.stopMovement() - - when (flyStage) { - 0 -> { - input.jump = true - flyStage = 1 - } - - 1 -> { - input.jump = false - flyStage = 2 - } - - 2 -> { - input.jump = true - flyStage = 3 - } - - 3 -> { - input.jump = false - } - } - - return true - } - -} diff --git a/src/main/kotlin/org/cobalt/pathfinder/state/pathing/PathingState.kt b/src/main/kotlin/org/cobalt/pathfinder/state/pathing/PathingState.kt new file mode 100644 index 0000000..6483593 --- /dev/null +++ b/src/main/kotlin/org/cobalt/pathfinder/state/pathing/PathingState.kt @@ -0,0 +1,62 @@ +package org.cobalt.pathfinder.state.pathing + +import org.cobalt.pathfinder.PathExecutor +import org.cobalt.pathfinder.calculate.Path +import org.cobalt.pathfinder.calculate.PathNode +import org.cobalt.pathfinder.state.ExecutorState +import org.cobalt.pathfinder.state.fly.StartFlyState +import org.cobalt.util.chat.ChatUtils +import org.cobalt.util.chat.MessageType +import org.cobalt.util.client.PlayerUtils + +class PathingState : ExecutorState() { + + private var path: Path? = null + + private inline var currPathIndex + get() = PathExecutor.pathIndex + set(value) { + PathExecutor.pathIndex = value + } + + override fun enter() { + path = PathExecutor.path ?: run { + ChatUtils.sendSystemMessage("Cannot traverse a nonexistent path...") + PathExecutor.stop() + return + } + } + + override fun exit() { + playerInput.stopMovement() + } + + override fun onTick() { + val path = path ?: return + + val nodes = path.nodes + val targetNode = nodes[currPathIndex] + + if (targetNode.useMovementFly && PlayerUtils.canFly && !PlayerUtils.isFlying) { + PathExecutor.changeState(StartFlyState()) + } + + if (hasArrived(targetNode)) { + currPathIndex++ + + if (currPathIndex >= nodes.size) { + ChatUtils.sendSystemMessage("Completed Path!", MessageType.DEBUG) + PathExecutor.stop() + } + + return + } + + // TODO: ROTATIONS & MOVEMENT + } + + private fun hasArrived(node: PathNode): Boolean { + return node.block == PlayerUtils.position + } + +} diff --git a/src/main/kotlin/org/cobalt/ui/UIScreen.kt b/src/main/kotlin/org/cobalt/ui/UIScreen.kt index ee8e0cb..63944d2 100644 --- a/src/main/kotlin/org/cobalt/ui/UIScreen.kt +++ b/src/main/kotlin/org/cobalt/ui/UIScreen.kt @@ -6,7 +6,7 @@ import net.minecraft.client.input.CharacterEvent import net.minecraft.client.input.KeyEvent import net.minecraft.client.input.MouseButtonEvent import net.minecraft.network.chat.Component -import org.cobalt.util.skia.SkiaPIP +import org.cobalt.util.render.skia.SkiaPIP abstract class UIScreen : Screen(Component.empty()) { diff --git a/src/main/kotlin/org/cobalt/ui/component/ModuleComponent.kt b/src/main/kotlin/org/cobalt/ui/component/ModuleComponent.kt index 35c1701..49032b7 100644 --- a/src/main/kotlin/org/cobalt/ui/component/ModuleComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/ModuleComponent.kt @@ -3,7 +3,7 @@ package org.cobalt.ui.component import org.cobalt.module.Module import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.EaseOutAnimation -import org.cobalt.util.skia.Skia +import org.cobalt.util.render.SkiaRenderer class ModuleComponent( val module: Module, @@ -43,7 +43,7 @@ class ModuleComponent( } override fun renderComponent() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.backgroundSecondary ) @@ -58,13 +58,13 @@ class ModuleComponent( } if (settings.isNotEmpty() && expandProgress > 0f) { - Skia.line( + SkiaRenderer.line( xPos + PADDING, yPos + BASE_HEIGHT, xPos + width - PADDING, yPos + BASE_HEIGHT, 1f, theme.border ) - Skia.pushScissor(xPos, yPos + BASE_HEIGHT, width, expandedSettingsHeight * expandProgress) + SkiaRenderer.pushScissor(xPos, yPos + BASE_HEIGHT, width, expandedSettingsHeight * expandProgress) var settingY = yPos + BASE_HEIGHT + 6f @@ -75,17 +75,17 @@ class ModuleComponent( settingY += setting.height } - Skia.popScissor() + SkiaRenderer.popScissor() } - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, 5f, theme.border ) - Skia.text( - Skia.regularFont, module.name, + SkiaRenderer.text( + SkiaRenderer.regularFont, module.name, xPos + PADDING, yPos + (BASE_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, theme.textPrimary ) diff --git a/src/main/kotlin/org/cobalt/ui/component/ScriptComponent.kt b/src/main/kotlin/org/cobalt/ui/component/ScriptComponent.kt index 178b00f..9b7e164 100644 --- a/src/main/kotlin/org/cobalt/ui/component/ScriptComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/ScriptComponent.kt @@ -1,15 +1,15 @@ package org.cobalt.ui.component -import org.cobalt.dsl.updateAlpha import org.cobalt.module.type.Script import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation import org.cobalt.ui.screen.ConfigScreen -import org.cobalt.util.MouseUtils -import org.cobalt.util.helper.TickScheduler -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.helper.SkiaImage +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.data.SkiaImage +import org.cobalt.util.scheduling.TickScheduler class ScriptComponent(val script: Script) : UIComponent( width = WIDTH, @@ -19,44 +19,44 @@ class ScriptComponent(val script: Script) : UIComponent( private val colorAnim = ColorAnimation(200L) private val alphaAnim = EaseOutAnimation(200L) private val backgroundPicture: SkiaImage? = if (script.backgroundResourcePath.isNotBlank()) { - Skia.createImage(script.backgroundResourcePath) + SkiaRenderer.createImage(script.backgroundResourcePath) } else { null } override fun renderComponent() { backgroundPicture?.let { - val (imageWidth, imageHeight) = Skia.imageSize(it) + val (imageWidth, imageHeight) = SkiaRenderer.imageSize(it) val scale = maxOf(width / imageWidth, height / imageHeight) val drawWidth = imageWidth * scale val drawHeight = imageHeight * scale val drawX = xPos + (width - drawWidth) / 2f val drawY = yPos + (height - drawHeight) / 2f - Skia.pushScissor(xPos, yPos, width, height, 5f) - Skia.blurredImage( + SkiaRenderer.pushScissor(xPos, yPos, width, height, 5f) + SkiaRenderer.blurredImage( it, drawX, drawY, drawWidth, drawHeight, radius = 2f, cornerRadius = 5f ) - Skia.popScissor() + SkiaRenderer.popScissor() } val borderColor = colorAnim.get(theme.border, theme.textMuted, !script.enabled) val alpha = alphaAnim.get(0f, 255f, !script.enabled).toInt() - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.backgroundPrimary.updateAlpha(100) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, 5f, borderColor ) if (script.enabled) { - Skia.image( + SkiaRenderer.image( pauseIcon, xPos + (width - ICON_SIZE) / 2, yPos + (height - ICON_SIZE) / 2, @@ -65,15 +65,15 @@ class ScriptComponent(val script: Script) : UIComponent( ) } - Skia.text( - Skia.regularFont, script.name, + SkiaRenderer.text( + SkiaRenderer.regularFont, script.name, xPos + PADDING, yPos + height - PADDING - FONT_SIZE, FONT_SIZE, theme.textPrimary ) } override fun mouseClicked(button: Int): Boolean { - if (button == 0 && MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (button == 0 && Mouse.isHoveringOver(xPos, yPos, width, height)) { colorAnim.start() if (script.enabled) { @@ -91,7 +91,7 @@ class ScriptComponent(val script: Script) : UIComponent( companion object { val WIDTH = (TopbarComponent.width - 60) / 2f - val pauseIcon = Skia.createImage("/assets/cobalt/ui/pause.svg") + val pauseIcon = SkiaRenderer.createImage("/assets/cobalt/ui/pause.svg") private const val PADDING = 20f private const val FONT_SIZE = 20f diff --git a/src/main/kotlin/org/cobalt/ui/component/SidebarComponent.kt b/src/main/kotlin/org/cobalt/ui/component/SidebarComponent.kt index 3169a32..811b200 100644 --- a/src/main/kotlin/org/cobalt/ui/component/SidebarComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/SidebarComponent.kt @@ -4,10 +4,10 @@ import org.cobalt.Cobalt.minecraft import org.cobalt.module.ModuleCategory import org.cobalt.ui.UIComponent import org.cobalt.ui.component.button.SidebarButton -import org.cobalt.util.helper.Multithreading -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.helper.SkiaCorner -import org.cobalt.util.skia.helper.SkiaImage +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.data.SkiaCorner +import org.cobalt.util.render.skia.data.SkiaImage +import org.cobalt.util.scheduling.Multithreading object SidebarComponent : UIComponent( width = 250f, @@ -15,7 +15,7 @@ object SidebarComponent : UIComponent( ) { private val buttons = mutableListOf() - private val steveFace = Skia.createImage("/assets/cobalt/ui/steve.png") + private val steveFace = SkiaRenderer.createImage("/assets/cobalt/ui/steve.png") private var playerFace: SkiaImage? = null init { @@ -26,23 +26,23 @@ object SidebarComponent : UIComponent( } Multithreading.runAsync { - playerFace = Skia.createImage("https://mc-heads.net/avatar/${minecraft.user.name}/100/face.png") + playerFace = SkiaRenderer.createImage("https://mc-heads.net/avatar/${minecraft.user.name}/100/face.png") } } override fun renderComponent() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 10f, theme.backgroundSecondary, SkiaCorner.LEFT_SIDE ) - val titleTextWidth = Skia.textWidth(Skia.boldFont, TITLE_TEXT, TITLE_FONT_SIZE) + val titleTextWidth = SkiaRenderer.textWidth(SkiaRenderer.boldFont, TITLE_TEXT, TITLE_FONT_SIZE) val titleTextX = xPos + (width - titleTextWidth) / 2 val titleTextY = yPos + TITLE_PADDING - Skia.text( - Skia.boldFont, TITLE_TEXT, + SkiaRenderer.text( + SkiaRenderer.boldFont, TITLE_TEXT, titleTextX, titleTextY, TITLE_FONT_SIZE, theme.textPrimary ) @@ -65,12 +65,12 @@ object SidebarComponent : UIComponent( val boxX = xPos + USER_INFO_OUTER_PADDING val boxY = yPos + height - (USER_INFO_HEIGHT + USER_INFO_OUTER_PADDING) - Skia.roundedRect( + SkiaRenderer.roundedRect( boxX, boxY, USER_INFO_WIDTH, USER_INFO_HEIGHT, USER_INFO_CORNER_RADIUS, theme.backgroundPrimary, ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( boxX, boxY, USER_INFO_WIDTH, USER_INFO_HEIGHT, 1f, USER_INFO_CORNER_RADIUS, theme.border ) @@ -78,14 +78,14 @@ object SidebarComponent : UIComponent( val playerFaceX = boxX + USER_INFO_INNER_PADDING val playerFaceY = boxY + (USER_INFO_HEIGHT - PLAYER_FACE_SIDE_LENGTH) / 2 - Skia.image( + SkiaRenderer.image( playerFace ?: steveFace, playerFaceX, playerFaceY, PLAYER_FACE_SIDE_LENGTH, PLAYER_FACE_SIDE_LENGTH, PLAYER_FACE_SIDE_LENGTH / 2 ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( playerFaceX, playerFaceY, PLAYER_FACE_SIDE_LENGTH, PLAYER_FACE_SIDE_LENGTH, 1f, PLAYER_FACE_SIDE_LENGTH / 2, theme.border @@ -94,13 +94,13 @@ object SidebarComponent : UIComponent( val textX = boxX + PLAYER_FACE_SIDE_LENGTH + (USER_INFO_INNER_PADDING * 2) val textY = boxY + USER_INFO_INNER_PADDING - Skia.text( - Skia.regularFont, minecraft.gameProfile.name, + SkiaRenderer.text( + SkiaRenderer.regularFont, minecraft.gameProfile.name, textX, textY, USER_INFO_TEXT_SIZE, theme.textPrimary ) - Skia.text( - Skia.regularFont, "User", + SkiaRenderer.text( + SkiaRenderer.regularFont, "User", textX, textY + USER_INFO_TEXT_SIZE + 2f, USER_INFO_TEXT_SIZE, theme.textSecondary, ) diff --git a/src/main/kotlin/org/cobalt/ui/component/SwitchComponent.kt b/src/main/kotlin/org/cobalt/ui/component/SwitchComponent.kt index e16988a..c2b7a8d 100644 --- a/src/main/kotlin/org/cobalt/ui/component/SwitchComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/SwitchComponent.kt @@ -4,8 +4,8 @@ import org.cobalt.module.Module import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class SwitchComponent(val module: Module) : UIComponent( width = 30f, @@ -19,12 +19,12 @@ class SwitchComponent(val module: Module) : UIComponent( val mainColor = colorAnimation.get(theme.backgroundPrimary, theme.accentPrimary, !module.enabled) val knobX = xOffsetAnimation.get(xPos + 1f, xPos + width - KNOB_SIZE - 1f, !module.enabled) - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, mainColor ) - Skia.circle( + SkiaRenderer.circle( knobX + KNOB_SIZE / 2f, yPos + height / 2f, KNOB_SIZE / 2f, @@ -33,7 +33,7 @@ class SwitchComponent(val module: Module) : UIComponent( } override fun mouseClicked(button: Int): Boolean { - if (button == 0 && MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (button == 0 && Mouse.isHoveringOver(xPos, yPos, width, height)) { module.enabled = !module.enabled colorAnimation.start() xOffsetAnimation.start() diff --git a/src/main/kotlin/org/cobalt/ui/component/TextInputComponent.kt b/src/main/kotlin/org/cobalt/ui/component/TextInputComponent.kt index 4d6408f..a8fb370 100644 --- a/src/main/kotlin/org/cobalt/ui/component/TextInputComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/TextInputComponent.kt @@ -3,11 +3,11 @@ package org.cobalt.ui.component import java.util.function.Consumer import net.minecraft.client.input.CharacterEvent import net.minecraft.client.input.KeyEvent -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.UIComponent import org.cobalt.ui.helper.TextInputHelper -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class TextInputComponent( width: Float, @@ -27,7 +27,7 @@ class TextInputComponent( override fun renderComponent() { inputHandler.updateBounds(xPos, yPos, width, height) - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.backgroundPrimary @@ -43,12 +43,12 @@ class TextInputComponent( val textX = xPos + TEXT_PADDING - xOffset val textY = yPos + (height - fontSize) / 2 - Skia.pushScissor(xPos, yPos, width, height) + SkiaRenderer.pushScissor(xPos, yPos, width, height) drawSelection(textX, textY) - Skia.text( - Skia.regularFont, + SkiaRenderer.text( + SkiaRenderer.regularFont, currentText, textX, textY, fontSize, textColor @@ -56,15 +56,15 @@ class TextInputComponent( if (inputHandler.focused && (System.currentTimeMillis() / 500) % 2 == 0L) { val caretX = textX + caretOffset - Skia.rect( + SkiaRenderer.rect( caretX, textY, 1.5f, fontSize, theme.textPrimary ) } - Skia.popScissor() - Skia.roundedOutline( + SkiaRenderer.popScissor() + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, 5f, theme.border @@ -92,12 +92,12 @@ class TextInputComponent( inputHandler.text.substring(0, inputHandler.selectionEnd) } - val selStartX = textX + Skia.textWidth(Skia.regularFont, selStartPrefix, fontSize) - val selEndX = textX + Skia.textWidth(Skia.regularFont, selEndPrefix, fontSize) + val selStartX = textX + SkiaRenderer.textWidth(SkiaRenderer.regularFont, selStartPrefix, fontSize) + val selEndX = textX + SkiaRenderer.textWidth(SkiaRenderer.regularFont, selEndPrefix, fontSize) val selWidth = selEndX - selStartX val selectionColor = theme.textPrimary.updateAlpha(40) - Skia.rect( + SkiaRenderer.rect( selStartX, textY, selWidth, fontSize, selectionColor @@ -123,11 +123,11 @@ class TextInputComponent( inputHandler.text.substring(0, inputHandler.caretIndex) } - return Skia.textWidth(Skia.regularFont, caretPrefix, fontSize) + return SkiaRenderer.textWidth(SkiaRenderer.regularFont, caretPrefix, fontSize) } private fun updateScrollOffset(currentText: String, maxTextWidth: Float, caretOffset: Float) { - val textWidth = Skia.textWidth(Skia.regularFont, currentText, fontSize) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, currentText, fontSize) if (textWidth <= maxTextWidth) { xOffset = 0f @@ -141,7 +141,7 @@ class TextInputComponent( } override fun mouseClicked(button: Int): Boolean { - val relativeX = MouseUtils.mouseX - (xPos + TEXT_PADDING - xOffset) + val relativeX = Mouse.mouseX - (xPos + TEXT_PADDING - xOffset) return inputHandler.mouseClicked(button, relativeX) || super.mouseClicked(button) } @@ -150,7 +150,7 @@ class TextInputComponent( } override fun mouseDragged(button: Int, offsetX: Double, offsetY: Double): Boolean { - val relativeX = MouseUtils.mouseX - (xPos + TEXT_PADDING - xOffset) + val relativeX = Mouse.mouseX - (xPos + TEXT_PADDING - xOffset) return inputHandler.mouseDragged(button, relativeX) || super.mouseDragged(button, offsetX, offsetY) } diff --git a/src/main/kotlin/org/cobalt/ui/component/ThemeComponent.kt b/src/main/kotlin/org/cobalt/ui/component/ThemeComponent.kt index 40a00ee..fd04262 100644 --- a/src/main/kotlin/org/cobalt/ui/component/ThemeComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/ThemeComponent.kt @@ -1,11 +1,11 @@ package org.cobalt.ui.component -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.UIComponent import org.cobalt.ui.theme.Theme import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class ThemeComponent(val newTheme: Theme) : UIComponent( width = WIDTH, @@ -13,13 +13,13 @@ class ThemeComponent(val newTheme: Theme) : UIComponent( ) { override fun renderComponent() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, newTheme.accentPrimary.updateAlpha(40) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, 5f, newTheme.accentPrimary @@ -28,8 +28,8 @@ class ThemeComponent(val newTheme: Theme) : UIComponent( val startX = xPos + INNER_PADDING var startY = yPos + INNER_PADDING - Skia.text( - Skia.regularFont, newTheme.name, + SkiaRenderer.text( + SkiaRenderer.regularFont, newTheme.name, startX, startY, THEME_NAME_FONT_SIZE, theme.textPrimary ) @@ -39,21 +39,21 @@ class ThemeComponent(val newTheme: Theme) : UIComponent( val textColor = if (isActive) theme.success else theme.textMuted val statusY = startY + THEME_NAME_FONT_SIZE + TEXT_PADDING - Skia.text( - Skia.regularFont, text, + SkiaRenderer.text( + SkiaRenderer.regularFont, text, startX, statusY, STATUS_FONT_SIZE, textColor ) startY = yPos + height - SWATCH_HEIGHT - INNER_PADDING - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, SWATCH_WIDTH, SWATCH_HEIGHT, 2.5f, newTheme.accentPrimary ) - Skia.roundedRect( + SkiaRenderer.roundedRect( startX + SWATCH_WIDTH + SWATCH_PADDING, startY, SWATCH_WIDTH, SWATCH_HEIGHT, 2.5f, newTheme.accentSecondary @@ -61,7 +61,7 @@ class ThemeComponent(val newTheme: Theme) : UIComponent( } override fun mouseClicked(button: Int): Boolean { - val isHovered = MouseUtils.isHoveringOver(xPos, yPos, width, height) + val isHovered = Mouse.isHoveringOver(xPos, yPos, width, height) if (button != 0 || !isHovered) { return false diff --git a/src/main/kotlin/org/cobalt/ui/component/TopbarComponent.kt b/src/main/kotlin/org/cobalt/ui/component/TopbarComponent.kt index 7ce9fba..f3f6a4a 100644 --- a/src/main/kotlin/org/cobalt/ui/component/TopbarComponent.kt +++ b/src/main/kotlin/org/cobalt/ui/component/TopbarComponent.kt @@ -7,9 +7,9 @@ import org.cobalt.ui.page.impl.ScriptsPage import org.cobalt.ui.page.impl.ThemesPage import org.cobalt.ui.screen.ConfigScreen import org.cobalt.ui.screen.HudEditorScreen -import org.cobalt.util.helper.TickScheduler -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.helper.SkiaCorner +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.data.SkiaCorner +import org.cobalt.util.scheduling.TickScheduler object TopbarComponent : UIComponent() { @@ -51,7 +51,7 @@ object TopbarComponent : UIComponent() { override fun renderComponent() { val currentPage = ConfigScreen.currentPage - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 10f, theme.backgroundSecondary, @@ -61,8 +61,8 @@ object TopbarComponent : UIComponent() { val textX = xPos + INNER_PADDING + 10f val textY = yPos + (height - CURRENT_PAGE_TITLE_FONT) / 2 - Skia.text( - Skia.regularFont, currentPage.title, + SkiaRenderer.text( + SkiaRenderer.regularFont, currentPage.title, textX, textY, CURRENT_PAGE_TITLE_FONT, theme.textPrimary ) diff --git a/src/main/kotlin/org/cobalt/ui/component/button/IconButton.kt b/src/main/kotlin/org/cobalt/ui/component/button/IconButton.kt index 270a8f6..d615723 100644 --- a/src/main/kotlin/org/cobalt/ui/component/button/IconButton.kt +++ b/src/main/kotlin/org/cobalt/ui/component/button/IconButton.kt @@ -1,11 +1,11 @@ package org.cobalt.ui.component.button -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class IconButton( resourcePath: String, @@ -15,14 +15,14 @@ class IconButton( height = 40f ) { - private val icon = Skia.createImage(resourcePath) + private val icon = SkiaRenderer.createImage(resourcePath) private val colorAnimation = ColorAnimation(150L) private val alphaAnimation = EaseOutAnimation(150L) private var wasHovering = false override fun renderComponent() { - val hovering = MouseUtils.isHoveringOver(xPos, yPos, width, height) + val hovering = Mouse.isHoveringOver(xPos, yPos, width, height) if (hovering != wasHovering) { colorAnimation.start() @@ -34,19 +34,19 @@ class IconButton( val borderColor = colorAnimation.get(theme.border, theme.accentPrimary, !hovering) val iconColor = colorAnimation.get(theme.textMuted, theme.accentPrimary, !hovering) - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.backgroundPrimary ) - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, 5f, theme.accentPrimary.updateAlpha(alpha) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, 5f, borderColor @@ -55,14 +55,14 @@ class IconButton( val iconX = xPos + (width - ICON_SIZE) / 2f val iconY = yPos + (height - ICON_SIZE) / 2f - Skia.image( + SkiaRenderer.image( icon, iconX, iconY, ICON_SIZE, ICON_SIZE, color = iconColor ) } override fun mouseClicked(button: Int): Boolean { - if (button != 0 || !MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (button != 0 || !Mouse.isHoveringOver(xPos, yPos, width, height)) { return false } diff --git a/src/main/kotlin/org/cobalt/ui/component/button/SidebarButton.kt b/src/main/kotlin/org/cobalt/ui/component/button/SidebarButton.kt index 0544741..e7a6feb 100644 --- a/src/main/kotlin/org/cobalt/ui/component/button/SidebarButton.kt +++ b/src/main/kotlin/org/cobalt/ui/component/button/SidebarButton.kt @@ -1,21 +1,21 @@ package org.cobalt.ui.component.button -import org.cobalt.dsl.updateAlpha import org.cobalt.module.ModuleCategory import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation import org.cobalt.ui.page.impl.ModulesPage import org.cobalt.ui.screen.ConfigScreen -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class SidebarButton(val category: ModuleCategory) : UIComponent( width = WIDTH, height = HEIGHT ) { - private val icon = Skia.createImage(category.iconPath) + private val icon = SkiaRenderer.createImage(category.iconPath) private val colorAnimation = ColorAnimation(150L) private val xOffsetAnimation = EaseOutAnimation(200L) @@ -38,14 +38,14 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( val xOffset = xOffsetAnimation.get(0F, TEXT_SELECTED_OFFSET, !isSelectedNow) if (isSelectedNow) { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, CORNER_RADIUS, opaqueColor ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos, yPos, width, height, 1f, CORNER_RADIUS, mainColor @@ -55,7 +55,7 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( val iconX = xPos + ICON_LEFT_PADDING fun iconY(iconSize: Float) = yPos + (height - iconSize) / 2F - Skia.image( + SkiaRenderer.image( icon, iconX + xOffset, iconY(ICON_SIZE), ICON_SIZE, ICON_SIZE, @@ -63,7 +63,7 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( ) if (isSelectedNow) { - Skia.image( + SkiaRenderer.image( selectedIcon, iconX, iconY(SELECTION_ICON_SIZE), SELECTION_ICON_SIZE, SELECTION_ICON_SIZE, @@ -74,8 +74,8 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( val textX = iconX + ICON_SIZE + ICON_TEXT_PADDING val textY = yPos + height / 2F - FONT_SIZE / 2F - Skia.text( - Skia.regularFont, + SkiaRenderer.text( + SkiaRenderer.regularFont, category.displayName, textX + xOffset, textY, FONT_SIZE, textColor @@ -83,7 +83,7 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( } override fun mouseClicked(button: Int): Boolean { - if (button == 0 && MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (button == 0 && Mouse.isHoveringOver(xPos, yPos, width, height)) { ConfigScreen.currentPage = ModulesPage ConfigScreen.selectedCategory = category return true @@ -104,7 +104,7 @@ class SidebarButton(val category: ModuleCategory) : UIComponent( private const val SELECTION_ICON_SIZE = 13f private const val TEXT_SELECTED_OFFSET = 17f - private val selectedIcon = Skia.createImage("/assets/cobalt/ui/selected.svg") + private val selectedIcon = SkiaRenderer.createImage("/assets/cobalt/ui/selected.svg") } } diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/Setting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/Setting.kt index 24b3cb8..319ab67 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/Setting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/Setting.kt @@ -8,7 +8,7 @@ import org.cobalt.ui.UIComponent import org.cobalt.ui.component.ModuleComponent import org.cobalt.ui.component.setting.impl.InfoSetting import org.cobalt.util.config.SettingContainer -import org.cobalt.util.skia.Skia +import org.cobalt.util.render.SkiaRenderer abstract class Setting( val name: String, @@ -31,15 +31,15 @@ abstract class Setting( val totalTextHeight = NAME_SIZE + extraHeight val textStartY = yPos + (BASE_HEIGHT - totalTextHeight) / 2 - Skia.text( - Skia.regularFont, name, + SkiaRenderer.text( + SkiaRenderer.regularFont, name, xPos + PADDING, textStartY, NAME_SIZE, theme.textPrimary ) if (description.isNotBlank()) { - Skia.text( - Skia.regularFont, description, + SkiaRenderer.text( + SkiaRenderer.regularFont, description, xPos + PADDING, textStartY + NAME_SIZE + TEXT_SPACING_Y, DESCRIPTION_SIZE, theme.textMuted ) diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/ButtonSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/ButtonSetting.kt index be53ee9..6e5cde3 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/ButtonSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/ButtonSetting.kt @@ -2,12 +2,12 @@ package org.cobalt.ui.component.setting.impl import com.google.gson.JsonElement import com.google.gson.JsonPrimitive -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class ButtonSetting( name: String, @@ -24,14 +24,14 @@ class ButtonSetting( private var wasHovering = false private val buttonWidth = - Skia.textWidth(Skia.regularFont, buttonLabel, FONT_SIZE) + 30f + SkiaRenderer.textWidth(SkiaRenderer.regularFont, buttonLabel, FONT_SIZE) + 30f override fun renderSetting() { val buttonWidth = buttonWidth val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 - val hovering = MouseUtils.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT) + val hovering = Mouse.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT) if (hovering != wasHovering) { colorAnim.start() @@ -43,28 +43,28 @@ class ButtonSetting( val borderColor = colorAnim.get(theme.border, theme.accentPrimary, !hovering) val textColor = colorAnim.get(theme.textPrimary, theme.accentPrimary, !hovering) - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, buttonWidth, BUTTON_HEIGHT, 5f, theme.backgroundPrimary ) - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, buttonWidth, BUTTON_HEIGHT, 5f, theme.accentPrimary.updateAlpha(alpha) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( startX, startY, buttonWidth, BUTTON_HEIGHT, 1f, 5f, borderColor ) - val textWidth = Skia.textWidth(Skia.regularFont, buttonLabel, FONT_SIZE) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, buttonLabel, FONT_SIZE) - Skia.text( - Skia.regularFont, buttonLabel, + SkiaRenderer.text( + SkiaRenderer.regularFont, buttonLabel, startX + (buttonWidth - textWidth) / 2, startY + (BUTTON_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, textColor @@ -75,7 +75,7 @@ class ButtonSetting( val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 - if (button == 0 && MouseUtils.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT)) { + if (button == 0 && Mouse.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT)) { onClick.run() return true } diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/CheckboxSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/CheckboxSetting.kt index d901457..18f30b8 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/CheckboxSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/CheckboxSetting.kt @@ -2,12 +2,12 @@ package org.cobalt.ui.component.setting.impl import com.google.gson.JsonElement import com.google.gson.JsonPrimitive -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.animation.ColorAnimation import org.cobalt.ui.animation.EaseOutAnimation import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class CheckboxSetting( name: String, @@ -34,19 +34,19 @@ class CheckboxSetting( val borderColor = colorAnimation.get(theme.border, theme.accentPrimary, !value) val bgColor = colorAnimation.get(theme.backgroundPrimary, theme.accentPrimary, !value) - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, SIZE, SIZE, 5f, bgColor.updateAlpha(alpha) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( startX, startY, SIZE, SIZE, 1f, 5f, borderColor ) - Skia.circle( + SkiaRenderer.circle( startX + SIZE / 2, startY + SIZE / 2, 2f, borderColor @@ -54,7 +54,7 @@ class CheckboxSetting( } override fun mouseClicked(button: Int): Boolean { - if (!MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (!Mouse.isHoveringOver(xPos, yPos, width, height)) { return false } diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/InfoSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/InfoSetting.kt index 3e3015d..e9f3f37 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/InfoSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/InfoSetting.kt @@ -2,9 +2,9 @@ package org.cobalt.ui.component.setting.impl import com.google.gson.JsonElement import com.google.gson.JsonPrimitive -import org.cobalt.dsl.updateAlpha import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.skia.Skia +import org.cobalt.util.color.updateAlpha +import org.cobalt.util.render.SkiaRenderer class InfoSetting( val text: String, @@ -15,13 +15,13 @@ class InfoSetting( override fun write(): JsonElement = JsonPrimitive("") override fun renderSetting() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos + INNER_PADDING, yPos + INNER_PADDING, width - (INNER_PADDING * 2), height - (INNER_PADDING * 2), 5f, color.updateAlpha(40) ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( xPos + INNER_PADDING, yPos + INNER_PADDING, width - (INNER_PADDING * 2), height - (INNER_PADDING * 2), 1f, 5f, color @@ -29,7 +29,7 @@ class InfoSetting( val imageY = yPos + 1f + (height - ICON_SIZE) / 2 - Skia.image( + SkiaRenderer.image( icon, xPos + PADDING, imageY, ICON_SIZE, ICON_SIZE, color = color @@ -38,8 +38,8 @@ class InfoSetting( val textX = xPos + ICON_SIZE + PADDING + 10f val textY = yPos + (height - NAME_SIZE) / 2 - Skia.text( - Skia.regularFont, text, + SkiaRenderer.text( + SkiaRenderer.regularFont, text, textX, textY, NAME_SIZE, color ) @@ -52,7 +52,7 @@ class InfoSetting( Type.ERROR -> theme.error } - private val icon = Skia.createImage( + private val icon = SkiaRenderer.createImage( when (type) { Type.INFO -> "/assets/cobalt/ui/info.svg" Type.WARNING -> "/assets/cobalt/ui/warning.svg" diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/KeyBindSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/KeyBindSetting.kt index 0058962..72378d2 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/KeyBindSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/KeyBindSetting.kt @@ -5,8 +5,8 @@ import com.google.gson.JsonPrimitive import com.mojang.blaze3d.platform.InputConstants import net.minecraft.client.input.KeyEvent import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer import org.lwjgl.glfw.GLFW class KeyBindSetting( @@ -35,28 +35,28 @@ class KeyBindSetting( get() = if (listening) "..." else value.displayName.string private val buttonWidth: Float - get() = Skia.textWidth(Skia.regularFont, displayText, FONT_SIZE) + 30f + get() = SkiaRenderer.textWidth(SkiaRenderer.regularFont, displayText, FONT_SIZE) + 30f override fun renderSetting() { val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, buttonWidth, BUTTON_HEIGHT, 5f, theme.backgroundPrimary ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( startX, startY, buttonWidth, BUTTON_HEIGHT, 1f, 5f, theme.border ) - val textWidth = Skia.textWidth(Skia.regularFont, displayText, FONT_SIZE) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, displayText, FONT_SIZE) - Skia.text( - Skia.regularFont, displayText, + SkiaRenderer.text( + SkiaRenderer.regularFont, displayText, startX + (buttonWidth - textWidth) / 2, startY + (BUTTON_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, theme.textPrimary @@ -66,7 +66,7 @@ class KeyBindSetting( override fun mouseClicked(button: Int): Boolean { val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 - val isHovered = MouseUtils.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT) + val isHovered = Mouse.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT) if (listening) { value = InputConstants.Type.MOUSE.getOrCreate(button) diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/ModeSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/ModeSetting.kt index b62260a..df21fc3 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/ModeSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/ModeSetting.kt @@ -3,8 +3,8 @@ package org.cobalt.ui.component.setting.impl import com.google.gson.JsonElement import com.google.gson.JsonPrimitive import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class ModeSetting( name: String, @@ -27,29 +27,29 @@ class ModeSetting( override fun renderSetting() { val display = options.getOrNull(value) ?: "" - val buttonWidth = Skia.textWidth(Skia.regularFont, display, FONT_SIZE) + 30f + val buttonWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, display, FONT_SIZE) + 30f val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 val borderColor = theme.border val textColor = theme.textPrimary - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, startY, buttonWidth, BUTTON_HEIGHT, 5f, theme.backgroundPrimary ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( startX, startY, buttonWidth, BUTTON_HEIGHT, 1f, 5f, borderColor ) - val textWidth = Skia.textWidth(Skia.regularFont, display, FONT_SIZE) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, display, FONT_SIZE) - Skia.text( - Skia.regularFont, display, + SkiaRenderer.text( + SkiaRenderer.regularFont, display, startX + (buttonWidth - textWidth) / 2, startY + (BUTTON_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, textColor @@ -62,11 +62,11 @@ class ModeSetting( } val display = options.getOrNull(value) ?: "" - val buttonWidth = Skia.textWidth(Skia.regularFont, display, FONT_SIZE) + 30f + val buttonWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, display, FONT_SIZE) + 30f val startX = xPos + width - buttonWidth - PADDING val startY = yPos + (height - BUTTON_HEIGHT) / 2 - if (!MouseUtils.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT)) { + if (!Mouse.isHoveringOver(startX, startY, buttonWidth, BUTTON_HEIGHT)) { return false } diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/RangeSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/RangeSetting.kt index 61f66a4..9a6a5d9 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/RangeSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/RangeSetting.kt @@ -4,8 +4,8 @@ import com.google.gson.JsonElement import com.google.gson.JsonObject import com.google.gson.JsonPrimitive import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class RangeSetting( name: String, @@ -43,22 +43,22 @@ class RangeSetting( val boxX = xPos + width - PADDING - boxWidth val boxY = yPos + (BASE_HEIGHT - VALUE_BOX_HEIGHT) / 2 - Skia.roundedRect( + SkiaRenderer.roundedRect( boxX, boxY, boxWidth, VALUE_BOX_HEIGHT, 5f, theme.backgroundPrimary ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( boxX, boxY, boxWidth, VALUE_BOX_HEIGHT, 1f, 5f, theme.border ) - val textWidth = Skia.textWidth(Skia.regularFont, text, FONT_SIZE) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, text, FONT_SIZE) - Skia.text( - Skia.regularFont, text, + SkiaRenderer.text( + SkiaRenderer.regularFont, text, boxX + (boxWidth - textWidth) / 2, boxY + (VALUE_BOX_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, theme.textPrimary @@ -66,24 +66,24 @@ class RangeSetting( val geometry = trackGeometry() - Skia.roundedRect( + SkiaRenderer.roundedRect( geometry.startX, geometry.trackY - 2f, geometry.trackWidth, 4f, 3f, theme.backgroundPrimary ) - Skia.roundedRect( + SkiaRenderer.roundedRect( geometry.startKnobX, geometry.trackY - 2f, (geometry.endKnobX - geometry.startKnobX).coerceAtLeast(0f), 4f, 3f, theme.accentPrimary ) - Skia.circle( + SkiaRenderer.circle( geometry.startKnobX, geometry.trackY, KNOB_RADIUS, theme.textPrimary ) - Skia.circle( + SkiaRenderer.circle( geometry.endKnobX, geometry.trackY, KNOB_RADIUS, theme.textPrimary ) @@ -97,14 +97,14 @@ class RangeSetting( val geometry = trackGeometry() dragging = when { - MouseUtils.isHoveringOver( + Mouse.isHoveringOver( geometry.startKnobX - KNOB_RADIUS, geometry.trackY - KNOB_RADIUS, KNOB_RADIUS * 2, KNOB_RADIUS * 2 ) -> Knob.START - MouseUtils.isHoveringOver( + Mouse.isHoveringOver( geometry.endKnobX - KNOB_RADIUS, geometry.trackY - KNOB_RADIUS, KNOB_RADIUS * 2, @@ -141,7 +141,7 @@ class RangeSetting( private fun updateValue() { val (startX, trackWidth) = trackGeometry() - val rel = ((MouseUtils.mouseX - startX) / trackWidth).coerceIn(0f, 1f) + val rel = ((Mouse.mouseX - startX) / trackWidth).coerceIn(0f, 1f) val raw = (min + rel * (max - min)).coerceIn(min.toFloat(), max.toFloat()) when (dragging) { @@ -191,7 +191,7 @@ class RangeSetting( } private fun boxWidth(text: String): Float = - Skia.textWidth(Skia.regularFont, text, FONT_SIZE) + VALUE_BOX_PADDING_X * 2f + SkiaRenderer.textWidth(SkiaRenderer.regularFont, text, FONT_SIZE) + VALUE_BOX_PADDING_X * 2f private data class TrackGeometry( val startX: Float, diff --git a/src/main/kotlin/org/cobalt/ui/component/setting/impl/SliderSetting.kt b/src/main/kotlin/org/cobalt/ui/component/setting/impl/SliderSetting.kt index 6293558..3bb45e3 100644 --- a/src/main/kotlin/org/cobalt/ui/component/setting/impl/SliderSetting.kt +++ b/src/main/kotlin/org/cobalt/ui/component/setting/impl/SliderSetting.kt @@ -3,8 +3,8 @@ package org.cobalt.ui.component.setting.impl import com.google.gson.JsonElement import com.google.gson.JsonPrimitive import org.cobalt.ui.component.setting.Setting -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer class SliderSetting( name: String, @@ -33,20 +33,20 @@ class SliderSetting( val boxX = xPos + width - PADDING - boxWidth val boxY = yPos + (BASE_HEIGHT - VALUE_BOX_HEIGHT) / 2 - Skia.roundedRect( + SkiaRenderer.roundedRect( boxX, boxY, boxWidth, VALUE_BOX_HEIGHT, 5f, theme.backgroundPrimary ) - Skia.roundedOutline( + SkiaRenderer.roundedOutline( boxX, boxY, boxWidth, VALUE_BOX_HEIGHT, 1f, 5f, theme.border ) - val textWidth = Skia.textWidth(Skia.regularFont, text, FONT_SIZE) + val textWidth = SkiaRenderer.textWidth(SkiaRenderer.regularFont, text, FONT_SIZE) - Skia.text( - Skia.regularFont, text, + SkiaRenderer.text( + SkiaRenderer.regularFont, text, boxX + (boxWidth - textWidth) / 2, boxY + (VALUE_BOX_HEIGHT - FONT_SIZE) / 2, FONT_SIZE, theme.textPrimary @@ -54,19 +54,19 @@ class SliderSetting( val (startX, trackWidth, trackY, knobX) = trackGeometry() - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, trackY - 2f, trackWidth, 4f, 3f, theme.backgroundPrimary ) - Skia.roundedRect( + SkiaRenderer.roundedRect( startX, trackY - 2f, (knobX - startX).coerceAtLeast(0f), 4f, 3f, theme.accentPrimary ) - Skia.circle( + SkiaRenderer.circle( knobX, trackY, KNOB_RADIUS, theme.textPrimary ) @@ -80,7 +80,7 @@ class SliderSetting( val (_, _, trackY, knobX) = trackGeometry() if ( - !MouseUtils.isHoveringOver( + !Mouse.isHoveringOver( knobX - KNOB_RADIUS, trackY - KNOB_RADIUS, KNOB_RADIUS * 2, KNOB_RADIUS * 2 ) @@ -115,7 +115,7 @@ class SliderSetting( private fun updateValue() { val (startX, trackWidth) = trackGeometry() - val rel = ((MouseUtils.mouseX - startX) / trackWidth).coerceIn(0f, 1f) + val rel = ((Mouse.mouseX - startX) / trackWidth).coerceIn(0f, 1f) rawValue = (min + rel * (max - min)).coerceIn(min.toFloat(), max.toFloat()) value = rawValue.toInt().coerceIn(min, max) @@ -132,7 +132,7 @@ class SliderSetting( } private fun valueBoxWidth(text: String): Float = - Skia.textWidth(Skia.regularFont, text, FONT_SIZE) + VALUE_BOX_PADDING_X * 2f + SkiaRenderer.textWidth(SkiaRenderer.regularFont, text, FONT_SIZE) + VALUE_BOX_PADDING_X * 2f private data class TrackGeometry( val startX: Float, diff --git a/src/main/kotlin/org/cobalt/ui/helper/DragHandler.kt b/src/main/kotlin/org/cobalt/ui/helper/DragHandler.kt index d7276a9..c92f0e1 100644 --- a/src/main/kotlin/org/cobalt/ui/helper/DragHandler.kt +++ b/src/main/kotlin/org/cobalt/ui/helper/DragHandler.kt @@ -1,13 +1,13 @@ package org.cobalt.ui.helper import org.cobalt.module.type.RenderableModule -import org.cobalt.util.MouseUtils -import org.cobalt.util.MouseUtils.mouseX -import org.cobalt.util.MouseUtils.mouseY -import org.cobalt.util.WindowUtils.scaleX -import org.cobalt.util.WindowUtils.scaleY -import org.cobalt.util.WindowUtils.windowHeight -import org.cobalt.util.WindowUtils.windowWidth +import org.cobalt.util.client.WindowUtils.scaleX +import org.cobalt.util.client.WindowUtils.scaleY +import org.cobalt.util.client.WindowUtils.windowHeight +import org.cobalt.util.client.WindowUtils.windowWidth +import org.cobalt.util.input.Mouse +import org.cobalt.util.input.Mouse.mouseX +import org.cobalt.util.input.Mouse.mouseY class DragHandler { @@ -43,7 +43,7 @@ class DragHandler { val squareOffset = squareSizeScaled / 2f if ( - !MouseUtils.isHoveringOver( + !Mouse.isHoveringOver( renderX + scaledWidth - squareOffset, renderY + scaledHeight - squareOffset, squareSizeScaled, squareSizeScaled @@ -103,7 +103,11 @@ class DragHandler { } val (snappedX, snappedY) = snapHelper.findAlignmentGuides( - clampedX, clampedY, width, height, windowWidth, windowHeight, otherBounds + clampedX, + clampedY, + width, + height, + otherBounds, ) module.xPos = snappedX / scaleX diff --git a/src/main/kotlin/org/cobalt/ui/helper/SnapHelper.kt b/src/main/kotlin/org/cobalt/ui/helper/SnapHelper.kt index 13b1810..f556aea 100644 --- a/src/main/kotlin/org/cobalt/ui/helper/SnapHelper.kt +++ b/src/main/kotlin/org/cobalt/ui/helper/SnapHelper.kt @@ -1,6 +1,7 @@ package org.cobalt.ui.helper import kotlin.math.abs +import org.cobalt.util.client.WindowUtils class SnapHelper(private val snapThreshold: Float = 5f) { @@ -12,8 +13,6 @@ class SnapHelper(private val snapThreshold: Float = 5f) { moduleY: Float, moduleW: Float, moduleH: Float, - screenWidth: Float, - screenHeight: Float, otherModuleBounds: List, ): Pair { val right = moduleX + moduleW @@ -21,8 +20,8 @@ class SnapHelper(private val snapThreshold: Float = 5f) { val bottom = moduleY + moduleH val centerY = moduleY + moduleH / 2f - val xTargets = mutableListOf(0f, screenWidth / 2f, screenWidth) - val yTargets = mutableListOf(0f, screenHeight / 2f, screenHeight) + val xTargets = mutableListOf(0f, WindowUtils.windowWidth / 2f, WindowUtils.windowWidth) + val yTargets = mutableListOf(0f, WindowUtils.windowHeight / 2f, WindowUtils.windowHeight) otherModuleBounds.forEach { bounds -> xTargets.add(bounds.x) @@ -35,15 +34,14 @@ class SnapHelper(private val snapThreshold: Float = 5f) { var snappedX = moduleX var snappedY = moduleY - var bestXDiff = snapThreshold + 1f - var bestYDiff = snapThreshold + 1f + val bestXDiff = snapThreshold + 1f + val bestYDiff = snapThreshold + 1f var xGuide: GuideLine? = null var yGuide: GuideLine? = null fun checkX(target: Float, edge: Float, newX: Float) { val diff = abs(edge - target) if (diff <= snapThreshold && diff < bestXDiff) { - bestXDiff = diff snappedX = newX xGuide = GuideLine(true, target) } @@ -52,7 +50,6 @@ class SnapHelper(private val snapThreshold: Float = 5f) { fun checkY(target: Float, edge: Float, newY: Float) { val diff = abs(edge - target) if (diff <= snapThreshold && diff < bestYDiff) { - bestYDiff = diff snappedY = newY yGuide = GuideLine(false, target) } diff --git a/src/main/kotlin/org/cobalt/ui/helper/TextInputHelper.kt b/src/main/kotlin/org/cobalt/ui/helper/TextInputHelper.kt index 5c6b4bf..b673dd8 100644 --- a/src/main/kotlin/org/cobalt/ui/helper/TextInputHelper.kt +++ b/src/main/kotlin/org/cobalt/ui/helper/TextInputHelper.kt @@ -5,8 +5,8 @@ import kotlin.math.abs import net.minecraft.client.input.CharacterEvent import net.minecraft.client.input.KeyEvent import org.cobalt.ui.component.TextInputComponent -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer import org.lwjgl.glfw.GLFW class TextInputHelper( @@ -79,7 +79,7 @@ class TextInputHelper( return false } - val hoveringOver = MouseUtils.isHoveringOver(xPos, yPos, width, height) + val hoveringOver = Mouse.isHoveringOver(xPos, yPos, width, height) focused = hoveringOver if (hoveringOver) { @@ -110,7 +110,7 @@ class TextInputHelper( return false } - focused = MouseUtils.isHoveringOver(xPos, yPos, width, height) + focused = Mouse.isHoveringOver(xPos, yPos, width, height) return focused } @@ -124,7 +124,7 @@ class TextInputHelper( for (i in 0..text.length) { val prefix = if (textInputType == TextInputComponent.Type.PASSWORD) "*".repeat(i) else text.substring(0, i) - val w = Skia.textWidth(Skia.regularFont, prefix, fontSize) + val w = SkiaRenderer.textWidth(SkiaRenderer.regularFont, prefix, fontSize) val diff = abs(w - relativeX) if (diff < minDiff) { diff --git a/src/main/kotlin/org/cobalt/ui/notification/Notification.kt b/src/main/kotlin/org/cobalt/ui/notification/Notification.kt index c5cd0b1..2c920c9 100644 --- a/src/main/kotlin/org/cobalt/ui/notification/Notification.kt +++ b/src/main/kotlin/org/cobalt/ui/notification/Notification.kt @@ -4,9 +4,9 @@ import kotlin.time.Duration import org.cobalt.ui.UIComponent import org.cobalt.ui.animation.BounceAnimation import org.cobalt.ui.animation.EaseOutAnimation -import org.cobalt.util.WindowUtils.windowWidth -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.helper.SkiaCorner +import org.cobalt.util.client.WindowUtils.windowWidth +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.data.SkiaCorner class Notification( private val title: String, @@ -60,7 +60,7 @@ class Notification( val resolvedY = targetY + slideDownAnim.get(previousY - targetY, 0f, false) updateBounds(resolvedX, resolvedY) - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, CORNER_RADIUS, theme.backgroundPrimary ) @@ -74,17 +74,17 @@ class Notification( val hasDescription = description.isNotBlank() val titleFontSize = if (hasDescription) TITLE_FONT_SIZE else TITLE_FONT_SIZE_ALONE - val titleHeight = Skia.wrappedTextHeight(Skia.boldFont, title, contentWidth, titleFontSize) + val titleHeight = SkiaRenderer.wrappedTextHeight(SkiaRenderer.boldFont, title, contentWidth, titleFontSize) - Skia.wrappedText( - Skia.boldFont, title, + SkiaRenderer.wrappedText( + SkiaRenderer.boldFont, title, xPos + CONTENT_PADDING, yPos + CONTENT_PADDING, contentWidth, titleFontSize, theme.textPrimary, ) if (hasDescription) { - Skia.wrappedText( - Skia.boldFont, description, + SkiaRenderer.wrappedText( + SkiaRenderer.boldFont, description, xPos + CONTENT_PADDING, yPos + CONTENT_PADDING + titleHeight + TITLE_DESCRIPTION_GAP, contentWidth, DESCRIPTION_FONT_SIZE, theme.textSecondary, ) @@ -95,7 +95,7 @@ class Notification( val progress = calculateProgress(System.currentTimeMillis()) val fillWidth = width * progress - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos + height - PROGRESS_BAR_HEIGHT, width, PROGRESS_BAR_HEIGHT, CORNER_RADIUS, @@ -104,7 +104,7 @@ class Notification( ) if (fillWidth > 0f) { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos + height - PROGRESS_BAR_HEIGHT, fillWidth, PROGRESS_BAR_HEIGHT, CORNER_RADIUS, @@ -146,8 +146,8 @@ class Notification( private fun calculateHeight(title: String, description: String): Float { val titleFontSize = if (description.isNotBlank()) TITLE_FONT_SIZE else TITLE_FONT_SIZE_ALONE - val titleHeight = Skia.wrappedTextHeight( - Skia.boldFont, title, + val titleHeight = SkiaRenderer.wrappedTextHeight( + SkiaRenderer.boldFont, title, DEFAULT_WIDTH - CONTENT_PADDING * 2, titleFontSize ) @@ -155,8 +155,8 @@ class Notification( var descHeight = 0f if (description.isNotBlank()) { - descHeight = Skia.wrappedTextHeight( - Skia.boldFont, description, + descHeight = SkiaRenderer.wrappedTextHeight( + SkiaRenderer.boldFont, description, DEFAULT_WIDTH - CONTENT_PADDING * 2, DESCRIPTION_FONT_SIZE ) diff --git a/src/main/kotlin/org/cobalt/ui/notification/NotificationManager.kt b/src/main/kotlin/org/cobalt/ui/notification/NotificationManager.kt index 9447101..82539dc 100644 --- a/src/main/kotlin/org/cobalt/ui/notification/NotificationManager.kt +++ b/src/main/kotlin/org/cobalt/ui/notification/NotificationManager.kt @@ -4,8 +4,8 @@ import kotlin.time.Duration import org.cobalt.event.EventBus import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.RenderEvent -import org.cobalt.util.WindowUtils.windowHeight -import org.cobalt.util.skia.SkiaPIP +import org.cobalt.util.client.WindowUtils.windowHeight +import org.cobalt.util.render.skia.SkiaPIP object NotificationManager { diff --git a/src/main/kotlin/org/cobalt/ui/page/Page.kt b/src/main/kotlin/org/cobalt/ui/page/Page.kt index 3dd7049..57c0fce 100644 --- a/src/main/kotlin/org/cobalt/ui/page/Page.kt +++ b/src/main/kotlin/org/cobalt/ui/page/Page.kt @@ -3,8 +3,8 @@ package org.cobalt.ui.page import org.cobalt.ui.UIComponent import org.cobalt.ui.component.SidebarComponent import org.cobalt.ui.component.TopbarComponent -import org.cobalt.util.skia.Skia -import org.cobalt.util.skia.helper.SkiaCorner +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.render.skia.data.SkiaCorner abstract class Page : UIComponent() { @@ -17,7 +17,7 @@ abstract class Page : UIComponent() { get() = SidebarComponent.height - TopbarComponent.height override fun renderComponent() { - Skia.roundedRect( + SkiaRenderer.roundedRect( xPos, yPos, width, height, CORNER_RADIUS, diff --git a/src/main/kotlin/org/cobalt/ui/page/impl/ModulesPage.kt b/src/main/kotlin/org/cobalt/ui/page/impl/ModulesPage.kt index bdf2b4f..74b34f2 100644 --- a/src/main/kotlin/org/cobalt/ui/page/impl/ModulesPage.kt +++ b/src/main/kotlin/org/cobalt/ui/page/impl/ModulesPage.kt @@ -6,8 +6,8 @@ import org.cobalt.ui.component.ModuleComponent import org.cobalt.ui.helper.ScrollHelper import org.cobalt.ui.page.Page import org.cobalt.ui.screen.ConfigScreen -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer object ModulesPage : Page() { @@ -63,7 +63,7 @@ object ModulesPage : Page() { val rightX = xPos + PADDING + ModuleComponent.WIDTH + COLUMN_GAP var rightY = yPos + PADDING + pageOffset - scrollHelper.scrollOffset - Skia.pushScissor(xPos, yPos, width, height) + SkiaRenderer.pushScissor(xPos, yPos, width, height) moduleComponents.forEachIndexed { index, component -> if (index % 2 == 0) { @@ -81,7 +81,7 @@ object ModulesPage : Page() { } } - Skia.popScissor() + SkiaRenderer.popScissor() val contentHeight = maxOf( leftY + scrollHelper.scrollOffset, @@ -93,7 +93,7 @@ object ModulesPage : Page() { override fun mouseScrolled(horizontalAmount: Double, verticalAmount: Double): Boolean { - if (MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (Mouse.isHoveringOver(xPos, yPos, width, height)) { scrollHelper.scroll(verticalAmount) return true } diff --git a/src/main/kotlin/org/cobalt/ui/page/impl/ScriptsPage.kt b/src/main/kotlin/org/cobalt/ui/page/impl/ScriptsPage.kt index 1525854..38d8d20 100644 --- a/src/main/kotlin/org/cobalt/ui/page/impl/ScriptsPage.kt +++ b/src/main/kotlin/org/cobalt/ui/page/impl/ScriptsPage.kt @@ -6,8 +6,8 @@ import org.cobalt.ui.animation.EaseOutAnimation import org.cobalt.ui.component.ScriptComponent import org.cobalt.ui.helper.ScrollHelper import org.cobalt.ui.page.Page -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer object ScriptsPage : Page() { @@ -59,13 +59,13 @@ object ScriptsPage : Page() { val pageOffset = openingOffset.get(-30f, 0f) var currentY = yPos + PADDING + pageOffset - scrollHelper.scrollOffset - Skia.pushScissor(xPos, yPos, width, height) + SkiaRenderer.pushScissor(xPos, yPos, width, height) scriptComponents .groupBy { (_, category) -> category } .forEach { (category, components) -> - Skia.text( - Skia.regularFont, category, + SkiaRenderer.text( + SkiaRenderer.regularFont, category, xPos + PADDING, currentY, CATEGORY_FONT_SIZE, theme.textMuted ) @@ -91,14 +91,14 @@ object ScriptsPage : Page() { currentY = columnY.max() + GROUP_GAP } - Skia.popScissor() + SkiaRenderer.popScissor() val contentHeight = currentY + scrollHelper.scrollOffset - yPos scrollHelper.updateMaxScroll(contentHeight, height) } override fun mouseScrolled(horizontalAmount: Double, verticalAmount: Double): Boolean { - if (MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (Mouse.isHoveringOver(xPos, yPos, width, height)) { scrollHelper.scroll(verticalAmount) return true } diff --git a/src/main/kotlin/org/cobalt/ui/page/impl/ThemesPage.kt b/src/main/kotlin/org/cobalt/ui/page/impl/ThemesPage.kt index 43b1100..c7b9523 100644 --- a/src/main/kotlin/org/cobalt/ui/page/impl/ThemesPage.kt +++ b/src/main/kotlin/org/cobalt/ui/page/impl/ThemesPage.kt @@ -7,8 +7,8 @@ import org.cobalt.ui.component.button.IconButton import org.cobalt.ui.helper.ScrollHelper import org.cobalt.ui.page.Page import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.MouseUtils -import org.cobalt.util.skia.Skia +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer object ThemesPage : Page() { @@ -62,7 +62,7 @@ object ThemesPage : Page() { val contentHeight = pageOffset + PADDING * 2 + rows * ThemeComponent.HEIGHT + (rows - 1) * SPACING scrollHelper.updateMaxScroll(contentHeight, height) - Skia.pushScissor(xPos, yPos, width, height) + SkiaRenderer.pushScissor(xPos, yPos, width, height) themeComponents.forEachIndexed { index, component -> val col = index % COLUMNS @@ -76,7 +76,7 @@ object ThemesPage : Page() { .renderComponent() } - Skia.popScissor() + SkiaRenderer.popScissor() val buttonX = xPos + width - PADDING - reloadButton.width val buttonY = yPos + height - PADDING - reloadButton.height @@ -87,7 +87,7 @@ object ThemesPage : Page() { } override fun mouseScrolled(horizontalAmount: Double, verticalAmount: Double): Boolean { - if (MouseUtils.isHoveringOver(xPos, yPos, width, height)) { + if (Mouse.isHoveringOver(xPos, yPos, width, height)) { scrollHelper.scroll(verticalAmount) return true } diff --git a/src/main/kotlin/org/cobalt/ui/screen/ConfigScreen.kt b/src/main/kotlin/org/cobalt/ui/screen/ConfigScreen.kt index 1544839..b5c48f5 100644 --- a/src/main/kotlin/org/cobalt/ui/screen/ConfigScreen.kt +++ b/src/main/kotlin/org/cobalt/ui/screen/ConfigScreen.kt @@ -13,10 +13,10 @@ import org.cobalt.ui.page.Page import org.cobalt.ui.page.impl.ModulesPage import org.cobalt.ui.theme.Theme import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.WindowUtils.windowHeight -import org.cobalt.util.WindowUtils.windowWidth -import org.cobalt.util.helper.Multithreading -import org.cobalt.util.skia.Skia +import org.cobalt.util.client.WindowUtils.windowHeight +import org.cobalt.util.client.WindowUtils.windowWidth +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.scheduling.Multithreading object ConfigScreen : UIScreen() { @@ -67,7 +67,7 @@ object ConfigScreen : UIScreen() { val centerX = windowWidth / 2f val centerY = windowHeight / 2f - Skia.push() + SkiaRenderer.push() val scale = when { closing -> closeAnim.get(1f, 0f) @@ -76,9 +76,9 @@ object ConfigScreen : UIScreen() { } if (scale != 1f) { - Skia.translate(centerX, centerY) - Skia.scale(scale, scale) - Skia.translate(-centerX, -centerY) + SkiaRenderer.translate(centerX, centerY) + SkiaRenderer.scale(scale, scale) + SkiaRenderer.translate(-centerX, -centerY) } val interfaceWidth = SidebarComponent.width + ModulesPage.width @@ -102,25 +102,25 @@ object ConfigScreen : UIScreen() { .updateBounds(pageX, pageY) .renderComponent() - Skia.roundedOutline( + SkiaRenderer.roundedOutline( pageX, pageY, interfaceWidth, interfaceHeight, 1f, 10f, theme.border ) - Skia.line( + SkiaRenderer.line( startX, pageY, startX, pageY + ModulesPage.height, 1f, theme.border ) - Skia.line( + SkiaRenderer.line( startX, startY, startX + TopbarComponent.width, startY, 1f, theme.border ) - Skia.pop() + SkiaRenderer.pop() if (closing && !closeAnim.isAnimating()) { closing = false diff --git a/src/main/kotlin/org/cobalt/ui/screen/HudEditorScreen.kt b/src/main/kotlin/org/cobalt/ui/screen/HudEditorScreen.kt index dcd1234..38429c2 100644 --- a/src/main/kotlin/org/cobalt/ui/screen/HudEditorScreen.kt +++ b/src/main/kotlin/org/cobalt/ui/screen/HudEditorScreen.kt @@ -9,13 +9,13 @@ import org.cobalt.ui.helper.DragHandler import org.cobalt.ui.helper.SnapHelper import org.cobalt.ui.theme.Theme import org.cobalt.ui.theme.ThemeManager -import org.cobalt.util.MouseUtils -import org.cobalt.util.WindowUtils.scaleX -import org.cobalt.util.WindowUtils.scaleY -import org.cobalt.util.WindowUtils.windowHeight -import org.cobalt.util.WindowUtils.windowWidth -import org.cobalt.util.helper.Multithreading -import org.cobalt.util.skia.Skia +import org.cobalt.util.client.WindowUtils.scaleX +import org.cobalt.util.client.WindowUtils.scaleY +import org.cobalt.util.client.WindowUtils.windowHeight +import org.cobalt.util.client.WindowUtils.windowWidth +import org.cobalt.util.input.Mouse +import org.cobalt.util.render.SkiaRenderer +import org.cobalt.util.scheduling.Multithreading object HudEditorScreen : UIScreen() { @@ -33,19 +33,19 @@ object HudEditorScreen : UIScreen() { override fun renderSkia() { modules.forEach { module -> - Skia.push() + SkiaRenderer.push() val renderX = module.xPos * scaleX val renderY = module.yPos * scaleY val finalScale = module.scale * scaleY - Skia.translate(renderX, renderY) - Skia.scale(finalScale, finalScale) - Skia.translate(-module.xPos, -module.yPos) + SkiaRenderer.translate(renderX, renderY) + SkiaRenderer.scale(finalScale, finalScale) + SkiaRenderer.translate(-module.xPos, -module.yPos) drawRenderableModule(module) - Skia.pop() + SkiaRenderer.pop() } drawSnapGuides() @@ -58,9 +58,9 @@ object HudEditorScreen : UIScreen() { snapHelper.activeGuides.forEach { guide -> if (guide.isVertical) { - Skia.line(guide.position, 0f, guide.position, windowHeight, 1f, theme.accentPrimary) + SkiaRenderer.line(guide.position, 0f, guide.position, windowHeight, 1f, theme.accentPrimary) } else { - Skia.line(0f, guide.position, windowWidth, guide.position, 1f, theme.accentPrimary) + SkiaRenderer.line(0f, guide.position, windowWidth, guide.position, 1f, theme.accentPrimary) } } } @@ -75,11 +75,11 @@ object HudEditorScreen : UIScreen() { val isSelected = module == selectedModule - Skia.outline(x, y, width, height, 1f, if (isSelected) theme.accentPrimary else theme.border) + SkiaRenderer.outline(x, y, width, height, 1f, if (isSelected) theme.accentPrimary else theme.border) if (isSelected) { val squareOffset = SQUARE_SIZE / 2.0f - Skia.rect( + SkiaRenderer.rect( x + width - squareOffset, y + height - squareOffset, SQUARE_SIZE, SQUARE_SIZE, theme.accentPrimary @@ -110,7 +110,7 @@ object HudEditorScreen : UIScreen() { return@firstOrNull true } - if (MouseUtils.isHoveringOver(renderX, renderY, scaledWidth, scaledHeight)) { + if (Mouse.isHoveringOver(renderX, renderY, scaledWidth, scaledHeight)) { dragHandler.startMove(renderX, renderY) return@firstOrNull true } @@ -152,7 +152,7 @@ object HudEditorScreen : UIScreen() { val scaledWidth = candidate.width * candidate.scale * resScale val scaledHeight = candidate.height * candidate.scale * resScale - MouseUtils.isHoveringOver(renderX, renderY, scaledWidth, scaledHeight) + Mouse.isHoveringOver(renderX, renderY, scaledWidth, scaledHeight) } ?: return super.mouseScrolled(x, y, scrollX, scrollY) selectedModule = module diff --git a/src/main/kotlin/org/cobalt/ui/theme/ThemeManager.kt b/src/main/kotlin/org/cobalt/ui/theme/ThemeManager.kt index 0246797..abb8b51 100644 --- a/src/main/kotlin/org/cobalt/ui/theme/ThemeManager.kt +++ b/src/main/kotlin/org/cobalt/ui/theme/ThemeManager.kt @@ -5,7 +5,7 @@ import java.awt.Color import java.nio.file.Files import kotlin.io.path.notExists import org.cobalt.Cobalt.configDir -import org.cobalt.util.config.BasicConfig +import org.cobalt.util.config.SimpleConfig object ThemeManager { @@ -19,7 +19,7 @@ object ThemeManager { "/assets/cobalt/themes/arcticFrost.json", ) - private val settingsConfig = BasicConfig( + private val settingsConfig = SimpleConfig( configDir.resolve("settings.json").toString(), Settings::class.java ) diff --git a/src/main/kotlin/org/cobalt/util/ColorUtils.kt b/src/main/kotlin/org/cobalt/util/ColorUtils.kt deleted file mode 100644 index 8b7f23d..0000000 --- a/src/main/kotlin/org/cobalt/util/ColorUtils.kt +++ /dev/null @@ -1,60 +0,0 @@ -package org.cobalt.util - -import kotlin.math.roundToInt -import net.minecraft.network.chat.Component -import net.minecraft.network.chat.MutableComponent -import net.minecraft.network.chat.Style -import net.minecraft.network.chat.TextColor -import org.cobalt.dsl.alpha -import org.cobalt.dsl.blue -import org.cobalt.dsl.green -import org.cobalt.dsl.red - -object ColorUtils { - - @JvmStatic - fun buildTextGradient( - text: String, - startColor: Int, - endColor: Int, - baseStyle: Style = Style.EMPTY, - ): MutableComponent { - val result = Component.empty() - val textLength = text.length - - if (textLength <= 1) { - return Component - .literal(text) - .setStyle(baseStyle.withColor(TextColor.fromRgb(startColor))) - } - - for (index in text.indices) { - val denominator = (textLength - 1).toDouble() - val ratio = index.toDouble() / denominator - val red = (startColor.red + ratio * (endColor.red - startColor.red)).roundToInt() - val green = (startColor.green + ratio * (endColor.green - startColor.green)).roundToInt() - val blue = (startColor.blue + ratio * (endColor.blue - startColor.blue)).roundToInt() - val interpolatedColor = (red shl 16) or (green shl 8) or blue - - val coloredChar = Component.literal(text[index].toString()) - .setStyle(baseStyle.withColor(TextColor.fromRgb(interpolatedColor))) - - result.append(coloredChar) - } - - return result - } - - @JvmStatic - fun getRed(colorRgb: Int) = colorRgb.red - - @JvmStatic - fun getGreen(colorRgb: Int) = colorRgb.green - - @JvmStatic - fun getBlue(colorRgb: Int) = colorRgb.blue - - @JvmStatic - fun getAlpha(colorRgb: Int) = colorRgb.alpha - -} diff --git a/src/main/kotlin/org/cobalt/util/block/BlockUtils.kt b/src/main/kotlin/org/cobalt/util/block/BlockUtils.kt new file mode 100644 index 0000000..adc7a7c --- /dev/null +++ b/src/main/kotlin/org/cobalt/util/block/BlockUtils.kt @@ -0,0 +1,103 @@ +package org.cobalt.util.block + +import net.minecraft.core.BlockPos +import net.minecraft.world.level.EmptyBlockGetter +import net.minecraft.world.level.block.* +import net.minecraft.world.level.block.piston.MovingPistonBlock +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.block.state.properties.SlabType +import net.minecraft.world.level.material.FlowingFluid +import net.minecraft.world.level.material.Fluids +import net.minecraft.world.phys.AABB +import net.minecraft.world.phys.Vec3 +import org.cobalt.pathfinder.helper.BlockStateAccessor + +fun BlockPos.centerVec(): Vec3 { + return Vec3(x + 0.5, y + 0.5, z + 0.5) +} + +fun Vec3.smallBox(): AABB { + return AABB( + x - 0.25, + y - 0.25, + z - 0.25, + x + 0.25, + y + 0.25, + z + 0.25 + ) +} + +object BlockUtils { + + @JvmStatic + fun isWater(state: BlockState): Boolean { + val fluid = state.fluidState.type + return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER + } + + @JvmStatic + fun isLava(state: BlockState): Boolean { + val fluid = state.fluidState.type + return fluid == Fluids.LAVA || fluid == Fluids.FLOWING_LAVA + } + + @JvmStatic + fun isBottomSlab(state: BlockState): Boolean { + return state.block is SlabBlock && + state.getValue(SlabBlock.TYPE) == SlabType.BOTTOM + } + + @JvmStatic + fun isBlockNormalCube(state: BlockState): Boolean { + val block = state.block + + if ( + block is BambooStalkBlock || + block is MovingPistonBlock || + block is ScaffoldingBlock + ) { + return false + } + + if ( + block is ShulkerBoxBlock || + block is PointedDripstoneBlock || + block is AmethystClusterBlock + ) { + return false + } + + return try { + Block.isShapeFullBlock(state.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO)) + } catch (_: Exception) { + false + } + } + + @JvmStatic + fun isFlowing(x: Int, y: Int, z: Int, state: BlockState, bsa: BlockStateAccessor): Boolean { + val fluidState = state.fluidState + + if (fluidState.type !is FlowingFluid) { + return false + } + + if (fluidState.type.getAmount(fluidState) != 8) { + return true + } + + return possiblyFlowing(bsa.get(x + 1, y, z)) + || possiblyFlowing(bsa.get(x - 1, y, z)) + || possiblyFlowing(bsa.get(x, y, z + 1)) + || possiblyFlowing(bsa.get(x, y, z - 1)) + } + + @JvmStatic + fun possiblyFlowing(state: BlockState): Boolean { + val fluidState = state.fluidState + + return fluidState.type is FlowingFluid && + fluidState.type.getAmount(fluidState) != 8 + } + +} diff --git a/src/main/kotlin/org/cobalt/util/FrustumUtils.kt b/src/main/kotlin/org/cobalt/util/block/FrustumUtils.kt similarity index 95% rename from src/main/kotlin/org/cobalt/util/FrustumUtils.kt rename to src/main/kotlin/org/cobalt/util/block/FrustumUtils.kt index e2dd466..1a89e6d 100644 --- a/src/main/kotlin/org/cobalt/util/FrustumUtils.kt +++ b/src/main/kotlin/org/cobalt/util/block/FrustumUtils.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.block import net.minecraft.client.renderer.culling.Frustum import net.minecraft.world.phys.AABB diff --git a/src/main/kotlin/org/cobalt/util/helper/ChatFormatter.kt b/src/main/kotlin/org/cobalt/util/chat/ChatFormatter.kt similarity index 98% rename from src/main/kotlin/org/cobalt/util/helper/ChatFormatter.kt rename to src/main/kotlin/org/cobalt/util/chat/ChatFormatter.kt index 2047737..5b89849 100644 --- a/src/main/kotlin/org/cobalt/util/helper/ChatFormatter.kt +++ b/src/main/kotlin/org/cobalt/util/chat/ChatFormatter.kt @@ -1,11 +1,10 @@ -package org.cobalt.util.helper +package org.cobalt.util.chat import net.minecraft.ChatFormatting import net.minecraft.network.chat.Component import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.Style import net.minecraft.network.chat.TextColor -import org.cobalt.util.ColorUtils object ChatFormatter { @@ -215,7 +214,7 @@ object ChatFormatter { flush() result.append( - ColorUtils.buildTextGradient( + ChatUtils.buildGradientComponent( text.substring(tagEnd + 1, closeStart), gradient.first, gradient.second, diff --git a/src/main/kotlin/org/cobalt/util/ChatUtils.kt b/src/main/kotlin/org/cobalt/util/chat/ChatUtils.kt similarity index 50% rename from src/main/kotlin/org/cobalt/util/ChatUtils.kt rename to src/main/kotlin/org/cobalt/util/chat/ChatUtils.kt index 4c3fd73..cc6637b 100644 --- a/src/main/kotlin/org/cobalt/util/ChatUtils.kt +++ b/src/main/kotlin/org/cobalt/util/chat/ChatUtils.kt @@ -1,21 +1,42 @@ -package org.cobalt.util +package org.cobalt.util.chat +import kotlin.math.roundToInt +import net.minecraft.network.chat.Component import net.minecraft.network.chat.MutableComponent +import net.minecraft.network.chat.Style +import net.minecraft.network.chat.TextColor import org.cobalt.Cobalt import org.cobalt.Cobalt.minecraft import org.cobalt.Cobalt.runOnClientThread import org.cobalt.module.impl.misc.Debug -import org.cobalt.util.helper.ChatFormatter +import org.cobalt.util.color.blue +import org.cobalt.util.color.green +import org.cobalt.util.color.red import org.slf4j.LoggerFactory +enum class MessageType { + DEFAULT, RAW, DEBUG +} + object ChatUtils { private val logger = LoggerFactory.getLogger(this::class.java) + private const val DARK_GRAY = "" + private const val RESET = "" + private const val GRADIENT_END = "" + + private const val DEFAULT_GRADIENT = "" + private const val DEBUG_GRADIENT = "" + + private const val PREFIX_START = "$DARK_GRAY[$DARK_GRAY" + private const val PREFIX_END = "$DARK_GRAY] $RESET" + private val defaultPrefix = - "[${Cobalt.MOD_NAME}] " + "$PREFIX_START$DEFAULT_GRADIENT${Cobalt.MOD_NAME}$GRADIENT_END$PREFIX_END" + private val debugPrefix = - "[${Cobalt.MOD_NAME} Debug] " + "$PREFIX_START$DEBUG_GRADIENT${Cobalt.MOD_NAME} Debug$GRADIENT_END$PREFIX_END" private var lastDebugMessage: String? = null @@ -65,6 +86,39 @@ object ChatUtils { } } + @JvmStatic + fun buildGradientComponent( + text: String, + startColor: Int, + endColor: Int, + baseStyle: Style = Style.EMPTY, + ): MutableComponent { + val result = Component.empty() + val textLength = text.length + + if (textLength <= 1) { + return Component + .literal(text) + .setStyle(baseStyle.withColor(TextColor.fromRgb(startColor))) + } + + for (index in text.indices) { + val denominator = (textLength - 1).toDouble() + val ratio = index.toDouble() / denominator + val red = (startColor.red + ratio * (endColor.red - startColor.red)).roundToInt() + val green = (startColor.green + ratio * (endColor.green - startColor.green)).roundToInt() + val blue = (startColor.blue + ratio * (endColor.blue - startColor.blue)).roundToInt() + val interpolatedColor = (red shl 16) or (green shl 8) or blue + + val coloredChar = Component.literal(text[index].toString()) + .setStyle(baseStyle.withColor(TextColor.fromRgb(interpolatedColor))) + + result.append(coloredChar) + } + + return result + } + private fun addToChat(component: MutableComponent) { runOnClientThread { val player = minecraft.player @@ -79,9 +133,3 @@ object ChatUtils { } } - -enum class MessageType { - DEFAULT, - RAW, - DEBUG -} diff --git a/src/main/kotlin/org/cobalt/util/PlayerUtils.kt b/src/main/kotlin/org/cobalt/util/client/PlayerUtils.kt similarity index 97% rename from src/main/kotlin/org/cobalt/util/PlayerUtils.kt rename to src/main/kotlin/org/cobalt/util/client/PlayerUtils.kt index 0184e05..25e99fc 100644 --- a/src/main/kotlin/org/cobalt/util/PlayerUtils.kt +++ b/src/main/kotlin/org/cobalt/util/client/PlayerUtils.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.client import kotlin.math.ceil import kotlin.math.floor @@ -7,7 +7,7 @@ import net.minecraft.core.BlockPos import net.minecraft.world.phys.Vec3 import org.cobalt.Cobalt.minecraft import org.cobalt.Cobalt.runOnClientThread -import org.cobalt.util.rotation.Rotation +import org.cobalt.util.rotation.data.Rotation object PlayerUtils { diff --git a/src/main/kotlin/org/cobalt/util/WindowUtils.kt b/src/main/kotlin/org/cobalt/util/client/WindowUtils.kt similarity index 92% rename from src/main/kotlin/org/cobalt/util/WindowUtils.kt rename to src/main/kotlin/org/cobalt/util/client/WindowUtils.kt index 0fa9214..5c50343 100644 --- a/src/main/kotlin/org/cobalt/util/WindowUtils.kt +++ b/src/main/kotlin/org/cobalt/util/client/WindowUtils.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.client import org.cobalt.Cobalt.minecraft diff --git a/src/main/kotlin/org/cobalt/dsl/Color.kt b/src/main/kotlin/org/cobalt/util/color/ColorExtensions.kt similarity index 77% rename from src/main/kotlin/org/cobalt/dsl/Color.kt rename to src/main/kotlin/org/cobalt/util/color/ColorExtensions.kt index 28f5064..6e3180a 100644 --- a/src/main/kotlin/org/cobalt/dsl/Color.kt +++ b/src/main/kotlin/org/cobalt/util/color/ColorExtensions.kt @@ -1,4 +1,6 @@ -package org.cobalt.dsl +@file:JvmName("ColorUtils") + +package org.cobalt.util.color import java.awt.Color @@ -12,7 +14,7 @@ inline val Int.blue get() = this and 0xFF inline val Int.alpha - get() = this shr 24 and 0xFF + get() = this ushr 24 fun Color.updateAlpha(alpha: Int): Color { return Color(red, green, blue, alpha) diff --git a/src/main/kotlin/org/cobalt/util/config/BasicConfig.kt b/src/main/kotlin/org/cobalt/util/config/SimpleConfig.kt similarity index 87% rename from src/main/kotlin/org/cobalt/util/config/BasicConfig.kt rename to src/main/kotlin/org/cobalt/util/config/SimpleConfig.kt index af58918..4f723be 100644 --- a/src/main/kotlin/org/cobalt/util/config/BasicConfig.kt +++ b/src/main/kotlin/org/cobalt/util/config/SimpleConfig.kt @@ -3,7 +3,7 @@ package org.cobalt.util.config import com.google.gson.GsonBuilder import java.io.File -class BasicConfig(path: String, private val clazz: Class) { +class SimpleConfig(path: String, private val clazz: Class) { private val file = File(path) diff --git a/src/main/kotlin/org/cobalt/util/KeybindUtils.kt b/src/main/kotlin/org/cobalt/util/input/Keyboard.kt similarity index 97% rename from src/main/kotlin/org/cobalt/util/KeybindUtils.kt rename to src/main/kotlin/org/cobalt/util/input/Keyboard.kt index bbcc8d0..2f0d0da 100644 --- a/src/main/kotlin/org/cobalt/util/KeybindUtils.kt +++ b/src/main/kotlin/org/cobalt/util/input/Keyboard.kt @@ -1,11 +1,11 @@ -package org.cobalt.util +package org.cobalt.util.input import com.mojang.blaze3d.platform.InputConstants import net.minecraft.client.KeyMapping import org.cobalt.Cobalt.minecraft import org.lwjgl.glfw.GLFW -object KeybindUtils { +object Keyboard { @JvmStatic val allKeys = arrayOf( diff --git a/src/main/kotlin/org/cobalt/util/MouseUtils.kt b/src/main/kotlin/org/cobalt/util/input/Mouse.kt similarity index 96% rename from src/main/kotlin/org/cobalt/util/MouseUtils.kt rename to src/main/kotlin/org/cobalt/util/input/Mouse.kt index bb5c2d1..8e9bce0 100644 --- a/src/main/kotlin/org/cobalt/util/MouseUtils.kt +++ b/src/main/kotlin/org/cobalt/util/input/Mouse.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.input import net.minecraft.client.input.MouseButtonInfo import org.cobalt.Cobalt.minecraft @@ -6,7 +6,19 @@ import org.cobalt.Cobalt.runOnClientThread import org.cobalt.mixin.client.MouseHandlerAccessor import org.lwjgl.glfw.GLFW -object MouseUtils { +enum class MouseButton { + LEFT, RIGHT, MIDDLE +} + +enum class MouseAction { + PRESS, RELEASE +} + +enum class MouseMode { + DEFAULT, UNGRAB_MOUSE, LOCK_MOUSE +} + +object Mouse { @JvmStatic var mouseMode: MouseMode = MouseMode.DEFAULT @@ -54,15 +66,3 @@ object MouseUtils { } } - -enum class MouseButton { - LEFT, RIGHT, MIDDLE -} - -enum class MouseAction { - PRESS, RELEASE -} - -enum class MouseMode { - DEFAULT, UNGRAB_MOUSE, LOCK_MOUSE -} diff --git a/src/main/kotlin/org/cobalt/util/InventoryUtils.kt b/src/main/kotlin/org/cobalt/util/inventory/InventoryUtils.kt similarity index 56% rename from src/main/kotlin/org/cobalt/util/InventoryUtils.kt rename to src/main/kotlin/org/cobalt/util/inventory/InventoryUtils.kt index 2509cc0..fb7bc15 100644 --- a/src/main/kotlin/org/cobalt/util/InventoryUtils.kt +++ b/src/main/kotlin/org/cobalt/util/inventory/InventoryUtils.kt @@ -1,8 +1,10 @@ -package org.cobalt.util +package org.cobalt.util.inventory import net.minecraft.world.inventory.ContainerInput import net.minecraft.world.item.Item +import net.minecraft.world.item.ItemStack import org.cobalt.Cobalt.minecraft +import org.cobalt.util.input.MouseButton object InventoryUtils { @@ -46,21 +48,9 @@ object InventoryUtils { val player = minecraft.player ?: return -1 val inventory = player.inventory - for (i in 0..8) { - val stack = inventory.getItem(i) - - if (stack.isEmpty) { - continue - } - - val displayName = stack.hoverName.string - - if (displayName.contains(name, ignoreCase = true)) { - return i - } + return findSlot(9, { inventory.getItem(it) }) { + it.hoverName.string.contains(name, ignoreCase = true) } - - return -1 } @JvmStatic @@ -68,21 +58,9 @@ object InventoryUtils { val player = minecraft.player ?: return -1 val inventory = player.inventory - for (slot in 0..8) { - val stack = inventory.getItem(slot) - - if (stack.isEmpty) { - continue - } - - for (line in ItemUtils.getLoreLines(stack)) { - if (line.string.contains(lore, ignoreCase = true)) { - return slot - } - } + return findSlot(9, { inventory.getItem(it) }) { stack -> + ItemUtils.getLoreLines(stack).any { it.string.contains(lore, ignoreCase = true) } } - - return -1 } @JvmStatic @@ -90,19 +68,9 @@ object InventoryUtils { val player = minecraft.player ?: return -1 val inventory = player.inventory - for (slot in 0 until inventory.containerSize) { - val stack = inventory.getItem(slot) - - if (stack.isEmpty) { - continue - } - - if (stack.hoverName.string.contains(name, ignoreCase = true)) { - return slot - } + return findSlot(inventory.containerSize, { inventory.getItem(it) }) { + it.hoverName.string.contains(name, ignoreCase = true) } - - return -1 } @JvmStatic @@ -110,19 +78,7 @@ object InventoryUtils { val player = minecraft.player ?: return -1 val inventory = player.inventory - for (slot in 0 until inventory.containerSize) { - val stack = inventory.getItem(slot) - - if (stack.isEmpty) { - continue - } - - if (stack.item == item) { - return slot - } - } - - return -1 + return findSlot(inventory.containerSize, { inventory.getItem(it) }) { it.item == item } } @JvmStatic @@ -131,19 +87,9 @@ object InventoryUtils { val menu = player.containerMenu val containerSlots = menu.slots.size - player.inventory.nonEquipmentItems.size - for (slot in 0 until containerSlots) { - val stack = menu.getSlot(slot).item - - if (stack.isEmpty) { - continue - } - - if (stack.hoverName.string.contains(name, ignoreCase = true)) { - return slot - } + return findSlot(containerSlots, { menu.getSlot(it).item }) { + it.hoverName.string.contains(name, ignoreCase = true) } - - return -1 } @JvmStatic @@ -152,19 +98,7 @@ object InventoryUtils { val menu = player.containerMenu val containerSlots = menu.slots.size - player.inventory.nonEquipmentItems.size - for (slot in 0 until containerSlots) { - val stack = menu.getSlot(slot).item - - if (stack.isEmpty) { - continue - } - - if (stack.item == item) { - return slot - } - } - - return -1 + return findSlot(containerSlots, { menu.getSlot(it).item }) { it.item == item } } @JvmStatic @@ -172,17 +106,25 @@ object InventoryUtils { val player = minecraft.player ?: return -1 val inventory = player.inventory - for (slot in 0 until inventory.containerSize) { - val stack = inventory.getItem(slot) + return findSlot(inventory.containerSize, { inventory.getItem(it) }) { stack -> + ItemUtils.getLoreLines(stack).any { it.string.contains(lore, ignoreCase = true) } + } + } + + private inline fun findSlot( + size: Int, + getStack: (Int) -> ItemStack, + predicate: (ItemStack) -> Boolean, + ): Int { + for (slot in 0 until size) { + val stack = getStack(slot) if (stack.isEmpty) { continue } - for (line in ItemUtils.getLoreLines(stack)) { - if (line.string.contains(lore, ignoreCase = true)) { - return slot - } + if (predicate(stack)) { + return slot } } diff --git a/src/main/kotlin/org/cobalt/util/ItemUtils.kt b/src/main/kotlin/org/cobalt/util/inventory/ItemUtils.kt similarity index 89% rename from src/main/kotlin/org/cobalt/util/ItemUtils.kt rename to src/main/kotlin/org/cobalt/util/inventory/ItemUtils.kt index f187525..e16f42d 100644 --- a/src/main/kotlin/org/cobalt/util/ItemUtils.kt +++ b/src/main/kotlin/org/cobalt/util/inventory/ItemUtils.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.inventory import net.minecraft.core.component.DataComponents import net.minecraft.network.chat.Component diff --git a/src/main/kotlin/org/cobalt/util/WorldRenderUtils.kt b/src/main/kotlin/org/cobalt/util/render/GizmoRenderer.kt similarity index 97% rename from src/main/kotlin/org/cobalt/util/WorldRenderUtils.kt rename to src/main/kotlin/org/cobalt/util/render/GizmoRenderer.kt index f50e780..6b5e8a1 100644 --- a/src/main/kotlin/org/cobalt/util/WorldRenderUtils.kt +++ b/src/main/kotlin/org/cobalt/util/render/GizmoRenderer.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.render import java.awt.Color import net.minecraft.core.BlockPos @@ -10,7 +10,7 @@ import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 import org.cobalt.Cobalt -object WorldRenderUtils { +object GizmoRenderer { @JvmStatic fun drawBlockPos( @@ -28,6 +28,7 @@ object WorldRenderUtils { ) } + @JvmStatic fun drawEntityOutline( entity: Entity, color: Color, diff --git a/src/main/kotlin/org/cobalt/util/skia/Skia.kt b/src/main/kotlin/org/cobalt/util/render/SkiaRenderer.kt similarity index 85% rename from src/main/kotlin/org/cobalt/util/skia/Skia.kt rename to src/main/kotlin/org/cobalt/util/render/SkiaRenderer.kt index 79a5ca7..9e8aa3d 100644 --- a/src/main/kotlin/org/cobalt/util/skia/Skia.kt +++ b/src/main/kotlin/org/cobalt/util/render/SkiaRenderer.kt @@ -1,21 +1,20 @@ @file:Suppress("TooManyFunctions") -package org.cobalt.util.skia +package org.cobalt.util.render import io.github.humbleui.skija.* -import io.github.humbleui.skija.paragraph.FontCollection import io.github.humbleui.skija.svg.SVGDOM import io.github.humbleui.skija.svg.SVGLengthContext import io.github.humbleui.types.RRect import io.github.humbleui.types.Rect import java.awt.Color import kotlin.math.max -import org.cobalt.util.skia.helper.SkiaCorner -import org.cobalt.util.skia.helper.SkiaFont -import org.cobalt.util.skia.helper.SkiaImage -import org.joml.Matrix3x2fc +import org.cobalt.util.render.skia.data.SkiaCorner +import org.cobalt.util.render.skia.data.SkiaFont +import org.cobalt.util.render.skia.data.SkiaImage +import org.cobalt.util.render.skia.helper.LineWrapper -object Skia { +object SkiaRenderer { private val imageCache = HashMap() private val fonts = HashMap() @@ -59,17 +58,6 @@ object Skia { canvas().translate(x, y) } - @JvmStatic - fun transform(matrix: Matrix3x2fc) { - val skiaMatrix = Matrix33( - matrix.m00(), matrix.m10(), matrix.m20(), - matrix.m01(), matrix.m11(), matrix.m21(), - 0f, 0f, 1f - ) - - canvas().concat(skiaMatrix) - } - @JvmStatic fun rotate(degrees: Float) { canvas().rotate(degrees) @@ -205,58 +193,11 @@ object Skia { @JvmStatic fun wrap(font: SkiaFont, text: String, maxWidth: Float, size: Float): List { - val lines = mutableListOf() - val line = StringBuilder() - - fun pushLine() { - lines.add(line.toString()) - line.clear() - } - - fun append(text: String) { - if (line.isNotEmpty()) { - line.append(' ') - } - - line.append(text) - } - - fun addWord(word: String) { - val candidate = if (line.isEmpty()) word else "$line $word" - - if (line.isNotEmpty() && textWidth(font, candidate, size) > maxWidth) { - pushLine() - } - - if (textWidth(font, word, size) <= maxWidth) { - append(word) - return - } - - val chunk = StringBuilder() - - for (char in word) { - if (chunk.isNotEmpty() && textWidth(font, "$chunk$char", size) > maxWidth) { - append(chunk.toString()) - pushLine() - chunk.clear() - } - - chunk.append(char) - } - - append(chunk.toString()) - } - - text.split('\n').forEach { paragraph -> - paragraph.split(' ').filter { it.isNotEmpty() }.forEach { addWord(it) } - - if (line.isNotEmpty()) { - pushLine() - } + val wrapper = LineWrapper(maxWidth) { stringToMeasure -> + textWidth(font, stringToMeasure, size) } - return lines + return wrapper.wrap(text) } @JvmStatic diff --git a/src/main/kotlin/org/cobalt/util/ResourceUtils.kt b/src/main/kotlin/org/cobalt/util/render/skia/ResourceUtils.kt similarity index 96% rename from src/main/kotlin/org/cobalt/util/ResourceUtils.kt rename to src/main/kotlin/org/cobalt/util/render/skia/ResourceUtils.kt index 7c15fb3..a408fda 100644 --- a/src/main/kotlin/org/cobalt/util/ResourceUtils.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/ResourceUtils.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.render.skia import java.io.File import java.io.FileNotFoundException diff --git a/src/main/kotlin/org/cobalt/util/skia/SkiaBootstrap.kt b/src/main/kotlin/org/cobalt/util/render/skia/SkiaBootstrap.kt similarity index 98% rename from src/main/kotlin/org/cobalt/util/skia/SkiaBootstrap.kt rename to src/main/kotlin/org/cobalt/util/render/skia/SkiaBootstrap.kt index ead7ee6..5c6e955 100644 --- a/src/main/kotlin/org/cobalt/util/skia/SkiaBootstrap.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/SkiaBootstrap.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.skia +package org.cobalt.util.render.skia import java.net.URI import java.nio.file.Files diff --git a/src/main/kotlin/org/cobalt/util/skia/SkiaPIP.kt b/src/main/kotlin/org/cobalt/util/render/skia/SkiaPIP.kt similarity index 96% rename from src/main/kotlin/org/cobalt/util/skia/SkiaPIP.kt rename to src/main/kotlin/org/cobalt/util/render/skia/SkiaPIP.kt index c76a5f0..e036c16 100644 --- a/src/main/kotlin/org/cobalt/util/skia/SkiaPIP.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/SkiaPIP.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.skia +package org.cobalt.util.render.skia import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.PoseStack @@ -8,7 +8,7 @@ import net.minecraft.client.gui.render.pip.PictureInPictureRenderer import net.minecraft.client.renderer.SubmitNodeCollector import net.minecraft.client.renderer.state.gui.pip.PictureInPictureRenderState import org.cobalt.Cobalt.minecraft -import org.cobalt.util.skia.surface.SkiaSurface +import org.cobalt.util.render.skia.surface.SkiaSurface import org.joml.Matrix3x2f class SkiaPIP : PictureInPictureRenderer() { diff --git a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaCorner.kt b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaCorner.kt similarity index 92% rename from src/main/kotlin/org/cobalt/util/skia/helper/SkiaCorner.kt rename to src/main/kotlin/org/cobalt/util/render/skia/data/SkiaCorner.kt index 42f8978..18538ff 100644 --- a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaCorner.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaCorner.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.skia.helper +package org.cobalt.util.render.skia.data enum class SkiaCorner { diff --git a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaFont.kt b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaFont.kt similarity index 57% rename from src/main/kotlin/org/cobalt/util/skia/helper/SkiaFont.kt rename to src/main/kotlin/org/cobalt/util/render/skia/data/SkiaFont.kt index 40cb49b..c10aad6 100644 --- a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaFont.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaFont.kt @@ -1,6 +1,6 @@ -package org.cobalt.util.skia.helper +package org.cobalt.util.render.skia.data -import org.cobalt.util.ResourceUtils +import org.cobalt.util.render.skia.ResourceUtils data class SkiaFont(val location: String) { diff --git a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaImage.kt b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaImage.kt similarity index 67% rename from src/main/kotlin/org/cobalt/util/skia/helper/SkiaImage.kt rename to src/main/kotlin/org/cobalt/util/render/skia/data/SkiaImage.kt index 5388fb2..97c1451 100644 --- a/src/main/kotlin/org/cobalt/util/skia/helper/SkiaImage.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/data/SkiaImage.kt @@ -1,6 +1,6 @@ -package org.cobalt.util.skia.helper +package org.cobalt.util.render.skia.data -import org.cobalt.util.ResourceUtils +import org.cobalt.util.render.skia.ResourceUtils class SkiaImage( val location: String, diff --git a/src/main/kotlin/org/cobalt/util/render/skia/helper/LineWrapper.kt b/src/main/kotlin/org/cobalt/util/render/skia/helper/LineWrapper.kt new file mode 100644 index 0000000..5117d7d --- /dev/null +++ b/src/main/kotlin/org/cobalt/util/render/skia/helper/LineWrapper.kt @@ -0,0 +1,68 @@ +package org.cobalt.util.render.skia.helper + +class LineWrapper( + private val maxWidth: Float, + private val measureWidth: (String) -> Float, +) { + + private val lines = mutableListOf() + private val line = StringBuilder() + + fun wrap(text: String): List { + text.split('\n').forEach { paragraph -> + paragraph.split(' ').filter { it.isNotEmpty() }.forEach { word -> + processWord(word) + } + + if (line.isNotEmpty()) { + pushLine() + } + } + + return lines + } + + private fun processWord(word: String) { + val candidate = if (line.isEmpty()) word else "$line $word" + + if (line.isNotEmpty() && measureWidth(candidate) > maxWidth) { + pushLine() + } + + if (measureWidth(word) <= maxWidth) { + append(word) + } else { + splitAndAppendLongWord(word) + } + } + + private fun splitAndAppendLongWord(word: String) { + val chunk = StringBuilder() + + for (char in word) { + if (chunk.isNotEmpty() && measureWidth("$chunk$char") > maxWidth) { + append(chunk.toString()) + pushLine() + chunk.clear() + } + + chunk.append(char) + } + + append(chunk.toString()) + } + + private fun pushLine() { + lines.add(line.toString()) + line.clear() + } + + private fun append(word: String) { + if (line.isNotEmpty()) { + line.append(' ') + } + + line.append(word) + } + +} diff --git a/src/main/kotlin/org/cobalt/util/skia/surface/GlSurface.kt b/src/main/kotlin/org/cobalt/util/render/skia/surface/GlSurface.kt similarity index 95% rename from src/main/kotlin/org/cobalt/util/skia/surface/GlSurface.kt rename to src/main/kotlin/org/cobalt/util/render/skia/surface/GlSurface.kt index 51c36d9..63ccbb9 100644 --- a/src/main/kotlin/org/cobalt/util/skia/surface/GlSurface.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/surface/GlSurface.kt @@ -1,10 +1,10 @@ -package org.cobalt.util.skia.surface +package org.cobalt.util.render.skia.surface import com.mojang.blaze3d.opengl.GlStateManager import com.mojang.blaze3d.opengl.GlTexture import com.mojang.blaze3d.textures.GpuTexture import io.github.humbleui.skija.* -import org.cobalt.util.skia.Skia +import org.cobalt.util.render.SkiaRenderer import org.lwjgl.opengl.GL11C import org.lwjgl.opengl.GL30C import org.lwjgl.opengl.GL33C @@ -42,12 +42,12 @@ internal class GlSurface : SkiaSurface { val skijaSurface = surfaceFor(width, height, colorTexId) - Skia.beginFrame(skijaSurface.canvas) + SkiaRenderer.beginFrame(skijaSurface.canvas) try { draw(skijaSurface.canvas) } finally { - Skia.endFrame() + SkiaRenderer.endFrame() } directContext.flushAndSubmit(skijaSurface, true) diff --git a/src/main/kotlin/org/cobalt/util/skia/surface/SkiaSurface.kt b/src/main/kotlin/org/cobalt/util/render/skia/surface/SkiaSurface.kt similarity index 93% rename from src/main/kotlin/org/cobalt/util/skia/surface/SkiaSurface.kt rename to src/main/kotlin/org/cobalt/util/render/skia/surface/SkiaSurface.kt index 778abaf..e2367a8 100644 --- a/src/main/kotlin/org/cobalt/util/skia/surface/SkiaSurface.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/surface/SkiaSurface.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.skia.surface +package org.cobalt.util.render.skia.surface import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.textures.GpuTexture diff --git a/src/main/kotlin/org/cobalt/util/skia/surface/VulkanSurface.kt b/src/main/kotlin/org/cobalt/util/render/skia/surface/VulkanSurface.kt similarity index 95% rename from src/main/kotlin/org/cobalt/util/skia/surface/VulkanSurface.kt rename to src/main/kotlin/org/cobalt/util/render/skia/surface/VulkanSurface.kt index bbe4d10..26e881f 100644 --- a/src/main/kotlin/org/cobalt/util/skia/surface/VulkanSurface.kt +++ b/src/main/kotlin/org/cobalt/util/render/skia/surface/VulkanSurface.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.skia.surface +package org.cobalt.util.render.skia.surface import com.mojang.blaze3d.GpuFormat import com.mojang.blaze3d.systems.RenderSystem @@ -7,7 +7,7 @@ import com.mojang.blaze3d.vulkan.VulkanDevice import com.mojang.blaze3d.vulkan.VulkanGpuTexture import io.github.humbleui.skija.* import org.cobalt.mixin.mojang.GpuDeviceAccessor -import org.cobalt.util.skia.Skia +import org.cobalt.util.render.SkiaRenderer import org.lwjgl.vulkan.VK import org.lwjgl.vulkan.VK12.* @@ -38,12 +38,12 @@ internal class VulkanSurface : SkiaSurface { val skijaSurface = surfaceFor(directContext, width, height, vkImage, vkFormat) - Skia.beginFrame(skijaSurface.canvas) + SkiaRenderer.beginFrame(skijaSurface.canvas) try { draw(skijaSurface.canvas) } finally { - Skia.endFrame() + SkiaRenderer.endFrame() } directContext.flushAndSubmit(skijaSurface, false) diff --git a/src/main/kotlin/org/cobalt/util/RotationUtils.kt b/src/main/kotlin/org/cobalt/util/rotation/RotationMath.kt similarity index 83% rename from src/main/kotlin/org/cobalt/util/RotationUtils.kt rename to src/main/kotlin/org/cobalt/util/rotation/RotationMath.kt index 1b72c3d..4bc5fb1 100644 --- a/src/main/kotlin/org/cobalt/util/RotationUtils.kt +++ b/src/main/kotlin/org/cobalt/util/rotation/RotationMath.kt @@ -1,15 +1,14 @@ -package org.cobalt.util +package org.cobalt.util.rotation import kotlin.math.abs import kotlin.math.atan2 import kotlin.math.sqrt import net.minecraft.util.Mth import net.minecraft.world.phys.Vec3 -import org.cobalt.Cobalt.minecraft -import org.cobalt.util.rotation.Rotation +import org.cobalt.Cobalt +import org.cobalt.util.rotation.data.Rotation - -object RotationUtils { +object RotationMath { @JvmStatic val gcd: Double @@ -18,7 +17,7 @@ object RotationUtils { @JvmStatic val mouseSensitivityFactor: Double get() { - val sensitivity = minecraft.options.sensitivity().get() + val sensitivity = Cobalt.minecraft.options.sensitivity().get() val f = sensitivity * 0.6f + 0.2f return f * f * f * 8.0 } @@ -51,7 +50,7 @@ object RotationUtils { @JvmStatic fun getRotation(end: Vec3): Rotation { - val start = minecraft.player?.eyePosition ?: return Rotation.ZERO + val start = Cobalt.minecraft.player?.eyePosition ?: return Rotation.ZERO return getRotation(start, end) } diff --git a/src/main/kotlin/org/cobalt/util/rotation/Rotation.kt b/src/main/kotlin/org/cobalt/util/rotation/data/Rotation.kt similarity index 73% rename from src/main/kotlin/org/cobalt/util/rotation/Rotation.kt rename to src/main/kotlin/org/cobalt/util/rotation/data/Rotation.kt index bd822b8..4bb6140 100644 --- a/src/main/kotlin/org/cobalt/util/rotation/Rotation.kt +++ b/src/main/kotlin/org/cobalt/util/rotation/data/Rotation.kt @@ -1,8 +1,8 @@ -package org.cobalt.util.rotation +package org.cobalt.util.rotation.data import kotlin.math.roundToInt -import org.cobalt.util.PlayerUtils -import org.cobalt.util.RotationUtils +import org.cobalt.util.client.PlayerUtils +import org.cobalt.util.rotation.RotationMath data class Rotation( val yaw: Float, @@ -17,7 +17,7 @@ data class Rotation( return this } - val gcd = RotationUtils.gcd + val gcd = RotationMath.gcd val diff = currentRotation.rotationDeltaTo(this) val g1 = (diff.deltaYaw / gcd).roundToInt() * gcd @@ -31,8 +31,8 @@ data class Rotation( fun rotationDeltaTo(other: Rotation): RotationDelta { return RotationDelta( - RotationUtils.angleDifference(other.yaw, this.yaw), - RotationUtils.angleDifference(other.pitch, this.pitch) + RotationMath.angleDifference(other.yaw, this.yaw), + RotationMath.angleDifference(other.pitch, this.pitch) ) } diff --git a/src/main/kotlin/org/cobalt/util/rotation/RotationDelta.kt b/src/main/kotlin/org/cobalt/util/rotation/data/RotationDelta.kt similarity index 66% rename from src/main/kotlin/org/cobalt/util/rotation/RotationDelta.kt rename to src/main/kotlin/org/cobalt/util/rotation/data/RotationDelta.kt index 5f8e23b..cc19104 100644 --- a/src/main/kotlin/org/cobalt/util/rotation/RotationDelta.kt +++ b/src/main/kotlin/org/cobalt/util/rotation/data/RotationDelta.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.rotation +package org.cobalt.util.rotation.data data class RotationDelta( val deltaYaw: Float, diff --git a/src/main/kotlin/org/cobalt/util/rotation/RotationTarget.kt b/src/main/kotlin/org/cobalt/util/rotation/data/RotationTarget.kt similarity index 82% rename from src/main/kotlin/org/cobalt/util/rotation/RotationTarget.kt rename to src/main/kotlin/org/cobalt/util/rotation/data/RotationTarget.kt index fc35383..5847d86 100644 --- a/src/main/kotlin/org/cobalt/util/rotation/RotationTarget.kt +++ b/src/main/kotlin/org/cobalt/util/rotation/data/RotationTarget.kt @@ -1,9 +1,9 @@ -package org.cobalt.util.rotation +package org.cobalt.util.rotation.data import net.minecraft.core.BlockPos import net.minecraft.world.entity.Entity import net.minecraft.world.phys.Vec3 -import org.cobalt.util.RotationUtils +import org.cobalt.util.rotation.RotationMath class RotationTarget { @@ -14,15 +14,12 @@ class RotationTarget { val targetRotation: Rotation get() { - rotation?.let { - return it - } val vec = vector ?: entity?.position() ?: blockPos?.let { Vec3.atCenterOf(it) } ?: error("No rotation target set.") - return RotationUtils.getRotation(vec) + return rotation ?: RotationMath.getRotation(vec) } constructor(entityTarget: Entity) { diff --git a/src/main/kotlin/org/cobalt/util/helper/Clock.kt b/src/main/kotlin/org/cobalt/util/scheduling/Clock.kt similarity index 68% rename from src/main/kotlin/org/cobalt/util/helper/Clock.kt rename to src/main/kotlin/org/cobalt/util/scheduling/Clock.kt index 7ebd979..c428fab 100644 --- a/src/main/kotlin/org/cobalt/util/helper/Clock.kt +++ b/src/main/kotlin/org/cobalt/util/scheduling/Clock.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.helper +package org.cobalt.util.scheduling class Clock { @@ -12,11 +12,6 @@ class Clock { this.isScheduled = true } - fun schedule(milliseconds: Double) { - this.endTime = (System.currentTimeMillis() + milliseconds.toLong()) - this.isScheduled = true - } - fun passed(): Boolean { return System.currentTimeMillis() >= endTime } diff --git a/src/main/kotlin/org/cobalt/util/helper/Multithreading.kt b/src/main/kotlin/org/cobalt/util/scheduling/Multithreading.kt similarity index 92% rename from src/main/kotlin/org/cobalt/util/helper/Multithreading.kt rename to src/main/kotlin/org/cobalt/util/scheduling/Multithreading.kt index f247c37..b2ec701 100644 --- a/src/main/kotlin/org/cobalt/util/helper/Multithreading.kt +++ b/src/main/kotlin/org/cobalt/util/scheduling/Multithreading.kt @@ -1,4 +1,4 @@ -package org.cobalt.util.helper +package org.cobalt.util.scheduling import java.util.concurrent.Executors import java.util.concurrent.atomic.AtomicInteger diff --git a/src/main/kotlin/org/cobalt/util/helper/TickScheduler.kt b/src/main/kotlin/org/cobalt/util/scheduling/TickScheduler.kt similarity index 92% rename from src/main/kotlin/org/cobalt/util/helper/TickScheduler.kt rename to src/main/kotlin/org/cobalt/util/scheduling/TickScheduler.kt index dd87595..fb2da01 100644 --- a/src/main/kotlin/org/cobalt/util/helper/TickScheduler.kt +++ b/src/main/kotlin/org/cobalt/util/scheduling/TickScheduler.kt @@ -1,6 +1,6 @@ -package org.cobalt.util.helper +package org.cobalt.util.scheduling -import java.util.* +import java.util.PriorityQueue import org.cobalt.event.EventBus import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.TickEvent diff --git a/src/main/kotlin/org/cobalt/util/ServerUtils.kt b/src/main/kotlin/org/cobalt/util/server/ConnectionTracker.kt similarity index 96% rename from src/main/kotlin/org/cobalt/util/ServerUtils.kt rename to src/main/kotlin/org/cobalt/util/server/ConnectionTracker.kt index 6b2f419..1ccb450 100644 --- a/src/main/kotlin/org/cobalt/util/ServerUtils.kt +++ b/src/main/kotlin/org/cobalt/util/server/ConnectionTracker.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.server import kotlin.math.min import net.minecraft.network.protocol.game.ClientboundSetTimePacket @@ -9,7 +9,7 @@ import org.cobalt.event.EventBus import org.cobalt.event.annotation.SubscribeEvent import org.cobalt.event.impl.PacketEvent -object ServerUtils { +object ConnectionTracker { @JvmStatic var averageTps = 20.0 diff --git a/src/main/kotlin/org/cobalt/util/ScoreboardUtils.kt b/src/main/kotlin/org/cobalt/util/server/Scoreboard.kt similarity index 96% rename from src/main/kotlin/org/cobalt/util/ScoreboardUtils.kt rename to src/main/kotlin/org/cobalt/util/server/Scoreboard.kt index 55d7eb7..bd4a610 100644 --- a/src/main/kotlin/org/cobalt/util/ScoreboardUtils.kt +++ b/src/main/kotlin/org/cobalt/util/server/Scoreboard.kt @@ -1,4 +1,4 @@ -package org.cobalt.util +package org.cobalt.util.server import net.minecraft.network.chat.Component import net.minecraft.network.chat.numbers.StyledFormat @@ -7,7 +7,7 @@ import net.minecraft.world.scores.PlayerTeam import org.cobalt.Cobalt.minecraft import org.cobalt.mixin.gui.HudAccessor -object ScoreboardUtils { +object Scoreboard { @JvmStatic val title: Component? diff --git a/src/main/kotlin/org/cobalt/util/TablistUtils.kt b/src/main/kotlin/org/cobalt/util/server/Tablist.kt similarity index 92% rename from src/main/kotlin/org/cobalt/util/TablistUtils.kt rename to src/main/kotlin/org/cobalt/util/server/Tablist.kt index 7a21735..90face7 100644 --- a/src/main/kotlin/org/cobalt/util/TablistUtils.kt +++ b/src/main/kotlin/org/cobalt/util/server/Tablist.kt @@ -1,10 +1,10 @@ -package org.cobalt.util +package org.cobalt.util.server import net.minecraft.network.chat.Component import net.minecraft.world.level.GameType import org.cobalt.Cobalt.minecraft -object TablistUtils { +object Tablist { @JvmStatic val lines: List diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 7f5a224..92ab789 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -20,7 +20,7 @@ "preLaunch": [ { "adapter": "kotlin", - "value": "org.cobalt.util.skia.SkiaBootstrap" + "value": "org.cobalt.util.render.skia.SkiaBootstrap" } ], "client": [