1
mirror of https://github.com/CarmJos/MoeTeleport.git synced 2024-09-19 21:35:56 +00:00

重新规划项目结构,完成back指令

This commit is contained in:
Carm Jos 2021-12-17 07:29:07 +08:00
parent f1a2a5c2d4
commit 50f1e1f7ce
30 changed files with 762 additions and 194 deletions

View File

@ -31,20 +31,20 @@
# /tpa <玩家>
- 请求传送到一个玩家身边。
# /tpahere <玩家>
# /tpaHere <玩家>
- 请求一个玩家传送到自己身边。
# /tpaccept [玩家]
# /tpAccept [玩家]
- 同意一个请求,可以限定某个玩家。
# /tpadeny [玩家]
# /tpDeny [玩家]
- 拒绝一个请求,可以限定某个玩家。
# /home [id]
- 返回家 (不填ID会返回第一个家)
# /listhome
# /home [name]
- 返回家 (不填name会返回第一个家,若存在home则优先返回home)
# /listHome
- 列出所有家的位置
# /sethome [id]
- 设置家 (不填ID默认为home)
# /delhome <ID>
# /setHome [name]
- 设置家 (不填name默认为home)
# /delHome <name>
- 删除家
```

View File

@ -1,7 +1,16 @@
package cc.carm.plugin.moeteleport;
import cc.carm.plugin.moeteleport.command.BackCommand;
import cc.carm.plugin.moeteleport.command.tpa.PlayerNameCompleter;
import cc.carm.plugin.moeteleport.command.home.*;
import cc.carm.plugin.moeteleport.command.tpa.TpAcceptCommand;
import cc.carm.plugin.moeteleport.command.tpa.TpDenyCommand;
import cc.carm.plugin.moeteleport.command.tpa.TpaCommand;
import cc.carm.plugin.moeteleport.command.tpa.TpaHereCommand;
import cc.carm.plugin.moeteleport.listener.UserListener;
import cc.carm.plugin.moeteleport.manager.ConfigManager;
import cc.carm.plugin.moeteleport.manager.RequestManager;
import cc.carm.plugin.moeteleport.manager.TeleportManager;
import cc.carm.plugin.moeteleport.manager.UserManager;
import cc.carm.plugin.moeteleport.util.ColorParser;
import org.bukkit.Bukkit;
@ -19,6 +28,8 @@ public class Main extends JavaPlugin {
public static boolean debugMode = true;
private UserManager userManager;
private TeleportManager teleportManager;
private RequestManager requestManager;
@Override
public void onEnable() {
@ -32,9 +43,25 @@ public class Main extends JavaPlugin {
log("加载用户管理器...");
this.userManager = new UserManager(this);
log("加载请求管理器...");
this.requestManager = new RequestManager();
log("注册监听器...");
regListener(new UserListener());
log("注册指令...");
registerCommand("back", new BackCommand());
registerCommand("home", new GoHomeCommand(), new HomeNameCompleter());
registerCommand("delHome", new DelHomeCommand(), new HomeNameCompleter());
registerCommand("setHome", new SetHomeCommand());
registerCommand("listHome", new ListHomeCommand());
registerCommand("tpa", new TpaCommand(), new PlayerNameCompleter());
registerCommand("tpaHere", new TpaHereCommand(), new PlayerNameCompleter());
registerCommand("tpAccept", new TpAcceptCommand(), new PlayerNameCompleter());
registerCommand("tpDeny", new TpDenyCommand(), new PlayerNameCompleter());
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
}
@ -95,4 +122,8 @@ public class Main extends JavaPlugin {
return Main.getInstance().userManager;
}
public static RequestManager getRequestManager() {
return Main.getInstance().requestManager;
}
}

View File

@ -1,4 +1,34 @@
package cc.carm.plugin.moeteleport.command;
public class BackCommand {
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.configuration.PluginMessages;
import cc.carm.plugin.moeteleport.manager.TeleportManager;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class BackCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
UserData data = Main.getUserManager().getData(player);
if (data.getLastLocation() == null) {
PluginMessages.NO_LAST_LOCATION.send(player);
return true;
}
if (!TeleportManager.isSafeLocation(data.getLastLocation())) {
PluginMessages.DANGEROUS.send(player);
return true;
}
TeleportManager.teleport(player, data.getLastLocation());
return true;
}
}

View File

@ -1,57 +0,0 @@
package cc.carm.plugin.moeteleport.command;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class HomeCommands {
public static class TeleportCommand implements CommandExecutor, TabCompleter {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return false;
}
@Nullable
@Override
public List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
return null;
}
}
public static class ListCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return false;
}
}
public static class DelCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return false;
}
}
public static class AddHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
return false;
}
}
}

View File

@ -0,0 +1,19 @@
package cc.carm.plugin.moeteleport.command.home;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class DelHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -0,0 +1,19 @@
package cc.carm.plugin.moeteleport.command.home;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class GoHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -0,0 +1,30 @@
package cc.carm.plugin.moeteleport.command.home;
import cc.carm.plugin.moeteleport.Main;
import com.google.common.collect.ImmutableList;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.Player;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.stream.Collectors;
public class HomeNameCompleter implements TabCompleter {
@Nullable
@Override
public java.util.List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
if (!(sender instanceof Player)) return ImmutableList.of();
if (args.length == 1) {
return Main.getUserManager().getData((Player) sender).getHomeLocations().keySet().stream()
.filter(s -> StringUtil.startsWithIgnoreCase(s, args[0]))
.limit(10).collect(Collectors.toList());
} else {
return ImmutableList.of();
}
}
}

View File

@ -0,0 +1,28 @@
package cc.carm.plugin.moeteleport.command.home;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.configuration.PluginMessages;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class ListHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
UserData data = Main.getUserManager().getData(player);
PluginMessages.Home.HEADER.sendWithPlaceholders(player);
data.getHomeLocations().forEach((name, loc) -> PluginMessages.Home.LIST_OBJECT
.sendWithPlaceholders(player,
new String[]{"%(name)", "%(location)"},
new Object[]{name, loc.toString()}
));
return true;
}
}

View File

@ -0,0 +1,21 @@
package cc.carm.plugin.moeteleport.command.home;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class SetHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -0,0 +1,47 @@
package cc.carm.plugin.moeteleport.command.tpa;
import com.google.common.collect.ImmutableList;
import org.bukkit.Bukkit;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.command.TabCompleter;
import org.bukkit.entity.HumanEntity;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
public class PlayerNameCompleter implements TabCompleter {
List<Integer> indexes;
public PlayerNameCompleter() {
this(1);
}
public PlayerNameCompleter(Integer index) {
this(new Integer[]{index});
}
public PlayerNameCompleter(Integer[] indexes) {
this.indexes = Arrays.asList(indexes);
}
@Nullable
@Override
public java.util.List<String> onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
if (args.length >= 1 && indexes.contains(args.length)) {
return Bukkit.getOnlinePlayers().stream()
.map(HumanEntity::getName)
.filter(s -> StringUtil.startsWithIgnoreCase(s, args[args.length - 1]))
.limit(10).collect(Collectors.toList());
} else {
return ImmutableList.of();
}
}
}

View File

@ -1,4 +1,18 @@
package cc.carm.plugin.moeteleport.command.tpa;
public class TpAcceptCommand {
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class TpAcceptCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -0,0 +1,18 @@
package cc.carm.plugin.moeteleport.command.tpa;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class TpDenyCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -1,4 +1,18 @@
package cc.carm.plugin.moeteleport.command.tpa;
public class TpaCommand {
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class TpaCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -1,4 +0,0 @@
package cc.carm.plugin.moeteleport.command.tpa;
public class TpaDenyCommand {
}

View File

@ -1,4 +1,18 @@
package cc.carm.plugin.moeteleport.command.tpa;
public class TpaHereCommand {
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
public class TpaHereCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
Player player = (Player) sender;
return true;
}
}

View File

@ -1,17 +1,24 @@
package cc.carm.plugin.moeteleport.configuration;
import cc.carm.plugin.moeteleport.configuration.values.ConfigValue;
import cc.carm.plugin.moeteleport.manager.ConfigManager;
import java.util.HashMap;
import cc.carm.plugin.moeteleport.configuration.values.ConfigValueList;
import cc.carm.plugin.moeteleport.configuration.values.ConfigValueMap;
public class PluginConfig {
public static HashMap<String, Integer> getPermissions() {
return ConfigManager.getPermissions();
}
public static final ConfigValueMap<String, Integer> PERMISSIONS = new ConfigValueMap<>(
"permissions", s -> s, Integer.class
);
public static final ConfigValue<Integer> EXPIRE_TIME = new ConfigValue<>("expireTime", Integer.class, 30);
public static final ConfigValue<Integer> DEFAULT_HOME = new ConfigValue<>("defaultHome", Integer.class, 1);
public static final ConfigValueList<String> DANGEROUS_TYPES = new ConfigValueList<>(
"dangerousBlocks", String.class, new String[]{"LAVA"}
);
public static final ConfigValue<Integer> EXPIRE_TIME = new ConfigValue<>(
"expireTime", Integer.class, 30
);
public static final ConfigValue<Integer> DEFAULT_HOME = new ConfigValue<>(
"defaultHome", Integer.class, 1
);
}

View File

@ -9,16 +9,20 @@ public class PluginMessages {
public static final ConfigMessageList TPA = new ConfigMessageList("tpa");
public static final ConfigMessageList TPA_HERE = new ConfigMessageList("tpahere");
public static final ConfigMessageList TPA_ACCEPT = new ConfigMessageList("tpaccept");
public static final ConfigMessageList TPA_DENY = new ConfigMessageList("tpadeny");
public static final ConfigMessageList TP_ACCEPT = new ConfigMessageList("tpaccept");
public static final ConfigMessageList TP_DENY = new ConfigMessageList("tpdeny");
public static final ConfigMessageList ACCEPTED = new ConfigMessageList("accepted");
public static final ConfigMessageList DENIED = new ConfigMessageList("denied");
public static final ConfigMessageList TELEPORTING = new ConfigMessageList("teleporting");
public static final ConfigMessageList DANGEROUS = new ConfigMessageList("dangerous");
public static final ConfigMessageList NOT_AVAILABLE = new ConfigMessageList("notAvailable");
public static class Request {
public static final ConfigMessageList OFFLINE = new ConfigMessageList("offline");
public static final ConfigMessageList MULTI = new ConfigMessageList("multi-requests");
public static final ConfigMessageList TIMEOUT = new ConfigMessageList("request-timeout");
public static final ConfigMessageList NOT_FOUND = new ConfigMessageList("no-request");

View File

@ -4,26 +4,27 @@ import cc.carm.plugin.moeteleport.configuration.values.ConfigValueList;
import cc.carm.plugin.moeteleport.manager.ConfigManager;
import cc.carm.plugin.moeteleport.util.MessageUtil;
import org.bukkit.command.CommandSender;
import org.jetbrains.annotations.Nullable;
public class ConfigMessageList extends ConfigValueList<String> {
public ConfigMessageList(String configSection) {
super(ConfigManager.getMessageConfig(), configSection, String.class);
}
public ConfigMessageList(String configSection) {
super(ConfigManager.getMessageConfig(), configSection, String.class);
}
public ConfigMessageList(String configSection, String[] defaultValue) {
super(ConfigManager.getMessageConfig(), configSection, String.class, defaultValue);
}
public ConfigMessageList(String configSection, String[] defaultValue) {
super(ConfigManager.getMessageConfig(), configSection, String.class, defaultValue);
}
public void send(CommandSender sender) {
MessageUtil.send(sender, get());
}
public void send(@Nullable CommandSender sender) {
MessageUtil.send(sender, get());
}
public void sendWithPlaceholders(CommandSender sender) {
MessageUtil.sendWithPlaceholders(sender, get());
}
public void sendWithPlaceholders(@Nullable CommandSender sender) {
MessageUtil.sendWithPlaceholders(sender, get());
}
public void sendWithPlaceholders(CommandSender sender, String[] params, Object[] values) {
MessageUtil.sendWithPlaceholders(sender, get(), params, values);
}
public void sendWithPlaceholders(@Nullable CommandSender sender, String[] params, Object[] values) {
MessageUtil.sendWithPlaceholders(sender, get(), params, values);
}
}

View File

@ -0,0 +1,79 @@
package cc.carm.plugin.moeteleport.configuration.values;
import cc.carm.plugin.moeteleport.configuration.file.FileConfig;
import cc.carm.plugin.moeteleport.manager.ConfigManager;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
public class ConfigValueMap<K, V> {
@NotNull FileConfig source;
@NotNull String configSection;
@NotNull Function<String, K> keyCast;
@NotNull Class<V> valueClazz;
@Nullable LinkedHashMap<K, V> valueCache;
public ConfigValueMap(@NotNull String configSection, @NotNull Function<String, K> keyCast,
@NotNull Class<V> valueClazz) {
this(ConfigManager.getPluginConfig(), configSection, keyCast, valueClazz);
}
public ConfigValueMap(@NotNull FileConfig configuration, @NotNull String configSection,
@NotNull Function<String, K> keyCast, @NotNull Class<V> valueClazz) {
this.source = configuration;
this.configSection = configSection;
this.keyCast = keyCast;
this.valueClazz = valueClazz;
}
public @NotNull FileConfiguration getConfiguration() {
return this.source.getConfig();
}
public void clearCache() {
this.valueCache = null;
}
@NotNull
public Map<K, V> get() {
if (valueCache != null) return valueCache;
ConfigurationSection section = getConfiguration().getConfigurationSection(this.configSection);
if (section == null) return new LinkedHashMap<>();
Set<String> keys = getConfiguration().getKeys(false);
if (keys.isEmpty()) return new LinkedHashMap<>();
else {
LinkedHashMap<K, V> result = new LinkedHashMap<>();
for (String key : keys) {
K finalKey = keyCast.apply(key);
Object val = getConfiguration().get(this.configSection);
V finalValue = this.valueClazz.isInstance(val) ? this.valueClazz.cast(val) : null;
if (finalKey != null && finalValue != null) {
result.put(finalKey, finalValue);
}
}
this.valueCache = result;
return result;
}
}
public void set(HashMap<K, V> valuesMap) {
getConfiguration().createSection(this.configSection, valuesMap);
this.save();
}
public void save() {
this.source.save();
}
}

View File

@ -1,7 +1,8 @@
package cc.carm.plugin.moeteleport.listener;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.user.UserData;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;
@ -20,8 +21,10 @@ public class UserListener implements Listener {
@EventHandler
public void onQuit(PlayerQuitEvent event) {
Main.getUserManager().getData(event.getPlayer()).save(); //保存
Main.getUserManager().getUserDataMap().remove(event.getPlayer().getUniqueId());
Player player = event.getPlayer();
Main.getRequestManager().cancelAllRequests(player);
Main.getUserManager().getData(player).save(); //保存
Main.getUserManager().getUserDataMap().remove(player.getUniqueId());
}
}

View File

@ -3,24 +3,15 @@ package cc.carm.plugin.moeteleport.manager;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.configuration.PluginConfig;
import cc.carm.plugin.moeteleport.configuration.file.FileConfig;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import java.util.HashMap;
import java.util.Set;
import java.util.stream.Collectors;
public class ConfigManager {
private static FileConfig config;
private static FileConfig messageConfig;
private static HashMap<String, Integer> permissionsMap;
public static void initConfig() {
ConfigManager.config = new FileConfig(Main.getInstance(), "config.yml");
ConfigManager.messageConfig = new FileConfig(Main.getInstance(), "messages.yml");
permissionsMap = loadPermissions();
}
public static FileConfig getPluginConfig() {
@ -31,27 +22,10 @@ public class ConfigManager {
return messageConfig;
}
public static HashMap<String, Integer> getPermissions() {
return permissionsMap;
}
public static HashMap<String, Integer> loadPermissions() {
FileConfiguration config = getPluginConfig().getConfig();
ConfigurationSection section = config.getConfigurationSection("permissions");
if (section == null) return new HashMap<>();
Set<String> permissionNodes = section.getKeys(false);
if (permissionNodes.isEmpty()) return new HashMap<>();
return permissionNodes.stream()
.collect(Collectors.toMap(
s -> s, s -> section.getInt(s, PluginConfig.DEFAULT_HOME.get()),
(a, b) -> b, HashMap::new
));
}
public static void reload() {
getPluginConfig().reload();
getMessageConfig().reload();
permissionsMap = loadPermissions();
PluginConfig.PERMISSIONS.clearCache();
}
public static void saveConfig() {

View File

@ -0,0 +1,80 @@
package cc.carm.plugin.moeteleport.manager;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.configuration.PluginMessages;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
public class RequestManager {
public void sendTpaRequest(Player sender, Player receiver) {
}
public void sendTpaHereRequest(Player sender, Player receiver) {
}
public void cancelAllRequests(Player player) {
UUID playerUUID = player.getUniqueId();
UserData data = Main.getUserManager().getData(player);
data.getSentRequests().keySet().stream()
.peek(receiverUUID -> PluginMessages.Request.OFFLINE.sendWithPlaceholders(
Bukkit.getPlayer(receiverUUID),
new String[]{"%(player)"}, new Object[]{player.getName()}
)).map(receiverUUID -> Main.getUserManager().getData(receiverUUID))
.filter(Objects::nonNull).map(UserData::getReceivedRequests)
.forEach(senders -> senders.remove(playerUUID));
data.getReceivedRequests().stream()
.peek(senderUUID -> PluginMessages.Request.OFFLINE.sendWithPlaceholders(
Bukkit.getPlayer(senderUUID),
new String[]{"%(player)"}, new Object[]{player.getName()}
)).map(senderUUID -> Main.getUserManager().getData(senderUUID))
.filter(Objects::nonNull).map(UserData::getSentRequests)
.forEach(receivers -> receivers.remove(playerUUID));
data.getSentRequests().clear();
data.getReceivedRequests().clear();
}
public Set<Player> getRequestedPlayers(Player player) {
UserData data = Main.getUserManager().getData(player);
HashSet<UUID> relatedUUIDs = new HashSet<>();
relatedUUIDs.addAll(data.getReceivedRequests());
relatedUUIDs.addAll(data.getSentRequests().keySet());
return relatedUUIDs.stream()
.map(Bukkit::getPlayer)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
}
/**
* 取消某玩家所有相关的传送请求
*
* @param player 玩家
*/
public void clearAllRequests(Player player) {
UUID playerUUID = player.getUniqueId();
UserData data = Main.getUserManager().getData(player);
data.getSentRequests().keySet().stream()
.map(receiver -> Main.getUserManager().getData(receiver))
.filter(Objects::nonNull).map(UserData::getReceivedRequests)
.forEach(senders -> senders.remove(playerUUID));
data.getReceivedRequests().stream()
.map(sender -> Main.getUserManager().getData(sender))
.filter(Objects::nonNull).map(UserData::getSentRequests)
.forEach(receivers -> receivers.remove(playerUUID));
data.getSentRequests().clear();
data.getReceivedRequests().clear();
}
}

View File

@ -0,0 +1,43 @@
package cc.carm.plugin.moeteleport.manager;
import cc.carm.plugin.moeteleport.configuration.PluginConfig;
import cc.carm.plugin.moeteleport.configuration.PluginMessages;
import cc.carm.plugin.moeteleport.configuration.location.DataLocation;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Player;
public class TeleportManager {
public static void teleport(Player player, Location targetLocation) {
if (targetLocation.isWorldLoaded()) {
player.teleport(targetLocation);
PluginMessages.TELEPORTING.sendWithPlaceholders(player,
new String[]{"%(location)"},
new Object[]{new DataLocation(targetLocation).toString()}
);
} else {
PluginMessages.NOT_AVAILABLE.sendWithPlaceholders(player,
new String[]{"%(location)"},
new Object[]{new DataLocation(targetLocation).toString()}
);
}
}
public static boolean isSafeLocation(Location location) {
Block leg = location.getBlock();
if (!leg.getType().isAir()) {
return false; // not transparent (will suffocate)
}
Block head = leg.getRelative(BlockFace.UP);
if (!head.getType().isAir()) {
return false; // not transparent (will suffocate)
}
Block ground = leg.getRelative(BlockFace.DOWN);
return ground.getType().isSolid()
&& !PluginConfig.DANGEROUS_TYPES.get().contains(ground.getType().name());
}
}

View File

@ -1,7 +1,7 @@
package cc.carm.plugin.moeteleport.manager;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.user.UserData;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

View File

@ -0,0 +1,74 @@
package cc.carm.plugin.moeteleport.model;
import cc.carm.plugin.moeteleport.configuration.PluginConfig;
import cc.carm.plugin.moeteleport.configuration.PluginMessages;
import cc.carm.plugin.moeteleport.configuration.location.DataLocation;
import cc.carm.plugin.moeteleport.manager.TeleportManager;
import org.bukkit.Location;
import org.bukkit.entity.Player;
public class TeleportRequest {
final Player sender;
final Player receiver;
/**
* 用于记录需要被传送的玩家
*/
final Player teleportPlayer;
final DataLocation targetLocation;
final long createTime;
public TeleportRequest(Player sender, Player receiver, Player teleportPlayer,
DataLocation targetLocation, long createTime) {
this.sender = sender;
this.receiver = receiver;
this.teleportPlayer = teleportPlayer;
this.targetLocation = targetLocation;
this.createTime = createTime;
}
public Player getSender() {
return sender;
}
public Player getReceiver() {
return receiver;
}
public Player getTeleportPlayer() {
return teleportPlayer;
}
public DataLocation getTargetLocation() {
return targetLocation;
}
public long getCreateTime() {
return createTime;
}
/**
* 尝试对玩家进行传送
*
* @return 是否传送成功
*/
public boolean tryTeleport() {
Location location = getTargetLocation().getBukkitLocation();
if (location == null) return false;
if (!TeleportManager.isSafeLocation(location)) {
PluginMessages.DANGEROUS.sendWithPlaceholders(getTeleportPlayer());
return false;
} else {
TeleportManager.teleport(getTeleportPlayer(), location);
return true;
}
}
public boolean isExpired() {
return (System.currentTimeMillis() - getCreateTime()) > PluginConfig.EXPIRE_TIME.get() * 10000;
}
}

View File

@ -1,24 +1,30 @@
package cc.carm.plugin.moeteleport.user;
package cc.carm.plugin.moeteleport.model;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.configuration.location.DataLocation;
import org.bukkit.Location;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Optional;
import java.util.UUID;
import java.util.*;
public class UserData {
private final @NotNull File dataFile;
private final @NotNull FileConfiguration dataConfig;
private @Nullable Location lastLocation;
private LinkedHashMap<String, DataLocation> homeLocations;
private HashMap<UUID/*receiverUUID*/, TeleportRequest> sentRequests; // 记录发出的请求
private HashSet<UUID/*senderUUID*/> receivedRequests; // 记录收到的传送请求
public UserData(@NotNull File dataFolder, @NotNull UUID uuid) {
this(new File(dataFolder, uuid + ".yml"));
}
@ -51,6 +57,41 @@ public class UserData {
return homeLocations;
}
public DataLocation getHomeLocation(@Nullable String homeName) {
LinkedHashMap<String, DataLocation> homes = getHomeLocations();
if (homeName == null) {
if (homes.size() > 1) {
return homes.get("home");
} else {
if (homes.containsKey("home")) return homes.get("home");
else return homes.values().stream().findFirst().orElse(null);
}
} else {
return homes.get(homeName);
}
}
public @Nullable Location getLastLocation() {
return lastLocation;
}
public boolean backToLocation(Player player) {
if (getLastLocation() == null) return false;
else {
player.teleport(getLastLocation());
return true;
}
}
public HashMap<UUID, TeleportRequest> getSentRequests() {
return sentRequests;
}
public HashSet<UUID> getReceivedRequests() {
return receivedRequests;
}
public @NotNull File getDataFile() {
return dataFile;
}
@ -59,7 +100,6 @@ public class UserData {
return dataConfig;
}
public LinkedHashMap<String, String> saveToMap() {
LinkedHashMap<String, DataLocation> homeLocations = getHomeLocations();
LinkedHashMap<String, String> data = new LinkedHashMap<>();
@ -68,7 +108,6 @@ public class UserData {
return data;
}
public void save() {
try {
getDataConfig().createSection("homes", saveToMap());

View File

@ -4,71 +4,73 @@ import me.clip.placeholderapi.PlaceholderAPI;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
import java.util.*;
public class MessageUtil {
public static boolean hasPlaceholderAPI() {
return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
}
public static boolean hasPlaceholderAPI() {
return Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null;
}
public static void send(CommandSender sender, List<String> messages) {
for (String s : messages) {
sender.sendMessage(ColorParser.parse(s));
}
}
public static void send(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty() || sender == null) return;
for (String s : messages) {
sender.sendMessage(ColorParser.parse(s));
}
}
public static void send(CommandSender sender, String... messages) {
send(sender, Arrays.asList(messages));
}
public static void send(@Nullable CommandSender sender, String... messages) {
send(sender, Arrays.asList(messages));
}
public static void sendWithPlaceholders(CommandSender sender, String... messages) {
sendWithPlaceholders(sender, Arrays.asList(messages));
}
public static void sendWithPlaceholders(CommandSender sender, String... messages) {
sendWithPlaceholders(sender, Arrays.asList(messages));
}
public static void sendWithPlaceholders(CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty()) return;
if (hasPlaceholderAPI() && sender instanceof Player) {
send(sender, PlaceholderAPI.setPlaceholders((Player) sender, messages));
} else {
send(sender, messages);
}
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages) {
if (messages == null || messages.isEmpty() || sender == null) return;
if (hasPlaceholderAPI() && sender instanceof Player) {
send(sender, PlaceholderAPI.setPlaceholders((Player) sender, messages));
} else {
send(sender, messages);
}
}
public static void sendWithPlaceholders(CommandSender sender, List<String> messages, String param, Object value) {
sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value});
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String param, Object value) {
sendWithPlaceholders(sender, messages, new String[]{param}, new Object[]{value});
}
public static void sendWithPlaceholders(CommandSender sender, List<String> messages, String[] params, Object[] values) {
sendWithPlaceholders(sender, setCustomParams(messages, params, values));
}
public static void sendWithPlaceholders(@Nullable CommandSender sender, List<String> messages, String[] params, Object[] values) {
sendWithPlaceholders(sender, setCustomParams(messages, params, values));
}
public static List<String> setCustomParams(List<String> messages, String param, Object value) {
return setCustomParams(messages, new String[]{param}, new Object[]{value});
}
public static List<String> setCustomParams(List<String> messages, String param, Object value) {
return setCustomParams(messages, new String[]{param}, new Object[]{value});
}
public static List<String> setCustomParams(List<String> messages, String[] params, Object[] values) {
if (params.length != values.length) return messages;
HashMap<String, Object> paramsMap = new HashMap<>();
for (int i = 0; i < params.length; i++) {
paramsMap.put(params[i], values[i]);
}
return setCustomParams(messages, paramsMap);
}
public static List<String> setCustomParams(List<String> messages, String[] params, Object[] values) {
if (params.length != values.length) return messages;
HashMap<String, Object> paramsMap = new HashMap<>();
for (int i = 0; i < params.length; i++) {
paramsMap.put(params[i], values[i]);
}
return setCustomParams(messages, paramsMap);
}
public static List<String> setCustomParams(List<String> messages, HashMap<String, Object> params) {
List<String> list = new ArrayList<>();
for (String message : messages) {
String afterMessage = message;
for (Map.Entry<String, Object> entry : params.entrySet()) {
afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString());
}
list.add(afterMessage);
}
return list;
}
public static List<String> setCustomParams(List<String> messages, HashMap<String, Object> params) {
List<String> list = new ArrayList<>();
for (String message : messages) {
String afterMessage = message;
for (Map.Entry<String, Object> entry : params.entrySet()) {
afterMessage = afterMessage.replace(entry.getKey(), entry.getValue().toString());
}
list.add(afterMessage);
}
return list;
}
}

View File

@ -9,4 +9,9 @@ permissions:
"home.vip": 10 # 最多可以设置10个家
# 传送请求过期时间
expireTime: 30
expireTime: 30
# 危险的方块类型,将判断目的地脚下的方块的类型是否在这个列表中
dangerousBlocks:
- LAVA
- AIR

View File

@ -3,19 +3,21 @@ no-last-location:
tpa:
- "&6%(player) &f请求传送到您身边您有30秒的时间处理。"
- "&a&l[同意] &f输入 &e/tpaccept &f同意该请求。"
- "&c&l[拒绝] &f输入 &e/tpadeny &f拒绝该请求。"
- "&c&l[拒绝] &f输入 &e/tpdeny &f拒绝该请求。"
tpahere:
- "&6%(player) &f请求传送您到Ta身边您有30秒的时间处理。"
- "&a&l[同意] &f输入 &e/tpaccept &f同意该请求。"
- "&c&l[拒绝] &f输入 &e/tpadeny &f拒绝该请求。"
- "&c&l[拒绝] &f输入 &e/tpdeny &f拒绝该请求。"
tpaccept:
- "&f您同意了 &6%(player) &f的传送请求。"
tpadeny:
tpdeny:
- "&f您&c拒绝&f了 &6%(player) &f的传送请求。"
accepted:
- "&6%(player) &f同意了您的传送请求。"
denied:
- "&6%(player) &c拒绝&f了您的传送请求。"
offline:
- "&6%(player) &f离线相关请求已自动取消。"
no-request:
- "&f您当前没有任何待处理的传送请求。"
@ -27,10 +29,12 @@ multi-requests:
request-timeout:
- "&f来自 &6%(player) &f的传送请求已超时。"
teleporting:
- "&f正在传送到 &6&(location) &f..."
- "&f正在传送到 &6%(location) &f..."
dangerous:
- "&f目标地点不安全传送被取消。若您执意传送可再次输入 &6/tpaccept &f。"
- "&f目标地点不安全传送被取消。"
notAvailable:
- "&f目标地点暂时无法前往传送被取消。"
home-list-header:
- "&f您当前设定的所有家"
home-list-object: "&8#&f%(id) &6(location)"
home-list-object: "&8#&f%(id) &6%(location)"

View File

@ -6,4 +6,33 @@ website: ${project.url}
description: ${project.description}
softdepend:
- PlaceholderAPI
- PlaceholderAPI
commands:
"back":
description: 返回传送前的上一个地点。
"tpa":
usage: "/tpa <玩家> "
description: 请求传送到一个玩家身边。
"tpaHere":
usage: "/tpaHere <玩家>"
description: 请求一个玩家传送到自己身边。
"tpaAccept":
usage: "/tpAccept [玩家]"
description: 同意一个请求,可以限定某个玩家。
"tpaDeny":
usage: "/tpDeny [玩家]"
description: 拒绝一个请求,可以限定某个玩家。
"home":
usage: "/home [名称] "
description: "返回家所在位置。"
"listHome":
description: "列出所有家的位置。"
"setHome":
usage: "/setHome [名称] "
description: "设置家的传送点 (不填名称默认为home)"
"delHome":
usage: "/delHome <名称> "
description: "删除家的传送点。"