Merge pull request #108 from TBMCPlugins/dev
1.14 support, better error handling
This commit is contained in:
commit
30e2da094a
34 changed files with 836 additions and 2141 deletions
|
@ -9,7 +9,7 @@ before_install: | # Wget BuildTools and run if cached folder not found
|
|||
fi
|
||||
language: java
|
||||
jdk:
|
||||
- oraclejdk8
|
||||
- oraclejdk11
|
||||
sudo: true
|
||||
deploy:
|
||||
# deploy develop to the staging environment
|
||||
|
|
38
pom.xml
38
pom.xml
|
@ -2,6 +2,12 @@
|
|||
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>
|
||||
|
||||
<parent>
|
||||
<groupId>com.github.TBMCPlugins.ButtonCore</groupId>
|
||||
<artifactId>CorePOM</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>com.github.TBMCPlugins</groupId>
|
||||
<artifactId>DiscordPlugin</artifactId>
|
||||
<version>master-SNAPSHOT</version>
|
||||
|
@ -34,26 +40,10 @@
|
|||
</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>
|
||||
</compilerArgs> -->
|
||||
<!-- <annotationProcessors>
|
||||
<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>
|
||||
<version>3.2.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
|
@ -148,7 +138,7 @@
|
|||
</repository> -->
|
||||
<repository>
|
||||
<id>Essentials</id>
|
||||
<url>http://repo.ess3.net/content/repositories/essrel/</url>
|
||||
<url>https://ci.ender.zone/plugin/repository/everything/</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>projectlombok.org</id>
|
||||
|
@ -174,7 +164,7 @@
|
|||
<dependency>
|
||||
<groupId>org.spigotmc</groupId>
|
||||
<artifactId>spigot-api</artifactId>
|
||||
<version>1.12-R0.1-SNAPSHOT</version>
|
||||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -183,11 +173,17 @@
|
|||
<version>1.12.2-R0.1-SNAPSHOT</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spigotmc.</groupId>
|
||||
<artifactId>spigot</artifactId>
|
||||
<version>1.14.4-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.6</version>
|
||||
<version>3.0.10</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-jdk14 -->
|
||||
<dependency>
|
||||
|
@ -217,7 +213,7 @@
|
|||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.16.16</version>
|
||||
<version>1.18.10</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
|
|
|
@ -163,4 +163,8 @@ public final class DPUtils {
|
|||
return getMessageChannel(config.getPath(), config.get());
|
||||
}
|
||||
|
||||
public static <T> Mono<T> ignoreError(Mono<T> mono) {
|
||||
return mono.onErrorResume(t -> Mono.empty());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
249
src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java
Executable file → Normal file
249
src/main/java/buttondevteam/discordplugin/DiscordConnectedPlayer.java
Executable file → Normal file
|
@ -1,25 +1,258 @@
|
|||
package buttondevteam.discordplugin;
|
||||
|
||||
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||
import buttondevteam.discordplugin.playerfaker.DiscordFakePlayer;
|
||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
||||
import buttondevteam.discordplugin.playerfaker.DiscordInventory;
|
||||
import buttondevteam.discordplugin.playerfaker.VCMDWrapper;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Delegate;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.attribute.AttributeModifier;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.ServerOperator;
|
||||
import org.mockito.MockSettings;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DiscordConnectedPlayer extends DiscordFakePlayer implements IMCPlayer<DiscordConnectedPlayer> {
|
||||
private static int nextEntityId = 10000;
|
||||
private @Getter VanillaCommandListener<DiscordConnectedPlayer> vanillaCmdListener;
|
||||
import static org.mockito.Answers.RETURNS_DEFAULTS;
|
||||
|
||||
public abstract class DiscordConnectedPlayer extends DiscordSenderBase implements IMCPlayer<DiscordConnectedPlayer> {
|
||||
private @Getter VCMDWrapper 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);
|
||||
vanillaCmdListener = new VanillaCommandListener<>(this);
|
||||
@Delegate(excludes = ServerOperator.class)
|
||||
private PermissibleBase origPerm;
|
||||
|
||||
private @Getter String name;
|
||||
|
||||
private @Getter OfflinePlayer basePlayer;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissibleBase perm;
|
||||
|
||||
private Location location;
|
||||
|
||||
private final MinecraftChatModule module;
|
||||
|
||||
@Getter
|
||||
private final UUID uniqueId;
|
||||
|
||||
/**
|
||||
* The parameters must match with {@link #create(User, MessageChannel, UUID, String, MinecraftChatModule)}
|
||||
*/
|
||||
protected DiscordConnectedPlayer(User user, MessageChannel channel, UUID uuid, String mcname,
|
||||
MinecraftChatModule module) {
|
||||
super(user, channel);
|
||||
location = Bukkit.getWorlds().get(0).getSpawnLocation();
|
||||
origPerm = perm = new PermissibleBase(basePlayer = Bukkit.getOfflinePlayer(uuid));
|
||||
name = mcname;
|
||||
this.module = module;
|
||||
uniqueId = uuid;
|
||||
displayName = mcname;
|
||||
try {
|
||||
vanillaCmdListener = new VCMDWrapper(VCMDWrapper.createListener(this));
|
||||
if (vanillaCmdListener.getListener() == null)
|
||||
DPUtils.getLogger().warning("Vanilla commands won't be available from Discord due to a compatibility error.");
|
||||
} catch (NoClassDefFoundError e) {
|
||||
DPUtils.getLogger().warning("Vanilla commands won't be available from Discord due to a compatibility error.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For testing
|
||||
*/
|
||||
protected DiscordConnectedPlayer(User user, MessageChannel channel) {
|
||||
super(user, channel);
|
||||
module = null;
|
||||
uniqueId = UUID.randomUUID();
|
||||
}
|
||||
|
||||
public void setOp(boolean value) { //CraftPlayer-compatible implementation
|
||||
this.origPerm.setOp(value);
|
||||
this.perm.recalculatePermissions();
|
||||
}
|
||||
|
||||
public boolean isOp() { return this.origPerm.isOp(); }
|
||||
|
||||
@Override
|
||||
public boolean teleport(Location location) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = location;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Location location, PlayerTeleportEvent.TeleportCause cause) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = location;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Entity destination) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = destination.getLocation();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Entity destination, PlayerTeleportEvent.TeleportCause cause) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = destination.getLocation();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation(Location loc) {
|
||||
if (loc != null) {
|
||||
loc.setWorld(getWorld());
|
||||
loc.setX(location.getX());
|
||||
loc.setY(location.getY());
|
||||
loc.setZ(location.getZ());
|
||||
loc.setYaw(location.getYaw());
|
||||
loc.setPitch(location.getPitch());
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server getServer() {
|
||||
return Bukkit.getServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawMessage(String message) {
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(String msg) {
|
||||
Bukkit.getPluginManager()
|
||||
.callEvent(new AsyncPlayerChatEvent(true, this, msg, new HashSet<>(Bukkit.getOnlinePlayers())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return Bukkit.getWorlds().get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return new Location(getWorld(), location.getX(), location.getY(), location.getZ(),
|
||||
location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxHealth() {
|
||||
return 20;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String displayName;
|
||||
|
||||
@Override
|
||||
public AttributeInstance getAttribute(Attribute attribute) {
|
||||
return new AttributeInstance() {
|
||||
@Override
|
||||
public Attribute getAttribute() {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getBaseValue() {
|
||||
return getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBaseValue(double value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<AttributeModifier> getModifiers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addModifier(AttributeModifier modifier) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeModifier(AttributeModifier modifier) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getValue() {
|
||||
return getDefaultValue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getDefaultValue() {
|
||||
return 20; //Works for max health, should be okay for the rest
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getGameMode() {
|
||||
return GameMode.SPECTATOR;
|
||||
}
|
||||
|
||||
public static DiscordConnectedPlayer create(User user, MessageChannel channel, UUID uuid, String mcname,
|
||||
MinecraftChatModule module) {
|
||||
return Mockito.mock(DiscordConnectedPlayer.class,
|
||||
getSettings().useConstructor(user, channel, uuid, mcname, module));
|
||||
}
|
||||
|
||||
public static DiscordConnectedPlayer createTest() {
|
||||
return Mockito.mock(DiscordConnectedPlayer.class, getSettings().useConstructor(null, null));
|
||||
}
|
||||
|
||||
private static MockSettings getSettings() {
|
||||
return Mockito.withSettings()
|
||||
.defaultAnswer(invocation -> {
|
||||
try {
|
||||
if (!Modifier.isAbstract(invocation.getMethod().getModifiers()))
|
||||
return invocation.callRealMethod();
|
||||
if (PlayerInventory.class.isAssignableFrom(invocation.getMethod().getReturnType()))
|
||||
return Mockito.mock(DiscordInventory.class, Mockito.withSettings().extraInterfaces(PlayerInventory.class));
|
||||
if (Inventory.class.isAssignableFrom(invocation.getMethod().getReturnType()))
|
||||
return new DiscordInventory();
|
||||
return RETURNS_DEFAULTS.answer(invocation);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error in mocked player!");
|
||||
e.printStackTrace();
|
||||
return RETURNS_DEFAULTS.answer(invocation);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package buttondevteam.discordplugin;
|
||||
|
||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
||||
import buttondevteam.discordplugin.playerfaker.VCMDWrapper;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
|
@ -36,12 +36,18 @@ import java.util.*;
|
|||
public class DiscordPlayerSender extends DiscordSenderBase implements IMCPlayer<DiscordPlayerSender> {
|
||||
|
||||
protected Player player;
|
||||
private @Getter VanillaCommandListener<DiscordPlayerSender> vanillaCmdListener;
|
||||
private @Getter VCMDWrapper vanillaCmdListener;
|
||||
|
||||
public DiscordPlayerSender(User user, MessageChannel channel, Player player) {
|
||||
super(user, channel);
|
||||
this.player = player;
|
||||
vanillaCmdListener = new VanillaCommandListener<DiscordPlayerSender>(this);
|
||||
try {
|
||||
vanillaCmdListener = new VCMDWrapper(VCMDWrapper.createListener(this, player));
|
||||
if (vanillaCmdListener.getListener() == null)
|
||||
DPUtils.getLogger().warning("Vanilla commands won't be available from Discord due to a compatibility error.");
|
||||
} catch (NoClassDefFoundError e) {
|
||||
DPUtils.getLogger().warning("Vanilla commands won't be available from Discord due to a compatibility error.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -298,10 +304,6 @@ public class DiscordPlayerSender extends DiscordSenderBase implements IMCPlayer<
|
|||
return player.addAttachment(plugin);
|
||||
}
|
||||
|
||||
public Block getTargetBlock(HashSet<Byte> transparent, int maxDistance) {
|
||||
return player.getTargetBlock(transparent, maxDistance);
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return player.getWorld();
|
||||
}
|
||||
|
@ -350,10 +352,6 @@ public class DiscordPlayerSender extends DiscordSenderBase implements IMCPlayer<
|
|||
player.setCompassTarget(loc);
|
||||
}
|
||||
|
||||
public List<Block> getLastTwoTargetBlocks(HashSet<Byte> transparent, int maxDistance) {
|
||||
return player.getLastTwoTargetBlocks(transparent, maxDistance);
|
||||
}
|
||||
|
||||
public Location getCompassTarget() {
|
||||
return player.getCompassTarget();
|
||||
}
|
||||
|
@ -1092,11 +1090,21 @@ public class DiscordPlayerSender extends DiscordSenderBase implements IMCPlayer<
|
|||
}
|
||||
|
||||
public void hidePlayer(Player player) {
|
||||
player.hidePlayer(player);
|
||||
this.player.hidePlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayer(Plugin plugin, Player player) {
|
||||
this.player.hidePlayer(plugin, player);
|
||||
}
|
||||
|
||||
public void showPlayer(Player player) {
|
||||
player.showPlayer(player);
|
||||
this.player.showPlayer(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPlayer(Plugin plugin, Player player) {
|
||||
this.player.showPlayer(plugin, player);
|
||||
}
|
||||
|
||||
public boolean canSee(Player player) {
|
||||
|
|
|
@ -143,13 +143,17 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
private void handleReady(List<GuildCreateEvent> event) {
|
||||
try {
|
||||
if (mainServer != null) { //This is not the first ready event
|
||||
getLogger().info("Ready event already handled");
|
||||
getLogger().info("Ready event already handled"); //TODO: It should probably handle disconnections
|
||||
return;
|
||||
}
|
||||
mainServer = mainServer().get().orElse(null); //Shouldn't change afterwards
|
||||
getCommand2MC().registerCommand(new DiscordMCCommand()); //Register so that the reset command works
|
||||
if (mainServer == null) {
|
||||
if (event.size() == 0) {
|
||||
getLogger().severe("Main server not found! Invite the bot and do /discord reset");
|
||||
dc.getApplicationInfo().subscribe(info -> {
|
||||
getLogger().severe("Click here: https://discordapp.com/oauth2/authorize?client_id=" + info.getId().asString() + "&scope=bot&permissions=268509264");
|
||||
});
|
||||
saveConfig(); //Put default there
|
||||
return; //We should have all guilds by now, no need to retry
|
||||
}
|
||||
|
@ -205,7 +209,6 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
|
||||
CommonListeners.register(dc.getEventDispatcher());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(), this);
|
||||
getCommand2MC().registerCommand(new DiscordMCCommand());
|
||||
TBMCCoreAPI.RegisterUserClass(DiscordPlayer.class);
|
||||
ChromaGamerBase.addConverter(sender -> Optional.ofNullable(sender instanceof DiscordSenderBase
|
||||
? ((DiscordSenderBase) sender).getChromaUser() : null));
|
||||
|
@ -266,8 +269,8 @@ public class DiscordPlugin extends ButtonPlugin {
|
|||
try {
|
||||
SafeMode = true; // Stop interacting with Discord
|
||||
ChromaBot.delete();
|
||||
timings.printElapsed("Updating presence...");
|
||||
dc.updatePresence(Presence.idle(Activity.playing("Chromacraft"))).block(); //No longer using the same account for testing
|
||||
//timings.printElapsed("Updating presence...");
|
||||
//dc.updatePresence(Presence.idle(Activity.playing("logging out"))).block(); //No longer using the same account for testing
|
||||
timings.printElapsed("Logging out...");
|
||||
dc.logout().block();
|
||||
mainServer = null; //Allow ReadyEvent again
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.bukkit.permissions.Permission;
|
|||
import org.bukkit.permissions.PermissionAttachment;
|
||||
import org.bukkit.permissions.PermissionAttachmentInfo;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -23,7 +24,8 @@ public class DiscordSender extends DiscordSenderBase implements CommandSender {
|
|||
public DiscordSender(User user, MessageChannel channel) {
|
||||
super(user, channel);
|
||||
val def = "Discord user";
|
||||
name = user == null ? def : user.asMember(DiscordPlugin.mainServer.getId()).blockOptional().map(Member::getDisplayName).orElse(def);
|
||||
name = user == null ? def : user.asMember(DiscordPlugin.mainServer.getId())
|
||||
.onErrorResume(t -> Mono.empty()).blockOptional().map(Member::getDisplayName).orElse(def);
|
||||
}
|
||||
|
||||
public DiscordSender(User user, MessageChannel channel, String name) {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package buttondevteam.discordplugin;
|
||||
|
||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
||||
import buttondevteam.discordplugin.playerfaker.VCMDWrapper;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface IMCPlayer<T extends DiscordSenderBase & IMCPlayer<T>> extends Player {
|
||||
VanillaCommandListener<T> getVanillaCmdListener();
|
||||
public interface IMCPlayer<T> extends Player {
|
||||
VCMDWrapper getVanillaCmdListener();
|
||||
}
|
||||
|
|
|
@ -12,24 +12,29 @@ public class GeneralEventBroadcasterModule extends Component<DiscordPlugin> {
|
|||
@Override
|
||||
protected void enable() {
|
||||
try {
|
||||
PlayerListWatcher.hookUp();
|
||||
PlayerListWatcher.hookUpDown(true);
|
||||
DPUtils.getLogger().info("Finished hooking into the player list");
|
||||
hooked = true;
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
||||
TBMCCoreAPI.SendException("Error while hacking the player list! Disable this module if you're on an incompatible version.", e);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
DPUtils.getLogger().warning("Error while hacking the player list! Disable this module if you're on an incompatible version.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disable() {
|
||||
try {
|
||||
if (PlayerListWatcher.hookDown())
|
||||
if (!hooked) return;
|
||||
if (PlayerListWatcher.hookUpDown(false))
|
||||
DPUtils.getLogger().info("Finished unhooking the player list!");
|
||||
else
|
||||
DPUtils.getLogger().info("Didn't have the player list hooked.");
|
||||
hooked = false;
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while hacking the player list!", e);
|
||||
} catch (NoClassDefFoundError ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,25 +2,21 @@ package buttondevteam.discordplugin.broadcaster;
|
|||
|
||||
import buttondevteam.discordplugin.mcchat.MCChatUtils;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import lombok.val;
|
||||
import net.minecraft.server.v1_12_R1.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_12_R1.util.CraftChatMessage;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.objenesis.ObjenesisStd;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class PlayerListWatcher extends DedicatedPlayerList {
|
||||
private DedicatedPlayerList plist;
|
||||
public class PlayerListWatcher {
|
||||
private static Object plist;
|
||||
private static Object mock;
|
||||
|
||||
public PlayerListWatcher(DedicatedServer minecraftserver) {
|
||||
/*public PlayerListWatcher(DedicatedServer minecraftserver) {
|
||||
super(minecraftserver); // <-- Does some init stuff and calls Bukkit.setServer() so we have to use Objenesis
|
||||
}
|
||||
|
||||
|
@ -38,7 +34,7 @@ public class PlayerListWatcher extends DedicatedPlayerList {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { // Needed so it calls the overriden method
|
||||
public void sendMessage(IChatBaseComponent ichatbasecomponent, boolean flag) { // Needed so it calls the overridden method
|
||||
plist.getServer().sendMessage(ichatbasecomponent);
|
||||
ChatMessageType chatmessagetype = flag ? ChatMessageType.SYSTEM : ChatMessageType.CHAT;
|
||||
|
||||
|
@ -57,306 +53,114 @@ public class PlayerListWatcher extends DedicatedPlayerList {
|
|||
for (IChatBaseComponent component : iChatBaseComponents) {
|
||||
sendMessage(component, true);
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
static void hookUp() throws Exception {
|
||||
Field conf = CraftServer.class.getDeclaredField("console");
|
||||
static boolean hookUpDown(boolean up) throws Exception {
|
||||
val csc = Bukkit.getServer().getClass();
|
||||
Field conf = csc.getDeclaredField("console");
|
||||
conf.setAccessible(true);
|
||||
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
||||
val plw = new ObjenesisStd().newInstance(PlayerListWatcher.class); // Cannot call super constructor
|
||||
plw.plist = (DedicatedPlayerList) server.getPlayerList();
|
||||
plw.maxPlayers = plw.plist.getMaxPlayers();
|
||||
Field plf = plw.getClass().getField("players");
|
||||
plf.setAccessible(true);
|
||||
Field modf = plf.getClass().getDeclaredField("modifiers");
|
||||
modf.setAccessible(true);
|
||||
modf.set(plf, plf.getModifiers() & ~Modifier.FINAL);
|
||||
plf.set(plw, plw.plist.players);
|
||||
server.a(plw);
|
||||
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
||||
pllf.setAccessible(true);
|
||||
pllf.set(Bukkit.getServer(), plw);
|
||||
}
|
||||
val server = conf.get(Bukkit.getServer());
|
||||
val nms = server.getClass().getPackage().getName();
|
||||
val dplc = Class.forName(nms + ".DedicatedPlayerList");
|
||||
val currentPL = server.getClass().getMethod("getPlayerList").invoke(server);
|
||||
if (up) {
|
||||
val icbcl = Class.forName(nms + ".IChatBaseComponent");
|
||||
val sendMessage = server.getClass().getMethod("sendMessage", icbcl);
|
||||
val cmtcl = Class.forName(nms + ".ChatMessageType");
|
||||
val systemType = cmtcl.getDeclaredField("SYSTEM").get(null);
|
||||
val chatType = cmtcl.getDeclaredField("CHAT").get(null);
|
||||
|
||||
static boolean hookDown() throws Exception {
|
||||
Field conf = CraftServer.class.getDeclaredField("console");
|
||||
conf.setAccessible(true);
|
||||
val server = (MinecraftServer) conf.get(Bukkit.getServer());
|
||||
val plist = (DedicatedPlayerList) server.getPlayerList();
|
||||
if (!(plist instanceof PlayerListWatcher))
|
||||
return false;
|
||||
server.a(((PlayerListWatcher) plist).plist);
|
||||
Field pllf = CraftServer.class.getDeclaredField("playerList");
|
||||
val obc = csc.getPackage().getName();
|
||||
val ccmcl = Class.forName(obc + ".util.CraftChatMessage");
|
||||
val fixComponent = ccmcl.getMethod("fixComponent", icbcl);
|
||||
val ppoc = Class.forName(nms + ".PacketPlayOutChat");
|
||||
val ppocC = Class.forName(nms + ".PacketPlayOutChat").getConstructor(icbcl, cmtcl);
|
||||
val sendAll = dplc.getMethod("sendAll", Class.forName(nms + ".Packet"));
|
||||
Method tpt;
|
||||
try {
|
||||
tpt = icbcl.getMethod("toPlainText");
|
||||
} catch (NoSuchMethodException e) {
|
||||
tpt = icbcl.getMethod("getString");
|
||||
}
|
||||
val toPlainText = tpt;
|
||||
mock = Mockito.mock(dplc, new Answer() { // Cannot call super constructor
|
||||
@Override
|
||||
public Object answer(InvocationOnMock invocation) throws Throwable {
|
||||
final Method method = invocation.getMethod();
|
||||
if (!method.getName().equals("sendMessage")) {
|
||||
if (method.getName().equals("sendAll")) {
|
||||
sendAll(invocation.getArgument(0));
|
||||
return null;
|
||||
}
|
||||
return method.invoke(plist, invocation.getArguments());
|
||||
}
|
||||
val args = invocation.getArguments();
|
||||
val params = method.getParameterTypes();
|
||||
if (params.length == 0) {
|
||||
TBMCCoreAPI.SendException("Found a strange method",
|
||||
new Exception("Found a sendMessage() method without arguments."));
|
||||
return null;
|
||||
}
|
||||
if (params[0].getSimpleName().equals("IChatBaseComponent[]"))
|
||||
for (val arg : (Object[]) args[0])
|
||||
sendMessage(arg, true);
|
||||
else if (params[0].getSimpleName().equals("IChatBaseComponent"))
|
||||
if (params.length > 1 && params[1].getSimpleName().equalsIgnoreCase("boolean"))
|
||||
sendMessage(args[0], (Boolean) args[1]);
|
||||
else
|
||||
sendMessage(args[0], true);
|
||||
else
|
||||
TBMCCoreAPI.SendException("Found a method with interesting params",
|
||||
new Exception("Found a sendMessage(" + params[0].getSimpleName() + ") method"));
|
||||
return null;
|
||||
}
|
||||
|
||||
private void sendMessage(Object chatComponent, boolean system) {
|
||||
try { //Converted to use reflection
|
||||
sendMessage.invoke(server, chatComponent);
|
||||
Object chatmessagetype = system ? systemType : chatType;
|
||||
|
||||
// CraftBukkit start - we run this through our processor first so we can get web links etc
|
||||
this.sendAll(ppocC.newInstance(fixComponent.invoke(null, chatComponent), chatmessagetype));
|
||||
// CraftBukkit end
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("An error occurred while passing a vanilla message through the player list", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void sendAll(Object packet) {
|
||||
try { // Some messages get sent by directly constructing a packet
|
||||
sendAll.invoke(plist, packet);
|
||||
if (packet.getClass() == ppoc) {
|
||||
Field msgf = ppoc.getDeclaredField("a");
|
||||
msgf.setAccessible(true);
|
||||
MCChatUtils.forAllMCChat(MCChatUtils.send((String) toPlainText.invoke(msgf.get(packet))));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Failed to broadcast message sent to all players - hacking failed.", e);
|
||||
}
|
||||
}
|
||||
});
|
||||
plist = currentPL;
|
||||
for (var plc = dplc; plc != null; plc = plc.getSuperclass()) { //Set all fields
|
||||
for (var f : plc.getDeclaredFields()) {
|
||||
f.setAccessible(true);
|
||||
Field modf = f.getClass().getDeclaredField("modifiers");
|
||||
modf.setAccessible(true);
|
||||
modf.set(f, f.getModifiers() & ~Modifier.FINAL);
|
||||
f.set(mock, f.get(plist));
|
||||
}
|
||||
}
|
||||
}
|
||||
try {
|
||||
server.getClass().getMethod("a", dplc).invoke(server, up ? mock : plist);
|
||||
} catch (NoSuchMethodException e) {
|
||||
server.getClass().getMethod("a", Class.forName(server.getClass().getPackage().getName() + ".PlayerList"))
|
||||
.invoke(server, up ? mock : plist);
|
||||
}
|
||||
Field pllf = csc.getDeclaredField("playerList");
|
||||
pllf.setAccessible(true);
|
||||
pllf.set(Bukkit.getServer(), ((PlayerListWatcher) plist).plist);
|
||||
pllf.set(Bukkit.getServer(), up ? mock : plist);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void a(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) {
|
||||
plist.a(entityhuman, ichatbasecomponent);
|
||||
}
|
||||
|
||||
public void a(EntityPlayer entityplayer, int i) {
|
||||
plist.a(entityplayer, i);
|
||||
}
|
||||
|
||||
public void a(EntityPlayer entityplayer, WorldServer worldserver) {
|
||||
plist.a(entityplayer, worldserver);
|
||||
}
|
||||
|
||||
public NBTTagCompound a(EntityPlayer entityplayer) {
|
||||
return plist.a(entityplayer);
|
||||
}
|
||||
|
||||
public void a(int i) {
|
||||
plist.a(i);
|
||||
}
|
||||
|
||||
public void a(NetworkManager networkmanager, EntityPlayer entityplayer) {
|
||||
plist.a(networkmanager, entityplayer);
|
||||
}
|
||||
|
||||
public void a(Packet<?> packet, int i) {
|
||||
plist.a(packet, i);
|
||||
}
|
||||
|
||||
public EntityPlayer a(UUID uuid) {
|
||||
return plist.a(uuid);
|
||||
}
|
||||
|
||||
public void addOp(GameProfile gameprofile) {
|
||||
plist.addOp(gameprofile);
|
||||
}
|
||||
|
||||
public void addWhitelist(GameProfile gameprofile) {
|
||||
plist.addWhitelist(gameprofile);
|
||||
}
|
||||
|
||||
public EntityPlayer attemptLogin(LoginListener loginlistener, GameProfile gameprofile, String hostname) {
|
||||
return plist.attemptLogin(loginlistener, gameprofile, hostname);
|
||||
}
|
||||
|
||||
public String b(boolean flag) {
|
||||
return plist.b(flag);
|
||||
}
|
||||
|
||||
public void b(EntityHuman entityhuman, IChatBaseComponent ichatbasecomponent) {
|
||||
plist.b(entityhuman, ichatbasecomponent);
|
||||
}
|
||||
|
||||
public void b(EntityPlayer entityplayer, WorldServer worldserver) {
|
||||
plist.b(entityplayer, worldserver);
|
||||
}
|
||||
|
||||
public List<EntityPlayer> b(String s) {
|
||||
return plist.b(s);
|
||||
}
|
||||
|
||||
public Location calculateTarget(Location enter, World target) {
|
||||
return plist.calculateTarget(enter, target);
|
||||
}
|
||||
|
||||
public void changeDimension(EntityPlayer entityplayer, int i, TeleportCause cause) {
|
||||
plist.changeDimension(entityplayer, i, cause);
|
||||
}
|
||||
|
||||
public void changeWorld(Entity entity, int i, WorldServer worldserver, WorldServer worldserver1) {
|
||||
plist.changeWorld(entity, i, worldserver, worldserver1);
|
||||
}
|
||||
|
||||
public int d() {
|
||||
return plist.d();
|
||||
}
|
||||
|
||||
public void d(EntityPlayer entityplayer) {
|
||||
plist.d(entityplayer);
|
||||
}
|
||||
|
||||
public String disconnect(EntityPlayer entityplayer) {
|
||||
return plist.disconnect(entityplayer);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
return plist.equals(obj);
|
||||
}
|
||||
|
||||
public String[] f() {
|
||||
return plist.f();
|
||||
}
|
||||
|
||||
public void f(EntityPlayer entityplayer) {
|
||||
plist.f(entityplayer);
|
||||
}
|
||||
|
||||
public boolean f(GameProfile gameprofile) {
|
||||
return plist.f(gameprofile);
|
||||
}
|
||||
|
||||
public GameProfile[] g() {
|
||||
return plist.g();
|
||||
}
|
||||
|
||||
public boolean getHasWhitelist() {
|
||||
return plist.getHasWhitelist();
|
||||
}
|
||||
|
||||
public IpBanList getIPBans() {
|
||||
return plist.getIPBans();
|
||||
}
|
||||
|
||||
public int getMaxPlayers() {
|
||||
return plist.getMaxPlayers();
|
||||
}
|
||||
|
||||
public OpList getOPs() {
|
||||
return plist.getOPs();
|
||||
}
|
||||
|
||||
public EntityPlayer getPlayer(String s) {
|
||||
return plist.getPlayer(s);
|
||||
}
|
||||
|
||||
public int getPlayerCount() {
|
||||
return plist.getPlayerCount();
|
||||
}
|
||||
|
||||
public GameProfileBanList getProfileBans() {
|
||||
return plist.getProfileBans();
|
||||
}
|
||||
|
||||
public String[] getSeenPlayers() {
|
||||
return plist.getSeenPlayers();
|
||||
}
|
||||
|
||||
public DedicatedServer getServer() {
|
||||
return plist.getServer();
|
||||
}
|
||||
|
||||
public WhiteList getWhitelist() {
|
||||
return plist.getWhitelist();
|
||||
}
|
||||
|
||||
public String[] getWhitelisted() {
|
||||
return plist.getWhitelisted();
|
||||
}
|
||||
|
||||
public AdvancementDataPlayer h(EntityPlayer entityplayer) {
|
||||
return plist.h(entityplayer);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return plist.hashCode();
|
||||
}
|
||||
|
||||
public boolean isOp(GameProfile gameprofile) {
|
||||
return plist.isOp(gameprofile);
|
||||
}
|
||||
|
||||
public boolean isWhitelisted(GameProfile gameprofile) {
|
||||
return plist.isWhitelisted(gameprofile);
|
||||
}
|
||||
|
||||
public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag, Location location,
|
||||
boolean avoidSuffocation) {
|
||||
return plist.moveToWorld(entityplayer, i, flag, location, avoidSuffocation);
|
||||
}
|
||||
|
||||
public EntityPlayer moveToWorld(EntityPlayer entityplayer, int i, boolean flag) {
|
||||
return plist.moveToWorld(entityplayer, i, flag);
|
||||
}
|
||||
|
||||
public String[] n() {
|
||||
return plist.n();
|
||||
}
|
||||
|
||||
public void onPlayerJoin(EntityPlayer entityplayer, String joinMessage) {
|
||||
plist.onPlayerJoin(entityplayer, joinMessage);
|
||||
}
|
||||
|
||||
public EntityPlayer processLogin(GameProfile gameprofile, EntityPlayer player) {
|
||||
return plist.processLogin(gameprofile, player);
|
||||
}
|
||||
|
||||
public void reload() {
|
||||
plist.reload();
|
||||
}
|
||||
|
||||
public void reloadWhitelist() {
|
||||
plist.reloadWhitelist();
|
||||
}
|
||||
|
||||
public void removeOp(GameProfile gameprofile) {
|
||||
plist.removeOp(gameprofile);
|
||||
}
|
||||
|
||||
public void removeWhitelist(GameProfile gameprofile) {
|
||||
plist.removeWhitelist(gameprofile);
|
||||
}
|
||||
|
||||
public void repositionEntity(Entity entity, Location exit, boolean portal) {
|
||||
plist.repositionEntity(entity, exit, portal);
|
||||
}
|
||||
|
||||
public int s() {
|
||||
return plist.s();
|
||||
}
|
||||
|
||||
public void savePlayers() {
|
||||
plist.savePlayers();
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void sendAll(Packet packet, EntityHuman entityhuman) {
|
||||
plist.sendAll(packet, entityhuman);
|
||||
}
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void sendAll(Packet packet, World world) {
|
||||
plist.sendAll(packet, world);
|
||||
}
|
||||
|
||||
public void sendPacketNearby(EntityHuman entityhuman, double d0, double d1, double d2, double d3, int i,
|
||||
Packet<?> packet) {
|
||||
plist.sendPacketNearby(entityhuman, d0, d1, d2, d3, i, packet);
|
||||
}
|
||||
|
||||
public void sendScoreboard(ScoreboardServer scoreboardserver, EntityPlayer entityplayer) {
|
||||
plist.sendScoreboard(scoreboardserver, entityplayer);
|
||||
}
|
||||
|
||||
public void setHasWhitelist(boolean flag) {
|
||||
plist.setHasWhitelist(flag);
|
||||
}
|
||||
|
||||
public void setPlayerFileData(WorldServer[] aworldserver) {
|
||||
plist.setPlayerFileData(aworldserver);
|
||||
}
|
||||
|
||||
public NBTTagCompound t() {
|
||||
return plist.t();
|
||||
}
|
||||
|
||||
public void tick() {
|
||||
plist.tick();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return plist.toString();
|
||||
}
|
||||
|
||||
public void u() {
|
||||
plist.u();
|
||||
}
|
||||
|
||||
public void updateClient(EntityPlayer entityplayer) {
|
||||
plist.updateClient(entityplayer);
|
||||
}
|
||||
|
||||
public List<EntityPlayer> v() {
|
||||
return plist.v();
|
||||
}
|
||||
|
||||
public ServerStatisticManager getStatisticManager(EntityPlayer entityhuman) {
|
||||
return plist.getStatisticManager(entityhuman);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ public class DebugCommand extends ICommand2DC {
|
|||
.flatMap(m -> DiscordPlugin.plugin.modRole().get()
|
||||
.map(mr -> m.getRoleIds().stream().anyMatch(r -> r.equals(mr.getId())))
|
||||
.switchIfEmpty(Mono.fromSupplier(() -> DiscordPlugin.mainServer.getOwnerId().asLong() == m.getId().asLong()))) //Role not found
|
||||
.subscribe(success -> {
|
||||
.onErrorReturn(false).subscribe(success -> {
|
||||
if (success)
|
||||
sender.sendMessage("debug " + (CommonListeners.debug() ? "enabled" : "disabled"));
|
||||
else
|
||||
|
|
|
@ -50,28 +50,28 @@ public class ExceptionListenerModule extends Component<DiscordPlugin> implements
|
|||
private static void SendException(Throwable e, String sourcemessage) {
|
||||
if (instance == null) return;
|
||||
try {
|
||||
Mono<MessageChannel> channel = getChannel();
|
||||
assert channel != null;
|
||||
Mono<Role> coderRole;
|
||||
if (channel instanceof GuildChannel)
|
||||
coderRole = instance.pingRole(((GuildChannel) channel).getGuild()).get();
|
||||
else
|
||||
coderRole = Mono.empty();
|
||||
coderRole.map(role -> TBMCCoreAPI.IsTestServer() ? new StringBuilder()
|
||||
: new StringBuilder(role.getMention()).append("\n"))
|
||||
.defaultIfEmpty(new StringBuilder())
|
||||
.flatMap(sb -> {
|
||||
sb.append(sourcemessage).append("\n");
|
||||
sb.append("```").append("\n");
|
||||
String stackTrace = Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n"))
|
||||
.filter(s -> !s.contains("\tat ") || s.contains("\tat buttondevteam."))
|
||||
.collect(Collectors.joining("\n"));
|
||||
if (sb.length() + stackTrace.length() >= 1980)
|
||||
stackTrace = stackTrace.substring(0, 1980 - sb.length());
|
||||
sb.append(stackTrace).append("\n");
|
||||
sb.append("```");
|
||||
return channel.flatMap(ch -> ch.createMessage(sb.toString()));
|
||||
}).subscribe();
|
||||
getChannel().flatMap(channel -> {
|
||||
Mono<Role> coderRole;
|
||||
if (channel instanceof GuildChannel)
|
||||
coderRole = instance.pingRole(((GuildChannel) channel).getGuild()).get();
|
||||
else
|
||||
coderRole = Mono.empty();
|
||||
return coderRole.map(role -> TBMCCoreAPI.IsTestServer() ? new StringBuilder()
|
||||
: new StringBuilder(role.getMention()).append("\n"))
|
||||
.defaultIfEmpty(new StringBuilder())
|
||||
.flatMap(sb -> {
|
||||
sb.append(sourcemessage).append("\n");
|
||||
sb.append("```").append("\n");
|
||||
String stackTrace = Arrays.stream(ExceptionUtils.getStackTrace(e).split("\\n"))
|
||||
.filter(s -> !s.contains("\tat ") || s.contains("\tat buttondevteam."))
|
||||
.collect(Collectors.joining("\n"));
|
||||
if (sb.length() + stackTrace.length() >= 1980)
|
||||
stackTrace = stackTrace.substring(0, 1980 - sb.length());
|
||||
sb.append(stackTrace).append("\n");
|
||||
sb.append("```");
|
||||
return channel.createMessage(sb.toString());
|
||||
});
|
||||
}).subscribe();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import lombok.val;
|
|||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.server.ServerCommandEvent;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
public class MCListener implements Listener {
|
||||
@EventHandler
|
||||
|
@ -33,13 +34,16 @@ public class MCListener implements Listener {
|
|||
DiscordPlayer dp = e.getPlayer().getAs(DiscordPlayer.class);
|
||||
if (dp == null || dp.getDiscordID() == null || dp.getDiscordID().equals(""))
|
||||
return;
|
||||
User user = DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID())).block();
|
||||
if (user == null) return;
|
||||
val userOpt = DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID())).onErrorResume(t -> Mono.empty()).blockOptional();
|
||||
if (!userOpt.isPresent()) return;
|
||||
User user = userOpt.get();
|
||||
e.addInfo("Discord tag: " + user.getUsername() + "#" + user.getDiscriminator());
|
||||
Member member = user.asMember(DiscordPlugin.mainServer.getId()).block();
|
||||
if (member == null) return;
|
||||
val pr = member.getPresence().block();
|
||||
if (pr == null) return;
|
||||
val memberOpt = user.asMember(DiscordPlugin.mainServer.getId()).onErrorResume(t -> Mono.empty()).blockOptional();
|
||||
if (!memberOpt.isPresent()) return;
|
||||
Member member = memberOpt.get();
|
||||
val prOpt = member.getPresence().blockOptional();
|
||||
if (!prOpt.isPresent()) return;
|
||||
val pr = prOpt.get();
|
||||
e.addInfo(pr.getStatus().toString());
|
||||
if (pr.getActivity().isPresent()) {
|
||||
val activity = pr.getActivity().get();
|
||||
|
|
|
@ -31,7 +31,7 @@ import java.util.stream.Collectors;
|
|||
"Use the ID (command) of the channel, for example `g` for the global chat.", //
|
||||
"To remove a connection use @ChromaBot channelcon remove in the channel.", //
|
||||
"Mentioning the bot is needed in this case because the / prefix only works in #bot.", //
|
||||
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" //
|
||||
"Invite link: <Unknown>" //
|
||||
})
|
||||
@RequiredArgsConstructor
|
||||
public class ChannelconCommand extends ICommand2DC {
|
||||
|
@ -90,6 +90,10 @@ public class ChannelconCommand extends ICommand2DC {
|
|||
@Command2.Subcommand
|
||||
public boolean def(Command2DCSender sender, String channelID) {
|
||||
val message = sender.getMessage();
|
||||
if (!module.allowCustomChat().get()) {
|
||||
sender.sendMessage("channel connection is not allowed on this Minecraft server.");
|
||||
return true;
|
||||
}
|
||||
if (checkPerms(message)) return true;
|
||||
if (MCChatCustom.hasCustomChat(message.getChannelId()))
|
||||
return respond(sender, "this channel is already connected to a Minecraft channel. Use `@ChromaBot channelcon remove` to remove it.");
|
||||
|
@ -107,7 +111,7 @@ public class ChannelconCommand extends ICommand2DC {
|
|||
return true;
|
||||
}
|
||||
val channel = message.getChannel().block();
|
||||
DiscordConnectedPlayer dcp = new DiscordConnectedPlayer(message.getAuthor().get(), channel, chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName(), module);
|
||||
DiscordConnectedPlayer dcp = DiscordConnectedPlayer.create(message.getAuthor().get(), channel, chp.getUUID(), Bukkit.getOfflinePlayer(chp.getUUID()).getName(), module);
|
||||
//Using a fake player with no login/logout, should be fine for this event
|
||||
String groupid = chan.get().getGroupID(dcp);
|
||||
if (groupid == null && !(chan.get() instanceof ChatRoom)) { //ChatRooms don't allow it unless the user joins, which happens later
|
||||
|
@ -151,7 +155,7 @@ public class ChannelconCommand extends ICommand2DC {
|
|||
"Use the ID (command) of the channel, for example `g` for the global chat.", //
|
||||
"To remove a connection use @ChromaBot channelcon remove in the channel.", //
|
||||
"Mentioning the bot is needed in this case because the " + DiscordPlugin.getPrefix() + " prefix only works in " + DPUtils.botmention() + ".", //
|
||||
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=226443037893591041&scope=bot&permissions=268509264>" // TODO: Set correct client ID
|
||||
"Invite link: <https://discordapp.com/oauth2/authorize?client_id=" + module.clientID + "&scope=bot&permissions=268509264>"
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ import buttondevteam.lib.TBMCCoreAPI;
|
|||
import buttondevteam.lib.chat.Command2;
|
||||
import buttondevteam.lib.chat.CommandClass;
|
||||
import discord4j.core.object.entity.PrivateChannel;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.val;
|
||||
|
||||
@CommandClass(helpText = {
|
||||
|
@ -17,10 +18,17 @@ import lombok.val;
|
|||
"It can be useful if you don't want your messages to be visible, for example when talking in a private channel.", //
|
||||
"You can also run all of the ingame commands you have access to using this command, if you have your accounts connected." //
|
||||
})
|
||||
@RequiredArgsConstructor
|
||||
public class MCChatCommand extends ICommand2DC {
|
||||
|
||||
private final MinecraftChatModule module;
|
||||
|
||||
@Command2.Subcommand
|
||||
public boolean def(Command2DCSender sender) {
|
||||
if (!module.allowPrivateChat().get()) {
|
||||
sender.sendMessage("using the private chat is not allowed on this Minecraft server.");
|
||||
return true;
|
||||
}
|
||||
val message = sender.getMessage();
|
||||
val channel = message.getChannel().block();
|
||||
@SuppressWarnings("OptionalGetWithoutIsPresent") val author = message.getAuthor().get();
|
||||
|
|
|
@ -10,6 +10,7 @@ import buttondevteam.discordplugin.DiscordSenderBase;
|
|||
import buttondevteam.discordplugin.listeners.CommandListener;
|
||||
import buttondevteam.discordplugin.listeners.CommonListeners;
|
||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener;
|
||||
import buttondevteam.discordplugin.playerfaker.VanillaCommandListener14;
|
||||
import buttondevteam.discordplugin.util.Timings;
|
||||
import buttondevteam.lib.*;
|
||||
import buttondevteam.lib.chat.ChatMessage;
|
||||
|
@ -78,7 +79,7 @@ public class MCChatListener implements Listener {
|
|||
|
||||
final String authorPlayer = "[" + DPUtils.sanitizeStringNoEscape(e.getChannel().DisplayName().get()) + "] " //
|
||||
+ ("Minecraft".equals(e.getOrigin()) ? "" : "[" + e.getOrigin().substring(0, 1) + "]") //
|
||||
+ (DPUtils.sanitizeStringNoEscape(ThorpeUtils.getDisplayName(e.getSender())));
|
||||
+ (DPUtils.sanitizeStringNoEscape(ChromaUtils.getDisplayName(e.getSender())));
|
||||
val color = e.getChannel().Color().get();
|
||||
final Consumer<EmbedCreateSpec> embed = ecs -> {
|
||||
ecs.setDescription(e.getMessage()).setColor(new Color(color.getRed(),
|
||||
|
@ -232,8 +233,8 @@ public class MCChatListener implements Listener {
|
|||
timings.printElapsed("Filter 1");
|
||||
return !(ev.getMessage().getChannelId().asLong() != module.chatChannel().get().asLong()
|
||||
&& !(channel instanceof PrivateChannel
|
||||
&& author.map(u -> MCChatPrivate.isMinecraftChatEnabled(u.getId().asString())).orElse(false)
|
||||
&& !hasCustomChat)); //Chat isn't enabled on this channel
|
||||
&& author.map(u -> MCChatPrivate.isMinecraftChatEnabled(u.getId().asString())).orElse(false))
|
||||
&& !hasCustomChat); //Chat isn't enabled on this channel
|
||||
}).filter(channel -> {
|
||||
timings.printElapsed("Filter 2");
|
||||
return !(channel instanceof PrivateChannel //Only in private chat
|
||||
|
@ -277,10 +278,11 @@ public class MCChatListener implements Listener {
|
|||
|
||||
for (User u : event.getMessage().getUserMentions().toIterable()) { //TODO: Role mentions
|
||||
dmessage = dmessage.replace(u.getMention(), "@" + u.getUsername()); // TODO: IG Formatting
|
||||
val m = u.asMember(DiscordPlugin.mainServer.getId()).block();
|
||||
if (m != null) {
|
||||
final String nick = m.getDisplayName();
|
||||
dmessage = dmessage.replace(m.getNicknameMention(), "@" + nick);
|
||||
val m = u.asMember(DiscordPlugin.mainServer.getId()).onErrorResume(t -> Mono.empty()).blockOptional();
|
||||
if (m.isPresent()) {
|
||||
val mm = m.get();
|
||||
final String nick = mm.getDisplayName();
|
||||
dmessage = dmessage.replace(mm.getNicknameMention(), "@" + nick);
|
||||
}
|
||||
}
|
||||
for (GuildChannel ch : event.getGuild().flux().flatMap(Guild::getChannels).toIterable()) {
|
||||
|
@ -321,7 +323,8 @@ public class MCChatListener implements Listener {
|
|||
return;
|
||||
}
|
||||
val ev = new TBMCCommandPreprocessEvent(dsender, dmessage);
|
||||
Bukkit.getPluginManager().callEvent(ev);
|
||||
Bukkit.getScheduler().runTask(DiscordPlugin.plugin, () ->
|
||||
Bukkit.getPluginManager().callEvent(ev));
|
||||
if (ev.isCancelled())
|
||||
return;
|
||||
int spi = cmdlowercased.indexOf(' ');
|
||||
|
@ -338,8 +341,18 @@ public class MCChatListener implements Listener {
|
|||
if (clmd != null) {
|
||||
channel.set(clmd.mcchannel); //Hack to send command in the channel
|
||||
} //TODO: Permcheck isn't implemented for commands
|
||||
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
|
||||
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmdlowercased);
|
||||
try {
|
||||
String mcpackage = Bukkit.getServer().getClass().getPackage().getName();
|
||||
if (mcpackage.contains("1_12"))
|
||||
VanillaCommandListener.runBukkitOrVanillaCommand(dsender, cmd);
|
||||
else if (mcpackage.contains("1_14"))
|
||||
VanillaCommandListener14.runBukkitOrVanillaCommand(dsender, cmd);
|
||||
else
|
||||
Bukkit.dispatchCommand(dsender, cmd);
|
||||
} catch (NoClassDefFoundError e) {
|
||||
TBMCCoreAPI.SendException("A class is not found when trying to run command " + cmd + "!", e);
|
||||
}
|
||||
Bukkit.getLogger().info(dsender.getName() + " issued command from Discord: /" + cmd);
|
||||
if (clmd != null)
|
||||
channel.set(chtmp);
|
||||
});
|
||||
|
|
|
@ -26,7 +26,7 @@ public class MCChatPrivate {
|
|||
val op = Bukkit.getOfflinePlayer(mcp.getUUID());
|
||||
val mcm = ComponentManager.getIfEnabled(MinecraftChatModule.class);
|
||||
if (start) {
|
||||
val sender = new DiscordConnectedPlayer(user, channel, mcp.getUUID(), op.getName(), mcm);
|
||||
val sender = DiscordConnectedPlayer.create(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
|
||||
MCChatUtils.callLoginEvents(sender);
|
||||
|
|
|
@ -10,7 +10,6 @@ import discord4j.core.object.entity.*;
|
|||
import discord4j.core.object.util.Snowflake;
|
||||
import io.netty.util.collection.LongObjectHashMap;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.experimental.var;
|
||||
import lombok.val;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
|
@ -53,7 +52,8 @@ public class MCChatUtils {
|
|||
private static HashMap<Class<? extends Event>, HashSet<String>> staticExcludedPlugins = new HashMap<>();
|
||||
|
||||
public static void updatePlayerList() {
|
||||
if (notEnabled()) return;
|
||||
val mod = getModule();
|
||||
if (mod == null || !mod.showPlayerListOnDC().get()) return;
|
||||
if (lastmsgdata != null)
|
||||
updatePL(lastmsgdata);
|
||||
MCChatCustom.lastmsgCustom.forEach(MCChatUtils::updatePL);
|
||||
|
@ -180,7 +180,10 @@ public class MCChatUtils {
|
|||
}
|
||||
|
||||
public static Consumer<Mono<MessageChannel>> send(String message) {
|
||||
return ch -> ch.flatMap(mc -> mc.createMessage(DPUtils.sanitizeString(message))).subscribe();
|
||||
return ch -> ch.flatMap(mc -> {
|
||||
resetLastMessage(mc);
|
||||
return mc.createMessage(DPUtils.sanitizeString(message));
|
||||
}).subscribe();
|
||||
}
|
||||
|
||||
public static void forAllowedMCChat(Consumer<Mono<MessageChannel>> action, TBMCSystemChatEvent event) {
|
||||
|
|
|
@ -18,13 +18,15 @@ 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.PlayerCommandSendEvent;
|
||||
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 org.bukkit.event.server.TabCompleteEvent;
|
||||
import reactor.core.publisher.Flux;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
|
@ -50,11 +52,13 @@ class MCListener implements Listener {
|
|||
final Player p = e.getPlayer();
|
||||
DiscordPlayer dp = e.GetPlayer().getAs(DiscordPlayer.class);
|
||||
if (dp != null) {
|
||||
val user = DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID())).block();
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, Objects.requireNonNull(user).getPrivateChannel().block(), p)); //TODO: Don't block
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, module.chatChannelMono().block(), p)); //Stored per-channel
|
||||
DiscordPlugin.dc.getUserById(Snowflake.of(dp.getDiscordID())).flatMap(user -> user.getPrivateChannel().flatMap(chan -> module.chatChannelMono().flatMap(cc -> {
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, chan, p));
|
||||
MCChatUtils.addSender(MCChatUtils.OnlineSenders, dp.getDiscordID(),
|
||||
new DiscordPlayerSender(user, cc, p)); //Stored per-channel
|
||||
return Mono.empty();
|
||||
}))).subscribe();
|
||||
}
|
||||
final String message = e.GetPlayer().PlayerName().get() + " joined the game";
|
||||
MCChatUtils.forAllowedCustomAndAllMCChat(MCChatUtils.send(message), e.getPlayer(), ChannelconBroadcast.JOINLEAVE, true);
|
||||
|
@ -114,7 +118,7 @@ class MCListener implements Listener {
|
|||
final DiscordPlayer p = TBMCPlayerBase.getPlayer(source.getPlayer().getUniqueId(), TBMCPlayer.class)
|
||||
.getAs(DiscordPlayer.class);
|
||||
if (p == null) return;
|
||||
DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID()))
|
||||
DPUtils.ignoreError(DiscordPlugin.dc.getUserById(Snowflake.of(p.getDiscordID()))
|
||||
.flatMap(user -> user.asMember(DiscordPlugin.mainServer.getId()))
|
||||
.flatMap(user -> role.flatMap(r -> {
|
||||
if (e.getValue())
|
||||
|
@ -127,7 +131,7 @@ class MCListener implements Listener {
|
|||
if (modlog != null)
|
||||
return modlog.flatMap(ch -> ch.createMessage(msg));
|
||||
return Mono.empty();
|
||||
})).subscribe();
|
||||
}))).subscribe();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
|
@ -154,4 +158,26 @@ class MCListener implements Listener {
|
|||
public void onNickChange(NickChangeEvent event) {
|
||||
MCChatUtils.updatePlayerList();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onTabComplete(TabCompleteEvent event) {
|
||||
int i = event.getBuffer().lastIndexOf(' ');
|
||||
String t = event.getBuffer().substring(i + 1); //0 if not found
|
||||
//System.out.println("Last token: " + t);
|
||||
if (!t.startsWith("@"))
|
||||
return;
|
||||
String token = t.substring(1);
|
||||
//System.out.println("Token: " + token);
|
||||
val x = DiscordPlugin.mainServer.getMembers()
|
||||
.flatMap(m -> Flux.just(m.getUsername(), m.getNickname().orElse("")))
|
||||
.filter(s -> s.startsWith(token))
|
||||
.map(s -> "@" + s)
|
||||
.doOnNext(event.getCompletions()::add).blockLast();
|
||||
//System.out.println("Finished - last: " + x);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onCommandSend(PlayerCommandSendEvent event) {
|
||||
event.getCommands().add("g");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,14 +77,44 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
|
|||
return getConfig().getData("allowFakePlayerTeleports", false);
|
||||
}
|
||||
|
||||
/**
|
||||
* If this is on, each chat channel will have a player list in their description.
|
||||
* It only gets added if there's no description yet or there are (at least) two lines of "----" following each other.
|
||||
* Note that it will replace <b>everything</b> between the first and last "----" but it will only detect exactly four dashes.
|
||||
* So if you want to use dashes for something else in the description, make sure it's either less or more dashes in one line.
|
||||
*/
|
||||
public ConfigData<Boolean> showPlayerListOnDC() {
|
||||
return getConfig().getData("showPlayerListOnDC", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This setting controls whether custom chat connections can be <i>created</i> (existing connections will always work).
|
||||
* Custom chat connections can be created using the channelcon command and they allow players to display town chat in a Discord channel for example.
|
||||
* See the channelcon command for more details.
|
||||
*/
|
||||
public ConfigData<Boolean> allowCustomChat() {
|
||||
return getConfig().getData("allowCustomChat", true);
|
||||
}
|
||||
|
||||
/**
|
||||
* This setting allows you to control if players can DM the bot to log on the server from Discord.
|
||||
* This allows them to both chat and perform any command they can in-game.
|
||||
*/
|
||||
public ConfigData<Boolean> allowPrivateChat() {
|
||||
return getConfig().getData("allowPrivateChat", true);
|
||||
}
|
||||
|
||||
String clientID;
|
||||
|
||||
@Override
|
||||
protected void enable() {
|
||||
if (DPUtils.disableIfConfigErrorRes(this, chatChannel(), chatChannelMono()))
|
||||
return;
|
||||
DiscordPlugin.dc.getApplicationInfo().subscribe(info -> clientID = info.getId().asString());
|
||||
listener = new MCChatListener(this);
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(listener, getPlugin());
|
||||
TBMCCoreAPI.RegisterEventsForExceptions(new MCListener(this), getPlugin());//These get undone if restarting/resetting - it will ignore events if disabled
|
||||
getPlugin().getManager().registerCommand(new MCChatCommand());
|
||||
getPlugin().getManager().registerCommand(new MCChatCommand(this));
|
||||
getPlugin().getManager().registerCommand(new ChannelconCommand(this));
|
||||
|
||||
val chcons = getConfig().getConfig().getConfigurationSection("chcons");
|
||||
|
@ -104,7 +134,7 @@ public class MinecraftChatModule extends Component<DiscordPlugin> {
|
|||
if (!mcch.isPresent() || ch == null || user == null || groupid == null)
|
||||
continue;
|
||||
Bukkit.getScheduler().runTask(getPlugin(), () -> { //<-- Needed because of occasional ConcurrentModificationExceptions when creating the player (PermissibleBase)
|
||||
val dcp = new DiscordConnectedPlayer(user, (MessageChannel) ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this);
|
||||
val dcp = DiscordConnectedPlayer.create(user, (MessageChannel) ch, UUID.fromString(chcon.getString("mcuid")), chcon.getString("mcname"), this);
|
||||
MCChatCustom.addCustomChat((MessageChannel) ch, groupid, mcch.get(), user, dcp, toggles, brtoggles.stream().map(TBMCSystemChatEvent.BroadcastTarget::get).filter(Objects::nonNull).collect(Collectors.toSet()));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,308 +0,0 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.discordplugin.DiscordSenderBase;
|
||||
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.block.PistonMoveReaction;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.entity.EntityDamageEvent;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
|
||||
import org.bukkit.metadata.MetadataValue;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
@SuppressWarnings("deprecated")
|
||||
public abstract class DiscordEntity extends DiscordSenderBase implements Entity {
|
||||
protected DiscordEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
|
||||
super(user, channel);
|
||||
this.entityId = entityId;
|
||||
uniqueId = uuid;
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
private HashMap<String, MetadataValue> metadata = new HashMap<String, MetadataValue>();
|
||||
|
||||
private Location location = new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
|
||||
private Vector velocity;
|
||||
private final int entityId;
|
||||
private EntityDamageEvent lastDamageCause;
|
||||
private final Set<String> scoreboardTags = new HashSet<String>();
|
||||
private final UUID uniqueId;
|
||||
private final MinecraftChatModule module;
|
||||
|
||||
@Override
|
||||
public void setMetadata(String metadataKey, MetadataValue newMetadataValue) {
|
||||
metadata.put(metadataKey, newMetadataValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<MetadataValue> getMetadata(String metadataKey) {
|
||||
return Collections.singletonList(metadata.get(metadataKey)); // Who needs multiple data anyways
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasMetadata(String metadataKey) {
|
||||
return metadata.containsKey(metadataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeMetadata(String metadataKey, Plugin owningPlugin) {
|
||||
metadata.remove(metadataKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation(Location loc) {
|
||||
if (loc != null) {
|
||||
loc.setWorld(getWorld());
|
||||
loc.setX(location.getX());
|
||||
loc.setY(location.getY());
|
||||
loc.setZ(location.getZ());
|
||||
loc.setYaw(location.getYaw());
|
||||
loc.setPitch(location.getPitch());
|
||||
}
|
||||
|
||||
return loc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getWidth() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnGround() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld() {
|
||||
return location.getWorld();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Location location) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = location;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Location location, TeleportCause cause) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = location;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Entity destination) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = destination.getLocation();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean teleport(Entity destination, TeleportCause cause) {
|
||||
if (module.allowFakePlayerTeleports().get())
|
||||
this.location = destination.getLocation();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> getNearbyEntities(double x, double y, double z) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFireTicks() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxFireTicks() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFireTicks(int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() { // Impossible to kill
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Server getServer() {
|
||||
return Bukkit.getServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getPassenger() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setPassenger(Entity passenger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> getPassengers() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPassenger(Entity passenger) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removePassenger(Entity passenger) { // Don't support passengers
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean eject() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFallDistance() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFallDistance(float distance) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTicksLived() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTicksLived(int value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(EntityEffect type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInsideVehicle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean leaveVehicle() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getVehicle() { // Don't support vehicles
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomNameVisible(boolean flag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCustomNameVisible() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGlowing(boolean flag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGlowing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setInvulnerable(boolean flag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInvulnerable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSilent() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSilent(boolean flag) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGravity() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGravity(boolean gravity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPortalCooldown() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPortalCooldown(int cooldown) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addScoreboardTag(String tag) {
|
||||
return scoreboardTags.add(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeScoreboardTag(String tag) {
|
||||
return scoreboardTags.remove(tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PistonMoveReaction getPistonMoveReaction() {
|
||||
return PistonMoveReaction.IGNORE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity.Spigot spigot() {
|
||||
return new Entity.Spigot();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,733 +0,0 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.Delegate;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.advancement.Advancement;
|
||||
import org.bukkit.advancement.AdvancementProgress;
|
||||
import org.bukkit.conversations.Conversation;
|
||||
import org.bukkit.conversations.ConversationAbandonedEvent;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.player.AsyncPlayerChatEvent;
|
||||
import org.bukkit.map.MapView;
|
||||
import org.bukkit.permissions.PermissibleBase;
|
||||
import org.bukkit.permissions.ServerOperator;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.scoreboard.Scoreboard;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class DiscordFakePlayer extends DiscordHumanEntity implements Player {
|
||||
protected DiscordFakePlayer(User user, MessageChannel channel, int entityId, UUID uuid, String mcname, MinecraftChatModule module) {
|
||||
super(user, channel, entityId, uuid, module);
|
||||
origPerm = perm = new PermissibleBase(basePlayer = Bukkit.getOfflinePlayer(uuid));
|
||||
name = mcname;
|
||||
}
|
||||
|
||||
@Delegate(excludes = ServerOperator.class)
|
||||
private PermissibleBase origPerm;
|
||||
|
||||
private @Getter String name;
|
||||
|
||||
private @Getter OfflinePlayer basePlayer;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private PermissibleBase perm;
|
||||
|
||||
public void setOp(boolean value) { //CraftPlayer-compatible implementation
|
||||
this.origPerm.setOp(value);
|
||||
this.perm.recalculatePermissions();
|
||||
}
|
||||
|
||||
public boolean isOp() { return this.origPerm.isOp(); }
|
||||
|
||||
@Override
|
||||
public EntityType getType() {
|
||||
return EntityType.PLAYER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCustomName() {
|
||||
return user.getUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCustomName(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isConversing() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acceptConversationInput(String input) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean beginConversation(Conversation conversation) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abandonConversation(Conversation conversation) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void abandonConversation(Conversation conversation, ConversationAbandonedEvent details) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isOnline() {
|
||||
return true;// Let's pretend
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBanned() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWhitelisted() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWhitelisted(boolean value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getFirstPlayed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getLastPlayed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPlayedBefore() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> serialize() {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendPluginMessage(Plugin source, String channel, byte[] message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getListeningPluginChannels() {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDisplayName() {
|
||||
return Objects.requireNonNull(user.asMember(DiscordPlugin.mainServer.getId()).block()).getDisplayName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisplayName(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPlayerListName() {
|
||||
return getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerListName(String name) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompassTarget(Location loc) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getCompassTarget() {
|
||||
return new Location(Bukkit.getWorlds().get(0), 0, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InetSocketAddress getAddress() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendRawMessage(String message) {
|
||||
sendMessage(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void kickPlayer(String message) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void chat(String msg) {
|
||||
Bukkit.getPluginManager()
|
||||
.callEvent(new AsyncPlayerChatEvent(true, this, msg, new HashSet<>(Bukkit.getOnlinePlayers())));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performCommand(String command) {
|
||||
return Bukkit.getServer().dispatchCommand(this, command);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSneaking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSneaking(boolean sneak) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSprinting() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSprinting(boolean sprinting) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void saveData() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadData() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSleepingIgnored(boolean isSleeping) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSleepingIgnored() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playNote(Location loc, byte instrument, byte note) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playNote(Location loc, Instrument instrument, Note note) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Location location, Sound sound, float volume, float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Location location, String sound, float volume, float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Location location, Sound sound, SoundCategory category, float volume, float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(Location location, String sound, SoundCategory category, float volume, float pitch) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(Sound sound) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(String sound) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(Sound sound, SoundCategory category) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopSound(String sound, SoundCategory category) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playEffect(Location loc, Effect effect, int data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void playEffect(Location loc, Effect effect, T data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockChange(Location loc, Material material, byte data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean sendChunkChange(Location loc, int sx, int sy, int sz, byte[] data) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendBlockChange(Location loc, int material, byte data) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendSignChange(Location loc, String[] lines) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMap(MapView map) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateInventory() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void awardAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAchievement(@SuppressWarnings("deprecation") Achievement achievement) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic, int amount) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic, int amount) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatistic(Statistic statistic, int newValue) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatistic(Statistic statistic) throws IllegalArgumentException {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatistic(Statistic statistic, Material material) throws IllegalArgumentException {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic, Material material, int amount) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatistic(Statistic statistic, Material material, int newValue) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStatistic(Statistic statistic, EntityType entityType) throws IllegalArgumentException {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void incrementStatistic(Statistic statistic, EntityType entityType, int amount)
|
||||
throws IllegalArgumentException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void decrementStatistic(Statistic statistic, EntityType entityType, int amount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatistic(Statistic statistic, EntityType entityType, int newValue) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerTime(long time, boolean relative) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPlayerTime() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPlayerTimeOffset() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerTimeRelative() {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPlayerTime() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPlayerWeather(WeatherType type) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public WeatherType getPlayerWeather() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetPlayerWeather() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveExp(int amount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void giveExpLevels(int amount) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExp() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExp(float exp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLevel() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLevel(int level) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getTotalExperience() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTotalExperience(int exp) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getExhaustion() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExhaustion(float value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSaturation() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSaturation(float value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFoodLevel() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFoodLevel(int value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getBedSpawnLocation() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBedSpawnLocation(Location location) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBedSpawnLocation(Location location, boolean force) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAllowFlight() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAllowFlight(boolean flight) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void hidePlayer(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showPlayer(Player player) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canSee(Player player) { // Nobody can see them
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFlying() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlying(boolean value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFlySpeed(float value) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setWalkSpeed(float value) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getFlySpeed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getWalkSpeed() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTexturePack(String url) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourcePack(String url) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setResourcePack(String url, byte[] hash) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Scoreboard getScoreboard() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setScoreboard(Scoreboard scoreboard) throws IllegalArgumentException, IllegalStateException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHealthScaled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHealthScaled(boolean scale) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHealthScale(double scale) throws IllegalArgumentException {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHealthScale() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getSpectatorTarget() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSpectatorTarget(Entity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String subtitle) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendTitle(String title, String subtitle, int fadeIn, int stay, int fadeOut) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetTitle() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int count) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double x, double y, double z, int count) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int count, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
|
||||
double offsetZ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
|
||||
double offsetY, double offsetZ) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
|
||||
double offsetZ, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
|
||||
double offsetY, double offsetZ, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
|
||||
double offsetZ, double extra) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
|
||||
double offsetY, double offsetZ, double extra) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, Location location, int count, double offsetX, double offsetY,
|
||||
double offsetZ, double extra, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> void spawnParticle(Particle particle, double x, double y, double z, int count, double offsetX,
|
||||
double offsetY, double offsetZ, double extra, T data) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public AdvancementProgress getAdvancementProgress(Advancement advancement) { // TODO: Test
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocale() {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player.Spigot spigot() {
|
||||
return new Player.Spigot();
|
||||
}
|
||||
}
|
|
@ -1,168 +0,0 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.entity.Villager;
|
||||
import org.bukkit.inventory.*;
|
||||
import org.bukkit.inventory.InventoryView.Property;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public abstract class DiscordHumanEntity extends DiscordLivingEntity implements HumanEntity {
|
||||
protected DiscordHumanEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
|
||||
super(user, channel, entityId, uuid, module);
|
||||
}
|
||||
|
||||
private PlayerInventory inv = new DiscordPlayerInventory(this);
|
||||
|
||||
@Override
|
||||
public PlayerInventory getInventory() {
|
||||
return inv;
|
||||
}
|
||||
|
||||
private Inventory enderchest = new DiscordInventory(this);
|
||||
|
||||
@Override
|
||||
public Inventory getEnderChest() {
|
||||
return enderchest;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MainHand getMainHand() {
|
||||
return MainHand.RIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setWindowProperty(Property prop, int value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView getOpenInventory() { // TODO: Test
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openInventory(Inventory inventory) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openWorkbench(Location location, boolean force) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openEnchanting(Location location, boolean force) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openInventory(InventoryView inventory) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openMerchant(Villager trader, boolean force) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryView openMerchant(Merchant merchant, boolean force) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void closeInventory() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand() { // TODO: Test all ItemStack methods
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(ItemStack item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemOnCursor() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemOnCursor(ItemStack item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCooldown(Material material) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCooldown(Material material) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCooldown(Material material, int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSleeping() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSleepTicks() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GameMode getGameMode() {
|
||||
return GameMode.SPECTATOR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameMode(GameMode mode) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlocking() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isHandRaised() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getExpToLevel() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getShoulderEntityLeft() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShoulderEntityLeft(Entity entity) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getShoulderEntityRight() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setShoulderEntityRight(Entity entity) {
|
||||
}
|
||||
|
||||
}
|
108
src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java
Executable file → Normal file
108
src/main/java/buttondevteam/discordplugin/playerfaker/DiscordInventory.java
Executable file → Normal file
|
@ -1,110 +1,110 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.HumanEntity;
|
||||
import org.bukkit.event.inventory.InventoryType;
|
||||
import org.bukkit.inventory.Inventory;
|
||||
import org.bukkit.inventory.InventoryHolder;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class DiscordInventory implements Inventory {
|
||||
public DiscordInventory(DiscordHumanEntity holder) {
|
||||
this.holder = holder;
|
||||
}
|
||||
private ItemStack[] items = new ItemStack[27];
|
||||
private List<ItemStack> itemStacks = Arrays.asList(items);
|
||||
@Getter
|
||||
@Setter
|
||||
public int maxStackSize;
|
||||
private static ItemStack emptyStack = new ItemStack(Material.AIR, 0);
|
||||
|
||||
@Override
|
||||
public int getSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaxStackSize() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxStackSize(int size) {
|
||||
return items.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "Player inventory";
|
||||
return "Discord inventory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItem(int index) {
|
||||
return null;
|
||||
if (index >= items.length)
|
||||
return emptyStack;
|
||||
else
|
||||
return items[index];
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> addItem(ItemStack... items) throws IllegalArgumentException { // Can't add anything
|
||||
return new HashMap<>(
|
||||
IntStream.range(0, items.length).boxed().collect(Collectors.toMap(i -> i, i -> items[i])));
|
||||
public void setItem(int index, ItemStack item) {
|
||||
if (index < items.length)
|
||||
items[index] = item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> addItem(ItemStack... items) throws IllegalArgumentException {
|
||||
return IntStream.range(0, items.length).collect(HashMap::new, (map, i) -> map.put(i, items[i]), HashMap::putAll); //Pretend that we can't add anything
|
||||
}
|
||||
|
||||
@Override
|
||||
public HashMap<Integer, ItemStack> removeItem(ItemStack... items) throws IllegalArgumentException {
|
||||
return new HashMap<>(
|
||||
IntStream.range(0, items.length).boxed().collect(Collectors.toMap(i -> i, i -> items[i])));
|
||||
return IntStream.range(0, items.length).collect(HashMap::new, (map, i) -> map.put(i, items[i]), HashMap::putAll); //Pretend that we can't add anything
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getContents() {
|
||||
return new ItemStack[0];
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setContents(ItemStack[] items) throws IllegalArgumentException {
|
||||
if (items.length > 0)
|
||||
throw new IllegalArgumentException("This inventory does not support items");
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getStorageContents() {
|
||||
return new ItemStack[0];
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStorageContents(ItemStack[] items) throws IllegalArgumentException {
|
||||
if (items.length > 0)
|
||||
throw new IllegalArgumentException("This inventory does not support items");
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean contains(int materialId) {
|
||||
return false;
|
||||
return itemStacks.stream().anyMatch(is -> is.getType().getId() == materialId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Material material) throws IllegalArgumentException {
|
||||
return false;
|
||||
return itemStacks.stream().anyMatch(is -> is.getType() == material);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ItemStack item) {
|
||||
return false;
|
||||
return itemStacks.stream().anyMatch(is -> is.getType() == item.getType() && is.getAmount() == item.getAmount());
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public boolean contains(int materialId, int amount) {
|
||||
return false;
|
||||
return itemStacks.stream().anyMatch(is -> is.getType().getId() == materialId && is.getAmount() == amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Material material, int amount) throws IllegalArgumentException {
|
||||
return false;
|
||||
return itemStacks.stream().anyMatch(is -> is.getType() == material && is.getAmount() == amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(ItemStack item, int amount) {
|
||||
return false;
|
||||
public boolean contains(ItemStack item, int amount) { //Not correct implementation but whatever
|
||||
return itemStacks.stream().anyMatch(is -> is.getType() == item.getType() && is.getAmount() == amount);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -161,52 +161,48 @@ public class DiscordInventory implements Inventory {
|
|||
|
||||
@Override
|
||||
public void clear(int index) {
|
||||
if (index < items.length)
|
||||
items[index] = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(items, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<HumanEntity> getViewers() {
|
||||
return new ArrayList<>(0);
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTitle() {
|
||||
return "Player inventory";
|
||||
return "Discord inventory";
|
||||
}
|
||||
|
||||
@Override
|
||||
public InventoryType getType() {
|
||||
return InventoryType.PLAYER;
|
||||
return InventoryType.CHEST;
|
||||
}
|
||||
|
||||
private ListIterator<ItemStack> iterator = new ArrayList<ItemStack>(0).listIterator();
|
||||
@Override
|
||||
public InventoryHolder getHolder() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("NullableProblems")
|
||||
@Override
|
||||
public ListIterator<ItemStack> iterator() {
|
||||
return iterator;
|
||||
return itemStacks.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<ItemStack> iterator(int index) {
|
||||
return iterator;
|
||||
return itemStacks.listIterator(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getLocation() {
|
||||
return holder.getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItem(int index, ItemStack item) {
|
||||
}
|
||||
|
||||
private HumanEntity holder;
|
||||
|
||||
@Override
|
||||
public HumanEntity getHolder() {
|
||||
return holder;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,298 +0,0 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.mcchat.MinecraftChatModule;
|
||||
import discord4j.core.object.entity.MessageChannel;
|
||||
import discord4j.core.object.entity.User;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.LivingEntity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.Projectile;
|
||||
import org.bukkit.inventory.EntityEquipment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.potion.PotionEffect;
|
||||
import org.bukkit.potion.PotionEffectType;
|
||||
import org.bukkit.util.Vector;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public abstract class DiscordLivingEntity extends DiscordEntity implements LivingEntity {
|
||||
|
||||
protected DiscordLivingEntity(User user, MessageChannel channel, int entityId, UUID uuid, MinecraftChatModule module) {
|
||||
super(user, channel, entityId, uuid, module);
|
||||
}
|
||||
|
||||
private @Getter EntityEquipment equipment = new DiscordEntityEquipment(this);
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private static class DiscordEntityEquipment implements EntityEquipment {
|
||||
|
||||
private float leggingsDropChance;
|
||||
private ItemStack leggings;
|
||||
private float itemInOffHandDropChance;
|
||||
private ItemStack itemInOffHand;
|
||||
private float itemInMainHandDropChance;
|
||||
private ItemStack itemInMainHand;
|
||||
private float itemInHandDropChance;
|
||||
private ItemStack itemInHand;
|
||||
private float helmetDropChance;
|
||||
private ItemStack helmet;
|
||||
private float chestplateDropChance;
|
||||
private ItemStack chestplate;
|
||||
private float bootsDropChance;
|
||||
private ItemStack boots;
|
||||
private ItemStack[] armorContents = new ItemStack[0]; // TODO
|
||||
private final Entity holder;
|
||||
|
||||
public DiscordEntityEquipment(Entity holder) {
|
||||
this.holder = holder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
armorContents = new ItemStack[0];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributeInstance getAttribute(Attribute attribute) { // We don't support any attributes
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(double amount) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void damage(double amount, Entity source) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getHealth() {
|
||||
return getMaxHealth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHealth(double health) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getMaxHealth() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaxHealth(double health) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetMaxHealth() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends Projectile> T launchProjectile(Class<? extends T> projectile, Vector velocity) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEyeHeight() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getEyeHeight(boolean ignoreSneaking) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Location getEyeLocation() {
|
||||
return getLocation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> getLineOfSight(Set<Material> transparent, int maxDistance) {
|
||||
return Arrays.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getTargetBlock(HashSet<Byte> transparent, int maxDistance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Block getTargetBlock(Set<Material> transparent, int maxDistance) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> getLastTwoTargetBlocks(HashSet<Byte> transparent, int maxDistance) {
|
||||
return Arrays.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Block> getLastTwoTargetBlocks(Set<Material> transparent, int maxDistance) {
|
||||
return Arrays.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRemainingAir() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemainingAir(int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumAir() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximumAir(int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumNoDamageTicks() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximumNoDamageTicks(int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getLastDamage() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLastDamage(double damage) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNoDamageTicks() {
|
||||
return 100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setNoDamageTicks(int ticks) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getKiller() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPotionEffect(PotionEffect effect) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPotionEffect(PotionEffect effect, boolean force) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addPotionEffects(Collection<PotionEffect> effects) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPotionEffect(PotionEffectType type) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PotionEffect getPotionEffect(PotionEffectType type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removePotionEffect(PotionEffectType type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<PotionEffect> getActivePotionEffects() {
|
||||
return Arrays.asList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLineOfSight(Entity other) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getRemoveWhenFarAway() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRemoveWhenFarAway(boolean remove) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCanPickupItems(boolean pickup) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getCanPickupItems() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLeashed() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entity getLeashHolder() throws IllegalStateException {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setLeashHolder(Entity holder) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGliding() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGliding(boolean gliding) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAI(boolean ai) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasAI() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCollidable(boolean collidable) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCollidable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,105 +0,0 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.PlayerInventory;
|
||||
|
||||
public class DiscordPlayerInventory extends DiscordInventory implements PlayerInventory {
|
||||
public DiscordPlayerInventory(DiscordHumanEntity holder) {
|
||||
super(holder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getArmorContents() {
|
||||
return new ItemStack[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack[] getExtraContents() {
|
||||
return new ItemStack[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getHelmet() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getChestplate() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getLeggings() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getBoots() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setArmorContents(ItemStack[] items) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setExtraContents(ItemStack[] items) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHelmet(ItemStack helmet) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChestplate(ItemStack chestplate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLeggings(ItemStack leggings) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBoots(ItemStack boots) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInMainHand() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInMainHand(ItemStack item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInOffHand() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInOffHand(ItemStack item) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getItemInHand() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setItemInHand(ItemStack stack) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeldItemSlot() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeldItemSlot(int slot) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int clear(int id, int data) {
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordSenderBase;
|
||||
import buttondevteam.discordplugin.IMCPlayer;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
@RequiredArgsConstructor
|
||||
public class VCMDWrapper {
|
||||
@Getter //Needed to mock the player
|
||||
private final Object listener;
|
||||
|
||||
/**
|
||||
* This constructor will only send raw vanilla messages to the sender in plain text.
|
||||
*
|
||||
* @param player The Discord sender player (the wrapper)
|
||||
*/
|
||||
public static <T extends DiscordSenderBase & IMCPlayer<T>> Object createListener(T player) {
|
||||
return createListener(player, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor will send both raw vanilla messages to the sender in plain text and forward the raw message to the provided player.
|
||||
*
|
||||
* @param player The Discord sender player (the wrapper)
|
||||
* @param bukkitplayer The Bukkit player to send the raw message to
|
||||
*/
|
||||
public static <T extends DiscordSenderBase & IMCPlayer<T>> Object createListener(T player, Player bukkitplayer) {
|
||||
String mcpackage = Bukkit.getServer().getClass().getPackage().getName();
|
||||
if (mcpackage.contains("1_12"))
|
||||
return bukkitplayer == null ? new VanillaCommandListener<>(player) : new VanillaCommandListener<>(player, bukkitplayer);
|
||||
else if (mcpackage.contains("1_14"))
|
||||
return bukkitplayer == null ? new VanillaCommandListener14<>(player) : new VanillaCommandListener14<>(player, bukkitplayer);
|
||||
else
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -87,7 +87,7 @@ public class VanillaCommandListener<T extends DiscordSenderBase & IMCPlayer<T>>
|
|||
if (!vcmd.testPermission(sender))
|
||||
return true;
|
||||
|
||||
ICommandListener icommandlistener = sender.getVanillaCmdListener();
|
||||
ICommandListener icommandlistener = (ICommandListener) sender.getVanillaCmdListener().getListener();
|
||||
String[] args = cmdstr.split(" ");
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,106 @@
|
|||
package buttondevteam.discordplugin.playerfaker;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordSenderBase;
|
||||
import buttondevteam.discordplugin.IMCPlayer;
|
||||
import lombok.Getter;
|
||||
import lombok.val;
|
||||
import net.minecraft.server.v1_14_R1.*;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftServer;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.CraftWorld;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.command.ProxiedNativeCommandSender;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.command.VanillaCommandWrapper;
|
||||
import org.bukkit.craftbukkit.v1_14_R1.entity.CraftPlayer;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class VanillaCommandListener14<T extends DiscordSenderBase & IMCPlayer<T>> implements ICommandListener {
|
||||
private @Getter T player;
|
||||
private Player bukkitplayer;
|
||||
|
||||
/**
|
||||
* This constructor will only send raw vanilla messages to the sender in plain text.
|
||||
*
|
||||
* @param player The Discord sender player (the wrapper)
|
||||
*/
|
||||
public VanillaCommandListener14(T player) {
|
||||
this.player = player;
|
||||
this.bukkitplayer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This constructor will send both raw vanilla messages to the sender in plain text and forward the raw message to the provided player.
|
||||
*
|
||||
* @param player The Discord sender player (the wrapper)
|
||||
* @param bukkitplayer The Bukkit player to send the raw message to
|
||||
*/
|
||||
public VanillaCommandListener14(T player, Player bukkitplayer) {
|
||||
this.player = player;
|
||||
this.bukkitplayer = bukkitplayer;
|
||||
if (!(bukkitplayer instanceof CraftPlayer))
|
||||
throw new ClassCastException("bukkitplayer must be a Bukkit player!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(IChatBaseComponent arg0) {
|
||||
player.sendMessage(arg0.getString());
|
||||
if (bukkitplayer != null)
|
||||
((CraftPlayer) bukkitplayer).getHandle().sendMessage(arg0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSendSuccess() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldSendFailure() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean shouldBroadcastCommands() {
|
||||
return true; //Broadcast to in-game admins
|
||||
}
|
||||
|
||||
@Override
|
||||
public CommandSender getBukkitSender(CommandListenerWrapper commandListenerWrapper) {
|
||||
return player;
|
||||
}
|
||||
|
||||
public static boolean runBukkitOrVanillaCommand(DiscordSenderBase dsender, String cmdstr) {
|
||||
val cmd = ((CraftServer) Bukkit.getServer()).getCommandMap().getCommand(cmdstr.split(" ")[0].toLowerCase());
|
||||
if (!(dsender instanceof Player) || !(cmd instanceof VanillaCommandWrapper))
|
||||
return Bukkit.dispatchCommand(dsender, cmdstr); // Unconnected users are treated well in vanilla cmds
|
||||
|
||||
if (!(dsender instanceof IMCPlayer))
|
||||
throw new ClassCastException(
|
||||
"dsender needs to implement IMCPlayer to use vanilla commands as it implements Player.");
|
||||
|
||||
IMCPlayer<?> sender = (IMCPlayer<?>) dsender; // Don't use val on recursive interfaces :P
|
||||
|
||||
val vcmd = (VanillaCommandWrapper) cmd;
|
||||
if (!vcmd.testPermission(sender))
|
||||
return true;
|
||||
|
||||
val world = ((CraftWorld) Bukkit.getWorlds().get(0)).getHandle();
|
||||
ICommandListener icommandlistener = (ICommandListener) sender.getVanillaCmdListener().getListener();
|
||||
val wrapper = new CommandListenerWrapper(icommandlistener, new Vec3D(0, 0, 0),
|
||||
new Vec2F(0, 0), world, 0, sender.getName(),
|
||||
new ChatComponentText(sender.getName()), world.getMinecraftServer(), null);
|
||||
val pncs = new ProxiedNativeCommandSender(wrapper, sender, sender);
|
||||
String[] args = cmdstr.split(" ");
|
||||
args = Arrays.copyOfRange(args, 1, args.length);
|
||||
try {
|
||||
return vcmd.execute(pncs, cmd.getLabel(), args);
|
||||
} catch (CommandException commandexception) {
|
||||
// Taken from CommandHandler
|
||||
ChatMessage chatmessage = new ChatMessage(commandexception.getMessage(), commandexception.a());
|
||||
chatmessage.getChatModifier().setColor(EnumChatFormat.RED);
|
||||
icommandlistener.sendMessage(chatmessage);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package buttondevteam.discordplugin.playerfaker.perm;
|
||||
|
||||
import buttondevteam.core.MainPlugin;
|
||||
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||
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;
|
||||
|
@ -87,10 +87,10 @@ public final class LPInjector implements Listener { //Disable login event for Lu
|
|||
/* 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))
|
||||
if (!(e.getPlayer() instanceof DiscordConnectedPlayer))
|
||||
return; //Normal players must be handled by the plugin
|
||||
|
||||
final DiscordFakePlayer player = (DiscordFakePlayer) e.getPlayer();
|
||||
final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer();
|
||||
|
||||
if (plugin.getConfiguration().get(ConfigKeys.DEBUG_LOGINS)) {
|
||||
plugin.getLogger().info("Processing login for " + player.getUniqueId() + " - " + player.getName());
|
||||
|
@ -155,10 +155,10 @@ public final class LPInjector implements Listener { //Disable login event for Lu
|
|||
// 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))
|
||||
if (!(e.getPlayer() instanceof DiscordConnectedPlayer))
|
||||
return;
|
||||
|
||||
final DiscordFakePlayer player = (DiscordFakePlayer) e.getPlayer();
|
||||
final DiscordConnectedPlayer player = (DiscordConnectedPlayer) e.getPlayer();
|
||||
|
||||
connectionListener.handleDisconnect(player.getUniqueId());
|
||||
|
||||
|
@ -183,7 +183,7 @@ public final class LPInjector implements Listener { //Disable login event for Lu
|
|||
}
|
||||
|
||||
//me.lucko.luckperms.bukkit.inject.permissible.PermissibleInjector
|
||||
private void inject(DiscordFakePlayer player, LPPermissible newPermissible, PermissibleBase oldPermissible) throws IllegalAccessException, InvocationTargetException {
|
||||
private void inject(DiscordConnectedPlayer player, LPPermissible newPermissible, PermissibleBase oldPermissible) throws IllegalAccessException, InvocationTargetException {
|
||||
|
||||
// seems we have already injected into this player.
|
||||
if (oldPermissible instanceof LPPermissible) {
|
||||
|
@ -207,7 +207,7 @@ public final class LPInjector implements Listener { //Disable login event for Lu
|
|||
player.setPerm(newPermissible);
|
||||
}
|
||||
|
||||
private void uninject(DiscordFakePlayer player, boolean dummy) throws Exception {
|
||||
private void uninject(DiscordConnectedPlayer player, boolean dummy) throws Exception {
|
||||
|
||||
// gets the players current permissible.
|
||||
PermissibleBase permissible = player.getPerm();
|
||||
|
|
|
@ -3,6 +3,7 @@ package buttondevteam.discordplugin.role;
|
|||
import buttondevteam.core.ComponentManager;
|
||||
import buttondevteam.discordplugin.DPUtils;
|
||||
import buttondevteam.discordplugin.DiscordPlugin;
|
||||
import buttondevteam.lib.TBMCCoreAPI;
|
||||
import buttondevteam.lib.architecture.Component;
|
||||
import buttondevteam.lib.architecture.ReadOnlyConfigData;
|
||||
import discord4j.core.event.domain.role.RoleCreateEvent;
|
||||
|
@ -26,7 +27,7 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
@Override
|
||||
protected void enable() {
|
||||
getPlugin().getManager().registerCommand(new RoleCommand(this));
|
||||
GameRoles = DiscordPlugin.mainServer.getRoles().filterWhen(this::isGameRole).map(Role::getName).collect(Collectors.toList()).block();
|
||||
GameRoles = DiscordPlugin.mainServer.getRoles().filterWhen(r -> isGameRole(r, false)).map(Role::getName).collect(Collectors.toList()).block();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -46,7 +47,7 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
if (roleEvent instanceof RoleCreateEvent) {
|
||||
Bukkit.getScheduler().runTaskLaterAsynchronously(DiscordPlugin.plugin, () -> {
|
||||
Role role=((RoleCreateEvent) roleEvent).getRole();
|
||||
grm.isGameRole(role).flatMap(b -> {
|
||||
grm.isGameRole(role, false).flatMap(b -> {
|
||||
if (!b)
|
||||
return Mono.empty(); //Deleted or not a game role
|
||||
GameRoles.add(role.getName());
|
||||
|
@ -67,7 +68,7 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
return;
|
||||
}
|
||||
Role or=event.getOld().get();
|
||||
grm.isGameRole(event.getCurrent()).flatMap(b -> {
|
||||
grm.isGameRole(event.getCurrent(), true).flatMap(b -> {
|
||||
if (!b) {
|
||||
if (GameRoles.remove(or.getName()) && logChannel != null)
|
||||
return logChannel.flatMap(ch -> ch.createMessage("Removed " + or.getName() + " as a game role because it's color changed."));
|
||||
|
@ -88,12 +89,25 @@ public class GameRoleModule extends Component<DiscordPlugin> {
|
|||
}
|
||||
}
|
||||
|
||||
private Mono<Boolean> isGameRole(Role r) {
|
||||
if (r.getGuildId().asLong() != DiscordPlugin.mainServer.getId().asLong())
|
||||
private Mono<Boolean> isGameRole(Role r, boolean debugMC) {
|
||||
boolean debug = debugMC && r.getName().equalsIgnoreCase("Minecraft");
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("Checking if Minecraft is a game role...");
|
||||
if (r.getGuildId().asLong() != DiscordPlugin.mainServer.getId().asLong()) {
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("Not in the main server: " + r.getGuildId().asString());
|
||||
return Mono.just(false); //Only allow on the main server
|
||||
}
|
||||
val rc = new Color(149, 165, 166, 0);
|
||||
return Mono.just(r.getColor().equals(rc)).filter(b -> b).flatMap(b ->
|
||||
DiscordPlugin.dc.getSelf().flatMap(u -> u.asMember(DiscordPlugin.mainServer.getId())).flatMap(m -> m.hasHigherRoles(Collections.singleton(r)))) //Below one of our roles
|
||||
.defaultIfEmpty(false);
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("Game role color: " + rc + " - MC color: " + r.getColor());
|
||||
return Mono.just(r.getColor().equals(rc))
|
||||
.doAfterSuccessOrError((b, e) -> {
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("1. b: " + b + " - e: " + e);
|
||||
}).filter(b -> b).flatMap(b ->
|
||||
DiscordPlugin.dc.getSelf().flatMap(u -> u.asMember(DiscordPlugin.mainServer.getId()))
|
||||
.doAfterSuccessOrError((m, e) -> {
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("2. m: " + m.getDisplayName() + " e: " + e);
|
||||
}).flatMap(m -> m.hasHigherRoles(Collections.singleton(r)))) //Below one of our roles
|
||||
.doAfterSuccessOrError((b, e) -> {
|
||||
if (debug) TBMCCoreAPI.sendDebugMessage("3. b: " + b + " - e: " + e);
|
||||
}).defaultIfEmpty(false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import buttondevteam.lib.chat.Command2;
|
|||
import buttondevteam.lib.chat.CommandClass;
|
||||
import discord4j.core.object.entity.Role;
|
||||
import lombok.val;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
@ -31,7 +32,8 @@ public class RoleCommand extends ICommand2DC {
|
|||
return true;
|
||||
try {
|
||||
sender.getMessage().getAuthorAsMember()
|
||||
.subscribe(m -> m.addRole(role.getId()).subscribe(r -> sender.sendMessage("added role.")));
|
||||
.flatMap(m -> m.addRole(role.getId()).switchIfEmpty(Mono.fromRunnable(() -> sender.sendMessage("added role."))))
|
||||
.subscribe();
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while adding role!", e);
|
||||
sender.sendMessage("an error occured while adding the role.");
|
||||
|
@ -49,7 +51,8 @@ public class RoleCommand extends ICommand2DC {
|
|||
return true;
|
||||
try {
|
||||
sender.getMessage().getAuthorAsMember()
|
||||
.subscribe(m -> m.removeRole(role.getId()).subscribe(r -> sender.sendMessage("removed role.")));
|
||||
.flatMap(m -> m.removeRole(role.getId()).switchIfEmpty(Mono.fromRunnable(() -> sender.sendMessage("removed role."))))
|
||||
.subscribe();
|
||||
} catch (Exception e) {
|
||||
TBMCCoreAPI.SendException("Error while removing role!", e);
|
||||
sender.sendMessage("an error occured while removing the role.");
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
name: Thorpe-Discord
|
||||
name: Chroma-Discord
|
||||
main: buttondevteam.discordplugin.DiscordPlugin
|
||||
version: 1.0
|
||||
author: NorbiPeti
|
||||
depend: [ThorpeCore]
|
||||
depend: [ChromaCore]
|
||||
commands:
|
||||
discord:
|
||||
website: 'https://github.com/TBMCPlugins/DiscordPlugin'
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package buttondevteam.DiscordPlugin;
|
||||
|
||||
import buttondevteam.discordplugin.DiscordConnectedPlayer;
|
||||
import junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestSuite;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
/**
|
||||
* Unit test for simple App.
|
||||
|
@ -29,6 +32,9 @@ public class AppTest extends TestCase {
|
|||
* Rigourous Test :-)
|
||||
*/
|
||||
public void testApp() {
|
||||
assertTrue(true);
|
||||
Player dcp = DiscordConnectedPlayer.createTest();
|
||||
|
||||
double h = dcp.getAttribute(Attribute.GENERIC_MAX_HEALTH).getDefaultValue(); ; ;
|
||||
System.out.println(h);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue