add: PingPlayerFeature (#1)

fix many bugs, rewrote some message decorators
to be refactored
This commit is contained in:
iceBear67 committed 2024-07-10 16:56:56 +08:00
1 parent 09a2e7330a
commit e6ec825bd2
6 files changed
+123 -20

No files matched your search

+3 -1
View File
@@ -7,8 +7,10 @@ import net.minecraft.server.network.ServerPlayerEntity;
@UtilityClass
public class SFConsts {
public static final String SPECIAL_SUDO = "sfcraft.special.state.sudo";
public static final Permission<PlayerEntity> USE_AT = ofSFCPermission("chat.at",true);
public static final Permission<PlayerEntity> USE_BROADCAST_LOCATION = ofSFCPermission("chat.xyz",true);
public static final Permission<PlayerEntity> COMMAND_BACK = ofSFCPermission("command.home", true);
public static final Permission<PlayerEntity> UNLIMITED_COMMAND_BACK = ofSFCPermission("command.home.unlimited", true);
public static final Permission<PlayerEntity> UNLIMITED_COMMAND_BACK = ofSFCPermission("command.home.unlimited", false);
public static final Permission<PlayerEntity> COMMAND_ADDWL = ofSFCPermission("command.addwl", false);
public static final Permission<PlayerEntity> COMMAND_UNBLOCKSERVER = ofSFCPermission("command.unblockserver", false);
@@ -1,9 +1,14 @@
package io.ib67.sfcraft.message;
import io.ib67.sfcraft.message.feature.PingPlayerFeature;
import io.ib67.sfcraft.message.feature.SendLocationFeature;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
public class SFMessageDecorator extends SimpleMessageDecorator {
public SFMessageDecorator() {
registerDecorator(new SendLocationFeature());
registerDecorator(new PingPlayerFeature());
}
}
@@ -21,9 +21,21 @@ public class SimpleMessageDecorator implements MessageDecorator {
@Override
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
var targets = new ArrayList<Text>();
targets.add(message);
for (MessageDecorator decorator : decorators) {
message = decorator.decorate(sender, message);
var newRd = new ArrayList<Text>();
for (Text target : targets) {
var r = decorator.decorate(sender, target);
var copy = r.copy();
copy.getSiblings().clear();
newRd.add(copy);
newRd.addAll(r.getSiblings());
}
targets = newRd;
}
return message;
var result = Text.empty();
targets.forEach(result::append);
return result;
}
}
@@ -0,0 +1,67 @@
package io.ib67.sfcraft.message.feature;
import io.ib67.sfcraft.SFConsts;
import io.ib67.sfcraft.SFCraft;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.message.MessageDecorator;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.sound.SoundEvents;
import net.minecraft.text.Text;
import net.minecraft.util.Colors;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.MatchResult;
import java.util.regex.Pattern;
public class PingPlayerFeature implements MessageDecorator {
private static final Pattern PING = Pattern.compile("(@[\\w]+)?");
@Override
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
if (sender != null) {
if (!SFConsts.USE_AT.hasPermission(sender)) {
return message;
}
}
var text = message.getLiteralString();
if (text == null) return message;
var match = PING.matcher(text);
if (!match.find()) return message;
var foundPlayers = new HashSet<PlayerEntity>();
var names = List.of(SFCraft.getInstance().getServer().getPlayerNames());
var r = Text.literal(match.replaceAll(it -> this.matchPlayer(it, names, foundPlayers)));
for (PlayerEntity foundPlayer : foundPlayers) {
if (sender != null) {
foundPlayer.sendMessage(Text.literal(sender.getName().getLiteralString() + " 正在叫你。").withColor(Colors.LIGHT_GRAY));
}
foundPlayer.playSoundToPlayer(
SoundEvent.of(SoundEvents.ENTITY_ITEM_PICKUP.getId()),
SoundCategory.PLAYERS,
0.8f,
0.5f
);
}
return r;
}
private String matchPlayer(MatchResult match, List<String> playerNames, Set<PlayerEntity> foundPlayers) {
for (int i = 0; i < match.groupCount(); i++) {
var r = match.group();
if (r.isEmpty()) continue;
final var d = r.substring(1);
return playerNames.stream()
.filter(it -> it.toLowerCase().startsWith(d))
.peek(it -> foundPlayers.add(SFCraft.getInstance().getServer().getPlayerManager().getPlayer(it)))
.findFirst()
.orElse(r);
}
return "";
}
}
@@ -0,0 +1,28 @@
package io.ib67.sfcraft.message.feature;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.text.Text;
import java.util.Locale;
import java.util.function.Function;
class ReplaceHelper {
public static Text replace(ServerPlayerEntity sender, Text message, String s, Function<ServerPlayerEntity, Text> generator) {
var text = message.getLiteralString();
if (text == null || text.isEmpty()) return message;
text = text.trim();
var result = Text.literal("");
var head = 0;
var lowercase = text.toLowerCase(Locale.ROOT);
var i = lowercase.indexOf(s);
while (i != -1) {
result.append(text.substring(0, i).trim());
result.append(generator.apply(sender));
head = i + s.length();
i = lowercase.indexOf(s, head + 1);
}
result.append(text.substring(head).trim());
return result;
}
}
@@ -1,6 +1,7 @@
package io.ib67.sfcraft.message.feature;
import io.ib67.sfcraft.Helper;
import io.ib67.sfcraft.SFConsts;
import net.minecraft.network.message.MessageDecorator;
import net.minecraft.registry.RegistryKey;
import net.minecraft.server.network.ServerPlayerEntity;
@@ -12,24 +13,12 @@ import org.jetbrains.annotations.Nullable;
public class SendLocationFeature implements MessageDecorator {
@Override
public Text decorate(@Nullable ServerPlayerEntity sender, Text message) {
var text = message.getLiteralString().trim();
if (text == null) {
return message;
if (sender != null) {
if (!SFConsts.USE_BROADCAST_LOCATION.hasPermission(sender)) {
return message;
}
}
if (text.trim().equals(".xyz")) {
return generateLocText(sender);
}
var result = Text.literal("");
var head = 0;
var i = text.indexOf(".xyz");
while (i != -1) {
result.append(text.substring(0, i).trim());
result.append(generateLocText(sender));
head = i + 4;
i = text.indexOf(".xyz", head + 1);
}
result.append(text.substring(head).trim());
return result;
return ReplaceHelper.replace(sender, message, ".xyz", SendLocationFeature::generateLocText);
}
private static Text generateLocText(ServerPlayerEntity sender) {