diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 1bf6b86..55b66ff 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: matrix: # Use these Java versions java: [ - 21, # Currently min for minecraft + 17, # Currently min for minecraft ] runs-on: ubuntu-22.04 steps: @@ -24,14 +24,16 @@ jobs: uses: actions/setup-java@v4 with: java-version: ${{ matrix.java }} - distribution: 'temurin' + distribution: temurin - name: make gradle wrapper executable run: chmod +x ./gradlew - name: build run: ./gradlew build - name: capture build artifacts - if: ${{ matrix.java == '21' }} # Only upload artifacts built from latest java + if: ${{ matrix.java == '17' }} # Only upload artifacts built from latest java uses: actions/upload-artifact@v4 with: name: Artifacts - path: build/libs/ \ No newline at end of file + path: | + */build/libs + if-no-files-found: error \ No newline at end of file diff --git a/.gitignore b/.gitignore index c476faf..c6728e1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,39 +1,22 @@ # gradle - .gradle/ build/ out/ classes/ -# eclipse - -*.launch - # idea - -.idea/ -*.iml +out *.ipr *.iws +*.iml +.idea/* +!.idea/scopes -# vscode - -.settings/ -.vscode/ -bin/ -.classpath -.project - -# macos - -*.DS_Store - -# fabric - -run/ +# other +run +runs # java - hs_err_*.log replay_*.log *.hprof diff --git a/README.md b/README.md index 3c8adac..5068d23 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Teleport Commands Teleport Commands Logo -A Minecraft fabric server-side mod that adds various teleportation related commands, like /home /tpa and /back +A Minecraft Fabric and NeoForge server-side mod that adds various teleportation related commands, like /home /tpa and /back ### This mod is still in beta, if there are any problems then let me know! diff --git a/build.gradle b/build.gradle index 189b207..a667404 100644 --- a/build.gradle +++ b/build.gradle @@ -1,86 +1,4 @@ -plugins { - id 'fabric-loom' version '1.6-SNAPSHOT' - id 'maven-publish' -} - -version = project.mod_version -group = project.maven_group - -base { - archivesName = project.archives_base_name -} - -repositories { - // Add repositories to retrieve artifacts from in here. - // You should only use this when depending on other mods because - // Loom adds the essential maven repositories to download Minecraft and libraries from automatically. - // See https://docs.gradle.org/current/userguide/declaring_repositories.html - // for more information about repositories. -} - -loom { - splitEnvironmentSourceSets() - - mods { - "teleport_commands" { - sourceSet sourceSets.main - } - } - -} - -dependencies { - // To change the versions see the gradle.properties file - minecraft "com.mojang:minecraft:${project.minecraft_version}" - mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" - modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" - - // Fabric API. This is technically optional, but you probably want it anyway. - modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" - -} - -processResources { - inputs.property "version", project.version - - filesMatching("fabric.mod.json") { - expand "version": project.version - } -} - -tasks.withType(JavaCompile).configureEach { - it.options.release = 17 -} - -java { - // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task - // if it is present. - // If you remove this line, sources will not be generated. - withSourcesJar() - - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 -} - -jar { - from("LICENSE") { - rename { "${it}_${project.base.archivesName.get()}"} - } -} - -// configure the maven publication -publishing { - publications { - create("mavenJava", MavenPublication) { - from components.java - } - } - - // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing. - repositories { - // Add repositories to publish to here. - // Notice: This block does NOT have the same function as the block in the top level. - // The repositories here will be used for publishing your artifact, not for - // retrieving dependencies. - } +plugins { + // Required for NeoGradle + id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7" } \ No newline at end of file diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle new file mode 100644 index 0000000..9a20d71 --- /dev/null +++ b/buildSrc/build.gradle @@ -0,0 +1,3 @@ +plugins { + id 'groovy-gradle-plugin' +} diff --git a/buildSrc/src/main/groovy/multiloader-common.gradle b/buildSrc/src/main/groovy/multiloader-common.gradle new file mode 100644 index 0000000..c19cd09 --- /dev/null +++ b/buildSrc/src/main/groovy/multiloader-common.gradle @@ -0,0 +1,111 @@ +plugins { + id 'java-library' + id 'maven-publish' +} + +base { + archivesName = "${mod_id}-${project.name}-${minecraft_version}" +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(java_version) + withSourcesJar() + withJavadocJar() +} + +repositories { + mavenCentral() + // https://docs.gradle.org/current/userguide/declaring_repositories.html#declaring_content_exclusively_found_in_one_repository + exclusiveContent { + forRepository { + maven { + name = 'Sponge' + url = 'https://repo.spongepowered.org/repository/maven-public' + } + } + filter { includeGroupAndSubgroups("org.spongepowered") } + } + maven { + name = 'BlameJared' + url = 'https://maven.blamejared.com' + } +} + +dependencies { + implementation 'org.jetbrains:annotations:24.1.0' +} + +// Declare capabilities on the outgoing configurations. +// Read more about capabilities here: https://docs.gradle.org/current/userguide/component_capabilities.html#sec:declaring-additional-capabilities-for-a-local-component +['apiElements', 'runtimeElements', 'sourcesElements', 'javadocElements'].each { variant -> + configurations."$variant".outgoing { + capability("$group:$mod_id-${project.name}-${minecraft_version}:$version") + capability("$group:$mod_id:$version") + } + publishing.publications.configureEach { + suppressPomMetadataWarningsFor(variant) + } +} + +sourcesJar { + from(rootProject.file("LICENSE")) { + rename { "${it}_${mod_name}" } + } +} + +jar { + from(rootProject.file("LICENSE")) { + rename { "${it}_${mod_name}" } + } + + manifest { + attributes([ + 'Specification-Title' : mod_name, + 'Specification-Vendor' : mod_author, + 'Specification-Version' : project.jar.archiveVersion, + 'Implementation-Title' : project.name, + 'Implementation-Version': project.jar.archiveVersion, + 'Implementation-Vendor' : mod_author, + 'Built-On-Minecraft' : minecraft_version + ]) + } +} + +processResources { + def expandProps = [ + "version": version, + "group": project.group, //Else we target the task's group. + "minecraft_version": minecraft_version, + "minecraft_version_range": minecraft_version_range, + "fabric_version": fabric_version, + "fabric_loader_version": fabric_loader_version, + "mod_name": mod_name, + "mod_author": mod_author, + "mod_id": mod_id, + "license": license, + "description": project.description, + "neoforge_version": neoforge_version, + "neoforge_loader_version_range": neoforge_loader_version_range, + "credits": credits, + "java_version": java_version + ] + + filesMatching(['pack.mcmeta', 'fabric.mod.json', 'META-INF/mods.toml', 'META-INF/neoforge.mods.toml', '*.mixins.json']) { + expand expandProps + } + inputs.properties(expandProps) +} + +publishing { + publications { + register('mavenJava', MavenPublication) { + artifactId base.archivesName.get() + from components.java + } + } + repositories { + maven { + url System.getenv("local_maven_url") + } + } +} diff --git a/buildSrc/src/main/groovy/multiloader-loader.gradle b/buildSrc/src/main/groovy/multiloader-loader.gradle new file mode 100644 index 0000000..f51ea40 --- /dev/null +++ b/buildSrc/src/main/groovy/multiloader-loader.gradle @@ -0,0 +1,44 @@ +plugins { + id 'multiloader-common' +} + +configurations { + commonJava{ + canBeResolved = true + } + commonResources{ + canBeResolved = true + } +} + +dependencies { + compileOnly(project(':common')) { + capabilities { + requireCapability "$group:$mod_id" + } + } + commonJava project(path: ':common', configuration: 'commonJava') + commonResources project(path: ':common', configuration: 'commonResources') +} + +tasks.named('compileJava', JavaCompile) { + dependsOn(configurations.commonJava) + source(configurations.commonJava) +} + +processResources { + dependsOn(configurations.commonResources) + from(configurations.commonResources) +} + +tasks.named('javadoc', Javadoc).configure { + dependsOn(configurations.commonJava) + source(configurations.commonJava) +} + +tasks.named("sourcesJar", Jar) { + dependsOn(configurations.commonJava) + from(configurations.commonJava) + dependsOn(configurations.commonResources) + from(configurations.commonResources) +} diff --git a/common/build.gradle b/common/build.gradle new file mode 100644 index 0000000..246b541 --- /dev/null +++ b/common/build.gradle @@ -0,0 +1,33 @@ +plugins { + id 'multiloader-common' + id 'org.spongepowered.gradle.vanilla' version '0.2.1-SNAPSHOT' +} + +minecraft { + version(minecraft_version) + def aw = file("src/main/resources/${mod_id}.accesswidener") + if(aw.exists()){ + accessWideners(aw) + } +} + +dependencies { + compileOnly group:'org.spongepowered', name:'mixin', version:'0.8.5' +} + +configurations { + commonJava { + canBeResolved = false + canBeConsumed = true + } + commonResources { + canBeResolved = false + canBeConsumed = true + } +} + +artifacts { + commonJava sourceSets.main.java.sourceDirectories.singleFile + commonResources sourceSets.main.resources.sourceDirectories.singleFile +} + diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java b/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java new file mode 100644 index 0000000..e6a5ee7 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java @@ -0,0 +1,57 @@ +package dev.mrsnowy.teleport_commands; + +import dev.mrsnowy.teleport_commands.storage.StorageManager; +import dev.mrsnowy.teleport_commands.commands.*; +import net.minecraft.commands.Commands; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.storage.LevelResource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Objects; + +import static dev.mrsnowy.teleport_commands.utils.tools.DeathLocationUpdater; + +public class TeleportCommands { + + public static final String MOD_ID = "teleport_commands"; + public static final String MOD_NAME = "Teleport Commands"; + public static final Logger LOGGER = LoggerFactory.getLogger(MOD_NAME); + public static String MOD_LOADER; + public static Path SAVE_DIR; + public static Path CONFIG_DIR; + public static MinecraftServer Server; + + public static void initializeMod(MinecraftServer server, String ModLoader) { + // initialize da variables + + MOD_LOADER = ModLoader; + + SAVE_DIR = Path.of(String.valueOf(server.getWorldPath(LevelResource.ROOT))); + + // Construct the game directory path + CONFIG_DIR = Paths.get(System.getProperty("user.dir")).resolve("config"); + + Server = server; + + // initialize commands, also allows me to easily disable any when there is a config + Commands commandManager = server.getCommands(); + back.register(commandManager); + home.register(commandManager); + tpa.register(commandManager); + + StorageManager.StorageInit(); + } + + public static void onPlayerDeath(ServerPlayer player) { + try { + // update /back command position + DeathLocationUpdater(player.position(), player.serverLevel(), player.getStringUUID()); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} \ No newline at end of file diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java new file mode 100644 index 0000000..b208c51 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/back.java @@ -0,0 +1,60 @@ +package dev.mrsnowy.teleport_commands.commands; + +import dev.mrsnowy.teleport_commands.TeleportCommands; +import dev.mrsnowy.teleport_commands.storage.StorageManager; +import java.util.Objects; +import net.minecraft.ChatFormatting; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; + +import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; +import static dev.mrsnowy.teleport_commands.utils.tools.Teleporter; + +public class back { + + public static void register(Commands commandManager) { + + commandManager.getDispatcher().register(Commands.literal("back").executes(context -> { + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Teleporting"), true); + ToDeathLocation(player); + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Teleporting!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + })); + } + + + + private static void ToDeathLocation(ServerPlayer player) throws Exception { + StorageManager.StorageClass.Player playerStorage = GetPlayerStorage(player.getStringUUID()).playerStorage; + + Vec3 pos = new Vec3(playerStorage.deathLocation.x, playerStorage.deathLocation.y, playerStorage.deathLocation.z); + + boolean found = false; + for (ServerLevel currentWorld : Objects.requireNonNull(player.getServer()).getAllLevels()) { + if (Objects.equals(currentWorld.dimension().location().toString(), playerStorage.deathLocation.world)) { + Teleporter(player, currentWorld, pos); + found = true; + break; + } + } + + if (!found) { + player.displayClientMessage(Component.literal("No Location Found!"), true); + } + } +} diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java new file mode 100644 index 0000000..47c6219 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/home.java @@ -0,0 +1,404 @@ +package dev.mrsnowy.teleport_commands.commands; + +import com.mojang.brigadier.arguments.StringArgumentType; +import dev.mrsnowy.teleport_commands.TeleportCommands; +import dev.mrsnowy.teleport_commands.storage.StorageManager; +import dev.mrsnowy.teleport_commands.suggestions.HomesuggestionProvider; +import java.util.Objects; +import net.minecraft.ChatFormatting; +import net.minecraft.commands.Commands; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.phys.Vec3; + +import static net.minecraft.commands.Commands.argument; +import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; +import static dev.mrsnowy.teleport_commands.storage.StorageManager.StorageSaver; +import static dev.mrsnowy.teleport_commands.utils.tools.Teleporter; + +public class home { + public static void register(Commands commandManager) { + + commandManager.getDispatcher().register(Commands.literal("sethome") + .then(argument("name", StringArgumentType.string()) + .executes(context -> { + final String name = StringArgumentType.getString(context, "name"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Home Set"), true); + SetHome(player, name); + + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Setting Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + }))); + + + commandManager.getDispatcher().register(Commands.literal("home") + .executes(context -> { + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Going Home"), true); + GoHome(player, ""); + + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Going Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + }) + .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) + .executes(context -> { + final String name = StringArgumentType.getString(context, "name"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Going Home"), true); + GoHome(player, name); + + } catch (Exception e) { + player.displayClientMessage(Component.literal("Error Going Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + TeleportCommands.LOGGER.error(String.valueOf(e)); + return 1; + } + return 0; + }))); + + commandManager.getDispatcher().register(Commands.literal("delhome") + .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) + .executes(context -> { + final String name = StringArgumentType.getString(context, "name"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Home Deleted"), true); + DeleteHome(player, name); + + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Deleting Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + }))); + + commandManager.getDispatcher().register(Commands.literal("renamehome") + .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) + .then(argument("newName", StringArgumentType.string()) + .executes(context -> { + final String name = StringArgumentType.getString(context, "name"); + final String newName = StringArgumentType.getString(context, "newName"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + player.displayClientMessage(Component.literal("Home Renamed"), true); + RenameHome(player, name, newName); + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Renaming Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + })))); + + + commandManager.getDispatcher().register(Commands.literal("homes") + .executes(context -> { + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + PrintHomes(player); + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Getting Homes!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + })); + + commandManager.getDispatcher().register(Commands.literal("defaulthome") + .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) + .executes(context -> { + final String name = StringArgumentType.getString(context, "name"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + try { + SetDefaultHome(player, name); + } catch (Exception e) { + TeleportCommands.LOGGER.error(String.valueOf(e)); + player.displayClientMessage(Component.literal("Error Changing Default Home!").withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true); + return 1; + } + return 0; + }))); + } + + + + private static void SetHome(ServerPlayer player, String homeName) throws Exception { + homeName = homeName.toLowerCase(); + Vec3 pos = player.position(); + ServerLevel world = player.serverLevel(); + + StorageManager.PlayerStorageResult storages = GetPlayerStorage(player.getStringUUID()); + StorageManager.StorageClass storage = storages.storage; + StorageManager.StorageClass.Player playerStorage = storages.playerStorage; + + boolean homeNotFound = true; + + // check for duplicates + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, homeName)) { + homeNotFound = false; + break; + } + } + + if (homeNotFound) { + // Create a new Home + StorageManager.StorageClass.Player.Home homeLocation = new StorageManager.StorageClass.Player.Home(); + + homeLocation.name = homeName; + homeLocation.x = Double.parseDouble(String.format("%.1f", pos.x())); + homeLocation.y = Double.parseDouble(String.format("%.1f", pos.y())); + homeLocation.z = Double.parseDouble(String.format("%.1f", pos.z())); + homeLocation.world = world.dimension().location().toString(); + + playerStorage.Homes.add(homeLocation); + + if (playerStorage.Homes.size() == 1) { + playerStorage.DefaultHome = homeName; + } + + StorageSaver(storage); + } else { + player.displayClientMessage(Component.literal("Home Already Exists!"), true); + } + } + + private static void GoHome(ServerPlayer player, String homeName) throws Exception { + homeName = homeName.toLowerCase(); + StorageManager.StorageClass.Player playerStorage = GetPlayerStorage(player.getStringUUID()).playerStorage; + + // check if there is a default exists + if (homeName.isEmpty()) { + if (playerStorage.DefaultHome.isEmpty()) { + player.displayClientMessage(Component.literal("You Have No Homes!"), true); + return; + } else { + homeName = playerStorage.DefaultHome; + } + } + + boolean foundHome = false; + boolean foundWorld = false; + + // find correct home + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, homeName)){ + foundHome = true; + + // find correct world + for (ServerLevel currentWorld : Objects.requireNonNull(player.getServer()).getAllLevels()) { + if (Objects.equals(currentWorld.dimension().location().toString(), currentHome.world)) { + Teleporter(player, currentWorld, new Vec3(currentHome.x, currentHome.y, currentHome.z)); + foundWorld = true; + break; + } + } + } + } + + if (!foundHome) { + player.displayClientMessage(Component.literal("Home Not Found!"), true); + } else if (!foundWorld) { + player.displayClientMessage(Component.literal("World Not Found!"), true); + } + } + + private static void DeleteHome(ServerPlayer player, String homeName) throws Exception { + homeName = homeName.toLowerCase(); + StorageManager.PlayerStorageResult storages = GetPlayerStorage(player.getStringUUID()); + StorageManager.StorageClass storage = storages.storage; + StorageManager.StorageClass.Player playerStorage = storages.playerStorage; + + StorageManager.StorageClass.Player.Home homeToDelete = null; + + // get correct home + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, homeName)){ + homeToDelete = currentHome; + break; + } + } + + if (Objects.nonNull(homeToDelete)) { + playerStorage.Homes.remove(homeToDelete); + StorageSaver(storage); + } else { + player.displayClientMessage(Component.literal("Home Not Found!"), true); + } + } + + private static void RenameHome(ServerPlayer player, String homeName, String newHomeName) throws Exception { + homeName = homeName.toLowerCase(); + newHomeName = newHomeName.toLowerCase(); + + StorageManager.PlayerStorageResult storages = GetPlayerStorage(player.getStringUUID()); + StorageManager.StorageClass storage = storages.storage; + StorageManager.StorageClass.Player playerStorage = storages.playerStorage; + + StorageManager.StorageClass.Player.Home homeToRename = null; + boolean newNameNotFound = true; + + // check for duplicates + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, newHomeName)) { + newNameNotFound = false; + break; + } + } + + if (newNameNotFound) { + // get correct home + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, homeName)){ + homeToRename = currentHome; + break; + } + } + + if (Objects.nonNull(homeToRename)) { + if (Objects.equals(playerStorage.DefaultHome, homeToRename.name)) { + playerStorage.DefaultHome = newHomeName; + } + + homeToRename.name = newHomeName; + StorageSaver(storage); + } else { + player.displayClientMessage(Component.literal("Home Not Found!"), true); + } + } else { + player.displayClientMessage(Component.literal("Home Already Exists!"), true); + } + + } + + private static void PrintHomes(ServerPlayer player) throws Exception { + StorageManager.StorageClass.Player playerStorage = GetPlayerStorage(player.getStringUUID()).playerStorage; + boolean anyHomes = false; + + for (StorageManager.StorageClass.Player.Home currenthome : playerStorage.Homes) { + if (!anyHomes) { + player.displayClientMessage(Component.literal("Homes: \n").withStyle(ChatFormatting.YELLOW, ChatFormatting.BOLD), false); + anyHomes = true; + } + + String name = String.format(" - %s", currenthome.name); + String nameDefault = " (Default)"; + + + String coords = String.format(" [X%.1f Y%.1f Z%.1f]", currenthome.x, currenthome.y, currenthome.z); + String dimension = String.format(" [%s]", currenthome.world); + + if (Objects.equals(currenthome.name, playerStorage.DefaultHome)) { + player.displayClientMessage(Component.literal(name).withStyle(ChatFormatting.AQUA) + .append(Component.literal(nameDefault).withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD)), + false + ); + } else { + player.displayClientMessage(Component.literal(name).withStyle(ChatFormatting.AQUA), false); + } + + + player.displayClientMessage(Component.literal(" |").withStyle(ChatFormatting.AQUA) + .append(Component.literal(coords).withStyle(ChatFormatting.LIGHT_PURPLE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.format("X%.2f Y%.2f Z%.2f", currenthome.x, currenthome.y, currenthome.z))))) + .append(Component.literal(dimension).withStyle(ChatFormatting.DARK_PURPLE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, currenthome.world)))), + false + ); + + player.displayClientMessage(Component.literal(" |").withStyle(ChatFormatting.AQUA) + .append(Component.literal(" [Tp]").withStyle(ChatFormatting.GREEN).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/home %s", currenthome.name))))) + .append(Component.literal(" [Rename]").withStyle(ChatFormatting.BLUE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.format("/renamehome %s ", currenthome.name))))) + .append(Component.literal(" [Delete]\n").withStyle(ChatFormatting.RED).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.format("/delhome %s", currenthome.name))))), + false + ); + } + + if (!anyHomes) { + player.displayClientMessage(Component.literal("No homes set"), true); + } + } + + private static void SetDefaultHome(ServerPlayer player, String homeName) throws Exception { + homeName = homeName.toLowerCase(); + StorageManager.PlayerStorageResult storages = GetPlayerStorage(player.getStringUUID()); + StorageManager.StorageClass storage = storages.storage; + StorageManager.StorageClass.Player playerStorage = storages.playerStorage; + + boolean homeExists = false; + + // check if home exists + for (StorageManager.StorageClass.Player.Home currentHome : playerStorage.Homes) { + if (Objects.equals(currentHome.name, homeName)){ + homeExists = true; + break; + } + } + + if (homeExists) { + if (Objects.equals(playerStorage.DefaultHome, homeName)) { + player.displayClientMessage(Component.literal("Home is already set as default!"), true); + + } else { + playerStorage.DefaultHome = homeName; + StorageSaver(storage); + } + } else { + player.displayClientMessage(Component.literal("Home not found!"), true); + } + } +} diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java new file mode 100644 index 0000000..2ffedb8 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/commands/tpa.java @@ -0,0 +1,200 @@ +package dev.mrsnowy.teleport_commands.commands; + +import dev.mrsnowy.teleport_commands.TeleportCommands; +import java.util.*; +import net.minecraft.ChatFormatting; +import net.minecraft.commands.Commands; +import net.minecraft.commands.arguments.EntityArgument; +import net.minecraft.network.chat.ClickEvent; +import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; + +import static dev.mrsnowy.teleport_commands.utils.tools.Teleporter; + +public class tpa { + + private static final ArrayList tpaList = new ArrayList<>(); + + private static class tpaArrayClass { + private String InitPlayer; + private String RecPlayer; + private boolean here; + } + + public static void register(Commands commandManager) { + + commandManager.getDispatcher().register(Commands.literal("tpa") + .then(Commands.argument("player", EntityArgument.player()) + .executes(context -> { + final ServerPlayer TargetPlayer = EntityArgument.getPlayer(context, "player"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + tpaCommandHandler(player, TargetPlayer, false); + return 0; + }))); + + commandManager.getDispatcher().register(Commands.literal("tpahere") + .then(Commands.argument("player", EntityArgument.player()) + .executes(context -> { + final ServerPlayer TargetPlayer = EntityArgument.getPlayer(context, "player"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + tpaCommandHandler(player, TargetPlayer, true); + return 0; + }))); + + commandManager.getDispatcher().register(Commands.literal("tpaaccept") + .then(Commands.argument("player", EntityArgument.player()) + .executes(context -> { + final ServerPlayer TargetPlayer = EntityArgument.getPlayer(context, "player"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + tpaAccept(player, TargetPlayer); + return 0; + }))); + + commandManager.getDispatcher().register(Commands.literal("tpadeny") + .then(Commands.argument("player", EntityArgument.player()) + .executes(context -> { + final ServerPlayer TargetPlayer = EntityArgument.getPlayer(context, "player"); + ServerPlayer player = context.getSource().getPlayer(); + + if (player == null) { + TeleportCommands.LOGGER.error("Error while executing the command, No player found!"); + return 1; + } + + tpaDeny(player, TargetPlayer); + return 0; + }))); + } + + + + private static void tpaCommandHandler(ServerPlayer FromPlayer, ServerPlayer ToPlayer, boolean here) { + + if (FromPlayer == ToPlayer) { + FromPlayer.displayClientMessage(Component.literal("Well, that was easy").withStyle(ChatFormatting.AQUA),true); + + } else { + String ToMessage; + String FromMessage; + + // Store da request + tpaArrayClass tpaRequest = new tpaArrayClass(); + tpaRequest.InitPlayer = FromPlayer.getStringUUID(); + tpaRequest.RecPlayer = ToPlayer.getStringUUID(); + tpaRequest.here = here; + tpaList.add(tpaRequest); + + if (here) { + ToMessage = "TpaHere Request Received From "; + FromMessage = "TpaHere Request Send to "; + + } else { + ToMessage = "Tpa Request Received From "; + FromMessage = "Tpa Request Send to "; + } + + String ToPlayerString = Objects.requireNonNull(ToPlayer.getName().tryCollapseToString()); + String FromPlayerString = Objects.requireNonNull(FromPlayer.getName().tryCollapseToString()); + + FromPlayer.displayClientMessage(Component.literal(FromMessage).withStyle(ChatFormatting.AQUA) + .append(Component.literal(ToPlayerString).withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD)) +// .append(Text.literal("\n[Cancel]").formatted(Formatting.BLUE, Formatting.BOLD)) + ,true + ); + + ToPlayer.displayClientMessage(Component.literal(ToMessage).withStyle(ChatFormatting.AQUA) + .append(Component.literal(FromPlayerString).withStyle(ChatFormatting.AQUA, ChatFormatting.BOLD)) + .append(Component.literal("\n[Accept]").withStyle(ChatFormatting.GREEN, ChatFormatting.BOLD).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/tpaaccept %s", FromPlayerString))))) + .append(Component.literal(" [Deny]").withStyle(ChatFormatting.RED, ChatFormatting.BOLD).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/tpadeny %s", FromPlayerString))))), + false + ); + + Timer timer = new Timer(); + timer.schedule( + new TimerTask() { + @Override + public void run() { + boolean successful = tpaList.remove(tpaRequest); + if (successful) { + if (here) { + FromPlayer.displayClientMessage(Component.literal("TpaHere Request Expired").withStyle(ChatFormatting.AQUA),true); + } else { + FromPlayer.displayClientMessage(Component.literal("Tpa Request Expired").withStyle(ChatFormatting.AQUA),true); + } + } + } + }, 30 * 1000 + ); + } + } + + private static void tpaAccept(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { + if (FromPlayer == ToPlayer) { + FromPlayer.displayClientMessage(Component.literal("Uhm.. no?").withStyle(ChatFormatting.AQUA),true); + } else { + Optional tpaStorage = tpaList.stream() + .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.InitPlayer)) + .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.RecPlayer)) + .findFirst(); + + if (tpaStorage.isPresent()) { + if (tpaStorage.get().here) { + FromPlayer.displayClientMessage(Component.literal("Teleporting"),true); + ToPlayer.displayClientMessage(Component.literal("Request Accepted"),true); + + Teleporter(FromPlayer, ToPlayer.serverLevel(), ToPlayer.position()); + } else { + ToPlayer.displayClientMessage(Component.literal("Teleporting"),true); + FromPlayer.displayClientMessage(Component.literal("Request Accepted"),true); + + Teleporter(ToPlayer, FromPlayer.serverLevel(), FromPlayer.position()); + } + + tpaList.remove(tpaStorage.get()); + } else { + FromPlayer.displayClientMessage(Component.literal("No Requests found!").withStyle(ChatFormatting.AQUA),true); + } + } + } + + private static void tpaDeny(ServerPlayer FromPlayer, ServerPlayer ToPlayer) { + if (FromPlayer == ToPlayer) { + FromPlayer.displayClientMessage(Component.literal("Uhm.. no?").withStyle(ChatFormatting.AQUA),true); + } else { + Optional tpaStorage = tpaList.stream() + .filter(tpa -> Objects.equals(ToPlayer.getStringUUID(), tpa.InitPlayer)) + .filter(tpa -> Objects.equals(FromPlayer.getStringUUID(), tpa.RecPlayer)) + .findFirst(); + + if (tpaStorage.isPresent()) { + tpaList.remove(tpaStorage.get()); + + if (tpaStorage.get().here) { + ToPlayer.displayClientMessage(Component.literal("Request Denied").withStyle(ChatFormatting.AQUA),true); + } else { + FromPlayer.displayClientMessage(Component.literal("Request Denied").withStyle(ChatFormatting.AQUA),true); + } + } else { + FromPlayer.displayClientMessage(Component.literal("No Requests found!").withStyle(ChatFormatting.AQUA),true); + } + } + } +} diff --git a/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java similarity index 99% rename from src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java rename to common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java index 984aee9..a8d6b20 100644 --- a/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/StorageManager.java @@ -14,7 +14,6 @@ import java.util.Objects; import java.util.Optional; public class StorageManager { - public static Path STORAGE_FOLDER; public static Path STORAGE_FILE; diff --git a/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java similarity index 50% rename from src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java rename to common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java index d6b1e81..1271693 100644 --- a/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/storage/configManager.java @@ -1,8 +1,6 @@ package dev.mrsnowy.teleport_commands.storage; -//import java.nio.file.Path; -//import net.fabricmc.loader.api.FabricLoader; - public class configManager { +// Currently nothing to see here... yet } diff --git a/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java similarity index 66% rename from src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java rename to common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java index 90358ad..40555c8 100644 --- a/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/suggestions/HomesuggestionProvider.java @@ -6,23 +6,19 @@ import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; import dev.mrsnowy.teleport_commands.TeleportCommands; import dev.mrsnowy.teleport_commands.storage.StorageManager; -import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.math.Vec3d; - import java.util.Objects; import java.util.concurrent.CompletableFuture; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.server.level.ServerPlayer; import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; -public class HomesuggestionProvider implements SuggestionProvider { +public class HomesuggestionProvider implements SuggestionProvider { @Override - public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { + public CompletableFuture getSuggestions(CommandContext context, SuggestionsBuilder builder) { try { - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - StorageManager.StorageClass.Player playerStorage = null; - playerStorage = GetPlayerStorage(player.getUuidAsString()).playerStorage; + ServerPlayer player = Objects.requireNonNull(context.getSource().getPlayer()); + StorageManager.StorageClass.Player playerStorage = GetPlayerStorage(player.getStringUUID()).playerStorage; for (StorageManager.StorageClass.Player.Home currenthome : playerStorage.Homes) { builder.suggest(currenthome.name); diff --git a/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java new file mode 100644 index 0000000..c481f03 --- /dev/null +++ b/common/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java @@ -0,0 +1,62 @@ +package dev.mrsnowy.teleport_commands.utils; + +import dev.mrsnowy.teleport_commands.storage.StorageManager; +import java.util.*; +import net.minecraft.core.particles.ParticleTypes; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.phys.Vec3; + +import static dev.mrsnowy.teleport_commands.storage.StorageManager.GetPlayerStorage; +import static dev.mrsnowy.teleport_commands.storage.StorageManager.StorageSaver; +import static net.minecraft.sounds.SoundEvents.ENDERMAN_TELEPORT; + +public class tools { + + public static void Teleporter(ServerPlayer player, ServerLevel world, Vec3 coords) { + world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() + 1, player.getZ(), 20, 0.0D, 0.0D, 0.0D, 0.01); + world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 1.0D, 0.0D, 0.03); + world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.getLocation()), SoundSource.PLAYERS, 0.4f, 1.0f); + + var flying = player.getAbilities().flying; + + player.teleportTo(world, coords.x, coords.y, coords.z, player.getYRot(), player.getXRot()); + + // Restore flying when teleporting dimensions + if (flying) { + player.getAbilities().flying = true; + player.onUpdateAbilities(); + } + + world.playSound(null, player.blockPosition(), SoundEvent.createVariableRangeEvent(ENDERMAN_TELEPORT.getLocation()), SoundSource.PLAYERS, 0.4f, 1.0f); + Timer timer = new Timer(); + + timer.schedule( + new TimerTask() { + @Override + public void run() { + world.sendParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); + world.sendParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); + } + }, 100 // hopefully good, 2 ticks + ); + } + + + + public static void DeathLocationUpdater(Vec3 pos, ServerLevel world, String UUID) throws Exception { + StorageManager.PlayerStorageResult storages = GetPlayerStorage(UUID); + + StorageManager.StorageClass storage = storages.storage; + StorageManager.StorageClass.Player playerStorage = storages.playerStorage; + + playerStorage.deathLocation.x = Double.parseDouble(String.format("%.1f", pos.x())); + playerStorage.deathLocation.y = Double.parseDouble(String.format("%.1f", pos.y())); + playerStorage.deathLocation.z = Double.parseDouble(String.format("%.1f", pos.z())); + playerStorage.deathLocation.world = world.dimension().location().toString(); + + StorageSaver(storage); + } +} diff --git a/common/src/main/resources/pack.mcmeta b/common/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..52854ec --- /dev/null +++ b/common/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "${mod_name}", + "pack_format": 8 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/teleport_commands/icon.png b/common/src/main/resources/teleport_commands.png similarity index 100% rename from src/main/resources/assets/teleport_commands/icon.png rename to common/src/main/resources/teleport_commands.png diff --git a/fabric/build.gradle b/fabric/build.gradle new file mode 100644 index 0000000..6acbfc5 --- /dev/null +++ b/fabric/build.gradle @@ -0,0 +1,34 @@ +plugins { + id 'multiloader-loader' + id 'fabric-loom' version '1.6-SNAPSHOT' +} +dependencies { + minecraft "com.mojang:minecraft:${minecraft_version}" + mappings loom.officialMojangMappings() + modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" + modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_version}" +} + +loom { + def aw = project(":common").file("src/main/resources/${mod_id}.accesswidener") + if (aw.exists()) { + accessWidenerPath.set(aw) + } + mixin { + defaultRefmapName.set("${mod_id}.refmap.json") + } + runs { + client { + client() + setConfigName("Fabric Client") + ideConfigGenerated(true) + runDir("runs/client") + } + server { + server() + setConfigName("Fabric Server") + ideConfigGenerated(true) + runDir("runs/server") + } + } +} \ No newline at end of file diff --git a/fabric/src/main/java/dev/mrsnowy/teleport_commands/fabricInit.java b/fabric/src/main/java/dev/mrsnowy/teleport_commands/fabricInit.java new file mode 100644 index 0000000..f584f28 --- /dev/null +++ b/fabric/src/main/java/dev/mrsnowy/teleport_commands/fabricInit.java @@ -0,0 +1,35 @@ +package dev.mrsnowy.teleport_commands; + +import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.minecraft.server.level.ServerPlayer; + +import java.util.Objects; + +public class fabricInit implements ModInitializer { + + @Override + public void onInitialize() { + // This code runs as soon as Minecraft is in a mod-load-ready state. + // However, some things (like resources) may still be uninitialized. + // Proceed with mild caution. + + TeleportCommands.LOGGER.info("Teleport Commands loaded! Hello Fabric!"); + + // initialize the mod + ServerLifecycleEvents.SERVER_STARTED.register((server) -> { + TeleportCommands.initializeMod(server, "Fabric"); + }); + + + // check if it is a player and check if the player died + ServerEntityEvents.ENTITY_UNLOAD.register((entity, world) -> { + if (entity instanceof ServerPlayer player) { + if (player.getRemovalReason() != null && (Objects.equals(player.getRemovalReason().toString(), "KILLED") || Objects.equals(player.getRemovalReason().toString(), "DISCARDED"))) { + TeleportCommands.onPlayerDeath(player); + } + } + }); + } +} \ No newline at end of file diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json new file mode 100644 index 0000000..9a1b48b --- /dev/null +++ b/fabric/src/main/resources/fabric.mod.json @@ -0,0 +1,41 @@ +{ + "schemaVersion": 1, + "id": "${mod_id}", + "version": "${version}", + "name": "${mod_name}", + "description": "${description}", + "authors": [ + "${mod_author}" + ], + "contact": { + "homepage": "https://mrsnowy.dev/", + "sources": "https://github.com/MrSn0wy/TeleportCommands", + "issues": "https://github.com/MrSn0wy/TeleportCommands/issues" + }, + "license": "${license}", + "icon": "${mod_id}.png", + "environment": "*", + "entrypoints": { + "main": [ + "dev.mrsnowy.teleport_commands.fabricInit" + ] + }, + "custom": { + "modmenu": { + "links": { + "modmenu.modrinth": "https://modrinth.com/mod/teleport-commands", + "modmenu.kofi": "https://ko-fi.com/mr_snowy" + } + } + }, + "depends": { + "fabricloader": ">=${fabric_loader_version}", + "fabric-api": "*", + "minecraft": "${minecraft_version}", + "java": ">=${java_version}" + }, + "suggests": { + "another-mod": "*" + } +} + \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 9f586ee..a5f9d92 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,17 +1,29 @@ -# Done to increase the memory available to gradle. -org.gradle.jvmargs=-Xmx2G -org.gradle.parallel=true +# Important Notes: +# Every field you add must be added to the root build.gradle expandProps map. -# Fabric Properties -# check these on https://fabricmc.net/develop +# Project +version=1.0.5 +group=dev.mrsnowy.teleport_commands +java_version=17 + +# Common minecraft_version=1.20.4 -yarn_mappings=1.20.4+build.3 -loader_version=0.15.9 +mod_name=Teleport Commands +mod_author=Mr. Snowy +mod_id=teleport_commands +license=MIT +credits=Mr. Snowy +description=A server-side mod that adds various teleportation related commands. +minecraft_version_range=[1.20.4, 1.21) + +# Fabric +fabric_version=0.97.0+1.20.4 +fabric_loader_version=0.15.10 -# Mod Properties -mod_version=1.0.2 -maven_group=dev.mrsnowy.teleport_commands -archives_base_name=teleport_commands +# NeoForge +neoforge_version=20.4.234 +neoforge_loader_version_range=[2,) -# Dependencies -fabric_version=0.97.0+1.20.4 \ No newline at end of file +# Gradle +org.gradle.jvmargs=-Xmx3G +org.gradle.daemon=false \ No newline at end of file diff --git a/neoforge/build.gradle b/neoforge/build.gradle new file mode 100644 index 0000000..01d6588 --- /dev/null +++ b/neoforge/build.gradle @@ -0,0 +1,38 @@ +plugins { + id 'multiloader-loader' + id 'net.neoforged.gradle.userdev' version '7.0.107' +} + +// Automatically enable neoforge AccessTransformers if the file exists +// This location is hardcoded in FML and can not be changed. +// https://github.com/neoforged/FancyModLoader/blob/a952595eaaddd571fbc53f43847680b00894e0c1/loader/src/main/java/net/neoforged/fml/loading/moddiscovery/ModFile.java#L118 +def at = file('src/main/resources/META-INF/accesstransformer.cfg') +if (at.exists()) { + minecraft.accessTransformers.file at +} +runs { + configureEach { + modSource project.sourceSets.main + } + client { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + server { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + programArgument '--nogui' + } + + gameTestServer { + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + } + + data { + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() + } +} + +sourceSets.main.resources { srcDir 'src/generated/resources' } + +dependencies { + implementation "net.neoforged:neoforge:${neoforge_version}" +} \ No newline at end of file diff --git a/neoforge/src/main/java/dev/mrsnowy/teleport_commands/neoforgeInit.java b/neoforge/src/main/java/dev/mrsnowy/teleport_commands/neoforgeInit.java new file mode 100644 index 0000000..5a95b2b --- /dev/null +++ b/neoforge/src/main/java/dev/mrsnowy/teleport_commands/neoforgeInit.java @@ -0,0 +1,40 @@ +package dev.mrsnowy.teleport_commands; + +import net.neoforged.bus.api.EventPriority; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.Mod; +import net.neoforged.neoforge.event.entity.living.LivingDeathEvent; +import net.neoforged.neoforge.event.server.ServerStartingEvent; +import net.minecraft.server.level.ServerPlayer; + +@Mod(TeleportCommands.MOD_ID) +public class neoforgeInit { + + public neoforgeInit(IEventBus eventBus) { + // This method is invoked by the NeoForge mod loader when it is ready + // to load your mod. You can access NeoForge and Common code in this + // project. + + TeleportCommands.LOGGER.info("Teleport Commands loaded! Hello NeoForge!"); + } + + @Mod.EventBusSubscriber(modid = TeleportCommands.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) + private static class NeoForgeEventSubscriber { + + @SubscribeEvent(priority = EventPriority.HIGHEST) + private static void onServerStarting(ServerStartingEvent event) { + // initialize the mod + TeleportCommands.initializeMod(event.getServer(), "NeoForge"); + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + private static void onEntityUnload(LivingDeathEvent event) { + // check if it is a player + if (event.getEntity() instanceof ServerPlayer player) { + TeleportCommands.onPlayerDeath(player); + } + } + } +} + diff --git a/neoforge/src/main/resources/META-INF/mods.toml b/neoforge/src/main/resources/META-INF/mods.toml new file mode 100644 index 0000000..64284bb --- /dev/null +++ b/neoforge/src/main/resources/META-INF/mods.toml @@ -0,0 +1,32 @@ +modLoader = "javafml" #mandatory +loaderVersion = "${neoforge_loader_version_range}" #mandatory +license = "${license}" # Review your options at https://choosealicense.com/. +issueTrackerURL="https://github.com/MrSn0wy/TeleportCommands/issues" #optional +[[mods]] #mandatory +modId = "${mod_id}" #mandatory +version = "${version}" #mandatory +displayName = "${mod_name}" #mandatory +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional (see https://docs.neoforged.net/docs/misc/updatechecker/) +displayURL="https://github.com/MrSn0wy/TeleportCommands" #optional (displayed in the mod UI) +logoFile="${mod_id}.png" #optional +credits="${credits}" #optional +authors = "${mod_author}" #optional +description = '''${description}''' #mandatory (Supports multiline text) +[[dependencies.${mod_id}]] #optional +modId = "neoforge" #mandatory +type="required" #mandatory (Can be one of "required", "optional", "incompatible" or "discouraged") +versionRange = "${neoforge_loader_version_range}" #mandatory +ordering = "NONE" # The order that this dependency should load in relation to your mod, required to be either 'BEFORE' or 'AFTER' if the dependency is not mandatory +side = "BOTH" # Side this dependency is applied on - 'BOTH', 'CLIENT' or 'SERVER' +[[dependencies.${mod_id}]] +modId = "minecraft" +type="required" #mandatory (Can be one of "required", "optional", "incompatible" or "discouraged") +versionRange = "${minecraft_version_range}" +ordering = "NONE" +side = "BOTH" + +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" \ No newline at end of file diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml new file mode 100644 index 0000000..68c011c --- /dev/null +++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml @@ -0,0 +1,32 @@ +modLoader = "javafml" #mandatory +loaderVersion = "${neoforge_loader_version_range}" #mandatory +license = "${license}" # Review your options at https://choosealicense.com/. +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +[[mods]] #mandatory +modId = "${mod_id}" #mandatory +version = "${version}" #mandatory +displayName = "${mod_name}" #mandatory +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional (see https://docs.neoforged.net/docs/misc/updatechecker/) +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional (displayed in the mod UI) +logoFile="${mod_id}.png" #optional +credits="${credits}" #optional +authors = "${mod_author}" #optional +description = '''${description}''' #mandatory (Supports multiline text) +[[dependencies.${mod_id}]] #optional +modId = "neoforge" #mandatory +type="required" #mandatory (Can be one of "required", "optional", "incompatible" or "discouraged") +versionRange = "${neoforge_loader_version_range}" #mandatory +ordering = "NONE" # The order that this dependency should load in relation to your mod, required to be either 'BEFORE' or 'AFTER' if the dependency is not mandatory +side = "BOTH" # Side this dependency is applied on - 'BOTH', 'CLIENT' or 'SERVER' +[[dependencies.${mod_id}]] +modId = "minecraft" +type="required" #mandatory (Can be one of "required", "optional", "incompatible" or "discouraged") +versionRange = "${minecraft_version_range}" +ordering = "NONE" +side = "BOTH" + +# Features are specific properties of the game environment, that you may want to declare you require. This example declares +# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't +# stop your mod loading on the server for example. +#[features.${mod_id}] +#openGLVersion="[3.2,)" \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 75c4d72..0a54af6 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,52 @@ -pluginManagement { - repositories { - maven { - name = 'Fabric' - url = 'https://maven.fabricmc.net/' - } - mavenCentral() - gradlePluginPortal() - } -} \ No newline at end of file +pluginManagement { + repositories { + gradlePluginPortal() + mavenCentral() + exclusiveContent { + forRepository { + maven { + name = 'Fabric' + url = uri("https://maven.fabricmc.net") + } + } + filter { + includeGroup("net.fabricmc") + includeGroup("fabric-loom") + } + } + exclusiveContent { + forRepository { + maven { + name = 'NeoForge' + url = uri("https://maven.neoforged.net/releases") + } + } + filter { + includeGroupAndSubgroups("net.neoforged") + includeGroup("codechicken") + } + } + exclusiveContent { + forRepository { + maven { + name = 'Sponge Snapshots' + url = uri("https://repo.spongepowered.org/repository/maven-public") + } + } + filter { + includeGroupAndSubgroups("org.spongepowered") + includeGroup("net.minecraftforge") + } + } + } +} + +plugins { + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' +} + +// This should match the folder name of the project, or else IDEA may complain (see https://youtrack.jetbrains.com/issue/IDEA-317606) +rootProject.name = 'MultiLoader-Template' +include("common") +include("fabric") +include("neoforge") diff --git a/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java b/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java deleted file mode 100644 index 4f55378..0000000 --- a/src/main/java/dev/mrsnowy/teleport_commands/TeleportCommands.java +++ /dev/null @@ -1,77 +0,0 @@ -package dev.mrsnowy.teleport_commands; - -import dev.mrsnowy.teleport_commands.storage.StorageManager; -import dev.mrsnowy.teleport_commands.utils.commands; -import net.fabricmc.api.ModInitializer; - -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerEntityEvents; -import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.entity.Entity; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; -import net.minecraft.world.World; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.nio.file.Path; -import java.util.Objects; - -import static dev.mrsnowy.teleport_commands.utils.tools.DeathLocationUpdater; - -public class TeleportCommands implements ModInitializer { - // This logger is used to write text to the console and the log file. - // It is considered best practice to use your mod id as the logger's name. - // That way, it's clear which mod wrote info, warnings, and errors. - public static final String MOD_ID = "teleport_commands"; - public static final Logger LOGGER = LoggerFactory.getLogger("teleport_commands"); - - public static Path SAVE_DIR; - public static Path CONFIG_DIR; - public static StorageManager Storage; - public static MinecraftServer Server; - - @Override - public void onInitialize() { - // This code runs as soon as Minecraft is in a mod-load-ready state. - // However, some things (like resources) may still be uninitialized. - // Proceed with mild caution. - ServerWorldEvents.LOAD.register(this::onWorldLoad); - - ServerEntityEvents.ENTITY_UNLOAD.register(this::onPlayerUnload); - - // todo: /back /tpa /tpahere /home /homes /sethome /delhome /renamehome /defaulthome /spawn /worldspawn - commands.registerCommands(); - } - - - - private void onPlayerUnload(Entity entity, ServerWorld world) { - if (entity instanceof ServerPlayerEntity player) { -// LOGGER.info(String.valueOf(entity.getRemovalReason())); - if (player.getRemovalReason() != null && (Objects.equals(player.getRemovalReason().toString(), "KILLED") || Objects.equals(player.getRemovalReason().toString(), "DISCARDED"))) { - try { - // /back command position - LOGGER.info(player.getPos().toString()); - DeathLocationUpdater(player.getPos(), player.getServerWorld(), player.getUuidAsString()); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - } - - private void onWorldLoad(MinecraftServer minecraftServer, ServerWorld serverWorld) { - // make it run only once - if (serverWorld.getRegistryKey() == World.OVERWORLD) { - // initialize da variables - SAVE_DIR = Path.of(String.valueOf(minecraftServer.getSavePath(WorldSavePath.ROOT))); - CONFIG_DIR = FabricLoader.getInstance().getConfigDir(); - - Server = minecraftServer; - StorageManager.StorageInit(); - } - } -} \ No newline at end of file diff --git a/src/main/java/dev/mrsnowy/teleport_commands/utils/commands.java b/src/main/java/dev/mrsnowy/teleport_commands/utils/commands.java deleted file mode 100644 index 4bd8358..0000000 --- a/src/main/java/dev/mrsnowy/teleport_commands/utils/commands.java +++ /dev/null @@ -1,192 +0,0 @@ -package dev.mrsnowy.teleport_commands.utils; - -import com.mojang.brigadier.arguments.StringArgumentType; -import dev.mrsnowy.teleport_commands.TeleportCommands; -import dev.mrsnowy.teleport_commands.suggestions.HomesuggestionProvider; -import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; -import net.minecraft.command.argument.EntityArgumentType; -import net.minecraft.server.command.CommandManager; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; - -import javax.swing.text.html.parser.Entity; -import java.util.Objects; - -import static net.minecraft.server.command.CommandManager.argument; -import static net.minecraft.server.command.CommandManager.literal; - -public class commands { - public static void registerCommands() { - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("back") - .executes(context -> { - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - try { - player.sendMessage(Text.literal("Teleporting"), true); - tools.ToDeathLocation(player); - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Teleporting!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - }))); - - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("sethome") - .then(argument("name", StringArgumentType.string()) - .executes(context -> { - final String name = StringArgumentType.getString(context, "name"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - try { - player.sendMessage(Text.literal("Home Set"), true); - tools.SetHome(player, name); - - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Setting Home!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("home") - .executes(context -> { - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - try { - player.sendMessage(Text.literal("Going Home"), true); - tools.GoHome(player, ""); - - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Going Home!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - }) - .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) - .executes(context -> { - final String name = StringArgumentType.getString(context, "name"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - try { - player.sendMessage(Text.literal("Going Home"), true); - tools.GoHome(player, name); - - } catch (Exception e) { - player.sendMessage(Text.literal("Error Going Home!").formatted(Formatting.RED, Formatting.BOLD), true); - TeleportCommands.LOGGER.error(String.valueOf(e)); - return 1; - } - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("delhome") - .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) - .executes(context -> { - final String name = StringArgumentType.getString(context, "name"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - try { - player.sendMessage(Text.literal("Home Deleted"), true); - tools.DeleteHome(player, name); - - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Deleting Home!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("renamehome") - .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) - .then(argument("newName", StringArgumentType.string()) - .executes(context -> { - final String name = StringArgumentType.getString(context, "name"); - final String newName = StringArgumentType.getString(context, "newName"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - try { - player.sendMessage(Text.literal("Home Renamed"), true); - tools.RenameHome(player, name, newName); - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Renaming Home!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - }))))); - - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("homes") - .executes(context -> { - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - try { - tools.PrintHomes(player); - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Getting Homes!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - }))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("defaulthome") - .then(argument("name", StringArgumentType.string()).suggests(new HomesuggestionProvider()) - .executes(context -> { - final String name = StringArgumentType.getString(context, "name"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - try { - tools.SetDefaultHome(player, name); - } catch (Exception e) { - TeleportCommands.LOGGER.error(String.valueOf(e)); - player.sendMessage(Text.literal("Error Changing Default Home!").formatted(Formatting.RED, Formatting.BOLD), true); - return 1; - } - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("tpa") - .then(CommandManager.argument("player", EntityArgumentType.player()) - .executes(context -> { - final ServerPlayerEntity TargetPlayer = EntityArgumentType.getPlayer(context, "player"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - tools.tpaCommandHandler(player, TargetPlayer, false); - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("tpahere") - .then(CommandManager.argument("player", EntityArgumentType.player()) - .executes(context -> { - final ServerPlayerEntity TargetPlayer = EntityArgumentType.getPlayer(context, "player"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - tools.tpaCommandHandler(player, TargetPlayer, true); - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("tpaaccept") - .then(CommandManager.argument("player", EntityArgumentType.player()) - .executes(context -> { - final ServerPlayerEntity TargetPlayer = EntityArgumentType.getPlayer(context, "player"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - tools.tpaAccept(player, TargetPlayer); - return 0; - })))); - - CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(literal("tpadeny") - .then(CommandManager.argument("player", EntityArgumentType.player()) - .executes(context -> { - final ServerPlayerEntity TargetPlayer = EntityArgumentType.getPlayer(context, "player"); - ServerPlayerEntity player = Objects.requireNonNull(context.getSource().getPlayer()); - - tools.tpaDeny(player, TargetPlayer); - return 0; - })))); - } -} diff --git a/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java b/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java deleted file mode 100644 index f9a1dbe..0000000 --- a/src/main/java/dev/mrsnowy/teleport_commands/utils/tools.java +++ /dev/null @@ -1,421 +0,0 @@ -package dev.mrsnowy.teleport_commands.utils; - -import net.fabricmc.fabric.api.dimension.v1.FabricDimensions; -import net.minecraft.particle.ParticleTypes; -import net.minecraft.server.network.ServerPlayerEntity; -import net.minecraft.server.world.ServerWorld; -import net.minecraft.sound.SoundCategory; -import net.minecraft.sound.SoundEvent; -import net.minecraft.text.ClickEvent; -import net.minecraft.text.Text; -import net.minecraft.util.Formatting; -import net.minecraft.util.math.Vec3d; -import net.minecraft.world.TeleportTarget; - -import java.util.*; - -import static dev.mrsnowy.teleport_commands.storage.StorageManager.*; -import static net.minecraft.sound.SoundEvents.ENTITY_ENDERMAN_TELEPORT; - -public class tools { - private static ArrayList tpaList = new ArrayList<>(); - - private static class tpaArrayClass { - private String InitPlayer; - private String RecPlayer; - private boolean here; - } - - private static void Teleporter(ServerPlayerEntity player, ServerWorld world, Vec3d coords) { - world.spawnParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() + 1, player.getZ(), 20, 0.0D, 0.0D, 0.0D, 0.01); - world.spawnParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 1.0D, 0.0D, 0.03); - world.playSound(null, player.getBlockPos(), SoundEvent.of(ENTITY_ENDERMAN_TELEPORT.getId()), SoundCategory.PLAYERS, 0.4f, 1.0f); - - FabricDimensions.teleport(player, world, new TeleportTarget(coords, Vec3d.ZERO, player.getYaw(), player.getPitch())); - - world.playSound(null, player.getBlockPos(), SoundEvent.of(ENTITY_ENDERMAN_TELEPORT.getId()), SoundCategory.PLAYERS, 0.4f, 1.0f); - Timer timer = new Timer(); - - timer.schedule( - new TimerTask() { - @Override - public void run() { - world.spawnParticles(ParticleTypes.SNOWFLAKE, player.getX(), player.getY() , player.getZ(), 20, 0.0D, 1.0D, 0.0D, 0.01); - world.spawnParticles(ParticleTypes.WHITE_SMOKE, player.getX(), player.getY(), player.getZ(), 15, 0.0D, 0.0D, 0.0D, 0.03); - } - }, 100 // hopefully good, 2 ticks - ); - } - - - public static void SetHome(ServerPlayerEntity player, String homeName) throws Exception { - homeName = homeName.toLowerCase(); - Vec3d pos = player.getPos(); - ServerWorld world = player.getServerWorld(); - - PlayerStorageResult storages = GetPlayerStorage(player.getUuidAsString()); - StorageClass storage = storages.storage; - StorageClass.Player playerStorage = storages.playerStorage; - - boolean homeNotFound = true; - - // check for duplicates - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, homeName)) { - homeNotFound = false; - break; - } - } - - if (homeNotFound) { - // Create a new Home - StorageClass.Player.Home homeLocation = new StorageClass.Player.Home(); - - homeLocation.name = homeName; - homeLocation.x = Double.parseDouble(String.format("%.1f", pos.getX())); - homeLocation.y = Double.parseDouble(String.format("%.1f", pos.getY()));; - homeLocation.z = Double.parseDouble(String.format("%.1f", pos.getZ()));; - homeLocation.world = world.getRegistryKey().getValue().toString(); - - playerStorage.Homes.add(homeLocation); - - if (playerStorage.Homes.size() == 1) { - playerStorage.DefaultHome = homeName; - } - - StorageSaver(storage); - } else { - player.sendMessage(Text.literal("Home Already Exists!"), true); - } - } - - public static void GoHome(ServerPlayerEntity player, String homeName) throws Exception { - homeName = homeName.toLowerCase(); - StorageClass.Player playerStorage = GetPlayerStorage(player.getUuidAsString()).playerStorage; - - // check if there is a default exists - if (homeName.isEmpty()) { - if (playerStorage.DefaultHome.isEmpty()) { - player.sendMessage(Text.literal("You Have No Homes!"), true); - return; - } else { - homeName = playerStorage.DefaultHome; - } - } - - boolean foundHome = false; - boolean foundWorld = false; - - // find correct home - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, homeName)){ - foundHome = true; - - // find correct world - for (ServerWorld currentWorld : Objects.requireNonNull(player.getServer()).getWorlds()) { - if (Objects.equals(currentWorld.getRegistryKey().getValue().toString(), currentHome.world)) { - Teleporter(player, currentWorld, new Vec3d(currentHome.x, currentHome.y, currentHome.z)); - foundWorld = true; - break; - } - } - } - } - - if (!foundHome) { - player.sendMessage(Text.literal("Home Not Found!"), true); - } else if (!foundWorld) { - player.sendMessage(Text.literal("World Not Found!"), true); - } - } - - public static void DeleteHome(ServerPlayerEntity player, String homeName) throws Exception { - homeName = homeName.toLowerCase(); - PlayerStorageResult storages = GetPlayerStorage(player.getUuidAsString()); - StorageClass storage = storages.storage; - StorageClass.Player playerStorage = storages.playerStorage; - - StorageClass.Player.Home homeToDelete = null; - - // get correct home - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, homeName)){ - homeToDelete = currentHome; - break; - } - } - - if (Objects.nonNull(homeToDelete)) { - playerStorage.Homes.remove(homeToDelete); - StorageSaver(storage); - } else { - player.sendMessage(Text.literal("Home Not Found!"), true); - } - } - - public static void RenameHome(ServerPlayerEntity player, String homeName, String newHomeName) throws Exception { - homeName = homeName.toLowerCase(); - newHomeName = newHomeName.toLowerCase(); - - PlayerStorageResult storages = GetPlayerStorage(player.getUuidAsString()); - StorageClass storage = storages.storage; - StorageClass.Player playerStorage = storages.playerStorage; - - StorageClass.Player.Home homeToRename = null; - boolean newNameNotFound = true; - - // check for duplicates - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, newHomeName)) { - newNameNotFound = false; - break; - } - } - - if (newNameNotFound) { - // get correct home - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, homeName)){ - homeToRename = currentHome; - break; - } - } - - if (Objects.nonNull(homeToRename)) { - if (Objects.equals(playerStorage.DefaultHome, homeToRename.name)) { - playerStorage.DefaultHome = newHomeName; - } - - homeToRename.name = newHomeName; - StorageSaver(storage); - } else { - player.sendMessage(Text.literal("Home Not Found!"), true); - } - } else { - player.sendMessage(Text.literal("Home Already Exists!"), true); - } - - } - - public static void PrintHomes(ServerPlayerEntity player) throws Exception { - StorageClass.Player playerStorage = GetPlayerStorage(player.getUuidAsString()).playerStorage; - boolean anyHomes = false; - - for (StorageClass.Player.Home currenthome : playerStorage.Homes) { - if (!anyHomes) { - player.sendMessage(Text.literal("Homes: \n").formatted(Formatting.YELLOW, Formatting.BOLD), false); - anyHomes = true; - } - - String name = String.format(" - %s", currenthome.name); - String nameDefault = " (Default)"; - - - String coords = String.format(" [X%.1f Y%.1f Z%.1f]", currenthome.x, currenthome.y, currenthome.z); - String dimension = String.format(" [%s]", currenthome.world); - - if (Objects.equals(currenthome.name, playerStorage.DefaultHome)) { - player.sendMessage(Text.literal(name).formatted(Formatting.AQUA) - .append(Text.literal(nameDefault).formatted(Formatting.AQUA, Formatting.BOLD)), - false - ); - } else { - player.sendMessage(Text.literal(name).formatted(Formatting.AQUA), false); - } - - - player.sendMessage(Text.literal(" |").formatted(Formatting.AQUA) - .append(Text.literal(coords).formatted(Formatting.LIGHT_PURPLE).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, String.format("X%.2f Y%.2f Z%.2f", currenthome.x, currenthome.y, currenthome.z))))) - .append(Text.literal(dimension).formatted(Formatting.DARK_PURPLE).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, currenthome.world)))), - false - ); - - player.sendMessage(Text.literal(" |").formatted(Formatting.AQUA) - .append(Text.literal(" [Tp]").formatted(Formatting.GREEN).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/home %s", currenthome.name))))) - .append(Text.literal(" [Rename]").formatted(Formatting.BLUE).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.format("/renamehome %s ", currenthome.name))))) - .append(Text.literal(" [Delete]\n").formatted(Formatting.RED).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, String.format("/delhome %s", currenthome.name))))), - false - ); - } - - if (!anyHomes) { - player.sendMessage(Text.literal("No homes set"), true); - } - } - - public static void SetDefaultHome(ServerPlayerEntity player, String homeName) throws Exception { - homeName = homeName.toLowerCase(); - PlayerStorageResult storages = GetPlayerStorage(player.getUuidAsString()); - StorageClass storage = storages.storage; - StorageClass.Player playerStorage = storages.playerStorage; - - boolean homeExists = false; - - // check if home exists - for (StorageClass.Player.Home currentHome : playerStorage.Homes) { - if (Objects.equals(currentHome.name, homeName)){ - homeExists = true; - break; - } - } - - if (homeExists) { - if (Objects.equals(playerStorage.DefaultHome, homeName)) { - player.sendMessage(Text.literal("Home is already set as default!"), true); - - } else { - playerStorage.DefaultHome = homeName; - StorageSaver(storage); - } - } else { - player.sendMessage(Text.literal("Home not found!"), true); - } - } - - - public static void ToDeathLocation(ServerPlayerEntity player) throws Exception { - StorageClass.Player playerStorage = GetPlayerStorage(player.getUuidAsString()).playerStorage; - - Vec3d pos = new Vec3d(playerStorage.deathLocation.x, playerStorage.deathLocation.y, playerStorage.deathLocation.z); - - boolean found = false; - for (ServerWorld currentWorld : Objects.requireNonNull(player.getServer()).getWorlds()) { - if (Objects.equals(currentWorld.getRegistryKey().getValue().toString(), playerStorage.deathLocation.world)) { - Teleporter(player, currentWorld, pos); - found = true; - break; - } - } - - if (!found) { - player.sendMessage(Text.literal("No Location Found!"), true); - } - } - - public static void tpaCommandHandler(ServerPlayerEntity FromPlayer, ServerPlayerEntity ToPlayer, boolean here) { - - if (FromPlayer == ToPlayer) { - FromPlayer.sendMessage(Text.literal("Well, that was easy").formatted(Formatting.AQUA),true); - - } else { - String ToMessage; - String FromMessage; - - // Store da request - tpaArrayClass tpaRequest = new tpaArrayClass(); - tpaRequest.InitPlayer = FromPlayer.getUuidAsString(); - tpaRequest.RecPlayer = ToPlayer.getUuidAsString(); - tpaRequest.here = here; - tpaList.add(tpaRequest); - - if (here) { - ToMessage = "TpaHere Request Received From "; - FromMessage = "TpaHere Request Send to "; - - } else { - ToMessage = "Tpa Request Received From "; - FromMessage = "Tpa Request Send to "; - } - - String ToPlayerString = Objects.requireNonNull(ToPlayer.getName().getLiteralString()); - String FromPlayerString = Objects.requireNonNull(FromPlayer.getName().getLiteralString()); - - FromPlayer.sendMessage(Text.literal(FromMessage).formatted(Formatting.AQUA) - .append(Text.literal(ToPlayerString).formatted(Formatting.AQUA, Formatting.BOLD)) -// .append(Text.literal("\n[Cancel]").formatted(Formatting.BLUE, Formatting.BOLD)) - ,true - ); - - ToPlayer.sendMessage(Text.literal(ToMessage).formatted(Formatting.AQUA) - .append(Text.literal(FromPlayerString).formatted(Formatting.AQUA, Formatting.BOLD)) - .append(Text.literal("\n[Accept]").formatted(Formatting.GREEN, Formatting.BOLD).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/tpaaccept %s", FromPlayerString))))) - .append(Text.literal(" [Deny]").formatted(Formatting.RED, Formatting.BOLD).styled(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, String.format("/tpadeny %s", FromPlayerString))))), - false - ); - - Timer timer = new Timer(); - timer.schedule( - new TimerTask() { - @Override - public void run() { - boolean successful = tpaList.remove(tpaRequest); - if (successful) { - if (here) { - FromPlayer.sendMessage(Text.literal("TpaHere Request Expired").formatted(Formatting.AQUA),true); - } else { - FromPlayer.sendMessage(Text.literal("Tpa Request Expired").formatted(Formatting.AQUA),true); - } - } - } - }, 30 * 1000 - ); - } - } - - public static void tpaAccept(ServerPlayerEntity FromPlayer, ServerPlayerEntity ToPlayer) { - if (FromPlayer == ToPlayer) { - FromPlayer.sendMessage(Text.literal("No").formatted(Formatting.AQUA),true); - } else { - Optional tpaStorage = tpaList.stream() - .filter(tpa -> Objects.equals(ToPlayer.getUuidAsString(), tpa.InitPlayer)) - .filter(tpa -> Objects.equals(FromPlayer.getUuidAsString(), tpa.RecPlayer)) - .findFirst(); - - if (tpaStorage.isPresent()) { - if (tpaStorage.get().here) { - FromPlayer.sendMessage(Text.literal("Teleporting"),true); - ToPlayer.sendMessage(Text.literal("Request Accepted"),true); - - Teleporter(FromPlayer, ToPlayer.getServerWorld(), ToPlayer.getPos()); - } else { - ToPlayer.sendMessage(Text.literal("Teleporting"),true); - FromPlayer.sendMessage(Text.literal("Request Accepted"),true); - - Teleporter(ToPlayer, FromPlayer.getServerWorld(), FromPlayer.getPos()); - } - - tpaList.remove(tpaStorage.get()); - } else { - FromPlayer.sendMessage(Text.literal("No Requests found!").formatted(Formatting.AQUA),true); - } - } - } - - public static void tpaDeny(ServerPlayerEntity FromPlayer, ServerPlayerEntity ToPlayer) { - if (FromPlayer == ToPlayer) { - FromPlayer.sendMessage(Text.literal("No").formatted(Formatting.AQUA),true); - } else { - Optional tpaStorage = tpaList.stream() - .filter(tpa -> Objects.equals(ToPlayer.getUuidAsString(), tpa.InitPlayer)) - .filter(tpa -> Objects.equals(FromPlayer.getUuidAsString(), tpa.RecPlayer)) - .findFirst(); - - if (tpaStorage.isPresent()) { - tpaList.remove(tpaStorage.get()); - - if (tpaStorage.get().here) { - ToPlayer.sendMessage(Text.literal("Request Denied").formatted(Formatting.AQUA),true); - } else { - FromPlayer.sendMessage(Text.literal("Request Denied").formatted(Formatting.AQUA),true); - } - } else { - FromPlayer.sendMessage(Text.literal("No Requests found!").formatted(Formatting.AQUA),true); - } - } - } - - - public static void DeathLocationUpdater(Vec3d pos, ServerWorld world, String UUID) throws Exception { - PlayerStorageResult storages = GetPlayerStorage(UUID); - - StorageClass storage = storages.storage; - StorageClass.Player playerStorage = storages.playerStorage; - - playerStorage.deathLocation.x = Double.parseDouble(String.format("%.1f", pos.getX()));; - playerStorage.deathLocation.y = Double.parseDouble(String.format("%.1f", pos.getY()));; - playerStorage.deathLocation.z = Double.parseDouble(String.format("%.1f", pos.getZ()));; - playerStorage.deathLocation.world = world.getRegistryKey().getValue().toString(); - - StorageSaver(storage); - } -} diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json deleted file mode 100644 index d7af2c2..0000000 --- a/src/main/resources/fabric.mod.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "schemaVersion": 1, - "id": "teleport_commands", - "version": "${version}", - "name": "Teleport Commands", - "description": "A fabric server-side mod that adds various teleportation related commands", - "authors": [ - "Mr. Snowy" - ], - "contact": { - "homepage": "https://mrsnowy.dev/", - "sources": "https://github.com/MrSn0wy/TeleportCommands", - "issues": "https://github.com/MrSn0wy/TeleportCommands/issues" - }, - "license": "MIT", - "icon": "assets/teleport_commands/icon.png", - "environment": "*", - "entrypoints": { - "main": [ - "dev.mrsnowy.teleport_commands.TeleportCommands" - ] - }, - "custom": { - "modmenu": { - "links": { - "modmenu.modrinth": "https://modrinth.com/mod/teleport-commands", - "modmenu.kofi": "https://ko-fi.com/mr_snowy" - } - } - }, - "depends": { - "fabricloader": ">=0.15.9", - "minecraft": "~1.20.4", - "java": ">=17", - "fabric-api": ">=0.97.0" - } -} \ No newline at end of file