Skip to content

Commit

Permalink
Merge branch 'develop' into version/1.20.1
Browse files Browse the repository at this point in the history
  • Loading branch information
Erdragh committed Feb 8, 2025
2 parents 6061ac7 + 315a57b commit e48ac37
Show file tree
Hide file tree
Showing 17 changed files with 133 additions and 42 deletions.
2 changes: 1 addition & 1 deletion buildSrc/src/main/groovy/multiloader-common.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ repositories {
}
maven {
name = "kotlinforforge"
url = uri("https://thedarkcolour.github.io/KotlinForForge/")
url = "https://thedarkcolour.github.io/KotlinForForge/"
}
maven {
name = "Sponge / Mixin"
Expand Down
6 changes: 3 additions & 3 deletions common/src/main/kotlin/dev/erdragh/astralbot/Bot.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package dev.erdragh.astralbot

import com.mojang.logging.LogUtils
import dev.erdragh.astralbot.listeners.CommandHandlingListener
import dev.erdragh.astralbot.listeners.UserEventListener
import dev.erdragh.astralbot.config.AstralBotConfig
Expand All @@ -13,8 +14,6 @@ import net.dv8tion.jda.api.entities.Guild
import net.dv8tion.jda.api.entities.channel.concrete.TextChannel
import net.dv8tion.jda.api.requests.GatewayIntent
import net.minecraft.server.MinecraftServer
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import java.io.File
import java.time.Duration
import java.time.LocalDateTime
Expand All @@ -23,7 +22,7 @@ import kotlin.io.path.absolute
import kotlin.properties.Delegates

const val MODID = "astralbot"
val LOGGER: Logger = LoggerFactory.getLogger(MODID)
val LOGGER = LogUtils.getLogger()

private lateinit var startTimestamp: LocalDateTime
var minecraftHandler: MinecraftHandler? = null
Expand Down Expand Up @@ -156,6 +155,7 @@ fun startAstralbot(server: MinecraftServer) {
fun stopAstralbot() {
LOGGER.info("Shutting down AstralBot")
shuttingDown.set(true)
minecraftHandler?.close()
if (baseDirectory != null) FAQHandler.stop()
if (jda != null) {
jda!!.shutdown()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package dev.erdragh.astralbot.commands.discord

import dev.erdragh.astralbot.util.GifWriter
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.interactions.commands.OptionType
import net.dv8tion.jda.api.interactions.commands.build.Commands
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData
import net.dv8tion.jda.api.utils.FileUpload
import java.awt.Color
import java.awt.Graphics2D
import java.awt.RenderingHints
import java.awt.image.BufferedImage
import java.io.ByteArrayOutputStream
import java.net.URL
Expand All @@ -15,7 +17,13 @@ object HeadpatCommand : HandledSlashCommand {
private const val USER_OPTION = "user"
override val command: SlashCommandData = Commands.slash("headpat", "Headpats a user")
.addOption(OptionType.USER, USER_OPTION, "The user whose avatar will be headpat.", true)
private val headpatBaseImage = ImageIO.read(this.javaClass.getResource("/headpat.png"))

private val ANIMATION = floatArrayOf(-.05f, .1f, .2f, .19f, .1f)
private val FRAMES: Array<BufferedImage> = Array(5) { ImageIO.read(this::class.java.getResourceAsStream("/headpat/pet$it.gif")) }
private val RENDERING_HINTS = RenderingHints(mapOf(
RenderingHints.KEY_ANTIALIASING to RenderingHints.VALUE_ANTIALIAS_ON,
RenderingHints.KEY_RENDERING to RenderingHints.VALUE_RENDER_QUALITY
))

override fun handle(event: SlashCommandInteractionEvent) {
event.deferReply(false).queue()
Expand All @@ -28,35 +36,40 @@ object HeadpatCommand : HandledSlashCommand {

val url = URL(user.effectiveAvatarUrl)
val avatar = ImageIO.read(url)
val headpatImage = BufferedImage(headpatBaseImage.width, headpatBaseImage.height, BufferedImage.TYPE_INT_ARGB)

val graphics = headpatImage.createGraphics()

val xOffset = 20
val yOffset = 20
graphics.drawImage(
avatar,
xOffset,
yOffset,
headpatImage.width - xOffset,
headpatImage.height - yOffset,
Color(0, 0, 0, 0),
null
)
graphics.drawImage(
headpatBaseImage,
0,
0,
headpatBaseImage.width,
headpatBaseImage.height,
Color(0, 0, 0, 0),
null
)

graphics.dispose()
val byteStream = ByteArrayOutputStream()
ImageIO.write(headpatImage, "png", byteStream)
event.hook.sendFiles(FileUpload.fromData(byteStream.toByteArray(), "headpat.png")).queue()
}

val stream: ByteArrayOutputStream

ByteArrayOutputStream().use { output ->
ImageIO.createImageOutputStream(output).use { out ->
GifWriter(
out, BufferedImage.TYPE_INT_ARGB,
timeBetweenFramesMS = 50, loopContinuously = true, transparent = true
).use { gifWriter ->
for (i in FRAMES.indices) {
val frame = BufferedImage(128, 128, BufferedImage.TYPE_INT_ARGB)
val graphics = frame.graphics as Graphics2D
// set rendering hints to slightly improve quality
graphics.setRenderingHints(RENDERING_HINTS)

val offset1 = Math.round(ANIMATION[i] * 64)
val offset2 = Math.round((-ANIMATION[i]) * 64)

// draw avatar
graphics.drawImage(avatar, 2, 32 + offset1, 128 - offset2, 128 - 32 - offset1, null)
// draw hand
graphics.drawImage(FRAMES[i], 0, 0, 128, 128, null)

gifWriter.write(frame)

graphics.dispose()
}
}
out.flush()

stream = output
}
}

event.hook.sendFiles(FileUpload.fromData(stream.toByteArray(), "headpat.gif")).queue()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -489,4 +489,8 @@ class MinecraftHandler(private val server: MinecraftServer) : ListenerAdapter()
private fun useWebhooks(): Boolean {
return AstralBotConfig.WEBHOOK_ENABLED.get() && webhookClient != null
}

fun close() {
webhookClient?.close()
}
}
70 changes: 70 additions & 0 deletions common/src/main/kotlin/dev/erdragh/astralbot/util/GifWriter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package dev.erdragh.astralbot.util

import java.awt.image.RenderedImage
import java.io.IOException
import javax.imageio.*
import javax.imageio.metadata.IIOMetadata
import javax.imageio.metadata.IIOMetadataNode
import javax.imageio.stream.ImageOutputStream

/**
* A simple utility for creating gifs.
*
* @author femmeromantic
*/
class GifWriter(
os: ImageOutputStream?, imageType: Int,
timeBetweenFramesMS: Int, loopContinuously: Boolean, transparent: Boolean
) : AutoCloseable {
private val writer: ImageWriter =
ImageIO.getImageWritersBySuffix("gif").next() ?: throw IOException("No GIF Image Writers Exist!")
private val imageWriteParam: ImageWriteParam = writer.defaultWriteParam
private val metadata: IIOMetadata = writer.getDefaultImageMetadata(
ImageTypeSpecifier.createFromBufferedImageType(imageType),
imageWriteParam
)

init {
val root = metadata.getAsTree(metadata.nativeMetadataFormatName) as IIOMetadataNode
setGifAttributes(root, timeBetweenFramesMS, transparent, loopContinuously)
metadata.setFromTree(metadata.nativeMetadataFormatName, root)
writer.output = os
writer.prepareWriteSequence(null)
}

fun write(img: RenderedImage) {
writer.writeToSequence(IIOImage(img, null, metadata), imageWriteParam)
}

override fun close() {
writer.endWriteSequence()
}

private fun getOrCreate(root: IIOMetadataNode, name: String): IIOMetadataNode =
(0 until root.length)
.map { root.item(it) as IIOMetadataNode }
.firstOrNull { it.nodeName == name }
?: IIOMetadataNode(name).also { root.appendChild(it) }

private fun setGifAttributes(
root: IIOMetadataNode, timeBetweenFramesMS: Int, transparent: Boolean, loopContinuously: Boolean
) {
getOrCreate(root, "GraphicControlExtension").apply {
setAttribute("disposalMethod", "restoreToBackgroundColor")
setAttribute("userInputFlag", "FALSE")
setAttribute("transparentColorFlag", if (transparent) "TRUE" else "FALSE")
setAttribute("delayTime", (timeBetweenFramesMS / 10).toString())
setAttribute("transparentColorIndex", "0")
}
getOrCreate(root, "CommentExtensions").setAttribute("CommentExtension", "Test Comment")

val appEN = getOrCreate(root, "ApplicationExtensions")
val loop = if (loopContinuously) 0 else 1
IIOMetadataNode("ApplicationExtension").apply {
setAttribute("applicationID", "NETSCAPE")
setAttribute("authenticationCode", "2.0")
userObject = byteArrayOf(0x1, loop.toByte(), 0)
appEN.appendChild(this)
}
}
}
Binary file removed common/src/main/resources/headpat.png
Binary file not shown.
Binary file added common/src/main/resources/headpat/pet0.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added common/src/main/resources/headpat/pet1.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added common/src/main/resources/headpat/pet2.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added common/src/main/resources/headpat/pet3.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added common/src/main/resources/headpat/pet4.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions fabric/src/main/kotlin/dev/erdragh/astralbot/fabric/BotMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import net.minecraftforge.fml.config.ModConfig

object BotMod : ModInitializer {
override fun onInitialize() {
ForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.SERVER, AstralBotConfig.SPEC)
ForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.SERVER, AstralBotTextConfig.SPEC, "astralbot-text.toml")
ForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.COMMON, AstralBotConfig.SPEC, "astralbot-server.toml")
ForgeConfigRegistry.INSTANCE.register(MODID, ModConfig.Type.COMMON, AstralBotTextConfig.SPEC, "astralbot-text.toml")

ServerLifecycleEvents.SERVER_STARTED.register {
LOGGER.info("Starting AstralBot on Fabric")
Expand Down
4 changes: 2 additions & 2 deletions forge/src/main/kotlin/dev/erdragh/astralbot/forge/BotMod.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import thedarkcolour.kotlinforforge.forge.MOD_BUS
@Mod("astralbot")
class BotMod () {
init {
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, AstralBotConfig.SPEC)
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, AstralBotTextConfig.SPEC, "astralbot-text.toml")
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, AstralBotConfig.SPEC, "astralbot-server.toml")
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, AstralBotTextConfig.SPEC, "astralbot-text.toml")
MOD_BUS.addListener(::onConfigReloaded)

FORGE_BUS.addListener(::onServerStart)
Expand Down
2 changes: 1 addition & 1 deletion forge/src/main/resources/META-INF/mods.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
modLoader = "kotlinforforge"
loaderVersion = "[4.6,)"
loaderVersion = "${kff_version_range}"
license = "${license}"
issueTrackerURL = "https://github.com/Erdragh/AstralBot/issues"

Expand Down
Binary file modified gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
4 changes: 3 additions & 1 deletion gradlew
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
# SPDX-License-Identifier: Apache-2.0
#

##############################################################################
#
Expand Down Expand Up @@ -84,7 +86,7 @@ done
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
Expand Down
2 changes: 2 additions & 0 deletions gradlew.bat
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem

@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
Expand Down

0 comments on commit e48ac37

Please sign in to comment.