Skip to content
Draft
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
77 changes: 56 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,65 @@ provides a straightforward interface for home management commands.

## Commands

| Command | Permission | Description |
|----------------|--------------------------|---------------------|
| `/sethome` | `homes.commands.sethome` | Sets a home |
| `/delhome` | `homes.commands.delhome` | Deletes a home |
| `/home` | `homes.commands.home` | Teleports to a home |
| `/homesreload` | `homes.reload` | Reloads the config |
| `/homelist` | `homes.commands.list` | Lists your homes |
| Command | Permission | Description |
|-----------------------|--------------------|------------------------------------|
| `/sethome` | `homes.sethome` | Sets a home |
| `/delhome` | `homes.delhome` | Deletes a home |
| `/home` | `homes.home` | Teleports to a home |
| `/homes` | `homes.list` | Lists your homes |
| `/homes admin reload` | `homes.reload` | Reloads the config |
| `/homes admin tp` | `homes.admin.tp` | Teleports to another player's home |
| `/homes admin list` | `homes.admin.list` | Lists another player's homes |

## Permissions

| Permission | Default | Description |
|--------------------------|---------|----------------------------------------------------------------------------------|
| `homes` | op | Allows base plugin functionality |
| `homes.commands` | op | Allows player to use commands |
| `homes.commands.sethome` | op | Allows player to set home |
| `homes.commands.delhome` | op | Allows player to delete home |
| `homes.commands.home` | op | Allows player to teleport to home |
| `homes.commands.list` | op | Allows you to list your own homes |
| `homes.bed` | op | Allows you to teleport to your bed |
| `homes.count` | op | Base for permission on number of homes you can have |
| `homes.count.<num>` | op | Base for permission on number of homes you can have |
| `homes.count.bypass` | op | Allows for setting infinite homes regardless of how many you have set as the max |
| `homes.reload` | op | Allows reloading the config |
| `homes.safety.bypass` | false | Allows bypassing the safety checks |
| Permission | Default | Description |
|-----------------------|---------|----------------------------------------------------------------------------------|
| `homes.sethome` | true | Allows player to set home |
| `homes.delhome` | true | Allows player to delete home |
| `homes.home` | true | Allows player to teleport to home |
| `homes.list` | true | Allows you to list your own homes |
| `homes.bed` | true | Allows you to teleport to your bed, requires configuration setting |
| `homes.reload` | op | Allows reloading the config |
| `homes.bypass.safety` | false | Allows bypassing the safety checks |
| `homes.bypass.delay` | op | Allows bypassing the teleport delay |
| `homes.bypass.count` | op | Allows for setting infinite homes regardless of how many you have set as the max |

## Configuring Number of Homes

The number of homes is determined by permission nodes you create within the `config.yml`.

```yml
# Configuration for number of homes based on permission
counts:
player:
permission: "homes.count.player"
home-count: 3
moderator:
permission: "homes.count.mod"
home-count: 5
```

In the above example, we can break down the counts part of the configuration into a few parts:

```yml
counts:
name:
permission: "string"
home-count: int
```

`name` can be anything, just has to be unique.

`permission` can be any string, just has to be unique across all plugins.

- We recommend using `homes.count.<something>`.
- This is the permission you will give to a player or group/rank.

`home-count` should be an integer, the number of homes you want it to be for the player.

- The highest home-count value given to a player will be applied. This means in the above example,
if a player has both then it will apply a maximum of 5 homes.

## Importing from other plugins

Expand Down
15 changes: 7 additions & 8 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<name>SimpleHomes</name>

<properties>
<java.version>1.8</java.version>
<java.version>21</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

Expand Down Expand Up @@ -61,17 +61,16 @@
</repositories>

<dependencies>

<dependency>
<groupId>org.xerial</groupId>
<artifactId>sqlite-jdbc</artifactId>
<version>3.45.1.0</version>
</dependency>
<dependency>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.20.4-R0.1-SNAPSHOT</version>
<version>1.21.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>6.3.0</version>
</dependency>
</dependencies>
</project>
2 changes: 1 addition & 1 deletion src/main/java/simplexity/simplehomes/SimpleHomes.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,6 @@ private void handleConfig(){
getConfig().options().copyDefaults(true);
saveConfig();
ConfigHandler.getInstance().loadConfigValues();
LocaleHandler.getInstance().loadLocale();
LocaleHandler.getInstance().reloadLocale();
}
}
192 changes: 2 additions & 190 deletions src/main/java/simplexity/simplehomes/commands/HomeCommand.java
Original file line number Diff line number Diff line change
@@ -1,192 +1,4 @@
package simplexity.simplehomes.commands;

import net.kyori.adventure.text.minimessage.tag.resolver.Placeholder;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabExecutor;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitTask;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import simplexity.simplehomes.Home;
import simplexity.simplehomes.SafetyCheck;
import simplexity.simplehomes.SafetyFlags;
import simplexity.simplehomes.SimpleHomes;
import simplexity.simplehomes.configs.ConfigHandler;
import simplexity.simplehomes.configs.LocaleHandler;
import simplexity.simplehomes.saving.Cache;
import simplexity.simplehomes.saving.SQLHandler;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class HomeCommand implements TabExecutor {

private static final String SAFETY_BYPASS = "homes.safety.bypass";
private static final String DELAY_BYPASS = "homes.delay.bypass";
public static HashMap<Player, Location> teleportRequests = new HashMap<>();
public static HashMap<Player, BukkitTask> teleportTasks = new HashMap<>();


@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String s, @NotNull String[] args) {
if (!(sender instanceof Player player)) {
sender.sendRichMessage(LocaleHandler.getInstance().getMustBePlayer());
return false;
}
List<Home> playerHomesList = Cache.getInstance().getPlayerHomes(player.getUniqueId());
//Check for lockout
if (CommandUtils.isLockedOut(player)) {
player.sendRichMessage(LocaleHandler.getInstance().getCannotUseCommand(),
Placeholder.parsed("value", String.valueOf(CommandUtils.maxHomesPermission(player))),
Placeholder.parsed("command", "/home"));
return false;
}
// Get the home to teleport the player to
Home playerHome;
if (args.length == 0) {
playerHome = handleNoArgs(player, playerHomesList);
if (playerHome == null) {
player.sendRichMessage(LocaleHandler.getInstance().getListNoHomes());
return false;
}
} else {
playerHome = handleHomeSelection(player, playerHomesList, args[0]);
if (playerHome == null) {
player.sendRichMessage(LocaleHandler.getInstance().getHomeNotFound(),
Placeholder.parsed("name", args[0]));
return false;
}
}
// Check that it's safe
if (!shouldTeleport(player, args, playerHome)) return false;
handleTeleport(player, playerHome);
return true;
}

