LP injecting, fake player fixes
#96 LuckPerms Added support for excluding plugins from certain events from code Also might have fixed some message timeouts by relocating netty
This commit is contained in:
parent
2bdba0af22
commit
bf538d9bd0
8 changed files with 1114 additions and 787 deletions
422
pom.xml
422
pom.xml
|
@ -1,45 +1,45 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>com.github.TBMCPlugins</groupId>
|
||||
<artifactId>DiscordPlugin</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
<groupId>com.github.TBMCPlugins</groupId>
|
||||
<artifactId>DiscordPlugin</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>DiscordPlugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<name>DiscordPlugin</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
|
||||
<build>
|
||||
<!-- <sourceDirectory>target/generated-sources/delombok</sourceDirectory>
|
||||
<testSourceDirectory>target/generated-test-sources/delombok</testSourceDirectory> -->
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>*.properties</include>
|
||||
<include>*.yml</include>
|
||||
<include>*.csv</include>
|
||||
<include>*.txt</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<finalName>DiscordPlugin</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<build>
|
||||
<!-- <sourceDirectory>target/generated-sources/delombok</sourceDirectory>
|
||||
<testSourceDirectory>target/generated-test-sources/delombok</testSourceDirectory> -->
|
||||
<sourceDirectory>src/main/java</sourceDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src</directory>
|
||||
<excludes>
|
||||
<exclude>**/*.java</exclude>
|
||||
</excludes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<includes>
|
||||
<include>*.properties</include>
|
||||
<include>*.yml</include>
|
||||
<include>*.csv</include>
|
||||
<include>*.txt</include>
|
||||
</includes>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<finalName>DiscordPlugin</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.6.2</version>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<!-- <compilerArgs>
|
||||
<arg>-processor</arg>
|
||||
<arg>buttondevteam.buttonproc.ButtonProcessor, lombok.core.AnnotationProcessor</arg>
|
||||
|
@ -48,104 +48,112 @@
|
|||
<annotationProcessor>lombok.launch.AnnotationProcessorHider$AnnotationProcessor</annotationProcessor>
|
||||
<annotationProcessor>buttondevteam.buttonproc.ButtonProcessor</annotationProcessor>
|
||||
</annotationProcessors> -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.spigotmc:spigot-api</exclude>
|
||||
<exclude>com.github.TBMCPlugins.ButtonCore:ButtonCore</exclude>
|
||||
<exclude>net.ess3:Essentials</exclude>
|
||||
</excludes> <!-- http://stackoverflow.com/questions/28458058/maven-shade-plugin-exclude-a-dependency-and-all-its-transitive-dependencies -->
|
||||
</artifactSet>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- <plugin> <groupId>org.projectlombok</groupId> <artifactId>lombok-maven-plugin</artifactId>
|
||||
<version>1.16.16.0</version> <executions> <execution> <id>delombok</id> <phase>generate-sources</phase>
|
||||
<goals> <goal>delombok</goal> </goals> <configuration> <addOutputDirectory>false</addOutputDirectory>
|
||||
<sourceDirectory>src/main/java</sourceDirectory> <verbose>true</verbose>
|
||||
</configuration> </execution> <execution> <id>test-delombok</id> <phase>generate-test-sources</phase>
|
||||
<goals> <goal>testDelombok</goal> </goals> <configuration> <addOutputDirectory>false</addOutputDirectory>
|
||||
<sourceDirectory>src/test/java</sourceDirectory> </configuration> </execution>
|
||||
</executions> </plugin> -->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-shade-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false
|
||||
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>shade</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactSet>
|
||||
<excludes>
|
||||
<exclude>org.spigotmc:spigot-api</exclude>
|
||||
<exclude>com.github.TBMCPlugins.ButtonCore:ButtonCore</exclude>
|
||||
<exclude>net.ess3:Essentials</exclude>
|
||||
</excludes> <!-- http://stackoverflow.com/questions/28458058/maven-shade-plugin-exclude-a-dependency-and-all-its-transitive-dependencies -->
|
||||
</artifactSet>
|
||||
<minimizeJar>true</minimizeJar>
|
||||
<relocations>
|
||||
<relocation>
|
||||
<pattern>io.netty</pattern>
|
||||
<shadedPattern>buttondevteam.discordplugin.io.netty</shadedPattern>
|
||||
<excludes>
|
||||
</excludes>
|
||||
</relocation>
|
||||
</relocations>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>target</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>resources</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<!-- <plugin> <groupId>org.projectlombok</groupId> <artifactId>lombok-maven-plugin</artifactId>
|
||||
<version>1.16.16.0</version> <executions> <execution> <id>delombok</id> <phase>generate-sources</phase>
|
||||
<goals> <goal>delombok</goal> </goals> <configuration> <addOutputDirectory>false</addOutputDirectory>
|
||||
<sourceDirectory>src/main/java</sourceDirectory> <verbose>true</verbose>
|
||||
</configuration> </execution> <execution> <id>test-delombok</id> <phase>generate-test-sources</phase>
|
||||
<goals> <goal>testDelombok</goal> </goals> <configuration> <addOutputDirectory>false</addOutputDirectory>
|
||||
<sourceDirectory>src/test/java</sourceDirectory> </configuration> </execution>
|
||||
</executions> </plugin> -->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.4.2</version>
|
||||
<configuration>
|
||||
<useSystemClassLoader>false
|
||||
</useSystemClassLoader> <!-- https://stackoverflow.com/a/53012553/2703239 -->
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<branch>
|
||||
master
|
||||
</branch> <!-- Should be master if building ButtonCore locally - the CI will overwrite it (see below) -->
|
||||
</properties>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository> <!-- This repo fixes issues with transitive dependencies -->
|
||||
<id>jcenter</id>
|
||||
<url>http://jcenter.bintray.com</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>spigot-repo</id>
|
||||
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
|
||||
</repository>
|
||||
<repository> <!-- This repo fixes issues with transitive dependencies -->
|
||||
<id>jcenter</id>
|
||||
<url>http://jcenter.bintray.com</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>jitpack.io</id>
|
||||
<url>https://jitpack.io</url>
|
||||
</repository>
|
||||
<!-- <repository>
|
||||
<id>vault-repo</id>
|
||||
<url>http://nexus.hc.to/content/repositories/pub_releases</url>
|
||||
</repository> -->
|
||||
<repository>
|
||||
<id>Essentials</id>
|
||||
<url>http://repo.ess3.net/content/repositories/essrel/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>projectlombok.org</id>
|
||||
<url>http://projectlombok.org/mavenrepo</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>Essentials</id>
|
||||
<url>http://repo.ess3.net/content/repositories/essrel/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>projectlombok.org</id>
|
||||
<url>http://projectlombok.org/mavenrepo</url>
|
||||
</repository>
|
||||
<!-- <repository>
|
||||
<id>pex-repo</id>
|
||||
<url>http://pex-repo.aoeu.xyz</url>
|
||||
|
@ -154,64 +162,64 @@
|
|||
<id>Reactor-Tools</id>
|
||||
<url>https://repo.spring.io/milestone</url>
|
||||
</repository> -->
|
||||
</repositories>
|
||||
</repositories>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.discord4j/Discord4J -->
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.discord4j/Discord4J -->
|
||||
<dependency>
|
||||
<groupId>com.discord4j</groupId>
|
||||
<artifactId>discord4j-core</artifactId>
|
||||
<version>3.0.5</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||
<artifactId>ButtonCore</artifactId>
|
||||
<version>${branch}-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.milkbowl</groupId> <!-- net.milkbowl.vault -->
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>master-SNAPSHOT</version> <!-- 1.6 -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>Essentials</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-jdk14</artifactId>
|
||||
<version>1.7.21</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||
<artifactId>ButtonCore</artifactId>
|
||||
<version>${branch}-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.16</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.milkbowl</groupId> <!-- net.milkbowl.vault -->
|
||||
<artifactId>VaultAPI</artifactId>
|
||||
<version>master-SNAPSHOT</version> <!-- 1.6 -->
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.ess3</groupId>
|
||||
<artifactId>Essentials</artifactId>
|
||||
<version>2.13.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.16</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>ru.tehkode</groupId>
|
||||
<artifactId>PermissionsEx</artifactId>
|
||||
|
@ -224,38 +232,44 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency> -->
|
||||
<!-- https://mvnrepository.com/artifact/org.objenesis/objenesis -->
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>2.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
<artifactId>emoji-java</artifactId>
|
||||
<version>4.0.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.objenesis/objenesis -->
|
||||
<dependency>
|
||||
<groupId>org.objenesis</groupId>
|
||||
<artifactId>objenesis</artifactId>
|
||||
<version>2.6</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.vdurmont</groupId>
|
||||
<artifactId>emoji-java</artifactId>
|
||||
<version>4.0.0</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/io.projectreactor.tools/blockhound -->
|
||||
<!-- <dependency>
|
||||
<groupId>io.projectreactor.tools</groupId>
|
||||
<artifactId>blockhound</artifactId>
|
||||
<version>1.0.0.M3</version>
|
||||
</dependency> -->
|
||||
</dependencies>
|
||||
<dependency>
|
||||
<groupId>com.github.lucko</groupId>
|
||||
<artifactId>LuckPerms</artifactId>
|
||||
<version>v4.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ci</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env.TRAVIS_BRANCH</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<!-- Override only if necessary -->
|
||||
<branch>${env.TRAVIS_BRANCH}</branch>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>ci</id>
|
||||
<activation>
|
||||
<property>
|
||||
<name>env.TRAVIS_BRANCH</name>
|
||||
</property>
|
||||
</activation>
|
||||
<properties>
|
||||
<!-- Override only if necessary -->
|
||||
<branch>${env.TRAVIS_BRANCH}</branch>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
@ -6,15 +6,19 @@ import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
|||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class DiscordConnectedPlayer extends DiscordFakePlayer implements IMCPlayer<DiscordConnectedPlayer> {
|
||||
private static int nextEntityId = 10000;
|
||||
private @Getter VanillaCommandListener<DiscordConnectedPlayer> vanillaCmdListener;
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean loggedIn = false;
|
||||
|
||||
public DiscordConnectedPlayer(User user, MessageChannel channel, UUID uuid, String mcname, MinecraftChatModule module) {
|
||||
super(user, channel, nextEntityId++, uuid, mcname ,module);
|
||||
super(user, channel, nextEntityId++, uuid, mcname, module);
|
||||
vanillaCmdListener = new VanillaCommandListener<>(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,12 @@ package buttondevteam.discordplugin.mcchat;
|
|||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||
import buttondevteam.discordplugin.DiscordPlayer;
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.lib.player.TBMCPlayer;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.PrivateChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
@ -32,11 +29,14 @@ public class MCChatPrivate {
|
|||
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName(), mcm);
|
||||
MCChatUtils.addSender(MCChatUtils.ConnectedSenders, user, sender);
|
||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||
MCListener.callLoginEvents(sender);
|
||||
MCChatUtils.callLoginEvents(sender);
|
||||
} else {
|
||||
val sender = MCChatUtils.removeSender(MCChatUtils.ConnectedSenders, channel.getId(), user);
|
||||
if (p == null)// Player is offline - If the player is online, that takes precedence
|
||||
callEventSync(new PlayerQuitEvent(sender, ""));
|
||||
assert sender != null;
|
||||
if (p == null // Player is offline - If the player is online, that takes precedence
|
||||
&& sender.isLoggedIn()) //Don't call the quit event if login failed
|
||||
MCChatUtils.callLogoutEvent(sender, true);
|
||||
sender.setLoggedIn(false);
|
||||
}
|
||||
} // ---- PermissionsEx warning is normal on logout ----
|
||||
if (!start)
|
||||
|
@ -60,11 +60,8 @@ public class MCChatPrivate {
|
|||
for (val entry : MCChatUtils.ConnectedSenders.entrySet())
|
||||
for (val valueEntry : entry.getValue().entrySet())
|
||||
if (MCChatUtils.getSender(MCChatUtils.OnlineSenders, valueEntry.getKey(), valueEntry.getValue().getUser()) == null) //If the player is online then the fake player was already logged out
|
||||
MCChatUtils.callEventExcludingSome(new PlayerQuitEvent(valueEntry.getValue(), "")); //This is sync
|
||||
MCChatUtils.callLogoutEvent(valueEntry.getValue(), false); //This is sync
|
||||
MCChatUtils.ConnectedSenders.clear();
|
||||
}
|
||||
|
||||
private static void callEventSync(Event event) {
|
||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> MCChatUtils.callEventExcludingSome(event));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import buttondevteam.discordplugin.*;
|
|||
import buttondevteam.discordplugin.broadcaster.GeneralEventBroadcasterModule;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import com.google.common.collect.Sets;
|
||||
import discord4j.core.object.entity.*;
|
||||
import discord4j.core.object.util.Snowflake;
|
||||
import io.netty.util.collection.LongObjectHashMap;
|
||||
|
@ -15,14 +16,20 @@ import org.bukkit.Bukkit;
|
|||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
|
||||
import org.bukkit.event.player.PlayerJoinEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.AuthorNagException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.net.InetAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
@ -43,6 +50,7 @@ public class MCChatUtils {
|
|||
static @Nullable LastMsgData lastmsgdata;
|
||||
static LongObjectHashMap<Message> lastmsgfromd = new LongObjectHashMap<>(); // Last message sent by a Discord user, used for clearing checkmarks
|
||||
private static MinecraftChatModule module;
|
||||
private static HashMap<Class<? extends Event>, HashSet<String>> staticExcludedPlugins = new HashMap<>();
|
||||
|
||||
public static void updatePlayerList() {
|
||||
if (notEnabled()) return;
|
||||
|
@ -74,19 +82,19 @@ public class MCChatUtils {
|
|||
if (s.length < 3)
|
||||
return;
|
||||
s[0] = Bukkit.getOnlinePlayers().size() + " player" + (Bukkit.getOnlinePlayers().size() != 1 ? "s" : "")
|
||||
+ " online";
|
||||
+ " online";
|
||||
s[s.length - 1] = "Players: " + Bukkit.getOnlinePlayers().stream()
|
||||
.map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", "));
|
||||
.map(p -> DPUtils.sanitizeString(p.getDisplayName())).collect(Collectors.joining(", "));
|
||||
((TextChannel) lmd.channel).edit(tce -> tce.setTopic(String.join("\n----\n", s)).setReason("Player list update")).subscribe(); //Don't wait
|
||||
}
|
||||
|
||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
||||
User user, T sender) {
|
||||
User user, T sender) {
|
||||
return addSender(senders, user.getId().asString(), sender);
|
||||
}
|
||||
|
||||
public static <T extends DiscordSenderBase> T addSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
||||
String did, T sender) {
|
||||
String did, T sender) {
|
||||
var map = senders.get(did);
|
||||
if (map == null)
|
||||
map = new HashMap<>();
|
||||
|
@ -96,7 +104,7 @@ public class MCChatUtils {
|
|||
}
|
||||
|
||||
public static <T extends DiscordSenderBase> T getSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
||||
Snowflake channel, User user) {
|
||||
Snowflake channel, User user) {
|
||||
var map = senders.get(user.getId().asString());
|
||||
if (map != null)
|
||||
return map.get(channel);
|
||||
|
@ -104,7 +112,7 @@ public class MCChatUtils {
|
|||
}
|
||||
|
||||
public static <T extends DiscordSenderBase> T removeSender(HashMap<String, HashMap<Snowflake, T>> senders,
|
||||
Snowflake channel, User user) {
|
||||
Snowflake channel, User user) {
|
||||
var map = senders.get(user.getId().asString());
|
||||
if (map != null)
|
||||
return map.remove(channel);
|
||||
|
@ -195,11 +203,11 @@ public class MCChatUtils {
|
|||
static DiscordSenderBase getSender(Snowflake channel, final User author) {
|
||||
//noinspection OptionalGetWithoutIsPresent
|
||||
return Stream.<Supplier<Optional<DiscordSenderBase>>>of( // https://stackoverflow.com/a/28833677/2703239
|
||||
() -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
|
||||
() -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it
|
||||
() -> Optional.ofNullable(getSender(UnconnectedSenders, channel, author)), //
|
||||
() -> Optional.of(addSender(UnconnectedSenders, author,
|
||||
new DiscordSender(author, (MessageChannel) DiscordPlugin.dc.getChannelById(channel).block())))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
|
||||
() -> Optional.ofNullable(getSender(OnlineSenders, channel, author)), // Find first non-null
|
||||
() -> Optional.ofNullable(getSender(ConnectedSenders, channel, author)), // This doesn't support the public chat, but it'll always return null for it
|
||||
() -> Optional.ofNullable(getSender(UnconnectedSenders, channel, author)), //
|
||||
() -> Optional.of(addSender(UnconnectedSenders, author,
|
||||
new DiscordSender(author, (MessageChannel) DiscordPlugin.dc.getChannelById(channel).block())))).map(Supplier::get).filter(Optional::isPresent).map(Optional::get).findFirst().get();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -213,7 +221,7 @@ public class MCChatUtils {
|
|||
System.out.println("Reset last message");
|
||||
if (channel.getId().asLong() == module.chatChannel().get().asLong()) {
|
||||
(lastmsgdata == null ? lastmsgdata = new LastMsgData(module.chatChannelMono().block(), null)
|
||||
: lastmsgdata).message = null;
|
||||
: lastmsgdata).message = null;
|
||||
System.out.println("Reset done: public chat");
|
||||
return;
|
||||
} // Don't set the whole object to null, the player and channel information should be preserved
|
||||
|
@ -227,9 +235,23 @@ public class MCChatUtils {
|
|||
//If it gets here, it's sending a message to a non-chat channel
|
||||
}
|
||||
|
||||
public static void addStaticExcludedPlugin(Class<? extends Event> event, String plugin) {
|
||||
staticExcludedPlugins.compute(event, (e, hs) -> hs == null
|
||||
? Sets.newHashSet(plugin)
|
||||
: (hs.add(plugin) ? hs : hs));
|
||||
}
|
||||
|
||||
public static void callEventExcludingSome(Event event) {
|
||||
if (notEnabled()) return;
|
||||
callEventExcluding(event, false, module.excludedPlugins().get());
|
||||
val second = staticExcludedPlugins.get(event.getClass());
|
||||
String[] first = module.excludedPlugins().get();
|
||||
String[] both = second == null ? first
|
||||
: Arrays.copyOf(first, first.length + second.size());
|
||||
int i = first.length;
|
||||
if (second != null)
|
||||
for (String plugin : second)
|
||||
both[i++] = plugin;
|
||||
callEventExcluding(event, false, both);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -290,6 +312,50 @@ public class MCChatUtils {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call it from an async thread.
|
||||
*/
|
||||
public static void callLoginEvents(DiscordConnectedPlayer dcp) {
|
||||
Consumer<Supplier<String>> loginFail = kickMsg -> {
|
||||
dcp.sendMessage("Minecraft chat disabled, as the login failed: " + kickMsg.get());
|
||||
MCChatPrivate.privateMCChat(dcp.getChannel(), false, dcp.getUser(), dcp.getChromaUser());
|
||||
}; //Probably also happens if the user is banned or so
|
||||
val event = new AsyncPlayerPreLoginEvent(dcp.getName(), InetAddress.getLoopbackAddress(), dcp.getUniqueId());
|
||||
callEventExcludingSome(event);
|
||||
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED) {
|
||||
loginFail.accept(event::getKickMessage);
|
||||
return;
|
||||
}
|
||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> {
|
||||
val ev = new PlayerLoginEvent(dcp, "localhost", InetAddress.getLoopbackAddress());
|
||||
callEventExcludingSome(ev);
|
||||
if (ev.getResult() != PlayerLoginEvent.Result.ALLOWED) {
|
||||
loginFail.accept(ev::getKickMessage);
|
||||
return;
|
||||
}
|
||||
callEventExcludingSome(new PlayerJoinEvent(dcp, ""));
|
||||
dcp.setLoggedIn(true);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Only calls the events if the player is actually logged in
|
||||
*
|
||||
* @param dcp The player
|
||||
* @param needsSync Whether we're in an async thread
|
||||
*/
|
||||
public static void callLogoutEvent(DiscordConnectedPlayer dcp, boolean needsSync) {
|
||||
if (!dcp.isLoggedIn()) return;
|
||||
val event = new PlayerQuitEvent(dcp, "");
|
||||
if (needsSync) callEventSync(event);
|
||||
else callEventExcludingSome(event);
|
||||
dcp.setLoggedIn(false);
|
||||
}
|
||||
|
||||
static void callEventSync(Event event) {
|
||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> callEventExcludingSome(event));
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public static class LastMsgData {
|
||||
public Message message;
|
||||
|
|
|
@ -18,12 +18,12 @@ import org.bukkit.event.EventHandler;
|
|||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.entity.PlayerDeathEvent;
|
||||
import org.bukkit.event.player.*;
|
||||
import org.bukkit.event.player.PlayerKickEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerLoginEvent.Result;
|
||||
import org.bukkit.event.server.BroadcastMessageEvent;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.util.Objects;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
|
@ -38,7 +38,7 @@ class MCListener implements Listener {
|
|||
return;
|
||||
MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream()) //Only private mcchat should be in ConnectedSenders
|
||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||
.ifPresent(dcp -> MCChatUtils.callEventExcludingSome(new PlayerQuitEvent(dcp, "")));
|
||||
.ifPresent(dcp -> MCChatUtils.callLogoutEvent(dcp, false));
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
|
@ -70,30 +70,13 @@ class MCListener implements Listener {
|
|||
Bukkit.getScheduler().runTaskAsynchronously(DiscordPlugin.plugin,
|
||||
() -> MCChatUtils.ConnectedSenders.values().stream().flatMap(v -> v.values().stream())
|
||||
.filter(s -> s.getUniqueId().equals(e.getPlayer().getUniqueId())).findAny()
|
||||
.ifPresent(MCListener::callLoginEvents));
|
||||
.ifPresent(MCChatUtils::callLoginEvents));
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin,
|
||||
ChromaBot.getInstance()::updatePlayerList, 5);
|
||||
final String message = e.GetPlayer().PlayerName().get() + " left the game";
|
||||
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call it from an async thread.
|
||||
*/
|
||||
public static void callLoginEvents(DiscordConnectedPlayer dcp) {
|
||||
val event = new AsyncPlayerPreLoginEvent(dcp.getName(), InetAddress.getLoopbackAddress(), dcp.getUniqueId());
|
||||
MCChatUtils.callEventExcludingSome(event);
|
||||
if (event.getLoginResult() != AsyncPlayerPreLoginEvent.Result.ALLOWED)
|
||||
return;
|
||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () -> {
|
||||
val ev = new PlayerLoginEvent(dcp, "localhost", InetAddress.getLoopbackAddress());
|
||||
MCChatUtils.callEventExcludingSome(ev);
|
||||
if (ev.getResult() != Result.ALLOWED)
|
||||
return;
|
||||
MCChatUtils.callEventExcludingSome(new PlayerJoinEvent(dcp, ""));
|
||||
});
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.HIGHEST)
|
||||
public void onPlayerKick(PlayerKickEvent e) {
|
||||
/*if (!DiscordPlugin.hooked && !e.getReason().equals("The server is restarting")
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package buttondevteam.discordplugin.mcchat;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.core.component.channel.Channel;
|
||||
import buttondevteam.discordplugin.DPUtils;
|
||||
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.discordplugin.playerfaker.perm.LPInjector;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.TBMCSystemChatEvent;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
|
@ -106,6 +108,12 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
new LPInjector(MainPlugin.Instance);
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Failed to init LuckPerms injector", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,240 @@
|
|||
package buttondevteam.discordplugin.playerfaker.perm;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.discordplugin.mcchat.MCChatUtils;
|
||||
import buttondevteam.discordplugin.playerfaker.DiscordFakePlayer;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitBootstrap;
|
||||
import me.lucko.luckperms.bukkit.LPBukkitPlugin;
|
||||
import me.lucko.luckperms.bukkit.inject.dummy.DummyPermissibleBase;
|
||||
import me.lucko.luckperms.bukkit.inject.permissible.LPPermissible;
|
||||
import me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener;
|
||||
import me.lucko.luckperms.common.config.ConfigKeys;
|
||||
import me.lucko.luckperms.common.locale.message.Message;
|
||||
import me.lucko.luckperms.common.model.User;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerLoginEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.PermissionAttachment;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public final class LPInjector implements Listener { //Disable login event for LuckPerms
|
||||
private LPBukkitPlugin plugin;
|
||||
private BukkitConnectionListener connectionListener;
|
||||
private Set<UUID> deniedLogin;
|
||||
private Field detectedCraftBukkitOfflineMode;
|
||||
private Method printCraftBukkitOfflineModeError;
|
||||
private Field PERMISSIBLE_BASE_ATTACHMENTS_FIELD;
|
||||
private Method convertAndAddAttachments;
|
||||
private Method getActive;
|
||||
private Method setOldPermissible;
|
||||
private Method getOldPermissible;
|
||||
|
||||
public LPInjector(MainPlugin mp) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException {
|
||||
LPBukkitBootstrap bs = (LPBukkitBootstrap) Bukkit.getPluginManager().getPlugin("LuckPerms");
|
||||
Field field = LPBukkitBootstrap.class.getDeclaredField("plugin");
|
||||
field.setAccessible(true);
|
||||
plugin = (LPBukkitPlugin) field.get(bs);
|
||||
MCChatUtils.addStaticExcludedPlugin(PlayerLoginEvent.class, "LuckPerms");
|
||||
MCChatUtils.addStaticExcludedPlugin(PlayerQuitEvent.class, "LuckPerms");
|
||||
|
||||
field = LPBukkitPlugin.class.getDeclaredField("connectionListener");
|
||||
field.setAccessible(true);
|
||||
connectionListener = (BukkitConnectionListener) field.get(plugin);
|
||||
field = connectionListener.getClass().getDeclaredField("deniedLogin");
|
||||
field.setAccessible(true);
|
||||
//noinspection unchecked
|
||||
deniedLogin = (Set<UUID>) field.get(connectionListener);
|
||||
field = connectionListener.getClass().getDeclaredField("detectedCraftBukkitOfflineMode");
|
||||
field.setAccessible(true);
|
||||
detectedCraftBukkitOfflineMode = field;
|
||||
printCraftBukkitOfflineModeError = connectionListener.getClass().getDeclaredMethod("printCraftBukkitOfflineModeError");
|
||||
printCraftBukkitOfflineModeError.setAccessible(true);
|
||||
|
||||
//PERMISSIBLE_FIELD = DiscordFakePlayer.class.getDeclaredField("perm");
|
||||
//PERMISSIBLE_FIELD.setAccessible(true); //Hacking my own plugin, while we're at it
|
||||
PERMISSIBLE_BASE_ATTACHMENTS_FIELD = PermissibleBase.class.getDeclaredField("attachments");
|
||||
PERMISSIBLE_BASE_ATTACHMENTS_FIELD.setAccessible(true);
|
||||
|
||||
convertAndAddAttachments = LPPermissible.class.getDeclaredMethod("convertAndAddAttachments", Collection.class);
|
||||
convertAndAddAttachments.setAccessible(true);
|
||||
getActive = LPPermissible.class.getDeclaredMethod("getActive");
|
||||
getActive.setAccessible(true);
|
||||
setOldPermissible = LPPermissible.class.getDeclaredMethod("setOldPermissible", PermissibleBase.class);
|
||||
setOldPermissible.setAccessible(true);
|
||||
getOldPermissible = LPPermissible.class.getDeclaredMethod("getOldPermissible");
|
||||
getOldPermissible.setAccessible(true);
|
||||
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(this, mp);
|
||||
}
|
||||
|
||||
|
||||
//Code copied from LuckPerms - me.lucko.luckperms.bukkit.listeners.BukkitConnectionListener
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPlayerLogin(PlayerLoginEvent e) {
|
||||
/* Called when the player starts logging into the server.
|
||||
At this point, the users data should be present and loaded. */
|
||||
|
||||
if (!(e.getPlayer() instanceof DiscordFakePlayer))
|
||||
return; //Normal players must be handled by the plugin
|
||||
|
||||
final DiscordFakePlayer player = (DiscordFakePlayer) e.getPlayer();
|
||||
|
||||
if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
plugin.getLogger().info("Processing login for " + player.getUniqueId() + " - " + player.getName());
|
||||
}
|
||||
|
||||
final User user = plugin.getUserManager().getIfLoaded(player.getUniqueId());
|
||||
|
||||
/* User instance is null for whatever reason. Could be that it was unloaded between asyncpre and now. */
|
||||
if (user == null) {
|
||||
deniedLogin.add(player.getUniqueId());
|
||||
|
||||
if (!connectionListener.getUniqueConnections().contains(player.getUniqueId())) {
|
||||
|
||||
plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
|
||||
" doesn't have data pre-loaded, they have never been processed during pre-login in this session." +
|
||||
" - denying login.");
|
||||
|
||||
try {
|
||||
if ((Boolean) detectedCraftBukkitOfflineMode.get(connectionListener)) {
|
||||
printCraftBukkitOfflineModeError.invoke(connectionListener);
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_STATE_ERROR_CB_OFFLINE_MODE.asString(plugin.getLocaleManager()));
|
||||
return;
|
||||
}
|
||||
} catch (IllegalAccessException | InvocationTargetException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
} else {
|
||||
plugin.getLogger().warn("User " + player.getUniqueId() + " - " + player.getName() +
|
||||
" doesn't currently have data pre-loaded, but they have been processed before in this session." +
|
||||
" - denying login.");
|
||||
}
|
||||
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_STATE_ERROR.asString(plugin.getLocaleManager()));
|
||||
return;
|
||||
}
|
||||
|
||||
// User instance is there, now we can inject our custom Permissible into the player.
|
||||
// Care should be taken at this stage to ensure that async tasks which manipulate bukkit data check that the player is still online.
|
||||
try {
|
||||
// get the existing PermissibleBase held by the player
|
||||
PermissibleBase oldPermissible = player.getPerm();
|
||||
|
||||
// Make a new permissible for the user
|
||||
LPPermissible lpPermissible = new LPPermissible(player, user, plugin);
|
||||
|
||||
// Inject into the player
|
||||
inject(player, lpPermissible, oldPermissible);
|
||||
|
||||
} catch (Throwable t) {
|
||||
plugin.getLogger().warn("Exception thrown when setting up permissions for " +
|
||||
player.getUniqueId() + " - " + player.getName() + " - denying login.");
|
||||
t.printStackTrace();
|
||||
|
||||
e.disallow(PlayerLoginEvent.Result.KICK_OTHER, Message.LOADING_SETUP_ERROR.asString(plugin.getLocaleManager()));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.refreshAutoOp(player, true);
|
||||
}
|
||||
|
||||
// Wait until the last priority to unload, so plugins can still perform permission checks on this event
|
||||
@EventHandler(priority = EventPriority.MONITOR)
|
||||
public void onPlayerQuit(PlayerQuitEvent e) {
|
||||
if (!(e.getPlayer() instanceof DiscordFakePlayer))
|
||||
return;
|
||||
|
||||
final DiscordFakePlayer player = (DiscordFakePlayer) e.getPlayer();
|
||||
|
||||
connectionListener.handleDisconnect(player.getUniqueId());
|
||||
|
||||
// perform unhooking from bukkit objects 1 tick later.
|
||||
// this allows plugins listening after us on MONITOR to still have intact permissions data
|
||||
this.plugin.getBootstrap().getServer().getScheduler().runTaskLaterAsynchronously(this.plugin.getBootstrap(), () -> {
|
||||
// Remove the custom permissible
|
||||
try {
|
||||
uninject(player, true);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
// Handle auto op
|
||||
if (this.plugin.getConfiguration().get(ConfigKeys.AUTO_OP)) {
|
||||
player.setOp(false);
|
||||
}
|
||||
|
||||
// remove their contexts cache
|
||||
this.plugin.getContextManager().onPlayerQuit(player);
|
||||
}, 1L);
|
||||
}
|
||||
|
||||
//me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector
|
||||
private void inject(DiscordFakePlayer player, LPPermissible newPermissible, PermissibleBase oldPermissible) throws IllegalAccessException, InvocationTargetException {
|
||||
|
||||
// seems we have already injected into this player.
|
||||
if (oldPermissible instanceof LPPermissible) {
|
||||
throw new IllegalStateException("LPPermissible already injected into player " + player.toString());
|
||||
}
|
||||
|
||||
// Move attachments over from the old permissible
|
||||
|
||||
//noinspection unchecked
|
||||
List<PermissionAttachment> attachments = (List<PermissionAttachment>) PERMISSIBLE_BASE_ATTACHMENTS_FIELD.get(oldPermissible);
|
||||
|
||||
convertAndAddAttachments.invoke(newPermissible, attachments);
|
||||
attachments.clear();
|
||||
oldPermissible.clearPermissions();
|
||||
|
||||
// Setup the new permissible
|
||||
((AtomicBoolean) getActive.invoke(newPermissible)).set(true);
|
||||
setOldPermissible.invoke(newPermissible, oldPermissible);
|
||||
|
||||
// inject the new instance
|
||||
player.setPerm(newPermissible);
|
||||
}
|
||||
|
||||
private void uninject(DiscordFakePlayer player, boolean dummy) throws Exception {
|
||||
|
||||
// gets the players current permissible.
|
||||
PermissibleBase permissible = player.getPerm();
|
||||
|
||||
// only uninject if the permissible was a luckperms one.
|
||||
if (permissible instanceof LPPermissible) {
|
||||
LPPermissible lpPermissible = ((LPPermissible) permissible);
|
||||
|
||||
// clear all permissions
|
||||
lpPermissible.clearPermissions();
|
||||
|
||||
// set to inactive
|
||||
((AtomicBoolean) getActive.invoke(lpPermissible)).set(false);
|
||||
|
||||
// handle the replacement permissible.
|
||||
if (dummy) {
|
||||
// just inject a dummy class. this is used when we know the player is about to quit the server.
|
||||
player.setPerm(DummyPermissibleBase.INSTANCE);
|
||||
|
||||
} else {
|
||||
PermissibleBase newPb = (PermissibleBase) getOldPermissible.invoke(lpPermissible);
|
||||
if (newPb == null) {
|
||||
newPb = new PermissibleBase(player);
|
||||
}
|
||||
|
||||
player.setPerm(newPb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue