Fix viewer engine bug
This commit is contained in:
parent
519dd91426
commit
d710683c9e
13 changed files with 361 additions and 26 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -8,6 +8,8 @@ test-plugin/run
|
|||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
discord-bot/.env
|
||||
|
||||
/website
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
|
|
21
api/src/main/java/me/tofaa/entitylib/meta/MultiMeta.java
Normal file
21
api/src/main/java/me/tofaa/entitylib/meta/MultiMeta.java
Normal file
|
@ -0,0 +1,21 @@
|
|||
package me.tofaa.entitylib.meta;
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.entity.data.EntityData;
|
||||
import me.tofaa.entitylib.utils.ConcurrentWeakIdentityHashMap;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
final class MultiMeta {
|
||||
|
||||
private final WeakReference<EntityMeta> parent;
|
||||
private final Map<UUID, List<EntityData>> replacements;
|
||||
|
||||
MultiMeta(EntityMeta parent) {
|
||||
this.parent = new WeakReference<>(parent);
|
||||
this.replacements = new ConcurrentWeakIdentityHashMap<>();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package me.tofaa.entitylib.ve;
|
||||
|
||||
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import me.tofaa.entitylib.EntityLib;
|
||||
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
@ -49,6 +50,11 @@ public class ViewerEngine {
|
|||
tracked.clear();
|
||||
}
|
||||
|
||||
public boolean canSpawnFor(User user, WrapperEntity entity) {
|
||||
if (entity.getViewerRules().stream().anyMatch(rule -> rule.shouldSee(user))) return true;
|
||||
return globalRules.stream().anyMatch(rule -> rule.shouldSee(user));
|
||||
}
|
||||
|
||||
public @UnmodifiableView Collection<WrapperEntity> getTracked() {
|
||||
return Collections.unmodifiableCollection(tracked);
|
||||
}
|
||||
|
|
|
@ -4,10 +4,14 @@ import com.github.retrooper.packetevents.event.PacketListenerAbstract;
|
|||
import com.github.retrooper.packetevents.event.PacketSendEvent;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketType;
|
||||
import com.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerUnloadChunk;
|
||||
import com.github.retrooper.packetevents.protocol.player.User;
|
||||
import com.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||
import com.github.retrooper.packetevents.wrapper.play.server.*;
|
||||
import me.tofaa.entitylib.EntityLib;
|
||||
import me.tofaa.entitylib.utils.Check;
|
||||
import me.tofaa.entitylib.wrapper.WrapperEntity;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
final class ViewerEngineListener extends PacketListenerAbstract {
|
||||
|
||||
|
@ -18,43 +22,82 @@ final class ViewerEngineListener extends PacketListenerAbstract {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onPacketSend(PacketSendEvent event) {
|
||||
PacketTypeCommon type = event.getPacketType();
|
||||
if (type == PacketType.Play.Server.UNLOAD_CHUNK) {
|
||||
PacketSendEvent copy = event.clone();
|
||||
engine.getExecutor().execute(() -> {
|
||||
public void onPacketSend(PacketSendEvent e) {
|
||||
PacketTypeCommon type = e.getPacketType();
|
||||
if (type == PacketType.Play.Server.SPAWN_PLAYER) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerSpawnPlayer packet = new WrapperPlayServerSpawnPlayer(event);
|
||||
genericSpawnCheck(packet.getEntityId(), event.getUser());
|
||||
});
|
||||
}
|
||||
else if (type == PacketType.Play.Server.SPAWN_WEATHER_ENTITY) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerSpawnWeatherEntity packet = new WrapperPlayServerSpawnWeatherEntity(event);
|
||||
genericSpawnCheck(packet.getEntityId(), event.getUser());
|
||||
});
|
||||
}
|
||||
else if (type == PacketType.Play.Server.SPAWN_EXPERIENCE_ORB) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerSpawnExperienceOrb packet = new WrapperPlayServerSpawnExperienceOrb(event);
|
||||
genericSpawnCheck(packet.getEntityId(), event.getUser());
|
||||
});
|
||||
}
|
||||
else if (type == PacketType.Play.Server.SPAWN_LIVING_ENTITY) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerSpawnLivingEntity packet = new WrapperPlayServerSpawnLivingEntity(event);
|
||||
genericSpawnCheck(packet.getEntityId(), event.getUser());
|
||||
});
|
||||
}
|
||||
else if (type == PacketType.Play.Server.SPAWN_ENTITY) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerSpawnEntity packet = new WrapperPlayServerSpawnEntity(event);
|
||||
genericSpawnCheck(packet.getEntityId(), event.getUser());
|
||||
});
|
||||
}
|
||||
else if (type == PacketType.Play.Server.UNLOAD_CHUNK) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerUnloadChunk packet = new WrapperPlayServerUnloadChunk(event);
|
||||
int chunkX = packet.getChunkX();
|
||||
int chunkZ = packet.getChunkZ();
|
||||
engine.getTracked0().forEach(entity -> {
|
||||
if (!Check.inChunk(entity.getLocation(), chunkX, chunkZ)) return;
|
||||
entity.removeViewer(event.getUser());
|
||||
entity.removeViewer(e.getUser());
|
||||
});
|
||||
copy.cleanUp();
|
||||
});
|
||||
}
|
||||
if (type == PacketType.Play.Server.CHUNK_DATA) {
|
||||
PacketSendEvent copy = event.clone();
|
||||
engine.getExecutor().execute(() -> {
|
||||
WrapperPlayServerUnloadChunk packet = new WrapperPlayServerUnloadChunk(event);
|
||||
int chunkX = packet.getChunkX();
|
||||
int chunkZ = packet.getChunkZ();
|
||||
else if (type == PacketType.Play.Server.CHUNK_DATA) {
|
||||
exec(e, (event) -> {
|
||||
WrapperPlayServerChunkData packet = new WrapperPlayServerChunkData(event);
|
||||
int chunkX = packet.getColumn().getX();
|
||||
int chunkZ = packet.getColumn().getZ();
|
||||
engine.getTracked0().forEach(entity -> {
|
||||
if (!Check.inChunk(entity.getLocation(), chunkX, chunkZ)) return;
|
||||
if (entity.hasViewer(event.getUser())) return;
|
||||
AtomicBoolean pass = new AtomicBoolean(false);
|
||||
entity.getViewerRules().forEach(rule -> {
|
||||
pass.set(rule.shouldSee(event.getUser()));
|
||||
});
|
||||
engine.getViewerRules().forEach(rule -> {
|
||||
pass.set(rule.shouldSee(event.getUser()));
|
||||
});
|
||||
if (!pass.get()) return;
|
||||
entity.addViewer(event.getUser());
|
||||
if (engine.canSpawnFor(event.getUser(), entity)) {
|
||||
entity.addViewer(event.getUser());
|
||||
}
|
||||
});
|
||||
copy.cleanUp();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void genericSpawnCheck(int entityId, User user) {
|
||||
WrapperEntity entity = EntityLib.getApi().getEntity(entityId);
|
||||
if (entity == null) return;
|
||||
if (engine.canSpawnFor(user, entity)) {
|
||||
entity.addViewer(user);
|
||||
}
|
||||
}
|
||||
|
||||
private <T extends PacketWrapper<T>> void exec(
|
||||
PacketSendEvent event,
|
||||
Consumer<PacketSendEvent> runnable
|
||||
) {
|
||||
PacketSendEvent copy = event.clone();
|
||||
engine.getExecutor().execute(() -> {
|
||||
runnable.accept(copy);
|
||||
copy.cleanUp();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import java.io.ByteArrayOutputStream
|
||||
|
||||
val fullVersion = "2.4.10"
|
||||
val fullVersion = "2.4.11"
|
||||
val snapshot = true
|
||||
|
||||
group = "me.tofaa.entitylib"
|
||||
|
|
16
discord-bot/build.gradle.kts
Normal file
16
discord-bot/build.gradle.kts
Normal file
|
@ -0,0 +1,16 @@
|
|||
plugins {
|
||||
entitylib.`shadow-conventions`
|
||||
entitylib.`library-conventions`
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(21)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation("net.dv8tion:JDA:5.2.0")
|
||||
implementation("ch.qos.logback:logback-classic:1.4.12")
|
||||
|
||||
implementation("com.google.auto.service:auto-service:1.1.1")
|
||||
annotationProcessor("com.google.auto.service:auto-service:1.1.1")
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package me.tofaa.entitylib.discord;
|
||||
|
||||
import me.tofaa.entitylib.discord.commands.Command;
|
||||
import net.dv8tion.jda.api.JDA;
|
||||
import net.dv8tion.jda.api.JDABuilder;
|
||||
import net.dv8tion.jda.api.hooks.EventListener;
|
||||
import net.dv8tion.jda.api.interactions.commands.DefaultMemberPermissions;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.CommandData;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.Commands;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.SlashCommandData;
|
||||
import net.dv8tion.jda.api.requests.GatewayIntent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
public final class DiscordBot {
|
||||
|
||||
public static Logger LOGGER = LoggerFactory.getLogger(DiscordBot.class);
|
||||
|
||||
private static DiscordBot instance;
|
||||
public static DiscordBot instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final JDA discord;
|
||||
private final Set<Command> commands;
|
||||
|
||||
DiscordBot(String[] args) {
|
||||
instance = this;
|
||||
if (args.length == 0) throw new RuntimeException("No token specified, use --token=token args");
|
||||
String token = args[0].replaceFirst("--token=", "");
|
||||
discord = JDABuilder.create(token, GatewayIntent.getIntents(GatewayIntent.ALL_INTENTS)).build();
|
||||
|
||||
this.commands = ConcurrentHashMap.newKeySet();
|
||||
}
|
||||
|
||||
|
||||
private void loadCommands() {
|
||||
ServiceLoader<Command> commands = ServiceLoader.load(Command.class);
|
||||
List<CommandData> data = new ArrayList<>();
|
||||
for (Command command : commands) {
|
||||
SlashCommandData cmd = Commands.slash(command.name(), command.description());
|
||||
if (command.hasPermission()) {
|
||||
cmd.setDefaultPermissions(DefaultMemberPermissions.enabledFor(command.permission()));
|
||||
}
|
||||
command.options().forEach(option -> {
|
||||
cmd.addOption(option.getType(), option.getName(), option.getDescription(), option.isRequired(), option.isAutoComplete());
|
||||
});
|
||||
data.add(cmd);
|
||||
LOGGER.info("Loaded command {}", command.name());
|
||||
this.commands.add(command);
|
||||
}
|
||||
discord.updateCommands().addCommands(data).queue();
|
||||
}
|
||||
|
||||
private void loadEvents() {
|
||||
ServiceLoader<EventListener> loader = ServiceLoader.load(EventListener.class);
|
||||
for (EventListener listener : loader) {
|
||||
discord.getEventManager().register(listener);
|
||||
LOGGER.info("Loaded event listener {}", listener.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
private void start() throws InterruptedException {
|
||||
discord.awaitReady();
|
||||
loadCommands();
|
||||
loadEvents();
|
||||
}
|
||||
|
||||
|
||||
public Set<Command> commands() {
|
||||
return commands;
|
||||
}
|
||||
|
||||
public JDA discord() {
|
||||
return discord;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws InterruptedException {
|
||||
DiscordBot bot = new DiscordBot(args);
|
||||
bot.start();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package me.tofaa.entitylib.discord.commands;
|
||||
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.interactions.Interaction;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class Command {
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
private final Collection<OptionData> options;
|
||||
private final Permission permission;
|
||||
|
||||
public Command(String name, String description, Collection<OptionData> options, @Nullable Permission permission) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.options = options;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
public Permission permission() {
|
||||
return permission;
|
||||
}
|
||||
|
||||
public boolean hasPermission() {
|
||||
return permission != null;
|
||||
}
|
||||
|
||||
public String name() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String description() {
|
||||
return description;
|
||||
}
|
||||
|
||||
public Collection<OptionData> options() {
|
||||
return options;
|
||||
}
|
||||
|
||||
public abstract void handle(SlashCommandInteraction interaction);
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package me.tofaa.entitylib.discord.commands.impl;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import me.tofaa.entitylib.discord.commands.Command;
|
||||
import net.dv8tion.jda.api.interactions.Interaction;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class PingCommand extends Command {
|
||||
|
||||
public PingCommand() {
|
||||
super("ping", "Ping command", Collections.emptyList(), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(SlashCommandInteraction interaction) {
|
||||
interaction.reply("Pong").queue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package me.tofaa.entitylib.discord.commands.impl;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import me.tofaa.entitylib.discord.commands.Command;
|
||||
import net.dv8tion.jda.api.Permission;
|
||||
import net.dv8tion.jda.api.interactions.commands.OptionType;
|
||||
import net.dv8tion.jda.api.interactions.commands.SlashCommandInteraction;
|
||||
import net.dv8tion.jda.api.interactions.commands.build.OptionData;
|
||||
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(Command.class)
|
||||
public class SendMessageCommand extends Command {
|
||||
|
||||
public SendMessageCommand() {
|
||||
super(
|
||||
"sendmessage",
|
||||
"Send a message in a channel",
|
||||
Arrays.asList(
|
||||
new OptionData(OptionType.STRING, "message", "The message", true),
|
||||
new OptionData(OptionType.STRING, "ping", "The type of ping to do", true)
|
||||
.addChoice("Everyone", "everyone")
|
||||
.addChoice("EntityLib", "elib")
|
||||
),
|
||||
Permission.ADMINISTRATOR
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(SlashCommandInteraction interaction) {
|
||||
String msg = interaction.getOption("message").getAsString();
|
||||
MessageCreateBuilder builder =new MessageCreateBuilder();
|
||||
builder.setContent(msg);
|
||||
|
||||
String pingType = interaction.getOption("ping").getAsString().toLowerCase();
|
||||
switch (pingType) {
|
||||
case "elib": {
|
||||
builder =builder.mentionRoles(1304607456650985502L);
|
||||
break;
|
||||
}
|
||||
case "everyone": {
|
||||
builder =builder.mentionRoles(1197504277787201616L);
|
||||
break;
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
interaction.getChannel().sendMessage(builder.build()).queue();;
|
||||
interaction.reply("Sent").setEphemeral(true).queue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package me.tofaa.entitylib.discord.listeners;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import me.tofaa.entitylib.discord.DiscordBot;
|
||||
import me.tofaa.entitylib.discord.commands.Command;
|
||||
import net.dv8tion.jda.api.events.GenericEvent;
|
||||
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
|
||||
import net.dv8tion.jda.api.hooks.EventListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@AutoService(EventListener.class)
|
||||
public class CommandListener implements EventListener {
|
||||
|
||||
@Override
|
||||
public void onEvent(@NotNull GenericEvent genericEvent) {
|
||||
if (!(genericEvent instanceof SlashCommandInteractionEvent)) {
|
||||
return;
|
||||
}
|
||||
SlashCommandInteractionEvent event = (SlashCommandInteractionEvent) genericEvent;
|
||||
Command command = DiscordBot.instance().commands().stream()
|
||||
.filter(f -> f.name().equalsIgnoreCase(event.getName()))
|
||||
.findAny().orElse(null);
|
||||
if (command == null) {
|
||||
return;
|
||||
}
|
||||
command.handle(event.getInteraction());
|
||||
}
|
||||
}
|
12
discord-bot/src/main/resources/logback.xml
Normal file
12
discord-bot/src/main/resources/logback.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<encoder>
|
||||
<pattern>%d{HH:mm:ss.SSS} %boldCyan(%-34.-34thread) %boldGreen(%-15.-15logger{0}) %highlight(%-6level) %msg%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="STDOUT" />
|
||||
</root>
|
||||
</configuration>
|
|
@ -35,6 +35,7 @@ include(":platforms:velocity")
|
|||
include(":platforms:standalone")
|
||||
|
||||
if (!System.getenv("JITPACK").toBoolean()) {
|
||||
include("discord-bot")
|
||||
include(":code-gen")
|
||||
include(":test-plugin")
|
||||
include(":block-bench-addon")
|
||||
|
|
Loading…
Reference in a new issue