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

完成Home功能

This commit is contained in:
Carm Jos 2021-12-17 09:49:44 +08:00
parent 2a4bffff78
commit 106e41492e
12 changed files with 252 additions and 50 deletions

View File

@ -1,12 +1,8 @@
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.command.tpa.*;
import cc.carm.plugin.moeteleport.listener.UserListener;
import cc.carm.plugin.moeteleport.manager.ConfigManager;
import cc.carm.plugin.moeteleport.manager.RequestManager;
@ -44,7 +40,7 @@ public class Main extends JavaPlugin {
this.userManager = new UserManager(this);
log("加载请求管理器...");
this.requestManager = new RequestManager();
this.requestManager = new RequestManager(this);
log("注册监听器...");
regListener(new UserListener());
@ -59,8 +55,8 @@ public class Main extends JavaPlugin {
registerCommand("tpa", new TpaCommand(), new PlayerNameCompleter());
registerCommand("tpaHere", new TpaHereCommand(), new PlayerNameCompleter());
registerCommand("tpAccept", new TpAcceptCommand(), new PlayerNameCompleter());
registerCommand("tpDeny", new TpDenyCommand(), new PlayerNameCompleter());
registerCommand("tpAccept", new TpAcceptCommand(), new TpRequestCompleter());
registerCommand("tpDeny", new TpDenyCommand(), new TpRequestCompleter());
log("加载完成 ,共耗时 " + (System.currentTimeMillis() - startTime) + " ms 。");
@ -71,6 +67,8 @@ public class Main extends JavaPlugin {
log(getName() + " " + getDescription().getVersion() + " 开始卸载...");
long startTime = System.currentTimeMillis();
getRequestManager().shutdown();
log("卸载监听器...");
Bukkit.getServicesManager().unregisterAll(this);

View File

@ -1,17 +1,37 @@
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.configuration.location.DataLocation;
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;
import java.util.Map;
public class DelHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command,
@NotNull String label, @NotNull String[] args) {
if (!(sender instanceof Player)) return false;
if (args.length < 1) return false;
Player player = (Player) sender;
UserData data = Main.getUserManager().getData(player);
String homeName = args[0];
Map.Entry<String, DataLocation> locationInfo = data.getHomeLocation(homeName);
if (locationInfo == null) {
PluginMessages.Home.NOT_FOUND.sendWithPlaceholders(player);
} else {
PluginMessages.Home.REMOVED.sendWithPlaceholders(player,
new String[]{"%(name)", "%(location)"},
new Object[]{locationInfo.getKey(), locationInfo.getValue().toString()});
data.delHomeLocation(homeName);
}
return true;
}

View File

@ -1,17 +1,33 @@
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.configuration.location.DataLocation;
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;
import java.util.Map;
public class GoHomeCommand implements CommandExecutor {
@Override
public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
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);
String homeName = args.length >= 1 ? args[0] : null;
Map.Entry<String, DataLocation> locationInfo = data.getHomeLocation(homeName);
if (locationInfo == null) {
PluginMessages.Home.NOT_FOUND.sendWithPlaceholders(player);
} else {
TeleportManager.teleport(player, locationInfo.getValue());
}
return true;
}

View File

@ -12,7 +12,8 @@ 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) {
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);

View File

@ -1,5 +1,8 @@
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;
@ -9,11 +12,16 @@ 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) {
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);
String homeName = args.length >= 1 ? args[0] : "home";
data.setHomeLocation(homeName, player.getLocation());
PluginMessages.Home.SET.sendWithPlaceholders(player,
new String[]{"%(name)"}, new Object[]{homeName}
);
return true;
}

View File

