Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion src/main/java/me/axeno/hommr/Hommr.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ public final class Hommr extends JavaPlugin {
@Getter
private Lamp<BukkitCommandActor> lamp;

/**
* Initializes the plugin on enable: sets the singleton instance, ensures default configuration,
* starts the HomeManager, creates and registers the Hommr API service, builds the command lamp,
* registers plugin commands, and emits the startup log banner.
*/
@Override
public void onEnable() {
instance = this;
Expand All @@ -43,12 +48,23 @@ public void onEnable() {
this.logLoadMessage();
}

/**
* Perform plugin shutdown tasks when the plugin is disabled.
*
* <p>Shuts down the HomeManager and logs a disable message to the SLF4J logger.</p>
*/
@Override
public void onDisable() {
HomeManager.shutdown();
this.getSLF4JLogger().info("Hommr Disabled");
}

/**
* Logs a stylized startup banner containing plugin, Java, and server information.
*
* <p>Emits a multi-line ASCII banner to the plugin logger that includes the plugin
* version, the running Java version, and the server name/version.</p>
*/
private void logLoadMessage() {
Logger logger = this.getSLF4JLogger();

Expand All @@ -64,4 +80,4 @@ private void logLoadMessage() {
logger.info("\u001B[1;34m |_||_|\\___/|_| |_|_| |_|_|_\\ \u001B[0m");
logger.info("\u001B[1;34m \u001B[0m");
}
}
}
30 changes: 29 additions & 1 deletion src/main/java/me/axeno/hommr/managers/DatabaseManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ public class DatabaseManager {
@Getter
private Dao<Home, Integer> homeDao;

/**
* Set up the database connection and DAO for Home entities based on configuration.
*
* Initializes the plugin data folder if necessary, creates a JDBC connection source
* (MySQL when `database.type` is `"mysql"`, otherwise SQLite using a `homes.db` file),
* and creates a Dao<Home, Integer> for accessing Home records. Ensures the Home table
* exists in the database; failures during folder creation, table creation, or overall
* initialization are logged.
*/
public void init() {
try {
File dataFolder = Hommr.getInstance().getDataFolder();
Expand Down Expand Up @@ -58,6 +67,11 @@ public void init() {
}
}

/**
* Closes the underlying database connection source and releases related resources.
*
* If an error occurs while closing, the exception is caught and a warning is logged.
*/
public void close() {
if (connectionSource != null) {
try {
Expand All @@ -68,10 +82,24 @@ public void close() {
}
}

/**
* Retrieve all Home records from the database.
*
* @return a list of all Home objects
* @throws SQLException if a database access error occurs while querying for homes
*/
public List<Home> getAllHomes() throws SQLException {
return homeDao.queryForAll();
}

/**
* Replaces all stored Home records with the provided list.
*
* Clears the Home table and inserts the given homes in a single batch operation.
*
* @param homes the list of Home objects to persist (may be empty)
* @throws SQLException if an error occurs while clearing the table or saving records
*/
public void saveAllHomes(List<Home> homes) throws SQLException {
TableUtils.clearTable(connectionSource, Home.class);
try {
Expand All @@ -88,4 +116,4 @@ public void saveAllHomes(List<Home> homes) throws SQLException {
throw new SQLException("Error saving all homes", e);
}
}
}
}
85 changes: 84 additions & 1 deletion src/main/java/me/axeno/hommr/managers/HomeManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,11 @@ public class HomeManager {
private static Map<UUID, PlayerHomes> playerHomesCache;
private static DatabaseManager databaseManager;

/**
* Initializes the HomeManager: ensures the database manager exists, creates the in-memory player homes cache, and loads all persisted homes into the cache.
*
* <p>On failure to read from the database, the method logs a severe error and continues (the cache will be empty).</p>
*/
public static void init() {
if (databaseManager == null) {
databaseManager = new DatabaseManager();
Expand All @@ -41,6 +46,11 @@ public static void init() {
}
}

/**
* Persists all homes currently held in the in-memory cache to persistent storage and closes the database manager.
*
* If the database manager is not initialized, this method does nothing. On failure to save homes a severe log entry is recorded.
*/
public static void shutdown() {
if (databaseManager != null) {
try {
Expand All @@ -57,10 +67,29 @@ public static void shutdown() {
}
}

/**
* Get the PlayerHomes object for the specified player, creating and caching a new one if none exists.
*
* @param playerId the UUID of the player
* @return the PlayerHomes for the specified player; created and stored in the cache if absent
*/
private static PlayerHomes getOrCreatePlayerHomes(UUID playerId) {
return playerHomesCache.computeIfAbsent(playerId, PlayerHomes::new);
}

/**
* Create or update a player's home with the given name and location.
*
* Attempts to store the provided location as a home for the player. If the player has reached
* the configured maximum number of homes and the operation would create a new home, the method
* fails and returns `false`. A HomeSetEvent is fired before the change; if that event is
* cancelled the operation is aborted.
*
* @param player the player who owns the home
* @param homeName the name of the home to create or update
* @param location the location to store for the home
* @return `true` if the home was created or updated, `false` if the operation was prevented (max homes reached or event cancelled)
*/
public static boolean setHome(Player player, String homeName, Location location) {
PlayerHomes playerHomes = getOrCreatePlayerHomes(player.getUniqueId());

Expand All @@ -83,11 +112,27 @@ public static boolean setHome(Player player, String homeName, Location location)
return true;
}

/**
* Retrieve the home with the given name for the specified player.
*
* If the player has no existing PlayerHomes entry in the in-memory cache, one will be created.
*
* @param playerId the UUID of the player
* @param homeName the name of the home to retrieve
* @return an Optional containing the Home if found, or an empty Optional if no home with that name exists
*/
public static Optional<Home> getHome(UUID playerId, String homeName) {
PlayerHomes playerHomes = getOrCreatePlayerHomes(playerId);
return playerHomes.getHome(homeName);
}

/**
* Delete the specified home for the given player, emitting a HomeDeleteEvent that can cancel the deletion.
*
* @param player the player who owns the home
* @param homeName the name of the home to delete
* @return `true` if the home was removed, `false` if the home did not exist or the deletion was cancelled
*/
public static boolean deleteHome(Player player, String homeName) {
PlayerHomes playerHomes = getOrCreatePlayerHomes(player.getUniqueId());

Expand All @@ -107,6 +152,16 @@ public static boolean deleteHome(Player player, String homeName) {
return playerHomes.removeHome(homeName);
}

/**
* Teleports the given player to the specified home if available and permitted.
*
* Attempts to locate the home by name for the player, reconstruct its location, fire a HomeTeleportEvent
* and, if the event is not cancelled, perform the teleport.
*
* @param player the player to teleport
* @param homeName the name of the home to teleport to
* @return `true` if the player was teleported, `false` if the home was not found, the location could not be reconstructed, or the teleport was cancelled
*/
public static boolean teleportToHome(Player player, String homeName) {
Optional<Home> homeOpt = getHome(player.getUniqueId(), homeName);
if (homeOpt.isEmpty()) {
Expand All @@ -131,21 +186,49 @@ public static boolean teleportToHome(Player player, String homeName) {
return true;
}

/**
* Retrieve the names of all homes for the specified player.
*
* @param playerId the UUID of the player whose home names to return
* @return the set of home names owned by the player, empty if the player has no homes
*/
public static Set<String> getHomeNames(UUID playerId) {
return getOrCreatePlayerHomes(playerId).getHomeNames();
}

/**
* Retrieve the number of homes owned by the specified player.
*
* @param playerId the UUID of the player
* @return the number of homes the player currently has
*/
public static int getHomeCount(UUID playerId) {
return getOrCreatePlayerHomes(playerId).getHomeCount();
}

/**
* Determines whether the specified player has a home with the given name.
*
* @param playerId the UUID of the player
* @param homeName the name of the home to check
* @return `true` if the player has a home with the given name, `false` otherwise
*/
public static boolean hasHome(UUID playerId, String homeName) {
return getOrCreatePlayerHomes(playerId).hasHome(homeName);
}


/**
* Determine the maximum number of homes allowed for the given player.
*
* <p>Currently returns a placeholder value indicating no limit; permission- or
* configuration-based limits should be implemented later.</p>
*
* @param player the player whose home limit is being queried
* @return `-1` if unlimited, otherwise the maximum number of homes permitted for the player
*/
public static int getMaxHomes(@SuppressWarnings("unused") Player player) {
// TODO: Implement a system to determine max homes based on permissions or other criteria
return -1; // -1 means unlimited
}
}
}
10 changes: 9 additions & 1 deletion src/main/java/me/axeno/hommr/models/Home.java
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ public class Home {
@DatabaseField(canBeNull = false)
private long createdAt;

/**
* Create a Home instance from a Bukkit Location for the given owner and name.
*
* @param owner the UUID of the player who owns the home
* @param name the display name for the home
* @param location the source Bukkit Location whose world, coordinates, yaw, and pitch are used
* @return a Home populated with the location data, owner and name; `id` is set to 0 and `createdAt` is set to the current system time in milliseconds
*/
public static Home fromLocation(UUID owner, String name, Location location) {
return new Home(
0,
Expand All @@ -69,4 +77,4 @@ public Location toLocation() {
}
return new Location(world, x, y, z, yaw, pitch);
}
}
}
15 changes: 14 additions & 1 deletion src/main/java/me/axeno/hommr/models/PlayerHomes.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,24 @@ public class PlayerHomes {
private final UUID playerId;
private final Map<String, Home> homes;

/**
* Creates a PlayerHomes instance for the specified player.
*
* Initializes the object and prepares an empty, thread-safe map for storing the player's named homes.
*
* @param playerId UUID identifying the player whose homes will be managed
*/
public PlayerHomes(UUID playerId) {
this.playerId = playerId;
this.homes = new ConcurrentHashMap<>();
}

/**
* Stores a Home under the given name for this player, using the lowercase form of the name.
*
* @param name the home name; its lowercase form is used as the storage key
* @param home the Home instance to store; replaces any existing home with the same lowercase name
*/
public void setHome(String name, Home home) {
homes.put(name.toLowerCase(), home);
}
Expand All @@ -38,4 +51,4 @@ public boolean hasHome(String name) {
public int getHomeCount() {
return homes.size();
}
}
}
Loading