├── .gitattributes
├── .github
└── workflows
│ └── build.yml
├── .gitignore
├── README.md
├── build.gradle.kts
├── buildSrc
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── CopyFile.kt
│ ├── SquareMarkerPlatformExtension.kt
│ ├── squaremarker.base.gradle.kts
│ ├── squaremarker.platform.gradle.kts
│ └── squaremarker.platform.loom.gradle.kts
├── common
├── build.gradle.kts
└── src
│ └── main
│ └── kotlin
│ ├── Components.kt
│ ├── Configuration.kt
│ ├── IO.kt
│ ├── Lang.kt
│ ├── SquareMarker.kt
│ ├── WorldIdentifierSerializer.kt
│ ├── command
│ ├── Commander.kt
│ ├── Commands.kt
│ ├── PlayerCommander.kt
│ ├── SquaremarkerCommand.kt
│ └── commands
│ │ ├── HelpCommand.kt
│ │ ├── ListMarkerCommand.kt
│ │ ├── RemoveMarkerCommand.kt
│ │ ├── SetMarkerCommand.kt
│ │ ├── ShowMarkerCommand.kt
│ │ └── UpdateMarkerCommand.kt
│ └── marker
│ ├── API.kt
│ ├── Marker.kt
│ ├── MarkerService.kt
│ └── MarkerTask.kt
├── fabric
├── build.gradle.kts
└── src
│ └── main
│ ├── kotlin
│ ├── SquareMarkerInitializer.kt
│ └── command
│ │ └── FabricCommander.kt
│ └── resources
│ └── fabric.mod.json
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── neoforge
├── build.gradle.kts
├── gradle.properties
└── src
│ └── main
│ ├── kotlin
│ ├── SquareMarkerInitializer.kt
│ └── command
│ │ └── ForgeCommander.kt
│ └── resources
│ ├── META-INF
│ └── neoforge.mods.toml
│ └── pack.mcmeta
├── paper
├── build.gradle.kts
└── src
│ └── main
│ ├── kotlin
│ ├── Folia.kt
│ ├── PaperWorldIdentifierSerializer.kt
│ ├── SquareMarkerPlugin.kt
│ └── command
│ │ └── PaperCommander.kt
│ └── resources
│ └── plugin.yml
├── resources
└── default_icon.png
└── settings.gradle.kts
/.gitattributes:
--------------------------------------------------------------------------------
1 | #
2 | # https://help.github.com/articles/dealing-with-line-endings/
3 | #
4 | # These are explicitly windows files and should use crlf
5 | *.bat text eol=crlf
6 |
--------------------------------------------------------------------------------
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: "build"
2 |
3 | on:
4 | push:
5 | branches: [ "**" ]
6 | tags-ignore: [ "**" ]
7 | pull_request:
8 |
9 | jobs:
10 | call-build:
11 | uses: "jpenilla/actions/.github/workflows/shared-ci.yml@master"
12 | with:
13 | artifacts-path: "build/libs/*.jar"
14 | loom: true
15 | jdk-version: 21
16 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .gradle
2 | .idea
3 | build
4 |
5 | **/run/
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # squaremarker
2 |
3 | A simple marker extension for squaremap (https://github.com/jpenilla/squaremap)
4 |
5 | This plugin is an extension and only works in combination with squaremap.
6 |
7 | It offers the possibility to easily create markers yourself, which are then displayed on the map.
8 | This project is still under development and will be improved and expanded in the future.
9 | Feel free to report any bugs you find via [GitHub Issues](https://github.com/SentixDev/squaremarker/issues).
10 |
11 | # Download
12 | Downloads are available via [GitHub Releases](https://github.com/SentixDev/squaremarker/releases).
13 |
14 | # Usage
15 |
16 | ## Commands
17 | | Command | Description | Permission |
18 | |--------------------------------------------------|------------------------------------------|-----------------------|
19 | | `/squaremarker help [query]` | Query help for squaremarker commands | `squaremarker.help` |
20 | | `/squaremarker list` | Shows a list with all existing markers | `squaremarker.list` |
21 | | `/squaremarker show ` | Shows details to a specific marker | `squaremarker.show` |
22 | | `/squaremarker set [content] [icon-url]` | Set a marker at your current location | `squaremarker.set` |
23 | | `/squaremarker update [content] [icon-url]` | Update a marker to your current location | `squaremarker.update` |
24 | | `/squaremarker remove ` | Remove a marker with ID | `squaremarker.remove` |
25 |
26 | ## Configuration
27 | ```yaml
28 | # Define the main command label
29 | command-label: squaremarker
30 |
31 | # Define the main command aliases
32 | command-aliases:
33 | - marker
34 | - squaremapmarker
35 | - smarker
36 |
37 | # Define the name of the layer
38 | layer-name: Marker
39 |
40 | # Define the link to the marker-icon-image
41 | icon-url: https://github.com/SentixDev/squaremarker/raw/master/resources/default_icon.png
42 |
43 | # Define the icon size
44 | icon-size: 16
45 |
46 | # Whether people can show/hide the markers on their map
47 | show-controls: true
48 |
49 | # Whether the markers are hidden by default
50 | default-hidden: false
51 |
52 | # The rate at which markers will update in milliseconds, defaults to 5000ms or 5 seconds
53 | update-rate-milliseconds: 5000
54 | ```
55 |
56 | ## Additional
57 | ***Of course, you can also use HTML tags in the content to customize the marker tooltips.***
58 |
59 | **Old marker files of the "Pl3xMap-Marker" addon are not compatible with this plugin.**
60 |
--------------------------------------------------------------------------------
/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | kotlin("jvm")
3 | id("org.jlleitschuh.gradle.ktlint")
4 | }
5 |
6 | tasks.jar {
7 | enabled = false
8 | }
9 |
--------------------------------------------------------------------------------
/buildSrc/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | `kotlin-dsl`
3 | id("org.jlleitschuh.gradle.ktlint") version "11.0.0"
4 | }
5 |
6 | repositories {
7 | gradlePluginPortal()
8 | mavenCentral()
9 | maven("https://repo.papermc.io/repository/maven-public/")
10 | maven("https://maven.fabricmc.net/")
11 | maven("https://maven.architectury.dev/")
12 | maven("https://repo.jpenilla.xyz/snapshots/")
13 | }
14 |
15 | dependencies {
16 | implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:2.0.20")
17 | implementation("org.jlleitschuh.gradle:ktlint-gradle:12.0.2")
18 | implementation("com.gradleup.shadow:shadow-gradle-plugin:8.3.0")
19 | implementation("xyz.jpenilla:quiet-architectury-loom:1.7-SNAPSHOT")
20 | }
21 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/CopyFile.kt:
--------------------------------------------------------------------------------
1 | import org.gradle.api.DefaultTask
2 | import org.gradle.api.file.RegularFileProperty
3 | import org.gradle.api.tasks.InputFile
4 | import org.gradle.api.tasks.OutputFile
5 | import org.gradle.api.tasks.TaskAction
6 |
7 | abstract class CopyFile : DefaultTask() {
8 | @get:InputFile
9 | abstract val fileToCopy: RegularFileProperty
10 |
11 | @get:OutputFile
12 | abstract val destination: RegularFileProperty
13 |
14 | @TaskAction
15 | private fun copyFile() {
16 | destination.get().asFile.parentFile.mkdirs()
17 | fileToCopy.get().asFile.copyTo(destination.get().asFile, overwrite = true)
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/SquareMarkerPlatformExtension.kt:
--------------------------------------------------------------------------------
1 | import org.gradle.api.file.RegularFileProperty
2 | import org.gradle.api.model.ObjectFactory
3 | import org.gradle.api.provider.Property
4 | import javax.inject.Inject
5 |
6 | abstract class SquareMarkerPlatformExtension {
7 | abstract val productionJar: RegularFileProperty
8 |
9 | abstract val modInfoFilePath: Property
10 | }
11 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/squaremarker.base.gradle.kts:
--------------------------------------------------------------------------------
1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
2 | import org.gradle.jvm.toolchain.JavaLanguageVersion
3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget
4 |
5 | plugins {
6 | base
7 | id("org.jetbrains.kotlin.jvm")
8 | id("java-library")
9 | id("org.jlleitschuh.gradle.ktlint")
10 | }
11 |
12 | kotlin {
13 | compilerOptions {
14 | jvmTarget = JvmTarget.JVM_21
15 | }
16 | }
17 |
18 | tasks {
19 | withType {
20 | listOf(
21 | "kotlin",
22 | "org.bstats",
23 | "io.leangen.geantyref",
24 | "org.spongepowered.configurate",
25 | "org.yaml.snakeyaml",
26 | ).forEach { relocate(it, "${rootProject.group}.lib.$it") }
27 | dependencies {
28 | exclude(dependency("org.jetbrains:annotations"))
29 | }
30 | }
31 | }
32 |
33 | kotlin {
34 | jvmToolchain {
35 | languageVersion = JavaLanguageVersion.of(21)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/squaremarker.platform.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("squaremarker.base")
3 | id("com.gradleup.shadow")
4 | }
5 |
6 | val platform = extensions.create("squareMarker", SquareMarkerPlatformExtension::class)
7 |
8 | tasks {
9 | val copyJar = register("copyJar") {
10 | fileToCopy.set(platform.productionJar)
11 | destination.set(
12 | platform.productionJar.flatMap {
13 | rootProject.layout.buildDirectory.file("libs/${it.asFile.name}")
14 | }
15 | )
16 | }
17 | shadowJar {
18 | dependencies {
19 | exclude {
20 | it.moduleGroup == "org.checkerframework"
21 | || it.moduleGroup == "com.google.errorprone"
22 | || it.moduleGroup == "org.apiguardian"
23 | }
24 | }
25 | }
26 | assemble {
27 | dependsOn(copyJar)
28 | }
29 | }
30 |
31 | afterEvaluate {
32 | tasks.processResources {
33 | inputs.property("version", project.version)
34 |
35 | filesMatching(platform.modInfoFilePath.get()) {
36 | expand("version" to project.version)
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/buildSrc/src/main/kotlin/squaremarker.platform.loom.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("squaremarker.platform")
3 | id("xyz.jpenilla.quiet-architectury-loom")
4 | id("com.gradleup.shadow")
5 | }
6 |
7 | val minecraftVersion: String by rootProject
8 |
9 | val projectImpl: Configuration by configurations.creating
10 | configurations.implementation {
11 | extendsFrom(projectImpl)
12 | }
13 |
14 | dependencies {
15 | minecraft("com.mojang:minecraft:$minecraftVersion")
16 | mappings(loom.officialMojangMappings())
17 | projectImpl(project(":squaremarker-common"))
18 | }
19 |
20 | val markerExt = extensions.getByType()
21 | markerExt.productionJar = tasks.remapJar.flatMap { it.archiveFile }
22 |
23 | tasks {
24 | shadowJar {
25 | configurations = listOf(projectImpl)
26 | dependencies {
27 | exclude {
28 | it.moduleGroup == "org.incendo"
29 | }
30 | }
31 | }
32 | remapJar {
33 | inputFile.set(shadowJar.flatMap { it.archiveFile })
34 | archiveFileName.set("${project.name}-mc$minecraftVersion-${project.version}.jar")
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/common/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("squaremarker.base")
3 | }
4 |
5 | val squaremapVersion: String by rootProject
6 | val cloudVersion: String by rootProject
7 | val cloudMinecraftVersion: String by rootProject
8 | val adventureVersion: String by rootProject
9 | val gsonVersion: String by rootProject
10 | val configurateVersion: String by rootProject
11 |
12 | dependencies {
13 | compileOnlyApi("xyz.jpenilla", "squaremap-api", squaremapVersion)
14 | api(platform("org.incendo:cloud-bom:$cloudVersion"))
15 | api(platform("org.incendo:cloud-minecraft-bom:$cloudMinecraftVersion"))
16 | api("org.incendo", "cloud-core")
17 | api("org.incendo", "cloud-brigadier")
18 | api("org.incendo", "cloud-annotations")
19 | api("org.incendo", "cloud-minecraft-extras") {
20 | isTransitive = false
21 | }
22 | api("org.incendo", "cloud-kotlin-extensions")
23 | compileOnly("com.google.code.gson", "gson", gsonVersion)
24 | compileOnly("net.kyori", "adventure-text-minimessage", adventureVersion)
25 | compileOnly("net.kyori", "adventure-text-logger-slf4j", adventureVersion)
26 | api(platform("org.spongepowered:configurate-bom:$configurateVersion"))
27 | api("org.spongepowered:configurate-yaml")
28 | }
29 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/Components.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | import net.kyori.adventure.audience.Audience
4 | import net.kyori.adventure.text.Component
5 | import net.kyori.adventure.text.minimessage.MiniMessage
6 |
7 | object Components {
8 | fun parse(input: String): Component {
9 | return MiniMessage.miniMessage().deserialize(input)
10 | }
11 |
12 | fun send(
13 | audience: Audience,
14 | input: String,
15 | ) {
16 | audience.sendMessage(parse("$input"))
17 | }
18 |
19 | fun sendPrefixed(
20 | audience: Audience,
21 | input: String,
22 | ) {
23 | audience.sendMessage(parse("${Lang.PREFIX} $input"))
24 | }
25 |
26 | fun url(
27 | content: String,
28 | hoverText: String,
29 | openUrl: String,
30 | ): String {
31 | return "${hoverable(hoverText)}$content"
32 | }
33 |
34 | fun clickable(
35 | content: String,
36 | hoverText: String,
37 | clickExecution: String,
38 | ): String {
39 | return "${hoverable(hoverText)}$content"
40 | }
41 |
42 | /*
43 | run_command
44 | suggest_command
45 | copy_to_clipboard
46 | open_file
47 | open_url
48 | */
49 | fun clickable(
50 | content: String,
51 | hoverText: String,
52 | clickAction: String,
53 | clickExecution: String,
54 | ): String {
55 | return "${hoverable(hoverText)}$content"
56 | }
57 |
58 | fun hoverable(hoverText: String): String {
59 | return ""
60 | }
61 |
62 | fun gradient(input: String): String {
63 | return "$input"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/Configuration.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | import org.spongepowered.configurate.objectmapping.ConfigSerializable
4 |
5 | @ConfigSerializable
6 | class Configuration {
7 | val commandLabel = "squaremarker"
8 | val commandAliases = mutableListOf("marker", "squaremapmarker", "smarker")
9 | val layerName = "Marker"
10 | val iconUrl = "https://github.com/SentixDev/squaremarker/raw/master/resources/default_icon.png"
11 | val iconSize = 16
12 | val showControls = true
13 | val defaultHidden = false
14 | val updateRateMilliseconds = 5L * 1000L // 5 seconds
15 | }
16 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/IO.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | import com.google.gson.Gson
4 | import com.google.gson.GsonBuilder
5 | import dev.sentix.squaremarker.marker.Marker
6 | import xyz.jpenilla.squaremap.api.WorldIdentifier
7 | import kotlin.io.path.bufferedReader
8 | import kotlin.io.path.bufferedWriter
9 | import kotlin.io.path.createDirectories
10 | import kotlin.io.path.exists
11 |
12 | object IO {
13 | val gson: Gson =
14 | GsonBuilder()
15 | .registerTypeAdapter(WorldIdentifier::class.java, SquareMarker.instance.worldIdentifierSerializer)
16 | .create()
17 |
18 | private val gsonPrettier: Gson =
19 | gson.newBuilder()
20 | .setPrettyPrinting()
21 | .create()
22 |
23 | private val markerFile = SquareMarker.instance.markerFile
24 |
25 | fun init() {
26 | val emptyMarkerList = emptyList()
27 | if (!markerFile.exists()) {
28 | write(emptyMarkerList)
29 | }
30 | }
31 |
32 | fun write(input: List) {
33 | if (!markerFile.parent.exists()) {
34 | markerFile.parent.createDirectories()
35 | }
36 | markerFile.bufferedWriter().use { it.write(gsonPrettier.toJson(input)) }
37 | }
38 |
39 | fun read(): String {
40 | return markerFile.bufferedReader().use { it.readText() }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/Lang.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | object Lang {
4 | const val PLAIN_PREFIX = "[squaremarker]"
5 | const val PREFIX = "[squaremarker]"
6 |
7 | const val NO_PERMISSION = "Not authorized."
8 |
9 | const val EMPTY = "$PREFIX No markers set."
10 |
11 | val HELP =
12 | Components.clickable(
13 | "$PREFIX ",
14 | Components.gradient("Click for SquareMarker command help"),
15 | "/${SquareMarker.instance.config.commandLabel} help",
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/SquareMarker.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | import dev.sentix.squaremarker.command.Commander
4 | import dev.sentix.squaremarker.command.Commands
5 | import dev.sentix.squaremarker.marker.API
6 | import org.incendo.cloud.CommandManager
7 | import org.slf4j.Logger
8 | import org.slf4j.LoggerFactory
9 | import org.spongepowered.configurate.yaml.NodeStyle
10 | import org.spongepowered.configurate.yaml.YamlConfigurationLoader
11 | import java.nio.file.Path
12 |
13 | class SquareMarker(
14 | commandManager: CommandManager,
15 | private val configFile: Path,
16 | dataDir: Path,
17 | val worldIdentifierSerializer: Any = WorldIdentifierSerializer,
18 | ) {
19 | companion object {
20 | val logger: Logger = LoggerFactory.getLogger(SquareMarker::class.java)
21 | lateinit var instance: SquareMarker
22 | }
23 |
24 | val markerFile: Path = dataDir.resolve("marker.json")
25 | val config: Configuration = loadConfiguration()
26 |
27 | init {
28 | instance = this
29 |
30 | Commands(this, commandManager).registerCommands()
31 | }
32 |
33 | fun init() {
34 | IO.init()
35 |
36 | API.init()
37 | }
38 |
39 | fun shutdown() {
40 | API.unregister()
41 | }
42 |
43 | private fun loadConfiguration(): Configuration {
44 | val loader =
45 | YamlConfigurationLoader.builder()
46 | .path(configFile)
47 | .nodeStyle(NodeStyle.BLOCK)
48 | .build()
49 | val node = loader.load()
50 | val configInst = node.get(Configuration::class.java) ?: error("Error reading config")
51 | val save = loader.createNode()
52 | save.set(configInst)
53 | loader.save(save)
54 | return configInst
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/WorldIdentifierSerializer.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker
2 |
3 | import com.google.gson.JsonDeserializationContext
4 | import com.google.gson.JsonDeserializer
5 | import com.google.gson.JsonElement
6 | import com.google.gson.JsonNull
7 | import com.google.gson.JsonPrimitive
8 | import com.google.gson.JsonSerializationContext
9 | import com.google.gson.JsonSerializer
10 | import xyz.jpenilla.squaremap.api.WorldIdentifier
11 | import java.lang.reflect.Type
12 |
13 | object WorldIdentifierSerializer :
14 | JsonSerializer,
15 | JsonDeserializer {
16 | override fun serialize(
17 | src: WorldIdentifier?,
18 | typeOfSrc: Type,
19 | context: JsonSerializationContext,
20 | ): JsonElement {
21 | if (src == null) return JsonNull.INSTANCE
22 | return JsonPrimitive(src.asString())
23 | }
24 |
25 | override fun deserialize(
26 | json: JsonElement?,
27 | typeOfT: Type,
28 | context: JsonDeserializationContext,
29 | ): WorldIdentifier? {
30 | if (json == null || json is JsonNull) return null
31 | return WorldIdentifier.parse(json.asString)
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/Commander.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command
2 |
3 | import net.kyori.adventure.audience.Audience
4 |
5 | interface Commander : Audience
6 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/Commands.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.Lang
5 | import dev.sentix.squaremarker.SquareMarker
6 | import dev.sentix.squaremarker.command.commands.HelpCommand
7 | import dev.sentix.squaremarker.command.commands.ListMarkerCommand
8 | import dev.sentix.squaremarker.command.commands.RemoveMarkerCommand
9 | import dev.sentix.squaremarker.command.commands.SetMarkerCommand
10 | import dev.sentix.squaremarker.command.commands.ShowMarkerCommand
11 | import dev.sentix.squaremarker.command.commands.UpdateMarkerCommand
12 | import net.kyori.adventure.text.Component.text
13 | import net.kyori.adventure.text.format.NamedTextColor
14 | import org.incendo.cloud.Command
15 | import org.incendo.cloud.CommandManager
16 | import org.incendo.cloud.description.Description.description
17 | import org.incendo.cloud.exception.InvalidCommandSenderException
18 | import org.incendo.cloud.exception.NoPermissionException
19 | import org.incendo.cloud.minecraft.extras.MinecraftExceptionHandler
20 | import org.incendo.cloud.util.TypeUtils
21 |
22 | class Commands(
23 | private val squareMarker: SquareMarker,
24 | val commandManager: CommandManager,
25 | ) {
26 | init {
27 | registerExceptionHandlers()
28 | }
29 |
30 | fun registerCommands() {
31 | listOf(
32 | HelpCommand(squareMarker, this),
33 | ListMarkerCommand(squareMarker, this),
34 | RemoveMarkerCommand(squareMarker, this),
35 | SetMarkerCommand(squareMarker, this),
36 | ShowMarkerCommand(squareMarker, this),
37 | UpdateMarkerCommand(squareMarker, this),
38 | ).forEach(SquaremarkerCommand::register)
39 | }
40 |
41 | private fun registerExceptionHandlers() {
42 | MinecraftExceptionHandler.createNative()
43 | .defaultArgumentParsingHandler()
44 | .defaultInvalidSenderHandler()
45 | .defaultCommandExecutionHandler()
46 | .handler(InvalidCommandSenderException::class.java) { _, ctx ->
47 | val requiredTypeDisplayName =
48 | when (ctx.exception().requiredSenderTypes().single()) {
49 | PlayerCommander::class.java -> "Players"
50 | else -> TypeUtils.simpleName(ctx.exception().requiredSenderTypes().single())
51 | }
52 | text()
53 | .content("This command can only be executed by ")
54 | .color(NamedTextColor.RED)
55 | .append(text(requiredTypeDisplayName, NamedTextColor.GRAY))
56 | .append(text('!'))
57 | .build()
58 | }
59 | .handler(NoPermissionException::class.java) { _, _ -> Components.parse(Lang.NO_PERMISSION) }
60 | .decorator { c -> Components.parse(Lang.HELP).append(c) }
61 | .registerTo(commandManager)
62 | }
63 |
64 | fun registerSubcommand(builderModifier: (Command.Builder) -> Command.Builder) {
65 | commandManager.command(builderModifier(rootBuilder()))
66 | }
67 |
68 | private fun rootBuilder(): Command.Builder =
69 | commandManager.commandBuilder(
70 | squareMarker.config.commandLabel,
71 | description("Squaremarker command. '/${squareMarker.config.commandLabel} help'"),
72 | *squareMarker.config.commandAliases.toTypedArray(),
73 | )
74 | }
75 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/PlayerCommander.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command
2 |
3 | import xyz.jpenilla.squaremap.api.WorldIdentifier
4 |
5 | interface PlayerCommander : Commander {
6 | val world: WorldIdentifier
7 | val x: Double
8 | val y: Double
9 | val z: Double
10 | }
11 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/SquaremarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command
2 |
3 | import dev.sentix.squaremarker.SquareMarker
4 |
5 | abstract class SquaremarkerCommand protected constructor(
6 | protected val squareMarker: SquareMarker,
7 | protected val commands: Commands,
8 | ) {
9 | abstract fun register()
10 | }
11 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/HelpCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.SquareMarker
5 | import dev.sentix.squaremarker.command.Commander
6 | import dev.sentix.squaremarker.command.Commands
7 | import dev.sentix.squaremarker.command.SquaremarkerCommand
8 | import net.kyori.adventure.text.format.NamedTextColor
9 | import net.kyori.adventure.text.format.TextColor
10 | import org.incendo.cloud.component.CommandComponent
11 | import org.incendo.cloud.context.CommandContext
12 | import org.incendo.cloud.minecraft.extras.AudienceProvider
13 | import org.incendo.cloud.minecraft.extras.MinecraftHelp
14 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
15 | import org.incendo.cloud.parser.standard.StringParser.greedyStringParser
16 | import org.incendo.cloud.suggestion.Suggestion.suggestion
17 | import org.incendo.cloud.suggestion.SuggestionProvider
18 |
19 | class HelpCommand(plugin: SquareMarker, commands: Commands) :
20 | SquaremarkerCommand(
21 | plugin,
22 | commands,
23 | ) {
24 | private val help = createHelp()
25 |
26 | override fun register() {
27 | val helpQueryArgument =
28 | CommandComponent.builder("query", greedyStringParser())
29 | .suggestionProvider(
30 | SuggestionProvider.blocking { context, _ ->
31 | commands.commandManager.createHelpHandler().queryRootIndex(context.sender())
32 | .entries()
33 | .map { it.syntax() }
34 | .map { suggestion(it) }
35 | .toList()
36 | },
37 | )
38 | .optional()
39 | .build()
40 |
41 | commands.registerSubcommand { builder ->
42 | builder.literal("help")
43 | .argument(helpQueryArgument)
44 | .commandDescription(richDescription(Components.parse("Show marker help.")))
45 | .permission("squaremarker.help")
46 | .handler(::execute)
47 | }
48 | }
49 |
50 | private fun execute(context: CommandContext) {
51 | help.queryCommands(context.getOrDefault("query", ""), context.sender())
52 | }
53 |
54 | private fun createHelp(): MinecraftHelp {
55 | return MinecraftHelp.builder()
56 | .commandManager(commands.commandManager)
57 | .audienceProvider(AudienceProvider.nativeAudience())
58 | .commandPrefix("/${squareMarker.config.commandLabel} help")
59 | .colors(
60 | MinecraftHelp.helpColors(
61 | TextColor.color(0x5B00FF),
62 | NamedTextColor.WHITE,
63 | TextColor.color(0xC028FF),
64 | NamedTextColor.GRAY,
65 | NamedTextColor.DARK_GRAY,
66 | ),
67 | )
68 | .messages(MinecraftHelp.MESSAGE_HELP_TITLE, "squaremarker command help")
69 | .build()
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/ListMarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.Lang
5 | import dev.sentix.squaremarker.SquareMarker
6 | import dev.sentix.squaremarker.command.Commander
7 | import dev.sentix.squaremarker.command.Commands
8 | import dev.sentix.squaremarker.command.SquaremarkerCommand
9 | import dev.sentix.squaremarker.marker.Marker
10 | import dev.sentix.squaremarker.marker.MarkerService
11 | import org.incendo.cloud.context.CommandContext
12 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
13 |
14 | class ListMarkerCommand(plugin: SquareMarker, commands: Commands) :
15 | SquaremarkerCommand(
16 | plugin,
17 | commands,
18 | ) {
19 | override fun register() {
20 | commands.registerSubcommand { builder ->
21 | builder.literal("list")
22 | .commandDescription(richDescription(Components.parse("List all markers.")))
23 | .permission("squaremarker.list")
24 | .handler(::execute)
25 | }
26 | }
27 |
28 | private fun execute(context: CommandContext) {
29 | val sender = context.sender()
30 |
31 | val markerList = MarkerService.getMarkerList()
32 |
33 | if (markerList.isNotEmpty()) {
34 | sendMarkerList(sender, markerList)
35 | } else {
36 | Components.send(sender, Lang.EMPTY)
37 | }
38 | }
39 |
40 | private fun sendMarkerList(
41 | sender: Commander,
42 | markerList: MutableList,
43 | ) {
44 | val gradient = Components.gradient("Marker")
45 |
46 | Components.send(sender, "")
47 | Components.send(
48 | sender,
49 | "» ------------- × $gradient × ------------- «",
50 | )
51 | Components.send(sender, "")
52 |
53 | Components.send(sender, " × Markers [" + markerList.size + "]")
54 | Components.send(sender, "")
55 | for (marker in markerList) {
56 | Components.send(
57 | sender,
58 | " × ${marker.id} ${
59 | Components.clickable(
60 | "[SHOW]",
61 | "SHOW",
62 | "/squaremarker show ${marker.id}",
63 | )
64 | }",
65 | )
66 | }
67 |
68 | Components.send(sender, "")
69 | Components.send(
70 | sender,
71 | "» ------------- × $gradient × ------------- «",
72 | )
73 | Components.send(sender, "")
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/RemoveMarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.SquareMarker
5 | import dev.sentix.squaremarker.command.Commander
6 | import dev.sentix.squaremarker.command.Commands
7 | import dev.sentix.squaremarker.command.SquaremarkerCommand
8 | import dev.sentix.squaremarker.marker.MarkerService
9 | import org.incendo.cloud.context.CommandContext
10 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
11 | import org.incendo.cloud.parser.standard.IntegerParser.integerParser
12 |
13 | class RemoveMarkerCommand(plugin: SquareMarker, commands: Commands) :
14 | SquaremarkerCommand(
15 | plugin,
16 | commands,
17 | ) {
18 | override fun register() {
19 | commands.registerSubcommand { builder ->
20 | builder.literal("remove")
21 | .required("id", integerParser())
22 | .commandDescription(richDescription(Components.parse("Remove a marker by id.")))
23 | .permission("squaremarker.remove")
24 | .handler(::execute)
25 | }
26 | }
27 |
28 | private fun execute(context: CommandContext) {
29 | val sender = context.sender()
30 |
31 | val id: Int = context.get("id")
32 |
33 | if (MarkerService.markerExist(id)) {
34 | MarkerService.removeMarker(id)
35 | Components.sendPrefixed(sender, "Removed marker with ID $id.")
36 | } else {
37 | Components.sendPrefixed(sender, "No marker with ID $id found.")
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/SetMarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.SquareMarker
5 | import dev.sentix.squaremarker.command.Commands
6 | import dev.sentix.squaremarker.command.PlayerCommander
7 | import dev.sentix.squaremarker.command.SquaremarkerCommand
8 | import dev.sentix.squaremarker.marker.Marker
9 | import dev.sentix.squaremarker.marker.MarkerService
10 | import org.incendo.cloud.component.DefaultValue
11 | import org.incendo.cloud.context.CommandContext
12 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
13 | import org.incendo.cloud.parser.standard.StringParser.greedyStringParser
14 | import xyz.jpenilla.squaremap.api.Key
15 | import xyz.jpenilla.squaremap.api.SquaremapProvider
16 | import java.net.URI
17 | import javax.imageio.ImageIO
18 | import kotlin.random.Random.Default.nextInt
19 |
20 | class SetMarkerCommand(plugin: SquareMarker, commands: Commands) :
21 | SquaremarkerCommand(
22 | plugin,
23 | commands,
24 | ) {
25 | override fun register() {
26 | commands.registerSubcommand { builder ->
27 | builder.literal("set")
28 | .optional("input", greedyStringParser(), DefaultValue.constant(" "))
29 | .commandDescription(richDescription(Components.parse("Set a marker at your position.")))
30 | .permission("squaremarker.set")
31 | .senderType(PlayerCommander::class.java)
32 | .handler(::execute)
33 | }
34 | }
35 |
36 | private fun execute(context: CommandContext) {
37 | val sender = context.sender()
38 |
39 | val id: Int = nextInt(9, 100000)
40 |
41 | val iconKey = "squaremarker_marker_icon_$id"
42 |
43 | val input: String = context.get("input")
44 |
45 | var content = input
46 |
47 | var url = ""
48 |
49 | if (input.contains("http")) {
50 | val split = input.split("http")
51 |
52 | content = split[0]
53 |
54 | url = "http${split[1]}"
55 | }
56 |
57 | val marker =
58 | Marker(
59 | id,
60 | content.trim(),
61 | url.trim(),
62 | iconKey,
63 | sender.world,
64 | sender.x,
65 | sender.y,
66 | sender.z,
67 | )
68 |
69 | if (!MarkerService.markerExist(id)) {
70 | MarkerService.addMarker(marker)
71 | Components.sendPrefixed(sender, "Created marker with ID $id.")
72 |
73 | try {
74 | SquaremapProvider.get().iconRegistry().register(
75 | Key.key(marker.iconKey),
76 | ImageIO.read(
77 | URI.create(marker.iconUrl).toURL(),
78 | ),
79 | )
80 | } catch (ex: Exception) {
81 | Components.sendPrefixed(sender, "Marker icon set to default.")
82 | }
83 | }
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/ShowMarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.SquareMarker
5 | import dev.sentix.squaremarker.command.Commander
6 | import dev.sentix.squaremarker.command.Commands
7 | import dev.sentix.squaremarker.command.SquaremarkerCommand
8 | import dev.sentix.squaremarker.marker.Marker
9 | import dev.sentix.squaremarker.marker.MarkerService
10 | import org.incendo.cloud.context.CommandContext
11 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
12 | import org.incendo.cloud.parser.standard.IntegerParser.integerParser
13 |
14 | class ShowMarkerCommand(plugin: SquareMarker, commands: Commands) :
15 | SquaremarkerCommand(
16 | plugin,
17 | commands,
18 | ) {
19 | override fun register() {
20 | commands.registerSubcommand { builder ->
21 | builder.literal("show")
22 | .required("id", integerParser())
23 | .commandDescription(richDescription(Components.parse("Show a marker by id.")))
24 | .permission("squaremarker.show")
25 | .handler(::execute)
26 | }
27 | }
28 |
29 | private fun execute(context: CommandContext) {
30 | val sender = context.sender()
31 |
32 | val id: Int = context.get("id")
33 |
34 | if (MarkerService.markerExist(id)) {
35 | sendMarkerOverview(sender, MarkerService.getMarker(id))
36 | } else {
37 | Components.sendPrefixed(sender, "No marker with ID $id found.")
38 | }
39 | }
40 |
41 | private fun sendMarkerOverview(
42 | sender: Commander,
43 | marker: Marker,
44 | ) {
45 | val gradient = Components.gradient("Marker")
46 | val div =
47 | "» ------------- × $gradient × ------------- «"
48 |
49 | Components.send(sender, "")
50 | Components.send(
51 | sender,
52 | div,
53 | )
54 | Components.send(sender, "")
55 |
56 | Components.send(sender, " × ID | ${marker.id}")
57 | if (marker.content.isNotBlank()) {
58 | Components.send(
59 | sender,
60 | " × TEXT | ${marker.content}",
61 | )
62 | }
63 | if (marker.iconUrl.isNotBlank()) {
64 | Components.send(
65 | sender,
66 | " × URL | ${
67 | Components.url(
68 | "${marker.iconUrl}",
69 | "SHOW",
70 | marker.iconUrl,
71 | )
72 | }",
73 | )
74 | }
75 |
76 | Components.send(sender, "")
77 | Components.send(
78 | sender,
79 | " × ${
80 | Components.clickable(
81 | "[UPDATE]",
82 | "UPDATE MARKER",
83 | "suggest_command",
84 | "/squaremarker update ${marker.id} ",
85 | )
86 | } ${
87 | Components.clickable(
88 | "[REMOVE]",
89 | "REMOVE MARKER",
90 | "/squaremarker remove ${marker.id}",
91 | )
92 | }",
93 | )
94 | Components.send(sender, "")
95 | Components.send(
96 | sender,
97 | " × ${
98 | Components.clickable(
99 | "[LIST]",
100 | "SHOW LIST",
101 | "/squaremarker list",
102 | )
103 | }",
104 | )
105 | Components.send(sender, "")
106 | Components.send(
107 | sender,
108 | div,
109 | )
110 | Components.send(sender, "")
111 | }
112 | }
113 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/command/commands/UpdateMarkerCommand.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.command.commands
2 |
3 | import dev.sentix.squaremarker.Components
4 | import dev.sentix.squaremarker.SquareMarker
5 | import dev.sentix.squaremarker.command.Commands
6 | import dev.sentix.squaremarker.command.PlayerCommander
7 | import dev.sentix.squaremarker.command.SquaremarkerCommand
8 | import dev.sentix.squaremarker.marker.Marker
9 | import dev.sentix.squaremarker.marker.MarkerService
10 | import org.incendo.cloud.component.DefaultValue
11 | import org.incendo.cloud.context.CommandContext
12 | import org.incendo.cloud.minecraft.extras.RichDescription.richDescription
13 | import org.incendo.cloud.parser.standard.IntegerParser.integerParser
14 | import org.incendo.cloud.parser.standard.StringParser.greedyStringParser
15 | import xyz.jpenilla.squaremap.api.Key
16 | import xyz.jpenilla.squaremap.api.SquaremapProvider
17 | import java.io.File
18 | import java.net.URI
19 | import javax.imageio.ImageIO
20 |
21 | class UpdateMarkerCommand(plugin: SquareMarker, commands: Commands) :
22 | SquaremarkerCommand(
23 | plugin,
24 | commands,
25 | ) {
26 | override fun register() {
27 | commands.registerSubcommand { builder ->
28 | builder.literal("update")
29 | .required("id", integerParser())
30 | .optional("input", greedyStringParser(), DefaultValue.constant(" "))
31 | .commandDescription(richDescription(Components.parse("Update a marker to your position.")))
32 | .permission("squaremarker.set")
33 | .senderType(PlayerCommander::class.java)
34 | .handler(::execute)
35 | }
36 | }
37 |
38 | private fun execute(context: CommandContext) {
39 | val sender = context.sender()
40 |
41 | val id: Int = context.get("id")
42 |
43 | val iconKey = "squaremarker_marker_icon_$id"
44 |
45 | val input: String = context.get("input")
46 |
47 | var content = input
48 |
49 | var url = ""
50 |
51 | if (input.contains("http")) {
52 | val split = input.split("http")
53 |
54 | content = split[0]
55 |
56 | url = "http${split[1]}"
57 | }
58 |
59 | val marker =
60 | Marker(
61 | id,
62 | content.trim(),
63 | url.trim(),
64 | iconKey,
65 | sender.world,
66 | sender.x,
67 | sender.y,
68 | sender.z,
69 | )
70 |
71 | if (MarkerService.markerExist(id)) {
72 | if (MarkerService.getMarker(id).iconUrl.isNotBlank()) {
73 | SquaremapProvider.get().iconRegistry().unregister(Key.key(marker.iconKey))
74 | File("${SquaremapProvider.get().webDir()}/images/icon/registered/${marker.iconKey}.png").delete()
75 | }
76 |
77 | try {
78 | SquaremapProvider.get().iconRegistry().register(
79 | Key.key(marker.iconKey),
80 | ImageIO.read(
81 | URI(marker.iconUrl).toURL(),
82 | ),
83 | )
84 | } catch (ex: Exception) {
85 | Components.sendPrefixed(sender, "Marker icon set to default.")
86 | }
87 |
88 | MarkerService.updateMarker(marker)
89 | Components.sendPrefixed(sender, "Updated existing marker with ID $id.")
90 | } else {
91 | Components.sendPrefixed(sender, "No marker with ID $id found.")
92 | }
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/marker/API.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.marker
2 |
3 | import dev.sentix.squaremarker.Lang
4 | import dev.sentix.squaremarker.SquareMarker
5 | import xyz.jpenilla.squaremap.api.Key
6 | import xyz.jpenilla.squaremap.api.MapWorld
7 | import xyz.jpenilla.squaremap.api.SimpleLayerProvider
8 | import xyz.jpenilla.squaremap.api.SquaremapProvider
9 | import xyz.jpenilla.squaremap.api.WorldIdentifier
10 | import java.net.URI
11 | import java.util.concurrent.Executors
12 | import java.util.concurrent.ScheduledExecutorService
13 | import java.util.concurrent.ScheduledFuture
14 | import java.util.concurrent.TimeUnit
15 | import javax.imageio.ImageIO
16 |
17 | object API {
18 | val markerIconKey: Key = Key.of("squaremarker_marker_icon_")
19 |
20 | private val executor: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
21 | private val providerMap: MutableMap, MarkerTask>> = HashMap()
22 |
23 | fun init() {
24 | registerIcons()
25 |
26 | SquaremapProvider.get().mapWorlds().forEach(::initWorld)
27 | }
28 |
29 | fun unloadWorld(mapWorld: MapWorld) {
30 | providerMap.remove(mapWorld.identifier())?.apply {
31 | second.disable()
32 | first.cancel(true)
33 | }
34 | }
35 |
36 | fun initWorld(mapWorld: MapWorld) {
37 | if (mapWorld.identifier() in providerMap) {
38 | return
39 | }
40 |
41 | val provider: SimpleLayerProvider =
42 | SimpleLayerProvider.builder(SquareMarker.instance.config.layerName).apply {
43 | defaultHidden(SquareMarker.instance.config.defaultHidden)
44 | showControls(SquareMarker.instance.config.showControls)
45 | }.build()
46 | val key = Key.of("squaremarker_marker")
47 | if (mapWorld.layerRegistry().hasEntry(key)) {
48 | mapWorld.layerRegistry().unregister(key)
49 | }
50 | mapWorld.layerRegistry().register(key, provider)
51 | val task = MarkerTask(mapWorld, provider)
52 | val scheduled =
53 | executor.scheduleAtFixedRate(
54 | task,
55 | 0,
56 | SquareMarker.instance.config.updateRateMilliseconds,
57 | TimeUnit.MILLISECONDS,
58 | )
59 | providerMap[mapWorld.identifier()] = Pair(scheduled, task)
60 | }
61 |
62 | private fun registerIcons() {
63 | SquaremapProvider.get().iconRegistry()
64 | .register(markerIconKey, ImageIO.read(URI.create(SquareMarker.instance.config.iconUrl).toURL()))
65 | for (marker in MarkerService.getMarkerList()) {
66 | if (marker.iconUrl.isNotBlank()) {
67 | try {
68 | SquaremapProvider.get().iconRegistry()
69 | .register(Key.of("squaremarker_marker_icon_${marker.id}"), ImageIO.read(URI.create(marker.iconUrl).toURL()))
70 | } catch (ex: Exception) {
71 | SquareMarker.logger.warn(
72 | "${Lang.PLAIN_PREFIX} There is an invalid url in your marker.json. Please fix \"${marker.iconUrl}\"!",
73 | ex,
74 | )
75 | }
76 | }
77 | }
78 | }
79 |
80 | fun cancel(world: WorldIdentifier) {
81 | providerMap[world]?.first?.cancel(true)
82 | }
83 |
84 | fun unregister() {
85 | providerMap.values.forEach { (future, task) ->
86 | task.disable()
87 | future.cancel(true)
88 | }
89 | providerMap.clear()
90 | executor.shutdownNow()
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/marker/Marker.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.marker
2 |
3 | import xyz.jpenilla.squaremap.api.WorldIdentifier
4 |
5 | data class Marker(
6 | val id: Int,
7 | val content: String,
8 | val iconUrl: String,
9 | val iconKey: String,
10 | val world: WorldIdentifier,
11 | val posX: Double,
12 | val posY: Double,
13 | val posZ: Double,
14 | )
15 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/marker/MarkerService.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.marker
2 |
3 | import com.google.gson.reflect.TypeToken
4 | import dev.sentix.squaremarker.IO
5 |
6 | object MarkerService {
7 | fun getMarkerList(): MutableList {
8 | val type = object : TypeToken>() {}.type
9 | return IO.gson.fromJson(IO.read(), type)
10 | }
11 |
12 | fun getMarker(id: Int): Marker {
13 | return getMarkerList().filter { it.id == id }[0]
14 | }
15 |
16 | fun markerExist(id: Int): Boolean {
17 | return try {
18 | getMarker(id)
19 | true
20 | } catch (_: IndexOutOfBoundsException) {
21 | false
22 | }
23 | }
24 |
25 | fun addMarker(marker: Marker) {
26 | val markerList = getMarkerList()
27 | markerList.add(marker)
28 | IO.write(markerList)
29 | }
30 |
31 | fun removeMarker(id: Int) {
32 | val markerList = getMarkerList()
33 | markerList.filter { it.id != id }.toMutableList().let { it1 -> IO.write(it1) }
34 | }
35 |
36 | fun updateMarker(marker: Marker) {
37 | removeMarker(marker.id)
38 | addMarker(marker)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/common/src/main/kotlin/marker/MarkerTask.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.marker
2 |
3 | import dev.sentix.squaremarker.SquareMarker
4 | import xyz.jpenilla.squaremap.api.Key
5 | import xyz.jpenilla.squaremap.api.MapWorld
6 | import xyz.jpenilla.squaremap.api.Point
7 | import xyz.jpenilla.squaremap.api.SimpleLayerProvider
8 | import xyz.jpenilla.squaremap.api.marker.Icon
9 | import xyz.jpenilla.squaremap.api.marker.Marker
10 | import xyz.jpenilla.squaremap.api.marker.MarkerOptions
11 |
12 | class MarkerTask(world: MapWorld, provider: SimpleLayerProvider) : Runnable {
13 | private val world: MapWorld
14 | private val provider: SimpleLayerProvider
15 | private var stop = false
16 |
17 | override fun run() {
18 | if (stop) {
19 | API.cancel(world.identifier())
20 | }
21 |
22 | provider.clearMarkers()
23 | MarkerService.getMarkerList().forEach { marker ->
24 | if (marker.world == world.identifier()) {
25 | val iconKey: Key =
26 | if (marker.iconUrl != "") {
27 | Key.of(marker.iconKey)
28 | } else {
29 | API.markerIconKey
30 | }
31 | handle(
32 | marker.id,
33 | marker.content,
34 | iconKey,
35 | marker.posX,
36 | marker.posZ,
37 | )
38 | }
39 | }
40 | }
41 |
42 | private fun handle(
43 | id: Int,
44 | name: String,
45 | iconKey: Key,
46 | x: Double,
47 | z: Double,
48 | ) {
49 | val icon: Icon = Marker.icon(Point.point(x, z), iconKey, SquareMarker.instance.config.iconSize)
50 | if (name.isNotBlank()) {
51 | icon.markerOptions(
52 | MarkerOptions.builder()
53 | .hoverTooltip(
54 | "$name",
55 | ),
56 | )
57 | }
58 | val markerId = "squaremarker_marker_$id"
59 | provider.addMarker(Key.of(markerId), icon)
60 | }
61 |
62 | fun disable() {
63 | stop = true
64 | provider.clearMarkers()
65 | }
66 |
67 | init {
68 | this.world = world
69 | this.provider = provider
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/fabric/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("squaremarker.platform.loom")
3 | }
4 |
5 | val fabricApiVersion: String by rootProject
6 | val fabricLoaderVersion: String by rootProject
7 | val cloudMinecraftModdedVersion: String by rootProject
8 | val adventureFabricVersion: String by rootProject
9 |
10 | dependencies {
11 | modImplementation("net.fabricmc:fabric-loader:$fabricLoaderVersion")
12 | modImplementation("net.fabricmc.fabric-api:fabric-api:$fabricApiVersion")
13 |
14 | // We don't include() these since squaremap already does and we depend on it
15 | modImplementation("org.incendo:cloud-fabric:$cloudMinecraftModdedVersion")
16 | modImplementation("net.kyori:adventure-platform-fabric:$adventureFabricVersion")
17 | }
18 |
19 | squareMarker {
20 | modInfoFilePath = "fabric.mod.json"
21 | }
22 |
--------------------------------------------------------------------------------
/fabric/src/main/kotlin/SquareMarkerInitializer.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.fabric
2 |
3 | import dev.sentix.squaremarker.SquareMarker
4 | import dev.sentix.squaremarker.command.Commander
5 | import dev.sentix.squaremarker.fabric.command.FabricCommander
6 | import dev.sentix.squaremarker.marker.API
7 | import net.fabricmc.api.ModInitializer
8 | import net.fabricmc.fabric.api.event.Event
9 | import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
10 | import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents
11 | import net.fabricmc.loader.api.FabricLoader
12 | import net.fabricmc.loader.api.ModContainer
13 | import net.minecraft.resources.ResourceLocation
14 | import org.incendo.cloud.CommandManager
15 | import org.incendo.cloud.SenderMapper
16 | import org.incendo.cloud.execution.ExecutionCoordinator
17 | import org.incendo.cloud.fabric.FabricServerCommandManager
18 | import xyz.jpenilla.squaremap.api.SquaremapProvider
19 | import xyz.jpenilla.squaremap.api.WorldIdentifier
20 |
21 | class SquareMarkerInitializer : ModInitializer {
22 | companion object {
23 | val modContainer: ModContainer = FabricLoader.getInstance().getModContainer("squaremarker").orElseThrow()
24 | }
25 |
26 | private val squareMarker: SquareMarker =
27 | SquareMarker(
28 | createCommandManager(),
29 | FabricLoader.getInstance().configDir.resolve("${modContainer.metadata.id}.yml"),
30 | FabricLoader.getInstance().gameDir.resolve(modContainer.metadata.id),
31 | )
32 |
33 | override fun onInitialize() {
34 | // Ensure we initialize after squaremap regardless of load order (future squaremap versions should provide a better mechanism)
35 | ServerLifecycleEvents.SERVER_STARTING.register { squareMarker.init() }
36 | ServerLifecycleEvents.SERVER_STOPPED.register { squareMarker.shutdown() }
37 |
38 | // Use custom late phase as workaround for squaremap <1.1.7
39 | val late = ResourceLocation.parse("squaremarker:late")
40 | ServerWorldEvents.LOAD.register(late) { _, world ->
41 | SquaremapProvider.get().getWorldIfEnabled(
42 | WorldIdentifier.parse(world.dimension().location().toString()),
43 | ).ifPresent(API::initWorld)
44 | }
45 | ServerWorldEvents.LOAD.addPhaseOrdering(Event.DEFAULT_PHASE, late)
46 |
47 | ServerWorldEvents.UNLOAD.register { _, world ->
48 | SquaremapProvider.get().getWorldIfEnabled(
49 | WorldIdentifier.parse(world.dimension().location().toString()),
50 | ).ifPresent(API::unloadWorld)
51 | }
52 | }
53 |
54 | private fun createCommandManager(): CommandManager {
55 | val mgr =
56 | FabricServerCommandManager(
57 | ExecutionCoordinator.simpleCoordinator(),
58 | SenderMapper.create(
59 | { stack -> FabricCommander.create(stack) },
60 | { commander -> (commander as FabricCommander).sender },
61 | ),
62 | )
63 | return mgr
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/fabric/src/main/kotlin/command/FabricCommander.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.fabric.command
2 |
3 | import dev.sentix.squaremarker.command.Commander
4 | import dev.sentix.squaremarker.command.PlayerCommander
5 | import net.kyori.adventure.audience.Audience
6 | import net.kyori.adventure.audience.ForwardingAudience
7 | import net.minecraft.commands.CommandSourceStack
8 | import net.minecraft.server.level.ServerPlayer
9 | import xyz.jpenilla.squaremap.api.WorldIdentifier
10 |
11 | open class FabricCommander(val sender: CommandSourceStack) : Commander, ForwardingAudience.Single {
12 | override fun audience(): Audience = sender
13 |
14 | class Player(sender: CommandSourceStack, private val player: ServerPlayer) : FabricCommander(sender), PlayerCommander {
15 | override val world: WorldIdentifier
16 | get() = WorldIdentifier.parse(player.level().dimension().location().toString())
17 | override val x: Double
18 | get() = player.x
19 | override val y: Double
20 | get() = player.y
21 | override val z: Double
22 | get() = player.z
23 | }
24 |
25 | companion object {
26 | fun create(sender: CommandSourceStack): Commander {
27 | if (sender.player != null) {
28 | return Player(sender, sender.playerOrException)
29 | }
30 | return FabricCommander(sender)
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/fabric/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "squaremarker",
4 | "version": "${version}",
5 | "name": "squaremarker",
6 | "description": "Marker addon for squaremap",
7 | "authors": [
8 | "Sentix"
9 | ],
10 | "contact": {
11 | "homepage": "https://github.com/SentixDev/squaremarker",
12 | "sources": "https://github.com/SentixDev/squaremarker"
13 | },
14 | "license": "Unknown (All Rights Reserved)",
15 | "icon": "assets/squaremarker/icon.png",
16 | "environment": "*",
17 | "entrypoints": {
18 | "main": [
19 | "dev.sentix.squaremarker.fabric.SquareMarkerInitializer"
20 | ]
21 | },
22 | "depends": {
23 | "fabricloader": ">=0.14.6",
24 | "fabric": "*",
25 | "minecraft": "~1.21",
26 | "java": ">=17",
27 | "squaremap": "*"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | group=dev.sentix
2 | version=1.0.7-SNAPSHOT
3 | description=Marker addon for squaremap
4 |
5 | kotlin.code.style=official
6 |
7 | org.gradle.parallel=true
8 | org.gradle.caching=true
9 | org.gradle.jvmargs=-Xmx3G
10 |
11 | minecraftVersion=1.21.1
12 | cloudVersion=2.0.0
13 | cloudMinecraftVersion=2.0.0-beta.10
14 | cloudMinecraftModdedVersion=2.0.0-beta.9
15 | bstatsVersion=3.1.0
16 | squaremapVersion=1.2.7
17 | adventureVersion=4.14.0
18 | adventureFabricVersion=5.14.1
19 | gsonVersion=2.10.1
20 | configurateVersion=4.1.2
21 | fabricApiVersion=0.105.0+1.21.1
22 | fabricLoaderVersion=0.16.5
23 | forgeVersion=21.1.62
24 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SentixDev/squaremarker/f46fa55bbe14f19a54d879d51b93a7f818dfd0fc/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
4 | networkTimeout=10000
5 | validateDistributionUrl=true
6 | zipStoreBase=GRADLE_USER_HOME
7 | zipStorePath=wrapper/dists
8 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | #
4 | # Copyright © 2015-2021 the original authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 | # SPDX-License-Identifier: Apache-2.0
19 | #
20 |
21 | ##############################################################################
22 | #
23 | # Gradle start up script for POSIX generated by Gradle.
24 | #
25 | # Important for running:
26 | #
27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
28 | # noncompliant, but you have some other compliant shell such as ksh or
29 | # bash, then to run this script, type that shell name before the whole
30 | # command line, like:
31 | #
32 | # ksh Gradle
33 | #
34 | # Busybox and similar reduced shells will NOT work, because this script
35 | # requires all of these POSIX shell features:
36 | # * functions;
37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»;
39 | # * compound commands having a testable exit status, especially «case»;
40 | # * various built-in commands including «command», «set», and «ulimit».
41 | #
42 | # Important for patching:
43 | #
44 | # (2) This script targets any POSIX shell, so it avoids extensions provided
45 | # by Bash, Ksh, etc; in particular arrays are avoided.
46 | #
47 | # The "traditional" practice of packing multiple parameters into a
48 | # space-separated string is a well documented source of bugs and security
49 | # problems, so this is (mostly) avoided, by progressively accumulating
50 | # options in "$@", and eventually passing that to Java.
51 | #
52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
54 | # see the in-line comments for details.
55 | #
56 | # There are tweaks for specific operating systems such as AIX, CygWin,
57 | # Darwin, MinGW, and NonStop.
58 | #
59 | # (3) This script is generated from the Groovy template
60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
61 | # within the Gradle project.
62 | #
63 | # You can find Gradle at https://github.com/gradle/gradle/.
64 | #
65 | ##############################################################################
66 |
67 | # Attempt to set APP_HOME
68 |
69 | # Resolve links: $0 may be a link
70 | app_path=$0
71 |
72 | # Need this for daisy-chained symlinks.
73 | while
74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
75 | [ -h "$app_path" ]
76 | do
77 | ls=$( ls -ld "$app_path" )
78 | link=${ls#*' -> '}
79 | case $link in #(
80 | /*) app_path=$link ;; #(
81 | *) app_path=$APP_HOME$link ;;
82 | esac
83 | done
84 |
85 | # This is normally unused
86 | # shellcheck disable=SC2034
87 | APP_BASE_NAME=${0##*/}
88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
90 | ' "$PWD" ) || exit
91 |
92 | # Use the maximum available, or set MAX_FD != -1 to use that value.
93 | MAX_FD=maximum
94 |
95 | warn () {
96 | echo "$*"
97 | } >&2
98 |
99 | die () {
100 | echo
101 | echo "$*"
102 | echo
103 | exit 1
104 | } >&2
105 |
106 | # OS specific support (must be 'true' or 'false').
107 | cygwin=false
108 | msys=false
109 | darwin=false
110 | nonstop=false
111 | case "$( uname )" in #(
112 | CYGWIN* ) cygwin=true ;; #(
113 | Darwin* ) darwin=true ;; #(
114 | MSYS* | MINGW* ) msys=true ;; #(
115 | NONSTOP* ) nonstop=true ;;
116 | esac
117 |
118 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
119 |
120 |
121 | # Determine the Java command to use to start the JVM.
122 | if [ -n "$JAVA_HOME" ] ; then
123 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
124 | # IBM's JDK on AIX uses strange locations for the executables
125 | JAVACMD=$JAVA_HOME/jre/sh/java
126 | else
127 | JAVACMD=$JAVA_HOME/bin/java
128 | fi
129 | if [ ! -x "$JAVACMD" ] ; then
130 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
131 |
132 | Please set the JAVA_HOME variable in your environment to match the
133 | location of your Java installation."
134 | fi
135 | else
136 | JAVACMD=java
137 | if ! command -v java >/dev/null 2>&1
138 | then
139 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
140 |
141 | Please set the JAVA_HOME variable in your environment to match the
142 | location of your Java installation."
143 | fi
144 | fi
145 |
146 | # Increase the maximum file descriptors if we can.
147 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
148 | case $MAX_FD in #(
149 | max*)
150 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
151 | # shellcheck disable=SC2039,SC3045
152 | MAX_FD=$( ulimit -H -n ) ||
153 | warn "Could not query maximum file descriptor limit"
154 | esac
155 | case $MAX_FD in #(
156 | '' | soft) :;; #(
157 | *)
158 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
159 | # shellcheck disable=SC2039,SC3045
160 | ulimit -n "$MAX_FD" ||
161 | warn "Could not set maximum file descriptor limit to $MAX_FD"
162 | esac
163 | fi
164 |
165 | # Collect all arguments for the java command, stacking in reverse order:
166 | # * args from the command line
167 | # * the main class name
168 | # * -classpath
169 | # * -D...appname settings
170 | # * --module-path (only if needed)
171 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
172 |
173 | # For Cygwin or MSYS, switch paths to Windows format before running java
174 | if "$cygwin" || "$msys" ; then
175 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
176 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
177 |
178 | JAVACMD=$( cygpath --unix "$JAVACMD" )
179 |
180 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
181 | for arg do
182 | if
183 | case $arg in #(
184 | -*) false ;; # don't mess with options #(
185 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
186 | [ -e "$t" ] ;; #(
187 | *) false ;;
188 | esac
189 | then
190 | arg=$( cygpath --path --ignore --mixed "$arg" )
191 | fi
192 | # Roll the args list around exactly as many times as the number of
193 | # args, so each arg winds up back in the position where it started, but
194 | # possibly modified.
195 | #
196 | # NB: a `for` loop captures its iteration list before it begins, so
197 | # changing the positional parameters here affects neither the number of
198 | # iterations, nor the values presented in `arg`.
199 | shift # remove old arg
200 | set -- "$@" "$arg" # push replacement arg
201 | done
202 | fi
203 |
204 |
205 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
206 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
207 |
208 | # Collect all arguments for the java command:
209 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
210 | # and any embedded shellness will be escaped.
211 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
212 | # treated as '${Hostname}' itself on the command line.
213 |
214 | set -- \
215 | "-Dorg.gradle.appname=$APP_BASE_NAME" \
216 | -classpath "$CLASSPATH" \
217 | org.gradle.wrapper.GradleWrapperMain \
218 | "$@"
219 |
220 | # Stop when "xargs" is not available.
221 | if ! command -v xargs >/dev/null 2>&1
222 | then
223 | die "xargs is not available"
224 | fi
225 |
226 | # Use "xargs" to parse quoted args.
227 | #
228 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed.
229 | #
230 | # In Bash we could simply go:
231 | #
232 | # readarray ARGS < <( xargs -n1 <<<"$var" ) &&
233 | # set -- "${ARGS[@]}" "$@"
234 | #
235 | # but POSIX shell has neither arrays nor command substitution, so instead we
236 | # post-process each arg (as a line of input to sed) to backslash-escape any
237 | # character that might be a shell metacharacter, then use eval to reverse
238 | # that process (while maintaining the separation between arguments), and wrap
239 | # the whole thing up as a single "set" statement.
240 | #
241 | # This will of course break if any of these variables contains a newline or
242 | # an unmatched quote.
243 | #
244 |
245 | eval "set -- $(
246 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
247 | xargs -n1 |
248 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
249 | tr '\n' ' '
250 | )" '"$@"'
251 |
252 | exec "$JAVACMD" "$@"
253 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 | @rem SPDX-License-Identifier: Apache-2.0
17 | @rem
18 |
19 | @if "%DEBUG%"=="" @echo off
20 | @rem ##########################################################################
21 | @rem
22 | @rem Gradle startup script for Windows
23 | @rem
24 | @rem ##########################################################################
25 |
26 | @rem Set local scope for the variables with windows NT shell
27 | if "%OS%"=="Windows_NT" setlocal
28 |
29 | set DIRNAME=%~dp0
30 | if "%DIRNAME%"=="" set DIRNAME=.
31 | @rem This is normally unused
32 | set APP_BASE_NAME=%~n0
33 | set APP_HOME=%DIRNAME%
34 |
35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
37 |
38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
40 |
41 | @rem Find java.exe
42 | if defined JAVA_HOME goto findJavaFromJavaHome
43 |
44 | set JAVA_EXE=java.exe
45 | %JAVA_EXE% -version >NUL 2>&1
46 | if %ERRORLEVEL% equ 0 goto execute
47 |
48 | echo. 1>&2
49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
50 | echo. 1>&2
51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
52 | echo location of your Java installation. 1>&2
53 |
54 | goto fail
55 |
56 | :findJavaFromJavaHome
57 | set JAVA_HOME=%JAVA_HOME:"=%
58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
59 |
60 | if exist "%JAVA_EXE%" goto execute
61 |
62 | echo. 1>&2
63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
64 | echo. 1>&2
65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2
66 | echo location of your Java installation. 1>&2
67 |
68 | goto fail
69 |
70 | :execute
71 | @rem Setup the command line
72 |
73 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
74 |
75 |
76 | @rem Execute Gradle
77 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
78 |
79 | :end
80 | @rem End local scope for the variables with windows NT shell
81 | if %ERRORLEVEL% equ 0 goto mainEnd
82 |
83 | :fail
84 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
85 | rem the _cmd.exe /c_ return code!
86 | set EXIT_CODE=%ERRORLEVEL%
87 | if %EXIT_CODE% equ 0 set EXIT_CODE=1
88 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
89 | exit /b %EXIT_CODE%
90 |
91 | :mainEnd
92 | if "%OS%"=="Windows_NT" endlocal
93 |
94 | :omega
95 |
--------------------------------------------------------------------------------
/neoforge/build.gradle.kts:
--------------------------------------------------------------------------------
1 | plugins {
2 | id("squaremarker.platform.loom")
3 | }
4 |
5 | val adventureVersion: String by rootProject
6 | val forgeVersion: String by rootProject
7 | val cloudMinecraftModdedVersion: String by rootProject
8 |
9 | dependencies {
10 | neoForge("net.neoforged:neoforge:$forgeVersion")
11 |
12 | // We don't include() these since squaremap already does and we depend on it
13 | modImplementation("org.incendo:cloud-neoforge:$cloudMinecraftModdedVersion")
14 | compileOnly("net.kyori:adventure-api:$adventureVersion")
15 | }
16 |
17 | squareMarker {
18 | modInfoFilePath = "META-INF/neoforge.mods.toml"
19 | }
20 |
--------------------------------------------------------------------------------
/neoforge/gradle.properties:
--------------------------------------------------------------------------------
1 | loom.platform=neoforge
2 |
--------------------------------------------------------------------------------
/neoforge/src/main/kotlin/SquareMarkerInitializer.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.forge
2 |
3 | import dev.sentix.squaremarker.SquareMarker
4 | import dev.sentix.squaremarker.command.Commander
5 | import dev.sentix.squaremarker.forge.command.ForgeCommander
6 | import dev.sentix.squaremarker.marker.API
7 | import net.minecraft.server.level.ServerLevel
8 | import net.neoforged.fml.ModContainer
9 | import net.neoforged.fml.common.Mod
10 | import net.neoforged.neoforge.common.NeoForge
11 | import net.neoforged.neoforge.event.level.LevelEvent
12 | import net.neoforged.neoforge.event.server.ServerStartingEvent
13 | import net.neoforged.neoforge.event.server.ServerStoppedEvent
14 | import org.incendo.cloud.CommandManager
15 | import org.incendo.cloud.SenderMapper
16 | import org.incendo.cloud.execution.ExecutionCoordinator
17 | import org.incendo.cloud.neoforge.NeoForgeServerCommandManager
18 | import xyz.jpenilla.squaremap.api.SquaremapProvider
19 | import xyz.jpenilla.squaremap.api.WorldIdentifier
20 | import java.io.File
21 | import java.nio.file.Path
22 |
23 | @Mod("squaremarker")
24 | class SquareMarkerInitializer(
25 | modContainer: ModContainer,
26 | ) {
27 | private val dir: Path = File(modContainer.modId).toPath()
28 | private val squareMarker: SquareMarker =
29 | SquareMarker(
30 | createCommandManager(),
31 | dir.resolve("config.yml"),
32 | dir,
33 | )
34 |
35 | init {
36 | // Ensure we initialize after squaremap regardless of load order (future squaremap versions should provide a better mechanism)
37 | NeoForge.EVENT_BUS.addListener { squareMarker.init() }
38 | NeoForge.EVENT_BUS.addListener { squareMarker.shutdown() }
39 |
40 | NeoForge.EVENT_BUS.addListener {
41 | val level = it.level as? ServerLevel ?: return@addListener
42 | SquaremapProvider.get().getWorldIfEnabled(
43 | WorldIdentifier.parse(level.dimension().location().toString()),
44 | ).ifPresent(API::initWorld)
45 | }
46 |
47 | NeoForge.EVENT_BUS.addListener {
48 | val level = it.level as? ServerLevel ?: return@addListener
49 | SquaremapProvider.get().getWorldIfEnabled(
50 | WorldIdentifier.parse(level.dimension().location().toString()),
51 | ).ifPresent(API::unloadWorld)
52 | }
53 | }
54 |
55 | private fun createCommandManager(): CommandManager {
56 | val mgr =
57 | NeoForgeServerCommandManager(
58 | ExecutionCoordinator.simpleCoordinator(),
59 | SenderMapper.create(
60 | { stack -> ForgeCommander.create(stack) },
61 | { commander -> (commander as ForgeCommander).sender },
62 | ),
63 | )
64 | return mgr
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/neoforge/src/main/kotlin/command/ForgeCommander.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.forge.command
2 |
3 | import dev.sentix.squaremarker.command.Commander
4 | import dev.sentix.squaremarker.command.PlayerCommander
5 | import net.kyori.adventure.audience.Audience
6 | import net.kyori.adventure.audience.ForwardingAudience
7 | import net.minecraft.commands.CommandSourceStack
8 | import net.minecraft.server.level.ServerPlayer
9 | import xyz.jpenilla.squaremap.api.WorldIdentifier
10 | import java.lang.reflect.Method
11 |
12 | open class ForgeCommander(val sender: CommandSourceStack) : Commander, ForwardingAudience.Single {
13 | override fun audience(): Audience = commandSourceAudienceMethod(null, sender) as Audience
14 |
15 | class Player(sender: CommandSourceStack, private val player: ServerPlayer) : ForgeCommander(sender), PlayerCommander {
16 | override val world: WorldIdentifier
17 | get() = WorldIdentifier.parse(player.level().dimension().location().toString())
18 | override val x: Double
19 | get() = player.x
20 | override val y: Double
21 | get() = player.y
22 | override val z: Double
23 | get() = player.z
24 | }
25 |
26 | companion object {
27 | val commandSourceAudienceMethod: Method =
28 | Class.forName("xyz.jpenilla.squaremap.forge.ForgeAdventure")
29 | .getDeclaredMethod("commandSourceAudience", CommandSourceStack::class.java)
30 |
31 | fun create(sender: CommandSourceStack): Commander {
32 | if (sender.player != null) {
33 | return Player(sender, sender.playerOrException)
34 | }
35 | return ForgeCommander(sender)
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/neoforge/src/main/resources/META-INF/neoforge.mods.toml:
--------------------------------------------------------------------------------
1 | modLoader = "javafml"
2 | loaderVersion = "[1,)"
3 | license = "MIT"
4 | issueTrackerURL = "https://github.com/SentixDev/squaremarker/issues"
5 | showAsResourcePack = false
6 |
7 | [[mods]]
8 | modId = "squaremarker"
9 | version = "${version}"
10 | displayName = "squaremarker"
11 | displayURL = "https://github.com/SentixDev/squaremarker"
12 | authors = "Sentix"
13 | description = "Marker addon for squaremap"
14 | displayTest = "IGNORE_ALL_VERSION"
15 |
16 | [[dependencies.squaremarker]]
17 | modId = "neoforge"
18 | mandatory = true
19 | versionRange = "[21.0,)"
20 | ordering = "NONE"
21 | side = "BOTH"
22 |
23 | [[dependencies.squaremarker]]
24 | modId = "minecraft"
25 | mandatory = true
26 | versionRange = "[1.21,1.22)"
27 | ordering = "NONE"
28 | side = "BOTH"
29 |
30 | [[dependencies.squaremarker]]
31 | modId = "cloud"
32 | mandatory = true
33 | versionRange = "*"
34 | ordering = "AFTER"
35 | side = "BOTH"
36 |
37 | [[dependencies.squaremarker]]
38 | modId = "squaremap"
39 | mandatory = true
40 | versionRange = "*"
41 | ordering = "AFTER"
42 | side = "BOTH"
43 |
--------------------------------------------------------------------------------
/neoforge/src/main/resources/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack": {
3 | "description": "squaremarker resources",
4 | "pack_format": 9
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/paper/build.gradle.kts:
--------------------------------------------------------------------------------
1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget
2 |
3 | plugins {
4 | id("squaremarker.platform")
5 | }
6 |
7 | val minecraftVersion: String by rootProject
8 | val bstatsVersion: String by rootProject
9 |
10 | dependencies {
11 | implementation(project(":squaremarker-common"))
12 |
13 | compileOnly("io.papermc.paper:paper-api:$minecraftVersion-R0.1-SNAPSHOT")
14 |
15 | implementation("org.incendo", "cloud-paper")
16 |
17 | implementation("org.bstats", "bstats-bukkit", bstatsVersion)
18 | }
19 |
20 | java {
21 | toolchain.languageVersion = JavaLanguageVersion.of(21)
22 | }
23 |
24 | kotlin {
25 | compilerOptions {
26 | jvmTarget = JvmTarget.JVM_21
27 | }
28 | }
29 |
30 | tasks {
31 | compileJava {
32 | options.encoding = Charsets.UTF_8.name()
33 | options.release = 21
34 | }
35 |
36 | jar {
37 | archiveClassifier = "not-shadowed"
38 | }
39 |
40 | shadowJar {
41 | archiveClassifier = null as String?
42 | listOf(
43 | "org.incendo",
44 | ).forEach { relocate(it, "${rootProject.group}.lib.$it") }
45 | dependencies {
46 | exclude(dependency("org.jetbrains:annotations"))
47 | }
48 | }
49 | }
50 |
51 | squareMarker {
52 | productionJar = tasks.shadowJar.flatMap { it.archiveFile }
53 | modInfoFilePath = "plugin.yml"
54 | }
55 |
--------------------------------------------------------------------------------
/paper/src/main/kotlin/Folia.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.paper
2 |
3 | val folia: Boolean by lazy {
4 | val regionizedServerCls: Class<*>? =
5 | runCatching {
6 | Class.forName("io.papermc.paper.threadedregions.RegionizedServer")
7 | }.getOrNull()
8 | regionizedServerCls != null
9 | }
10 |
--------------------------------------------------------------------------------
/paper/src/main/kotlin/PaperWorldIdentifierSerializer.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.paper
2 |
3 | import com.google.gson.JsonDeserializationContext
4 | import com.google.gson.JsonDeserializer
5 | import com.google.gson.JsonElement
6 | import com.google.gson.JsonNull
7 | import com.google.gson.JsonParseException
8 | import com.google.gson.JsonPrimitive
9 | import com.google.gson.JsonSerializationContext
10 | import com.google.gson.JsonSerializer
11 | import org.bukkit.NamespacedKey
12 | import org.bukkit.Server
13 | import xyz.jpenilla.squaremap.api.BukkitAdapter
14 | import xyz.jpenilla.squaremap.api.WorldIdentifier
15 | import java.lang.reflect.Type
16 |
17 | class PaperWorldIdentifierSerializer(private val server: Server) :
18 | JsonSerializer,
19 | JsonDeserializer {
20 | override fun serialize(
21 | src: WorldIdentifier?,
22 | typeOfSrc: Type,
23 | context: JsonSerializationContext,
24 | ): JsonElement {
25 | if (src == null) return JsonNull.INSTANCE
26 | return JsonPrimitive(src.asString())
27 | }
28 |
29 | override fun deserialize(
30 | json: JsonElement?,
31 | typeOfT: Type,
32 | context: JsonDeserializationContext,
33 | ): WorldIdentifier? {
34 | if (json == null || json is JsonNull) return null
35 | val tryDeserializeKey = NamespacedKey.fromString(json.asString)
36 | if (tryDeserializeKey != null) {
37 | val world = server.getWorld(tryDeserializeKey)
38 | if (world != null) return WorldIdentifier.parse(json.asString)
39 | }
40 | val world = server.getWorld(json.asString)
41 | if (world == null) {
42 | try {
43 | return WorldIdentifier.parse(json.asString)
44 | } catch (ex: Exception) {
45 | throw JsonParseException("'${json.asString}' is an invalid WorldIdentifier and no world exists with that name.", ex)
46 | }
47 | }
48 | return BukkitAdapter.worldIdentifier(world)
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/paper/src/main/kotlin/SquareMarkerPlugin.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.paper
2 |
3 | import dev.sentix.squaremarker.SquareMarker
4 | import dev.sentix.squaremarker.command.Commander
5 | import dev.sentix.squaremarker.marker.API
6 | import dev.sentix.squaremarker.paper.command.PaperCommander
7 | import org.bstats.bukkit.Metrics
8 | import org.bukkit.event.EventHandler
9 | import org.bukkit.event.Listener
10 | import org.bukkit.event.world.WorldLoadEvent
11 | import org.bukkit.plugin.java.JavaPlugin
12 | import org.incendo.cloud.SenderMapper
13 | import org.incendo.cloud.execution.ExecutionCoordinator
14 | import org.incendo.cloud.paper.LegacyPaperCommandManager
15 | import xyz.jpenilla.squaremap.api.BukkitAdapter
16 | import xyz.jpenilla.squaremap.api.SquaremapProvider
17 |
18 | class SquareMarkerPlugin : JavaPlugin(), Listener {
19 | private lateinit var squareMarker: SquareMarker
20 |
21 | override fun onEnable() {
22 | squareMarker =
23 | SquareMarker(
24 | createCommandManager(),
25 | dataFolder.toPath().resolve("config.yml"),
26 | dataFolder.toPath(),
27 | PaperWorldIdentifierSerializer(server),
28 | ).also { it.init() }
29 |
30 | server.pluginManager.registerEvents(this, this)
31 |
32 | // https://bstats.org/plugin/bukkit/squaremarker/14117
33 | Metrics(this, 14117)
34 | }
35 |
36 | override fun onDisable() {
37 | squareMarker.shutdown()
38 | }
39 |
40 | private fun createCommandManager(): LegacyPaperCommandManager {
41 | val mgr =
42 | LegacyPaperCommandManager(
43 | this,
44 | ExecutionCoordinator.builder()
45 | .synchronizeExecution(folia)
46 | .build(),
47 | SenderMapper.create(
48 | { sender -> PaperCommander.create(sender) },
49 | { commander -> (commander as PaperCommander).sender },
50 | ),
51 | )
52 | mgr.registerBrigadier()
53 | return mgr
54 | }
55 |
56 | @EventHandler
57 | fun handleLoad(event: WorldLoadEvent) {
58 | SquaremapProvider.get().getWorldIfEnabled(BukkitAdapter.worldIdentifier(event.world)).ifPresent(API::initWorld)
59 | }
60 |
61 | @EventHandler
62 | fun handleunLoad(event: WorldLoadEvent) {
63 | SquaremapProvider.get().getWorldIfEnabled(BukkitAdapter.worldIdentifier(event.world)).ifPresent(API::unloadWorld)
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/paper/src/main/kotlin/command/PaperCommander.kt:
--------------------------------------------------------------------------------
1 | package dev.sentix.squaremarker.paper.command
2 |
3 | import dev.sentix.squaremarker.command.Commander
4 | import dev.sentix.squaremarker.command.PlayerCommander
5 | import net.kyori.adventure.audience.Audience
6 | import net.kyori.adventure.audience.ForwardingAudience
7 | import org.bukkit.command.CommandSender
8 | import xyz.jpenilla.squaremap.api.BukkitAdapter
9 | import xyz.jpenilla.squaremap.api.WorldIdentifier
10 |
11 | open class PaperCommander(val sender: CommandSender) : Commander, ForwardingAudience.Single {
12 | override fun audience(): Audience = sender
13 |
14 | class Player(private val player: org.bukkit.entity.Player) : PaperCommander(player), PlayerCommander {
15 | override val world: WorldIdentifier
16 | get() = BukkitAdapter.worldIdentifier(player.world)
17 | override val x: Double
18 | get() = player.location.x
19 | override val y: Double
20 | get() = player.location.y
21 | override val z: Double
22 | get() = player.location.z
23 | }
24 |
25 | companion object {
26 | fun create(sender: CommandSender): Commander {
27 | if (sender is org.bukkit.entity.Player) {
28 | return Player(sender)
29 | }
30 | return PaperCommander(sender)
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/paper/src/main/resources/plugin.yml:
--------------------------------------------------------------------------------
1 | name: squaremarker
2 | version: $version
3 | main: dev.sentix.squaremarker.paper.SquareMarkerPlugin
4 | description: Marker addon for squaremap
5 | load: POSTWORLD
6 | authors:
7 | - Sentix
8 | website: https://github.com/SentixDev/squaremarker
9 | depend:
10 | - squaremap
11 | prefix: squaremarker
12 | api-version: 1.19
13 | folia-supported: true
14 |
--------------------------------------------------------------------------------
/resources/default_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SentixDev/squaremarker/f46fa55bbe14f19a54d879d51b93a7f818dfd0fc/resources/default_icon.png
--------------------------------------------------------------------------------
/settings.gradle.kts:
--------------------------------------------------------------------------------
1 | rootProject.name = "squaremarker"
2 |
3 | pluginManagement {
4 | repositories {
5 | gradlePluginPortal()
6 | mavenCentral()
7 | maven("https://repo.papermc.io/repository/maven-public/")
8 | maven("https://maven.fabricmc.net/")
9 | maven("https://maven.architectury.dev/")
10 | maven("https://repo.jpenilla.xyz/snapshots/")
11 | }
12 | }
13 |
14 | dependencyResolutionManagement {
15 | repositories {
16 | mavenCentral()
17 | maven("https://repo.papermc.io/repository/maven-public/")
18 | maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
19 | mavenContent { snapshotsOnly() }
20 | }
21 | }
22 | repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
23 | }
24 |
25 | plugins {
26 | id("xyz.jpenilla.quiet-architectury-loom") version "1.7-SNAPSHOT"
27 | id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
28 | }
29 |
30 | include("common")
31 | project(":common").name = "squaremarker-common"
32 |
33 | include("fabric")
34 | project(":fabric").name = "squaremarker-fabric"
35 |
36 | include("neoforge")
37 | project(":neoforge").name = "squaremarker-neoforge"
38 |
39 | include("paper")
40 | project(":paper").name = "squaremarker-paper"
41 |
--------------------------------------------------------------------------------