// If player has a bed home and supplied no args, return a new home from that location and the configured bed home name.
// Otherwise, if they only have one home, return that one.
// Otherwise, return null

private Home handleNoArgs(Player player, List<Home> homesList) {
Location bedHome = getBedLocation(player);
if (bedHome != null) return new Home(ConfigHandler.getInstance().getBedHomesName(), bedHome);
if (homesList.size() == 1) {
return homesList.get(0);
}
return null;
}

private Home handleHomeSelection(Player player, List<Home> homesList, String suppliedName) {
Location bedLocation = getBedLocation(player);
if (suppliedName.equalsIgnoreCase(ConfigHandler.getInstance().getBedHomesName()) && bedLocation != null) {
return new Home(ConfigHandler.getInstance().getBedHomesName(), bedLocation);
}
return CommandUtils.getHomeFromList(homesList, suppliedName);
}

// Do config, permission, and API checks for bed location
private Location getBedLocation(Player player) {
if (player.getPotentialBedLocation() == null) return null;
if (!ConfigHandler.getInstance().areBedHomesEnabled()) return null;
if (!player.hasPermission(CommandUtils.BED_PERMISSION)) return null;
return player.getPotentialBedLocation();
}

// Safety Check
private boolean shouldTeleport(Player player, String[] args, Home home) {
if (player.hasPermission(SAFETY_BYPASS)) return true;
if (CommandUtils.shouldOverride(args)) return true;
int safetyFlags = SafetyCheck.checkSafetyFlags(home.location(), ConfigHandler.getInstance().getBlacklistedBlocks());
if (safetyFlags == 0) return true;
String safetyWarning = getSafetyWarning(safetyFlags);
if (safetyWarning == null) {
player.sendRichMessage(LocaleHandler.getInstance().getErrorHasOccurred());
return false;
}
player.sendRichMessage(safetyWarning);
return false;
}

// Gets the configured messages for the safety warnings
private String getSafetyWarning(int safetyFlags) {
String warning = "";
if (safetyFlags == 0) return null;
if (SafetyFlags.DAMAGE_RISK.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getBlacklistedWarning();
}
if (SafetyFlags.FALLING.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getVoidWarning();
}
if (SafetyFlags.FIRE.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getFireWarning();
}
if (SafetyFlags.LAVA.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getLavaWarning();
}
if (SafetyFlags.NOT_SOLID.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getVoidWarning();
}
if (SafetyFlags.SUFFOCATION.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getBlocksWarning();
}
if (SafetyFlags.UNDERWATER.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getWaterWarning();
}
if (SafetyFlags.UNSTABLE.matches(safetyFlags)) {
warning = LocaleHandler.getInstance().getVoidWarning();
}
warning = warning + LocaleHandler.getInstance().getInsertOverride();
return warning;
}

private void handleTeleport(Player player, Home home) {
if (!ConfigHandler.getInstance().isDelayEnabled()) {
normalTeleport(player, home);
return;
}
if (player.hasPermission(DELAY_BYPASS)) {
normalTeleport(player, home);
return;
}
delayTeleport(player, home);
}

private void normalTeleport(Player player, Home home) {
player.teleportAsync(home.location());
player.sendRichMessage(LocaleHandler.getInstance().getHomeTeleported(),
Placeholder.parsed("name", home.name()));
}

// Runnable that allows delaying the teleport, tied into the player move listener
private void delayTeleport(Player player, Home home) {
player.sendRichMessage(LocaleHandler.getInstance().getPleaseWait(),
Placeholder.parsed("value", String.valueOf(ConfigHandler.getInstance().getTimeInSeconds())));
teleportRequests.put(player, player.getLocation());
BukkitTask teleportTask = Bukkit.getScheduler().runTaskLater(SimpleHomes.getInstance(), () -> {
if (!teleportRequests.containsKey(player)) return;
player.teleportAsync(home.location());
teleportRequests.remove(player);
player.sendRichMessage(LocaleHandler.getInstance().getHomeTeleported(),
Placeholder.parsed("name", home.name()));
}, ConfigHandler.getInstance().getTimeInSeconds() * 20L);
teleportTasks.put(player, teleportTask);
}

@Override
public @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String[] strings) {
if (!(commandSender instanceof Player player)) return List.of();
List<Home> homesList = SQLHandler.getInstance().getHomes(player.getUniqueId());
List<String> stringList = new ArrayList<>();
for (Home home : homesList) {
stringList.add(home.name());
}
if (player.hasPermission(CommandUtils.BED_PERMISSION) && getBedLocation(player) != null) {
stringList.add(ConfigHandler.getInstance().getBedHomesName());
}
return stringList;
}
}
public class HomeCommand {
}
Loading
Loading