···66and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7788### [W.I.P]
99+#### Changed
910- Storage is loaded in memory instead of reading it again and again, Improves speed and IO usage, however there might be slightly higher passive memory usage.
1011- Added a new merged jar file that combines the jars of the mod-loaders into one. (Thanks to [forgix](https://github.com/PacifistMC/Forgix)!) (This will also from now on be published on Modrinth)
1112- Made it so the DeathLocations (for `/back`) are only kept in memory. (before they would get saved and deleted on startup lol)
1213- Improved the Storage classes and it's functions (I'm doing proper java, yipie)
1314- Improved the error messages for command suggestions.
1414-- Improved the error handling for when a world isn't found (when going back, going home or warping).
1515+- Improved the messages styling for when no safe location is found while running `/back` or `/worldspawn`
1616+- Improved the sending of the homes/warps when doing `/homes` or `/warps` (They now get sent in one message instead of multiple)
1717+- Reduced the size of the mod icon by 60% (a 40kb reduction) using some `zopflipng` black magic. (sadly this only made the mod jar 5kb smaller :<)
1818+1919+#### Fixed
2020+- Fixed the markdown for the translations from being bundled with the mod jar.
2121+- Fixed the usage of an invalid translation string when renaming a Home or Warp to a name that already exists.
2222+- Fixed the error handling for when a world isn't found (when going back, going home or warping).
1523 - It now throws a warning and gives the player a new error message (before it would give an incorrect `notFound` error)
1616-- Improved the sending of the homes/warps when doing `/home` or `/warps` (They now get sent in one message instead of multiple)
1717-- Reduced the size of the mod icon by 60% (a 40kb reduction) using some `zopflipng` black magic. (sadly this only made the mod jar 5kb smaller :<)
1818-- Removed the markdown for the translations from being bundled with the mod jar.
2424+2525+#### Added
2626+- added version
1927- Added hover effects for warp and homes text (W.I.P)
2028- Added comments to a lot of code (W.I.P)
2129- Added a new `home.defaultNone` translation key for when there is no default house set. (before this would give `home.homeless` for some reason)
2230- Added a new `common.worldNotFound` translation key for when a world cannot be found
2331- Added a new `common.defaultPrompt` translation key for a new "Set Default" button for `/homes`
3232+- Added a new `common.nameExists` translation key for when that name already exists
24332534### [v1.2.2]
2635- Handled a case where the client (geyser) will return the language as uppercase instead of lowercase.
+3-2
build.gradle
···11plugins {
22- // Required for NeoGradle
33- id "org.jetbrains.gradle.plugin.idea-ext" version "1.1.7"
22+ id 'fabric-loom' version "${fabric_loom}" apply false
33+ id 'net.neoforged.moddev' version "${neoforge_moddevgradle}" apply false
44+45 id "io.github.pacifistmc.forgix" version "1.2.9"
56}
67
···11+package dev.mrsnowy.teleport_commands;
22+33+import org.slf4j.Logger;
44+import org.slf4j.LoggerFactory;
55+66+public class Constants {
77+ public static final String MOD_ID = "teleport_commands";
88+ public static final String MOD_NAME = "Teleport Commands";
99+ public static final String VERSION = "1.3.0";
1010+1111+ public static final Logger LOGGER = LoggerFactory.getLogger(MOD_NAME);
1212+}
···11package dev.mrsnowy.teleport_commands.commands;
2233import com.mojang.brigadier.arguments.StringArgumentType;
44-import dev.mrsnowy.teleport_commands.TeleportCommands;
44+import dev.mrsnowy.teleport_commands.Constants;
55import dev.mrsnowy.teleport_commands.storage.StorageManager;
66import dev.mrsnowy.teleport_commands.common.NamedLocation;
77import dev.mrsnowy.teleport_commands.common.Player;
88import dev.mrsnowy.teleport_commands.suggestions.HomeSuggestionProvider;
991010-import java.awt.*;
1110import java.util.List;
1211import java.util.Optional;
1312···2221import net.minecraft.server.level.ServerLevel;
2322import net.minecraft.server.level.ServerPlayer;
2423import net.minecraft.world.phys.Vec3;
2525-import org.apache.logging.log4j.core.config.builder.api.ComponentBuilder;
26242725import static dev.mrsnowy.teleport_commands.storage.StorageManager.STORAGE;
2826import static dev.mrsnowy.teleport_commands.utils.tools.getTranslatedText;
···4341 SetHome(player, name);
44424543 } catch (Exception e) {
4646- TeleportCommands.LOGGER.error("Error while setting a home! => ", e);
4444+ Constants.LOGGER.error("Error while setting a home! => ", e);
4745 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.setError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
4846 return 1;
4947 }
···6058 GoHome(player, "");
61596260 } catch (Exception e) {
6363- TeleportCommands.LOGGER.error("Error while going home! => ", e);
6161+ Constants.LOGGER.error("Error while going home! => ", e);
6462 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.goError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
6563 return 1;
6664 }
···7674 GoHome(player, name);
77757876 } catch (Exception e) {
7979- TeleportCommands.LOGGER.error("Error while going to a specific home! => ", e);
7777+ Constants.LOGGER.error("Error while going to a specific home! => ", e);
8078 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.goError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
8179 return 1;
8280 }
···9492 DeleteHome(player, name);
95939694 } catch (Exception e) {
9797- TeleportCommands.LOGGER.error("Error while deleting a home! => ", e);
9595+ Constants.LOGGER.error("Error while deleting a home! => ", e);
9896 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.deleteError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
9997 return 1;
10098 }
···114112 RenameHome(player, name, newName);
115113116114 } catch (Exception e) {
117117- TeleportCommands.LOGGER.error("Error while renaming a home! => ", e);
115115+ Constants.LOGGER.error("Error while renaming a home! => ", e);
118116 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.renameError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
119117 return 1;
120118 }
···133131 SetDefaultHome(player, name);
134132135133 } catch (Exception e) {
136136- TeleportCommands.LOGGER.error("Error while setting the default home! => ", e);
134134+ Constants.LOGGER.error("Error while setting the default home! => ", e);
137135 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.defaultError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
138136 return 1;
139137 }
···149147 PrintHomes(player);
150148151149 } catch (Exception e) {
152152- TeleportCommands.LOGGER.error("Error while printing the homes! => ", e);
150150+ Constants.LOGGER.error("Error while printing the homes! => ", e);
153151 player.displayClientMessage(getTranslatedText("commands.teleport_commands.homes.error", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
154152 return 1;
155153 }
···166164 BlockPos blockPos = player.blockPosition();
167165 String worldString = player.serverLevel().dimension().location().toString();
168166169169- // Gets player storage and makes it if it doesn't exist
167167+ // Gets the player's storage and creates it if it doesn't exist
170168 Player playerStorage = StorageManager.STORAGE.addPlayer(player.getStringUUID());
171169172172- // check for duplicates
173173- if (playerStorage.getHome(homeName).isPresent()) {
170170+ // Create the NamedLocation
171171+ NamedLocation warp = new NamedLocation(homeName, blockPos, worldString);
172172+173173+ // Adds the home, returns true if the home already exists
174174+ boolean homeExists = playerStorage.addHome(warp);
175175+176176+ if (homeExists) {
177177+ // Display error message that the home already exists
174178 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.exists", player).withStyle(ChatFormatting.RED), true);
175175- return;
176176- }
177179178178- // Create a new NamedLocation
179179- playerStorage.setHome(homeName, blockPos, worldString);
180180+ } else {
181181+ // Set it as the default if there are no other homes
182182+ if (playerStorage.getHomes().size() == 1) {
183183+ playerStorage.setDefaultHome(homeName);
184184+ }
180185181181- // Set it as the default if there are no other homes
182182- if (playerStorage.getHomes().size() == 1) {
183183- playerStorage.setDefaultHome(homeName);
186186+ // Display message that the home has been set
187187+ player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.set", player), true);
184188 }
185185-186186- // Display message that the home as been set
187187- player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.set", player), true);
188189 }
189190190191 // Teleports the player to the home. It will go to the defaultHome if homeName is empty
···227228 Optional<ServerLevel> optionalWorld = home.getWorld();
228229229230 if (optionalWorld.isEmpty()) {
230230- TeleportCommands.LOGGER.warn("({}) Error while going to the home \"{}\"! \nCouldn't find a world with the id: \"{}\" \nAvailable worlds: {}",
231231+ Constants.LOGGER.warn("({}) Error while going to the home \"{}\"! \nCouldn't find a world with the id: \"{}\" \nAvailable worlds: {}",
231232 player.getName().getString(),
232233 home.getName(),
233234 home.getWorldString(),
···302303 Player playerStorage = optionalPlayerStorage.get();
303304304305 // Check if there already is a home with the new name
305305- playerStorage.getHome("newHomeName").ifPresent(name -> {
306306- player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.renameExists", player).withStyle(ChatFormatting.RED), true);
306306+ if (playerStorage.getHome(newHomeName).isPresent()) {
307307+ player.displayClientMessage(getTranslatedText("commands.teleport_commands.common.nameExists", player).withStyle(ChatFormatting.RED), true);
307308 return;
308308- // todo! does this exit correctly?
309309- });
309309+ }
310310311311 // Get the home that needs to be renamed
312312 Optional<NamedLocation> optionalHome = playerStorage.getHome(homeName);
···2233import java.util.*;
4455-import dev.mrsnowy.teleport_commands.TeleportCommands;
55+import dev.mrsnowy.teleport_commands.Constants;
66import dev.mrsnowy.teleport_commands.suggestions.tpaSuggestionProvider;
7788import net.minecraft.ChatFormatting;
···4848 } catch (Exception e) {
4949 // this shouldn't happen with any of these commands, but if it does happen I am at least printing it to the logs and catching it.
5050 // if it appears that this can happen then I'll add error messages for the client, for now the default minecraft ones will do
5151- TeleportCommands.LOGGER.error("Error while sending a tpa request! => ", e);
5151+ Constants.LOGGER.error("Error while sending a tpa request! => ", e);
5252 return 1;
5353 }
5454 return 0;
···6565 tpaCommandHandler(player, TargetPlayer, true);
66666767 } catch (Exception e) {
6868- TeleportCommands.LOGGER.error("Error while sending a tpahere request! => ", e);
6868+ Constants.LOGGER.error("Error while sending a tpahere request! => ", e);
6969 return 1;
7070 }
7171 return 0;
···8282 tpaAccept(player, TargetPlayer);
83838484 } catch (Exception e) {
8585- TeleportCommands.LOGGER.error("Error while accepting a tpa(here) request! => ", e);
8585+ Constants.LOGGER.error("Error while accepting a tpa(here) request! => ", e);
8686 return 1;
8787 }
8888···100100 tpaDeny(player, TargetPlayer);
101101102102 } catch (Exception e) {
103103- TeleportCommands.LOGGER.error("Error while denying a tpa(here) request! => ", e);
103103+ Constants.LOGGER.error("Error while denying a tpa(here) request! => ", e);
104104 player.displayClientMessage(getTranslatedText("commands.teleport_commands.home.setError", player).withStyle(ChatFormatting.RED, ChatFormatting.BOLD), true);
105105 return 1;
106106 }
···4848 StorageManager.StorageSaver();
4949 }
50505151- // todo! modify this so it uses a NamedLocation
5252- // creates a new home, if there already is a home it will update the existing one
5353- public void setHome(String name, BlockPos pos, String world) throws Exception {
5454- Optional<NamedLocation> optionalHome = getHome(name);
5555- NamedLocation home;
5656-5757- if (optionalHome.isEmpty()) {
5858- home = new NamedLocation(name, pos, world);
5151+ // Adds a NamedLocation to the home list, returns true if it already exists
5252+ public boolean addHome(NamedLocation home) throws Exception {
5353+ if (getHome(home.getName()).isPresent()) {
5454+ // Home with same name found!
5555+ return true;
59566060- Homes.add(home);
6157 } else {
6262- home = optionalHome.get();
6363-6464- home.setName(name);
5858+ Homes.add(home);
5959+ StorageManager.StorageSaver();
6060+ return false;
6561 }
6666-6767- StorageManager.StorageSaver();
6862 }
69637064 // -----
···2233import com.google.gson.Gson;
44import com.google.gson.GsonBuilder;
55+import dev.mrsnowy.teleport_commands.Constants;
56import dev.mrsnowy.teleport_commands.TeleportCommands;
67import dev.mrsnowy.teleport_commands.common.NamedLocation;
78import dev.mrsnowy.teleport_commands.common.Player;
88-import net.minecraft.core.BlockPos;
991010import java.io.File;
1111import java.nio.file.Files;
···4545 }
46464747 } catch (Exception e) {
4848- TeleportCommands.LOGGER.error("Error while creating the storage file! Exiting! => ", e);
4848+ Constants.LOGGER.error("Error while creating the storage file! Exiting! => ", e);
4949 // crashing is probably better here, otherwise the whole mod will be broken
5050 System.exit(1);
5151 }
···87878888 // -----
89899090- // todo! modify this so it uses a NamedLocation as an input
9191- // creates a new warp, if there already is a warp it will update the existing one
9292- public void setWarp(String name, BlockPos pos, String world) throws Exception {
9393- Optional<NamedLocation> OptionalWarp = getWarp(name);
9090+ // Adds a NamedLocation to the warp list, returns true if a warp with the same name already exists
9191+ public boolean addWarp(NamedLocation warp) throws Exception {
9292+ if (getWarp(warp.getName()).isPresent()) {
9393+ // Warp with same name found!
9494+ return true;
94959595- if (OptionalWarp.isEmpty()) {
9696- // create a new warp
9797- NamedLocation warp = new NamedLocation(name, pos, world);
9898- Warps.add(warp);
9996 } else {
100100- // modify existing warp
101101- NamedLocation warp = OptionalWarp.get();
102102- warp.setName(name);
9797+ Warps.add(warp);
9898+ StorageSaver();
9999+ return false;
103100 }
104104-105105- StorageSaver();
106101 }
107102108108- // creates a new player, if there already is a player it will return the existing one. The player won't be saved unless they actually do something lol
109109- // todo! check if this works fully
103103+ // Creates a new player, if there already is a player it will return the existing one. The player won't be saved unless they actually do something lol
104104+ // The name of this function is wack but whatever kewk
110105 public Player addPlayer(String uuid) {
111106 final Optional<Player> OptionalPlayer = getPlayer(uuid);
112107113108 if (OptionalPlayer.isEmpty()) {
114114- // create new player
109109+ // create and return new player
115110 Player player = new Player(uuid);
116111 Players.add(player);
117117-// TeleportCommands.LOGGER.info("Player '{}' added successfully in storage!", uuid); // todo! prob remove these loggers
118112119113 return player;
120114 } else {
121115 // return existing player
122122-// TeleportCommands.LOGGER.info("Player '{}' already exists!", uuid);
123116 return OptionalPlayer.get();
124117 }
125118 }
126119127120 // -----
128121129129- public void rmWarp(NamedLocation warp) throws Exception {
122122+ // Remove a warp, if the warp isn't found then nothing will happen
123123+ public void removeWarp(NamedLocation warp) throws Exception {
130124 Warps.remove(warp);
131125 StorageSaver();
132126 }
···11plugins {
22 id 'multiloader-loader'
33- id 'fabric-loom' version "${fabric_loom}"
33+ id 'fabric-loom'
44}
5566dependencies {
77 minecraft "com.mojang:minecraft:${minecraft_version}"
88 mappings loom.layered() {
99 officialMojangMappings()
1010+ parchment("org.parchmentmc.data:parchment-${parchment_minecraft}:${parchment_version}@zip")
1011 }
1112 modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}"
1213// modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api}"
+14-2
gradle.properties
···1414license=MIT
1515credits=Mr. Snowy
1616description=A server-side mod that adds various teleportation related commands.
1717-minecraft_version_range=[1.21.4,1.22]
1717+minecraft_version_range=[1.21.4, 1.22]
1818+1919+# see https://projects.neoforged.net/neoforged/neoform for new versions
2020+neo_form_version=1.21.4-20241203.161809
2121+2222+# see https://parchmentmc.org/docs/getting-started#choose-a-version for new versions
2323+parchment_minecraft=1.21.4
2424+parchment_version=2025.03.23
18251926# Fabric
2027fabric_loader_version=0.16.9
2128#fabric_api=0.97.0+1.20.4
2222-fabric_loom=1.9-SNAPSHOT
2929+3030+# see https://fabricmc.net/develop/ for new versions
3131+fabric_loom=1.10-SNAPSHOT
23322433# Quilt (Currently disabled since fabric port works better)
2534#quilt_loader_version=0.25.0
···3140neoforge_version=21.4.0-beta
3241neoforge_loader_version_range=[2,)
3342NeoGradle=7.0.171
4343+4444+# see https://projects.neoforged.net/neoforged/moddevgradle for new versions
4545+neoforge_moddevgradle=2.0.80
34463547# Gradle
3648org.gradle.jvmargs=-Xmx6G
···11package dev.mrsnowy.teleport_commands;
2233+import net.neoforged.bus.api.IEventBus;
34import net.neoforged.fml.common.Mod;
4555-@Mod(TeleportCommands.MOD_ID)
66+@Mod(Constants.MOD_ID)
67public class neoforgeInit {
7888- public neoforgeInit() {
99+ public neoforgeInit(IEventBus eventBus) {
910 // This method is invoked by the NeoForge mod loader when it is ready
1011 // to load your mod. You can access NeoForge and Common code in this
1112 // project.