@ -0,0 +1,53 @@
package cc.carm.plugin.moeteleport.command.tpa;
import cc.carm.plugin.moeteleport.Main;
import cc.carm.plugin.moeteleport.model.UserData;
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.entity.Player;
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.Objects;
import java.util.stream.Collectors;
public class TpRequestCompleter implements TabCompleter {
List<Integer> indexes;
public TpRequestCompleter() {
this(1);
}
public TpRequestCompleter(Integer index) {
this(new Integer[]{index});
}
public TpRequestCompleter(Integer[] indexes) {
this.indexes = Arrays.asList(indexes);
}
@Nullable
@Override
public 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 && indexes.contains(args.length)) {
UserData data = Main.getUserManager().getData((Player) sender);
return data.getReceivedRequests().stream()
.map(Bukkit::getPlayer).filter(Objects::nonNull).map(HumanEntity::getName)
.filter(s -> StringUtil.startsWithIgnoreCase(s, args[args.length - 1]))
.limit(10).collect(Collectors.toList());
} else {
return ImmutableList.of();
}
}
}

View File

@ -18,13 +18,18 @@ public class PluginMessages {
public static final ConfigMessageList TELEPORTING = new ConfigMessageList("teleporting");
public static final ConfigMessageList DANGEROUS = new ConfigMessageList("dangerous");
public static final ConfigMessageList DANGEROUS_HERE = new ConfigMessageList("dangerous-here");
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 SENT = new ConfigMessageList("request-sent");
public static final ConfigMessageList MULTI = new ConfigMessageList("multi-requests");
public static final ConfigMessageList TIMEOUT = new ConfigMessageList("request-timeout");
public static final ConfigMessageList SENT_TIMEOUT = new ConfigMessageList("request-sent-timeout");
public static final ConfigMessageList RECEIVED_TIMEOUT = new ConfigMessageList("request-received-timeout");
public static final ConfigMessageList NOT_FOUND = new ConfigMessageList("no-request");
public static final ConfigMessageList NOT_FOUND_PLAYER = new ConfigMessageList("no-request-player");
}
@ -32,6 +37,12 @@ public class PluginMessages {
public static class Home {
public static final ConfigMessageList HEADER = new ConfigMessageList("home-list-header");
public static final ConfigMessage LIST_OBJECT = new ConfigMessage("home-list-object");
public static final ConfigMessageList NOT_FOUND = new ConfigMessageList("home-not-found");
public static final ConfigMessageList SET = new ConfigMessageList("home-set");
public static final ConfigMessageList REMOVED = new ConfigMessageList("home-removed");
}

View File

@ -1,10 +1,13 @@
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.PluginMessages;
import cc.carm.plugin.moeteleport.model.TeleportRequest;
import cc.carm.plugin.moeteleport.model.UserData;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import java.util.HashSet;
import java.util.Objects;
@ -14,11 +17,72 @@ import java.util.stream.Collectors;
public class RequestManager {
public void sendTpaRequest(Player sender, Player receiver) {
public BukkitRunnable checkRunnable;
public RequestManager(Main main) {
this.checkRunnable = new BukkitRunnable() {
@Override
public void run() {
checkRequests();
}
};
this.checkRunnable.runTaskTimerAsynchronously(main, 100L, 20L);
}
public void shutdown() {
if (!this.checkRunnable.isCancelled()) {
this.checkRunnable.cancel();
}
}
public void checkRequests() {
Main.getUserManager().getUserDataMap().values()
.forEach(data -> data.getSentRequests().entrySet().stream()
.filter(entry -> entry.getValue().isExpired())
.peek(entry -> PluginMessages.Request.SENT_TIMEOUT.sendWithPlaceholders(
entry.getValue().getSender(), new String[]{"%(player)"},
new Object[]{entry.getValue().getReceiver().getName()}))
.peek(entry -> PluginMessages.Request.RECEIVED_TIMEOUT.sendWithPlaceholders(
entry.getValue().getReceiver(), new String[]{"%(player)"},
new Object[]{entry.getValue().getSender().getName()}))
.forEach(entry -> data.getSentRequests().remove(entry.getKey()))
);
}
public void sendTpaRequest(Player sender, Player receiver) {
int expireTime = PluginConfig.EXPIRE_TIME.get();
PluginMessages.Request.SENT.sendWithPlaceholders(sender,
new String[]{"%(player)", "%(expire)"},
new Object[]{receiver, expireTime}
);
PluginMessages.TPA.sendWithPlaceholders(receiver,
new String[]{"%(player)", "%(expire)"},
new Object[]{sender.getName(), expireTime}
);
TeleportRequest request = new TeleportRequest(sender, receiver, sender);
Main.getUserManager().getData(sender).getSentRequests().put(receiver.getUniqueId(), request);
Main.getUserManager().getData(receiver).getReceivedRequests().add(sender.getUniqueId());
}
public void sendTpaHereRequest(Player sender, Player receiver) {
int expireTime = PluginConfig.EXPIRE_TIME.get();
PluginMessages.Request.SENT.sendWithPlaceholders(sender,
new String[]{"%(player)", "%(expire)"},
new Object[]{receiver, expireTime}
);
PluginMessages.TPA_HERE.sendWithPlaceholders(receiver,
new String[]{"%(player)", "%(expire)"},
new Object[]{sender.getName(), expireTime}
);
TeleportRequest request = new TeleportRequest(sender, receiver, receiver);
Main.getUserManager().getData(sender).getSentRequests().put(receiver.getUniqueId(), request);
Main.getUserManager().getData(receiver).getReceivedRequests().add(sender.getUniqueId());
}

View File

@ -10,6 +10,18 @@ import org.bukkit.entity.Player;
public class TeleportManager {
public static void teleport(Player player, DataLocation targetLocation) {
Location location = targetLocation.getBukkitLocation();
if (location == null) {
PluginMessages.NOT_AVAILABLE.sendWithPlaceholders(player,
new String[]{"%(location)"},
new Object[]{targetLocation.toString()}
);
} else {
teleport(player, location);
}
}
public static void teleport(Player player, Location targetLocation) {
if (targetLocation.isWorldLoaded()) {
player.teleport(targetLocation);

View File

@ -2,61 +2,55 @@ 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;
import org.jetbrains.annotations.NotNull;
public class TeleportRequest {
final Player sender;
final Player receiver;
final @NotNull Player sender;
final @NotNull Player receiver;
/**
* 用于记录需要被传送的玩家
*/
final Player teleportPlayer;
final DataLocation targetLocation;
final @NotNull Player teleportPlayer;
final long createTime;
public TeleportRequest(Player sender, Player receiver, Player teleportPlayer,
DataLocation targetLocation, long createTime) {
public TeleportRequest(@NotNull Player sender,
@NotNull Player receiver,
@NotNull Player teleportPlayer) {
this.sender = sender;
this.receiver = receiver;
this.teleportPlayer = teleportPlayer;
this.targetLocation = targetLocation;
this.createTime = createTime;
this.createTime = System.currentTimeMillis();
}
public Player getSender() {
public @NotNull Player getSender() {
return sender;
}
public Player getReceiver() {
public @NotNull Player getReceiver() {
return receiver;
}
public Player getTeleportPlayer() {
public @NotNull 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;
public boolean tryTeleport(@NotNull Location location) {
if (!location.isWorldLoaded()) return false;
if (!TeleportManager.isSafeLocation(location)) {
PluginMessages.DANGEROUS.sendWithPlaceholders(getTeleportPlayer());
return false;

View File

@ -12,6 +12,7 @@ import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
public class UserData {
@ -22,7 +23,7 @@ public class UserData {
private LinkedHashMap<String, DataLocation> homeLocations;
private HashMap<UUID/*receiverUUID*/, TeleportRequest> sentRequests; // 记录发出的请求
private ConcurrentHashMap<UUID/*receiverUUID*/, TeleportRequest> sentRequests; // 记录发出的请求
private HashSet<UUID/*senderUUID*/> receivedRequests; // 记录收到的传送请求
public UserData(@NotNull File dataFolder, @NotNull UUID uuid) {
@ -57,17 +58,28 @@ public class UserData {
return homeLocations;
}
public DataLocation getHomeLocation(@Nullable String homeName) {
public void setHomeLocation(String homeName, Location location) {
delHomeLocation(homeName);
getHomeLocations().put(homeName, new DataLocation(location));
}
public void delHomeLocation(String homeName) {
Map.Entry<String, DataLocation> lastLocation = getHomeLocation(homeName);
if (lastLocation != null) getHomeLocations().remove(lastLocation.getKey());
}
public Map.Entry<String, DataLocation> getHomeLocation(@Nullable String homeName) {
LinkedHashMap<String, DataLocation> homes = getHomeLocations();
if (homeName == null) {
if (homes.size() > 1) {
return homes.get("home");
if (homes.containsKey("home")) {
return new AbstractMap.SimpleEntry<>("home", homes.get("home"));
} else {
if (homes.containsKey("home")) return homes.get("home");
else return homes.values().stream().findFirst().orElse(null);
return homes.entrySet().stream().findFirst().orElse(null);
}
} else {
return homes.get(homeName);
return homes.entrySet().stream()
.filter(entry -> entry.getKey().equalsIgnoreCase(homeName))
.findFirst().orElse(null);
}
}
@ -84,7 +96,7 @@ public class UserData {
}
public HashMap<UUID, TeleportRequest> getSentRequests() {
public ConcurrentHashMap<UUID, TeleportRequest> getSentRequests() {
return sentRequests;
}

View File

@ -1,11 +1,11 @@
no-last-location:
- "&f您当前没有进行传送无法返回上个地点。"
tpa:
- "&6%(player) &f请求传送到您身边您有30秒的时间处理。"
- "&6%(player) &f请求传送到您身边您有%(expire)秒的时间回应。"
- "&a&l[同意] &f输入 &e/tpaccept &f同意该请求。"
- "&c&l[拒绝] &f输入 &e/tpdeny &f拒绝该请求。"
tpahere:
- "&6%(player) &f请求传送您到Ta身边您有30秒的时间处理。"
- "&6%(player) &f请求传送您到Ta身边您有%(expire)秒的时间回应。"
- "&a&l[同意] &f输入 &e/tpaccept &f同意该请求。"
- "&c&l[拒绝] &f输入 &e/tpdeny &f拒绝该请求。"
tpaccept:
@ -19,22 +19,35 @@ denied:
offline:
- "&6%(player) &f离线相关请求已自动取消。"
request-sent:
- "&f成功向玩家 &6%(player) 发送传送请求,对方有%(expire)秒的时间回应该请求。"
no-request:
- "&f您当前没有任何待处理的传送请求。"
no-request-player:
- "&f您当前没有收到来自 &6%(player) &f的传送请求。"
multi-requests:
- "&f您当前有条请求待处理请输入 &6%(command) <玩家名> &f决定处理谁的请求。"
- "&f您也可以再次输入 &6%(command) &f直接处理最近的一条请求。"
request-timeout:
- "&f您当前有条请求待处理请输入 &6%(command) <玩家名> &f决定回应谁的请求。"
- "&f您也可以再次输入 &6%(command) &f直接回应最近的一条请求。"
request-sent-timeout:
- "&f发往 &6%(player) &f的传送请求已超时。"
request-received-timeout:
- "&f来自 &6%(player) &f的传送请求已超时。"
teleporting:
- "&f正在传送到 &6%(location) &f..."
dangerous:
- "&f目标地点不安全传送被取消。"
dangerous-here:
- "&f当前地点不安全无法发送传送请求。"
notAvailable:
- "&f目标地点暂时无法前往传送被取消。"
home-list-header:
- "&f您当前设定的所有家"
home-list-object: "&8#&f%(id) &6%(location)"
home-list-object: "&8#&f%(id) &6%(location)"
home-not-found:
- "&f您还没有设置这个家请先输入 &e/setHome <家名称> &f设置一个吧"
home-set:
- "&f成功设定名为 &6%(name) &f的家传送点。"
home-removed:
- "&f成功移除名为 &6%(name) &f的家传送点。"
- "&7原先位置为 &f%(location) &7。"