Compare commits

..

4 Commits

Author SHA1 Message Date
f63362a9fb Properly check for permissions using NM,
add prefixes support to chats
Fix up the list module a bit more
2022-05-24 18:32:27 -07:00
54b803e09b Work on the module list to support permissions 2022-05-23 23:15:12 -07:00
9fba895088 Begin working on permissions implementation. I don't know where every usage is but I've done a generalized implementation so far for commands. 2022-05-23 22:44:08 -07:00
feba260744 Bump aormsby/Fork-Sync-With-Upstream-action from 2.1 to 3.3
Bumps [aormsby/Fork-Sync-With-Upstream-action](https://github.com/aormsby/Fork-Sync-With-Upstream-action) from 2.1 to 3.3.
- [Release notes](https://github.com/aormsby/Fork-Sync-With-Upstream-action/releases)
- [Commits](https://github.com/aormsby/Fork-Sync-With-Upstream-action/compare/v2.1...v3.3)

---
updated-dependencies:
- dependency-name: aormsby/Fork-Sync-With-Upstream-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-05-23 01:40:31 +00:00
120 changed files with 4404 additions and 2324 deletions

View File

@ -21,11 +21,11 @@ jobs:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@v2
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@v4
uses: codacy/codacy-analysis-cli-action@4.0.0
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
@ -41,6 +41,6 @@ jobs:
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v1
with:
sarif_file: results.sarif

View File

@ -35,10 +35,10 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v2
- name: Setup Java JDK
uses: actions/setup-java@v3
uses: actions/setup-java@v2.3.0
with:
# The Java version to make available on the path. Takes a whole or semver Java version, or 1.x syntax (e.g. 1.8 => Java 8.x). Early access versions can be specified in the form of e.g. 14-ea, 14.0.0-ea, or 14.0.0-ea.28
java-version: 17
@ -46,7 +46,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -57,7 +57,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
uses: github/codeql-action/autobuild@v1
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
@ -71,4 +71,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
uses: github/codeql-action/analyze@v1

43
.github/workflows/downstream.yml vendored Normal file
View File

@ -0,0 +1,43 @@
# This is a basic workflow to help you get started with Actions
name: Downstream Branch Updates
on:
schedule:
- cron: '20 7 * * *'
# scheduled at 07:00 every Monday and Thursday
workflow_dispatch: # click the button on Github repo!
jobs:
sync_with_upstream:
runs-on: ubuntu-latest
name: Sync main with upstream latest
steps:
# Step 1: run a standard checkout action, provided by github
- name: Checkout main
uses: actions/checkout@v2
with:
ref: main
# submodules: 'recursive' ### may be needed in your situation
# Step 2: run this sync action - specify the upstream repo, upstream branch to sync with, and target sync branch
- name: Pull (Fast-Forward) upstream changes
id: sync
uses: aormsby/Fork-Sync-With-Upstream-action@v3.3
with:
upstream_repository: AtlasMediaGroup/TotalFreedomMod
upstream_branch: main
target_branch: development
git_pull_args: --ff-only # optional arg use, defaults to simple 'pull'
# Step 3: Display a message if 'sync' step had new commits (simple test)
- name: Check for new commits
if: steps.sync.outputs.has_new_commits
run: echo "There were new commits."
# Step 4: Print a helpful timestamp for your records (not required, just nice)
- name: Timestamp
run: date

View File

@ -9,11 +9,11 @@ jobs:
steps:
# Checkout the code
- uses: actions/checkout@v4
- uses: actions/checkout@v1
# Java 16 Builds
- name: Set up JDK 17
uses: actions/setup-java@v3
uses: actions/setup-java@v2.3.0
with:
java-version: 17
distribution: 'adopt'

3
.gitignore vendored
View File

@ -39,6 +39,3 @@ manifest.mf
ehthumbs.db
Thumbs.db
.idea/inspectionProfiles/Project_Default.xml
# Common working directory
run/

View File

@ -1,4 +1,4 @@
# TotalFreedomMod [![Maven-Build](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/java17-maven.yml/badge.svg)](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/java17-maven.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/29c0f964da304666bd654bc7b1d556db)](https://www.codacy.com/gh/AtlasMediaGroup/TotalFreedomMod/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AtlasMediaGroup/TotalFreedomMod&utm_campaign=Badge_Grade) [![CodeQL](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/codeql-analysis.yml)
# TotalFreedomMod [![Maven-Build](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/maven.yml/badge.svg)](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/maven.yml) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/29c0f964da304666bd654bc7b1d556db)](https://www.codacy.com/gh/AtlasMediaGroup/TotalFreedomMod/dashboard?utm_source=github.com&utm_medium=referral&utm_content=AtlasMediaGroup/TotalFreedomMod&utm_campaign=Badge_Grade) [![CodeQL](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/AtlasMediaGroup/TotalFreedomMod/actions/workflows/codeql-analysis.yml)
TotalFreedomMod is a CraftBukkit server plugin designed primarily to support the [Official TotalFreedom Minecraft Server](https://totalfreedom.me/). However, you are more than welcome to adapt the source for your own server.

View File

@ -9,16 +9,16 @@ In terms of plugin releases, our support matrix is as follows:
### Actively Supported
These versions are currently actively supported by our team, and you should expect security patches where appropriate for these versions.
| Version | Supported | Support End: |
| ------------------- | ---------- | ------------------------------ |
| 2022.02 | | No Earlier than May 2022 |
| Version | Supported | Support End: |
| ------------------- | ------------------ | ------------------------------ |
| 2021.09 | :white_check_mark: | No Earlier than December 2021 |
### Legacy Supported
These versions are no longer under active development, however we will look to release critical secuirty patches where appropriate.
| Version | Supported | Support End: |
| ------------------- | ---------- | ------------ |
| 2021.09 | ⚠️ | April 2022 |
| Version | Supported | Support End: |
| ------------------- | ------------------ | ------------ |
| 2021.06 | :white_check_mark: | October 2021 |
### No Longer Supported
@ -26,9 +26,8 @@ These versions are no longer supported at all. It is strongly advised to update
| Version | Supported | Support Ended: |
| ------------------- | ------------------ | ------------------- |
| 2021.06 | :x: | October 2021 |
| 2021.05 | :x: | September 2021 |
| 2021.04 | :x: | July 2021 |
| 2021.05 | :white_check_mark: | September 2021 |
| 2021.04 | :white_check_mark: | July 2021 |
| 2021.02 | :x: | 6 June 2021 |
| 2020.11 | :x: | 3 May 2021 |
| 6.0.x (Pre-Release) | :x: | December 2020 |

View File

@ -13,7 +13,7 @@ You can copy and paste the single properties, into the pom.xml file and the IDE
That way multiple projects can share the same settings (useful for formatting rules for example).
Any value defined here will override the pom.xml file value but is only applicable to the current project.
-->
<netbeans.hint.jdkPlatform>JDK_17</netbeans.hint.jdkPlatform>
<netbeans.hint.jdkPlatform>JDK_11</netbeans.hint.jdkPlatform>
<netbeans.checkstyle.format>true</netbeans.checkstyle.format>
</properties>
</project-shared-configuration>

119
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>me.totalfreedom</groupId>
<artifactId>TotalFreedomMod</artifactId>
<version>2022.06.1</version>
<version>2022.02-RC01</version>
<packaging>jar</packaging>
<properties>
@ -39,7 +39,17 @@
</scm>
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
<repository>
<id>networkmanager-repo</id>
<url>https://repo.networkmanager.xyz/repository/maven-public/</url>
</repository>
<repository>
<id>atlas-nexus-01-totalfreedom-development</id>
<url>https://nexus-01.core.atlas-media.co.uk/repository/totalfreedom-development/</url>
@ -65,6 +75,11 @@
<url>https://maven.elmakers.com/repository/</url>
</repository>
<repository>
<id>sk89q-snapshots</id>
<url>https://maven.sk89q.com/artifactory/repo</url>
</repository>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
@ -86,11 +101,17 @@
<url>https://repo.dmulloy2.net/nexus/repository/public/</url>
</repository>
<repository>
<id>sk89q-repo</id>
<url>https://maven.sk89q.com/repo/</url>
</repository>
<repository>
<id>esentialsx-repo</id>
<url>https://repo.essentialsx.net/releases/</url>
</repository>
</repositories>
<dependencies>
@ -98,28 +119,28 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
<version>2.11.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.13.0</version>
<version>3.12.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.totalfreedom.scissors</groupId>
<artifactId>Scissors-API</artifactId>
<version>1.19.4-R0.1-SNAPSHOT</version>
<groupId>io.papermc.paper</groupId>
<artifactId>paper-api</artifactId>
<version>1.17.1-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -140,35 +161,35 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.15</version>
<version>7.2.8</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<version>4.4.1_353</version>
<version>4.2.1_255</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.coreprotect</groupId>
<artifactId>coreprotect</artifactId>
<version>21.3</version>
<version>21.2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.8</version>
<version>7.0.6</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.papermc</groupId>
<artifactId>paperlib</artifactId>
<version>1.0.8</version>
<version>1.0.6</version>
<scope>compile</scope>
</dependency>
@ -178,54 +199,92 @@
<version>v1.9</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.essentialsx</groupId>
<artifactId>EssentialsX</artifactId>
<version>2.20.0</version>
<version>2.19.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.10.2</version>
<version>0.9.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.29.1-GA</version>
<version>3.28.0-GA</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.totalfreedom</groupId>
<artifactId>tfguilds</artifactId>
<version>2021.06-RC2</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>24.0.1</version>
<version>22.0.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.0</version>
<version>3.1.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<version>5.8.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.inject</artifactId>
<version>0.3.5</version>
<version>0.3.4</version>
</dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bstats</groupId>
<artifactId>bstats</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>nl.chimpgamer.networkmanager</groupId>
<artifactId>api</artifactId>
<version>2.11.4</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.github.slimjar</groupId>
<artifactId>slimjar</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220320</version>
</dependency>
</dependencies>
<pluginRepositories>
@ -249,7 +308,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.11.0</version>
<version>3.8.1</version>
<configuration>
<outputFileName>TotalFreedomMod.jar</outputFileName>
<compilerVersion>17</compilerVersion>
@ -303,7 +362,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<version>3.0.0</version>
<executions>
<execution>
<id>default-cli</id>
@ -333,7 +392,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>properties-maven-plugin</artifactId>
<version>1.1.0</version>
<version>1.0.0</version>
<executions>
<execution>
<phase>initialize</phase>
@ -353,7 +412,7 @@
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>3.2.0</version>
<version>1.4</version>
<executions>
<execution>
<phase>generate-resources</phase>
@ -378,7 +437,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.3.1-SNAPSHOT</version>
<executions>
<execution>
<phase>package</phase>
@ -400,10 +459,14 @@
</relocations>
<artifactSet>
<includes>
<include>commons-io:commons-io</include>
<include>org.apache.commons:commons-lang3</include>
<include>org.reflections:reflections</include>
<include>org.javassist:javassist</include>
<include>io.papermc:paperlib</include>
<include>org.bstats:bstats-bukkit</include>
<include>org.bstats:bstats-base</include>
<include>org.jetbrains:annotations</include>
</includes>
</artifactSet>
</configuration>

View File

@ -2,8 +2,8 @@ package me.totalfreedom.totalfreedommod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -35,10 +35,10 @@ public class AntiNuke extends FreedomService
if (fPlayer.incrementAndGetBlockDestroyCount() > ConfigEntry.NUKE_MONITOR_COUNT_BREAK.getInteger())
{
server.broadcast(Component.text(player.getName()).append(Component.text(" is breaking blocks too fast!"))
.color(NamedTextColor.RED));
player.kick(Component.text("You are breaking blocks too fast. Nukers are not permitted on this server.",
NamedTextColor.RED));
FUtil.bcastMsg(player.getName() + " is breaking blocks too fast!", ChatColor.RED);
//plugin.ae.autoEject(player, "You are breaking blocks too fast. Nukers are not permitted on this server.");
player.kickPlayer(ChatColor.RED + "You are breaking blocks too fast. Nukers are not permitted on this server.");
fPlayer.resetBlockDestroyCount();
event.setCancelled(true);
@ -58,9 +58,10 @@ public class AntiNuke extends FreedomService
if (fPlayer.incrementAndGetBlockPlaceCount() > ConfigEntry.NUKE_MONITOR_COUNT_PLACE.getInteger())
{
server.broadcast(Component.text(player.getName()).append(Component.text(" is placing blocks too fast!"))
.color(NamedTextColor.RED));
player.kick(Component.text("You are placing blocks too fast.", NamedTextColor.RED));
FUtil.bcastMsg(player.getName() + " is placing blocks too fast!", ChatColor.RED);
//plugin.ae.autoEject(player, "You are placing blocks too fast.");
player.kickPlayer(ChatColor.RED + "You are placing blocks too fast.");
fPlayer.resetBlockPlaceCount();
event.setCancelled(true);

View File

@ -2,48 +2,60 @@ package me.totalfreedom.totalfreedommod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import me.totalfreedom.totalfreedommod.util.FSync;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class AntiSpam extends FreedomService
{
private ScheduledThreadPoolExecutor cycle;
public static final int MSG_PER_CYCLE = 8;
public static final int TICKS_PER_CYCLE = 2 * 10;
//
public BukkitTask cycleTask = null;
private Map<Player, Integer> muteCounts = new HashMap<>();
@Override
public void onStart()
{
cycle = new ScheduledThreadPoolExecutor(1);
cycle.scheduleAtFixedRate(this::cycle, 0, 1, TimeUnit.SECONDS);
new BukkitRunnable()
{
@Override
public void run()
{
cycle();
}
}.runTaskTimer(plugin, TICKS_PER_CYCLE, TICKS_PER_CYCLE);
}
@Override
public void onStop()
{
cycle.shutdownNow();
FUtil.cancel(cycleTask);
}
private void cycle()
{
server.getOnlinePlayers().stream().map(player -> plugin.pl.getPlayer(player)).forEach(fPlayer ->
for (Player player : server.getOnlinePlayers())
{
final FPlayer playerdata = plugin.pl.getPlayer(player);
// TODO: Move each to their own section
fPlayer.resetMsgCount();
fPlayer.resetBlockDestroyCount();
fPlayer.resetBlockPlaceCount();
});
playerdata.resetMsgCount();
playerdata.resetBlockDestroyCount();
playerdata.resetBlockPlaceCount();
}
}
@EventHandler(priority = EventPriority.LOW)
@ -69,16 +81,17 @@ public class AntiSpam extends FreedomService
int time = count * minutes;
playerdata.setMuted(true, time);
server.broadcast(Component.text(player.getName()).append(Component.text(" has been automatically muted for "))
.append(Component.text(time)).append(Component.text(" minutes for spamming chat."))
.color(NamedTextColor.RED));
FSync.bcastMsg(String.format("%s has automatically been muted for %d minutes for spamming chat.",
player.getName(),
time),
ChatColor.RED);
playerdata.resetMsgCount();
event.setCancelled(true);
}
else if (playerdata.incrementAndGetMsgCount() > MSG_PER_CYCLE / 2)
{
player.sendMessage(Component.text("Please refrain from spamming chat.", NamedTextColor.GRAY));
FUtil.playerMsg(player, "Please refrain from spamming chat.", ChatColor.GRAY);
event.setCancelled(true);
}
@ -94,7 +107,7 @@ public class AntiSpam extends FreedomService
if (fPlayer.allCommandsBlocked())
{
player.sendMessage(Component.text("Your commands have been blocked by an admin.", NamedTextColor.RED));
FUtil.playerMsg(player, "Your commands have been blocked by an admin.", ChatColor.RED);
event.setCancelled(true);
return;
}
@ -106,9 +119,7 @@ public class AntiSpam extends FreedomService
if (fPlayer.incrementAndGetMsgCount() > MSG_PER_CYCLE)
{
server.broadcast(Component.text(player.getName())
.append(Component.text(" was automatically kicked for spamming commands."))
.color(NamedTextColor.RED));
FUtil.bcastMsg(player.getName() + " was automatically kicked for spamming commands.", ChatColor.RED);
plugin.ae.autoEject(player, "Kicked for spamming commands.");
fPlayer.resetMsgCount();

View File

@ -91,7 +91,7 @@ public class AutoEject extends FreedomService
}
case STRIKE_THREE:
{
plugin.bm.addBan(Ban.forPlayer(player, Bukkit.getConsoleSender(), null, kickMessage));
plugin.bm.addBan(Ban.forPlayerFuzzy(player, Bukkit.getConsoleSender(), null, kickMessage));
FUtil.bcastMsg(ChatColor.RED + player.getName() + " has been banned.");

View File

@ -4,11 +4,13 @@ import com.google.common.base.Strings;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Displayable;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FSync;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.md_5.bungee.api.ChatColor;
import org.bukkit.Bukkit;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.command.CommandSender;
@ -46,17 +48,23 @@ public class ChatManager extends FreedomService
private void handleChatEvent(AsyncPlayerChatEvent event)
{
final Player player = event.getPlayer();
String originalMessage = event.getMessage();
if (plugin.mu.onPlayerChat(player) || plugin.sh.handlePlayerChat(player, originalMessage))
{
event.setCancelled(true);
return;
}
String message = originalMessage.trim();
String message = event.getMessage().trim();
// Format colors and strip &k
message = FUtil.colorize(message);
message = message.replaceAll(ChatColor.MAGIC.toString(), "&k");
if (ConfigEntry.SHOP_ENABLED.getBoolean() && ConfigEntry.SHOP_REACTIONS_ENABLED.getBoolean() && !plugin.sh.reactionString.isEmpty() && message.equals(plugin.sh.reactionString))
{
event.setCancelled(true);
PlayerData data = plugin.pl.getData(player);
data.setCoins(data.getCoins() + plugin.sh.coinsPerReactionWin);
plugin.pl.save(data);
plugin.sh.endReaction(player.getName());
player.sendMessage(ChatColor.GREEN + "You have been given " + ChatColor.GOLD + plugin.sh.coinsPerReactionWin + ChatColor.GREEN + " coins!");
return;
}
if (!ConfigEntry.TOGGLE_CHAT.getBoolean() && !plugin.al.isAdmin(player))
{
event.setCancelled(true);
@ -87,14 +95,11 @@ public class ChatManager extends FreedomService
return;
}
plugin.dc.onPlayerChat(player, ChatColor.stripColor(message));
// Check for 4chan trigger
boolean green = ChatColor.stripColor(message).toLowerCase().startsWith(">");
boolean orange = ChatColor.stripColor(message).toLowerCase().endsWith("<");
if (ConfigEntry.FOURCHAN_ENABLED.getBoolean())
{
boolean green = ChatColor.stripColor(message).toLowerCase().startsWith(">");
boolean orange = ChatColor.stripColor(message).toLowerCase().endsWith("<");
if (green)
{
message = ChatColor.GREEN + message;
@ -118,27 +123,23 @@ public class ChatManager extends FreedomService
}
// Check for mentions
String stripped = ChatColor.stripColor(message).toLowerCase();
/* There is an issue would have allowed muted players to ping players. The issue is caused by the order in which
* these event handlers are registered when the plugin starts up. Muter is registered after the ChatManager,
* which results in latter being called first (before the former can cancel it). EventPriority does not seem to
* make a difference. As a short-term solution I've added this mute check alongside the usual isCancelled check
* so that the issue is mitigated, but a long-term solution should be to change the order in which things like
* ChatManager and Muter are registered. */
if (!event.isCancelled() && !plugin.pl.getPlayer(player).isMuted())
boolean mentionEveryone = ChatColor.stripColor(message).toLowerCase().contains("@everyone") && plugin.al.isAdmin(player);
for (Player p : server.getOnlinePlayers())
{
server.getOnlinePlayers().forEach(pl ->
if (ChatColor.stripColor(message).toLowerCase().contains("@" + p.getName().toLowerCase()) || mentionEveryone)
{
if (stripped.contains("@" + pl.getName()) || (plugin.al.isAdmin(player) && stripped.contains("@everyone")))
{
pl.playSound(pl.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, SoundCategory.MASTER, 1337F, 0.9F);
}
});
p.playSound(p.getLocation(), Sound.BLOCK_NOTE_BLOCK_PLING, SoundCategory.MASTER, 1337F, 0.9F);
}
}
// Set format
event.setFormat(format);
// Send to discord
if (!ConfigEntry.ADMIN_ONLY_MODE.getBoolean() && !Bukkit.hasWhitelist() && !plugin.pl.getPlayer(player).isMuted() && !plugin.tfg.inGuildChat(player))
{
plugin.dc.messageChatChannel(player.getName() + " \u00BB " + ChatColor.stripColor(message));
}
}
public ChatColor getColor(Displayable display)
@ -161,8 +162,7 @@ public class ChatManager extends FreedomService
server.getOnlinePlayers().stream().filter(player -> plugin.al.isAdmin(player)).forEach(player ->
{
Admin admin = plugin.al.getAdmin(player);
if (!Strings.isNullOrEmpty(admin.getAcFormat()))
{
if (!Strings.isNullOrEmpty(admin.getAcFormat())) {
String format = admin.getAcFormat();
ChatColor color = getColor(display);
String msg = format.replace("%name%", sender.getName()).replace("%rank%", display.getAbbr()).replace("%rankcolor%", color.toString()).replace("%msg%", message);
@ -175,15 +175,15 @@ public class ChatManager extends FreedomService
});
}
public void reportAction(Player reporter, String reportedName, String report)
public void reportAction(Player reporter, Player reported, String report)
{
for (Player player : server.getOnlinePlayers())
{
if (plugin.al.isAdmin(player))
{
playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reportedName + " for " + report);
playerMsg(player, ChatColor.RED + "[REPORTS] " + ChatColor.GOLD + reporter.getName() + " has reported " + reported.getName() + " for " + report);
}
}
FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reportedName + " for " + report);
FLog.info("[REPORTS] " + reporter.getName() + " has reported " + reported.getName() + " for " + report);
}
}

View File

@ -1,7 +1,7 @@
package me.totalfreedom.totalfreedommod;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
@ -21,9 +21,15 @@ public class CommandSpy extends FreedomService
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerCommandPreprocess(PlayerCommandPreprocessEvent event)
{
server.getOnlinePlayers().stream().filter(player -> plugin.al.isAdmin(player)
&& plugin.al.getAdmin(player).getCommandSpy() && player != event.getPlayer()).forEach(player ->
player.sendMessage(Component.text(event.getPlayer().getName(), NamedTextColor.GRAY).append(Component.text(": ", NamedTextColor.GRAY))
.append(Component.text(event.getMessage(), NamedTextColor.GRAY))));
for (Player player : server.getOnlinePlayers())
{
if (plugin.al.isAdmin(player) && plugin.al.getAdmin(player).getCommandSpy())
{
if (player != event.getPlayer())
{
FUtil.playerMsg(player, event.getPlayer().getName() + ": " + event.getMessage());
}
}
}
}
}

View File

@ -0,0 +1,201 @@
package me.totalfreedom.totalfreedommod;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
public class LogViewer extends FreedomService
{
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
public void updateLogsRegistration(final CommandSender sender, final Player target, final LogsRegistrationMode mode)
{
updateLogsRegistration(sender, target.getName(), mode);
}
public void updateLogsRegistration(final CommandSender sender, final String targetName, final LogsRegistrationMode mode)
{
final String logsRegisterUrl = ConfigEntry.LOGS_URL.getString();
final String logsRegisterPassword = ConfigEntry.LOGS_SECRET.getString();
if (logsRegisterUrl == null || logsRegisterPassword == null || logsRegisterUrl.isEmpty() || logsRegisterPassword.isEmpty())
{
return;
}
new BukkitRunnable()
{
@Override
public void run()
{
try
{
if (sender != null)
{
sender.sendMessage(ChatColor.YELLOW + "Connecting...");
}
final String key = SecureCodeGenerator.generateCode(20);
final URL urlAdd = new URLBuilder(logsRegisterUrl)
.addQueryParameter("mode", mode.name())
.addQueryParameter("password", logsRegisterPassword)
.addQueryParameter("name", targetName)
.addQueryParameter("key", key)
.getURL();
final HttpURLConnection connection = (HttpURLConnection)urlAdd.openConnection();
connection.setConnectTimeout(1000 * 5);
connection.setReadTimeout(1000 * 5);
connection.setUseCaches(false);
connection.setRequestMethod("HEAD");
final int responseCode = connection.getResponseCode();
if (sender != null)
{
if (!plugin.isEnabled())
{
return;
}
new BukkitRunnable()
{
@Override
public void run()
{
if (responseCode == 200)
{
if (mode == LogsRegistrationMode.ADD)
{
String link = null;
try
{
final URL urlVerify = new URLBuilder(logsRegisterUrl)
.addQueryParameter("mode", LogsRegistrationMode.VERIFY.name())
.addQueryParameter("name", targetName)
.addQueryParameter("key", key)
.getURL();
link = urlVerify.toString();
}
catch (Exception ex)
{
FLog.severe(ex);
}
sender.sendMessage(ChatColor.GREEN + "Open this link to verify your logviewer registration:\n" + ChatColor.DARK_GREEN + link);
}
else
{
sender.sendMessage(ChatColor.GREEN + "Logviewer access revoked successfully.");
}
}
else
{
sender.sendMessage(ChatColor.RED + "Error contacting logs registration server.");
}
}
}.runTask(plugin);
}
}
catch (Exception ex)
{
FLog.severe(ex);
}
}
}.runTaskAsynchronously(plugin);
}
public enum LogsRegistrationMode
{
ADD, DELETE, VERIFY
}
private static class URLBuilder
{
private final String requestPath;
private final Map<String, String> queryStringMap = new HashMap<>();
private URLBuilder(String requestPath)
{
this.requestPath = requestPath;
}
public URLBuilder addQueryParameter(String key, String value)
{
queryStringMap.put(key, value);
return this;
}
public URL getURL() throws MalformedURLException
{
List<String> pairs = new ArrayList<>();
for (Map.Entry<String, String> pair : queryStringMap.entrySet())
{
try
{
pairs.add(URLEncoder.encode(pair.getKey(), "UTF-8") + "=" + URLEncoder.encode(pair.getValue(), "UTF-8"));
}
catch (UnsupportedEncodingException ex)
{
FLog.severe(ex);
}
}
return new URL(requestPath + "?" + StringUtils.join(pairs, "&"));
}
}
private static class SecureCodeGenerator
{
private static final String CHARACTER_SET = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
public static String generateCode(final int length)
{
SecureRandom random;
try
{
random = SecureRandom.getInstance("SHA1PRNG", "SUN");
}
catch (NoSuchAlgorithmException | NoSuchProviderException ex)
{
random = new SecureRandom();
FLog.severe(ex);
}
final StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++)
{
sb.append(CHARACTER_SET.charAt(random.nextInt(CHARACTER_SET.length())));
}
return sb.toString();
}
}
}

View File

@ -179,7 +179,7 @@ public class LoginProcess extends FreedomService
}
// Whitelist
if (server.hasWhitelist() && !player.isWhitelisted())
if (server.isWhitelistEnforced() && !player.isWhitelisted())
{
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "You are not whitelisted on this server.");
}

View File

@ -1,17 +1,25 @@
package me.totalfreedom.totalfreedommod;
import com.google.common.collect.Multimap;
import io.papermc.lib.PaperLib;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.attribute.Attribute;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.PlayerItemHeldEvent;
import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent;
import org.spigotmc.event.player.PlayerSpawnLocationEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class MovementValidator extends FreedomService
{
@ -33,36 +41,67 @@ public class MovementValidator extends FreedomService
public void onPlayerTeleport(PlayerTeleportEvent event)
{
// Check absolute value to account for negatives
if (isOutOfBounds(event.getTo()))
if (Math.abs(Objects.requireNonNull(event.getTo()).getX()) >= MAX_XYZ_COORD || Math.abs(event.getTo().getZ()) >= MAX_XYZ_COORD || Math.abs(event.getTo().getY()) >= MAX_XYZ_COORD)
{
event.setCancelled(true); // illegal position, cancel it
}
}
private boolean isOutOfBounds(final Location position)
{
return Math.abs(position.getX()) >= MAX_XYZ_COORD || Math.abs(position.getY()) >= MAX_XYZ_COORD || Math.abs(position.getZ()) >= MAX_XYZ_COORD;
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerMove(PlayerMoveEvent event)
{
final Player player = event.getPlayer();
Location from = event.getFrom();
Location to = event.getTo();
double distance = from.distanceSquared(to);
if (distance >= MAX_DISTANCE_TRAVELED)
assert to != null;
if (to.getX() >= from.getX() + MAX_DISTANCE_TRAVELED || to.getY() >= from.getY() + MAX_DISTANCE_TRAVELED || to.getZ() >= from.getZ() + MAX_DISTANCE_TRAVELED)
{
event.setCancelled(true);
player.kick(Component.text("You were moving too quickly!", NamedTextColor.RED));
player.kickPlayer(ChatColor.RED + "You were moving too quickly!");
}
// Check absolute value to account for negatives
if (isOutOfBounds(event.getTo()))
if (Math.abs(event.getTo().getX()) >= MAX_XYZ_COORD || Math.abs(event.getTo().getZ()) >= MAX_XYZ_COORD || Math.abs(event.getTo().getY()) >= MAX_XYZ_COORD)
{
event.setCancelled(true);
PaperLib.teleportAsync(player, player.getWorld().getSpawnLocation());
}
if (exploitItem(event.getPlayer().getInventory().getHelmet()))
{
event.getPlayer().getInventory().setHelmet(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your helmet slot.");
event.setCancelled(true);
}
if (exploitItem(event.getPlayer().getInventory().getBoots()))
{
event.getPlayer().getInventory().setBoots(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your boots slot.");
event.setCancelled(true);
}
if (exploitItem(event.getPlayer().getInventory().getLeggings()))
{
event.getPlayer().getInventory().setLeggings(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your leggings slot.");
event.setCancelled(true);
}
if (exploitItem(event.getPlayer().getInventory().getChestplate()))
{
event.getPlayer().getInventory().setChestplate(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your chestplate slot.");
event.setCancelled(true);
}
if (exploitItem(event.getPlayer().getInventory().getItemInMainHand()))
{
event.getPlayer().getInventory().setItemInMainHand(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your hand.");
event.setCancelled(true);
}
if (exploitItem(event.getPlayer().getInventory().getItemInOffHand()))
{
event.getPlayer().getInventory().setItemInOffHand(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your offhand.");
event.setCancelled(true);
}
}
@EventHandler(priority = EventPriority.HIGH)
@ -71,28 +110,72 @@ public class MovementValidator extends FreedomService
final Player player = event.getPlayer();
// Validate position
if (isOutOfBounds(player.getLocation()))
if (Math.abs(player.getLocation().getX()) >= MAX_XYZ_COORD || Math.abs(player.getLocation().getZ()) >= MAX_XYZ_COORD || Math.abs(player.getLocation().getY()) >= MAX_XYZ_COORD)
{
PaperLib.teleportAsync(player, player.getWorld().getSpawnLocation()); // Illegal position, teleport to spawn
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerSpawn(PlayerSpawnLocationEvent event)
@EventHandler
public void onPlayerHoldItem(PlayerItemHeldEvent event)
{
final Location playerSpawn = event.getSpawnLocation();
final Location worldSpawn = event.getPlayer().getWorld().getSpawnLocation();
// If the player's spawn is equal to the world's spawn, there is no need to check.
// This will also prevent any possible feedback loops pertaining to setting an out of bounds world spawn to the same world spawn.
if (playerSpawn == worldSpawn)
if (exploitItem(event.getPlayer().getInventory().getItemInMainHand()))
{
return;
event.getPlayer().getInventory().setItemInMainHand(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your hand.");
}
if (isOutOfBounds(worldSpawn))
if (exploitItem(event.getPlayer().getInventory().getItemInOffHand()))
{
event.setSpawnLocation(worldSpawn);
event.getPlayer().getInventory().setItemInOffHand(new ItemStack(Material.AIR));
event.getPlayer().sendMessage(ChatColor.RED + "An item with both negative infinity and positive infinity attributes was cleared from your offhand.");
}
}
private Boolean exploitItem(ItemStack item)
{
if (item == null)
{
return false;
}
ItemMeta meta = item.getItemMeta();
if (meta != null)
{
Multimap<Attribute, AttributeModifier> attributes = meta.getAttributeModifiers();
if (attributes != null)
{
Map<Attribute, Collection<AttributeModifier>> attrMap = attributes.asMap();
// For every attribute...
for (Attribute attr : attributes.keySet())
{
// Default values
boolean posInf = false;
boolean negInf = false;
// For every AttributeModifier...
for (AttributeModifier modifier : attrMap.get(attr))
{
// Are they ∞ or -∞?
if (modifier.getAmount() == Double.POSITIVE_INFINITY)
{
posInf = true;
}
else if (modifier.getAmount() == Double.NEGATIVE_INFINITY)
{
negInf = true;
}
}
// Are both values set as true?
if (posInf && negInf)
{
return true;
}
}
}
}
return false;
}
}

View File

@ -1,19 +1,25 @@
package me.totalfreedom.totalfreedommod;
import java.util.ArrayList;
import java.util.List;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import me.totalfreedom.totalfreedommod.util.FSync;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
import org.bukkit.event.player.PlayerJoinEvent;
public class Muter extends FreedomService
{
public final List<String> MUTED_PLAYERS = new ArrayList<>();
@Override
public void onStart()
{
@ -24,23 +30,27 @@ public class Muter extends FreedomService
{
}
public boolean onPlayerChat(Player player)
@EventHandler(priority = EventPriority.HIGHEST)
public void onAsyncPlayerChatEvent(AsyncPlayerChatEvent event)
{
Player player = event.getPlayer();
FPlayer fPlayer = plugin.pl.getPlayerSync(player);
if (!fPlayer.isMuted())
{
return false;
return;
}
if (plugin.al.isAdminSync(player))
{
fPlayer.setMuted(false);
return false;
MUTED_PLAYERS.remove(player.getName());
return;
}
player.sendMessage(Component.text("You are muted.", NamedTextColor.RED));
return true;
FSync.playerMsg(event.getPlayer(), ChatColor.RED + "You are muted.");
event.setCancelled(true);
}
@EventHandler(priority = EventPriority.LOW)
@ -77,7 +87,7 @@ public class Muter extends FreedomService
if (ConfigEntry.MUTED_BLOCKED_COMMANDS.getStringList().contains(cmdName))
{
player.sendMessage(Component.text("That command is blocked while you are muted.", NamedTextColor.RED));
player.sendMessage(ChatColor.RED + "That command is blocked while you are muted.");
event.setCancelled(true);
return;
}
@ -88,4 +98,16 @@ public class Muter extends FreedomService
FLog.info(String.format("[PREPROCESS_COMMAND] %s(%s): %s", player.getName(), ChatColor.stripColor(player.getDisplayName()), message), true);
}
}
@EventHandler(priority = EventPriority.LOW)
public void onPlayerJoin(PlayerJoinEvent event)
{
Player player = event.getPlayer();
FPlayer playerdata = plugin.pl.getPlayer(player);
if (MUTED_PLAYERS.contains(player.getName()))
{
playerdata.setMuted(true);
}
}
}

View File

@ -0,0 +1,214 @@
package me.totalfreedom.totalfreedommod;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import com.google.common.base.Strings;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import me.totalfreedom.totalfreedommod.util.Response;
import org.json.simple.JSONObject;
import org.json.simple.parser.ParseException;
public class Pterodactyl extends FreedomService
{
public final String URL = ConfigEntry.PTERO_URL.getString();
private final String SERVER_KEY = ConfigEntry.PTERO_SERVER_KEY.getString();
private final String ADMIN_KEY = ConfigEntry.PTERO_ADMIN_KEY.getString();
private final List<String> SERVER_HEADERS = Arrays.asList("Accept:Application/vnd.pterodactyl.v1+json", "Content-Type:application/json", "Authorization:Bearer " + SERVER_KEY);
private final List<String> ADMIN_HEADERS = Arrays.asList("Accept:Application/vnd.pterodactyl.v1+json", "Content-Type:application/json", "Authorization:Bearer " + ADMIN_KEY);
private boolean enabled = !Strings.isNullOrEmpty(URL);
public void onStart()
{
}
public void onStop()
{
}
public void updateAccountStatus(Admin admin)
{
String id = admin.getPteroID();
if (Strings.isNullOrEmpty(id) || !enabled)
{
return;
}
if (!admin.isActive() || admin.getRank() != Rank.SENIOR_ADMIN)
{
FLog.debug("Disabling ptero acc");
removeAccountFromServer(id);
return;
}
FLog.debug("Enabling ptero acc");
addAccountToServer(id);
}
@SuppressWarnings("unchecked")
public String createAccount(String username, String password)
{
JSONObject json = new JSONObject();
json.put("username", username);
json.put("password", password);
json.put("email", username.toLowerCase() + "@" + ConfigEntry.PTERO_DEFAULT_EMAIL_DOMAIN.getString());
json.put("first_name", username);
json.put("last_name", "\u200E"); // required, so I made it appear empty
Response response;
JSONObject jsonResponse;
try
{
response = FUtil.sendRequest(URL + "/api/application/users", "POST", ADMIN_HEADERS, json.toJSONString());
jsonResponse = response.getJSONMessage();
}
catch (IOException | ParseException e)
{
FLog.severe(e);
return null;
}
return ((JSONObject)jsonResponse.get("attributes")).get("id").toString();
}
public boolean deleteAccount(String id)
{
JSONObject json = new JSONObject();
try
{
return FUtil.sendRequest(URL + "/api/application/users/" + id, "DELETE", ADMIN_HEADERS, json.toJSONString()).getCode() == 204;
}
catch (IOException e)
{
FLog.severe(e);
return false;
}
}
@SuppressWarnings("unchecked")
public void addAccountToServer(String id)
{
String url = URL + "/api/client/servers/" + ConfigEntry.PTERO_SERVER_UUID.getString() + "/users";
JSONObject userData = getUserData(id);
if (userData == null)
{
FLog.severe("The Pterodactyl user with the ID of " + id + " was not found");
return;
}
JSONObject json = new JSONObject();
json.put("email", userData.get("email").toString());
json.put("permissions", Arrays.asList("control.console", "control.start", "control.restart", "control.stop", "control.kill"));
try
{
FUtil.sendRequest(url, "POST", SERVER_HEADERS, json.toJSONString());
}
catch (IOException e)
{
FLog.severe(e);
}
}
public void removeAccountFromServer(String id)
{
JSONObject userData = getUserData(id);
if (userData == null)
{
FLog.severe("The Pterodactyl user with the ID of " + id + " was not found");
return;
}
String url = URL + "/api/client/servers/" + ConfigEntry.PTERO_SERVER_UUID.getString() + "/users/" + userData.get("uuid");
try
{
FUtil.sendRequest(url, "DELETE", SERVER_HEADERS, null);
}
catch (IOException e)
{
FLog.severe(e);
}
}
public JSONObject getUserData(String id)
{
Response response;
JSONObject jsonResponse;
try
{
response = FUtil.sendRequest(URL + "/api/application/users/" + id, "GET", ADMIN_HEADERS, null);
jsonResponse = response.getJSONMessage();
}
catch (IOException | ParseException e)
{
FLog.severe(e);
return null;
}
return (JSONObject)jsonResponse.get("attributes");
}
// API patch function on users doesnt work rn, it throws 500 errors, so it's probably not written yet
@SuppressWarnings("unchecked")
public void setPassword(String id, String password)
{
JSONObject json = new JSONObject();
json.put("password", password);
try
{
FUtil.sendRequest(URL + "/api/application/users/" + id, "PATCH", ADMIN_HEADERS, json.toJSONString());
}
catch (IOException e)
{
FLog.severe(e);
}
}
public String getURL()
{
return URL;
}
public String getServerKey()
{
return SERVER_KEY;
}
public String getAdminKey()
{
return ADMIN_KEY;
}
public List<String> getServerHeaders()
{
return SERVER_HEADERS;
}
public List<String> getAdminHeaders()
{
return ADMIN_HEADERS;
}
public boolean isEnabled()
{
return enabled;
}
public void setEnabled(boolean enabled)
{
this.enabled = enabled;
}
}

View File

@ -0,0 +1,34 @@
package me.totalfreedom.totalfreedommod;
import me.totalfreedom.totalfreedommod.command.Command_sit;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.Entity;
import org.bukkit.event.EventHandler;
import org.spigotmc.event.entity.EntityDismountEvent;
public class Sitter extends FreedomService
{
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
@EventHandler
public void onEntityDismount(EntityDismountEvent e)
{
Entity dm = e.getDismounted();
if (dm instanceof ArmorStand)
{
if (Command_sit.STANDS.contains(dm))
{
Command_sit.STANDS.remove(dm);
dm.remove();
}
}
}
}

View File

@ -3,6 +3,7 @@ package me.totalfreedom.totalfreedommod;
import java.io.File;
import java.io.InputStream;
import java.util.Properties;
import me.totalfreedom.totalfreedommod.admin.ActivityLog;
import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.banning.BanManager;
@ -19,6 +20,7 @@ import me.totalfreedom.totalfreedommod.bridge.BukkitTelnetBridge;
import me.totalfreedom.totalfreedommod.bridge.CoreProtectBridge;
import me.totalfreedom.totalfreedommod.bridge.EssentialsBridge;
import me.totalfreedom.totalfreedommod.bridge.LibsDisguisesBridge;
import me.totalfreedom.totalfreedommod.bridge.TFGuildsBridge;
import me.totalfreedom.totalfreedommod.bridge.WorldEditBridge;
import me.totalfreedom.totalfreedommod.bridge.WorldGuardBridge;
import me.totalfreedom.totalfreedommod.caging.Cager;
@ -34,6 +36,10 @@ import me.totalfreedom.totalfreedommod.fun.Trailer;
import me.totalfreedom.totalfreedommod.httpd.HTTPDaemon;
import me.totalfreedom.totalfreedommod.permissions.PermissionConfig;
import me.totalfreedom.totalfreedommod.permissions.PermissionManager;
import me.totalfreedom.totalfreedommod.permissions.handler.DefaultPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.IPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.NMPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.VaultPermissionHandler;
import me.totalfreedom.totalfreedommod.player.PlayerList;
import me.totalfreedom.totalfreedommod.punishments.PunishmentList;
import me.totalfreedom.totalfreedommod.rank.RankManager;
@ -72,6 +78,7 @@ public class TotalFreedomMod extends JavaPlugin
public CommandLoader cl;
// Services
public WorldManager wm;
public LogViewer lv;
public AdminList al;
public ActivityLog acl;
public RankManager rm;
@ -117,16 +124,21 @@ public class TotalFreedomMod extends JavaPlugin
public HTTPDaemon hd;
public WorldRestrictions wr;
public EntityWiper ew;
public Sitter st;
public VanishHandler vh;
public Pterodactyl ptero;
//
// Bridges
public BukkitTelnetBridge btb;
public EssentialsBridge esb;
public LibsDisguisesBridge ldb;
public CoreProtectBridge cpb;
public TFGuildsBridge tfg;
public WorldEditBridge web;
public WorldGuardBridge wgb;
public IPermissionHandler permissionHandler;
public static TotalFreedomMod getPlugin()
{
return plugin;
@ -138,7 +150,7 @@ public class TotalFreedomMod extends JavaPlugin
{
if (plugin.getName().equalsIgnoreCase(pluginName))
{
return (TotalFreedomMod)plugin;
return (TotalFreedomMod) plugin;
}
}
return null;
@ -203,6 +215,20 @@ public class TotalFreedomMod extends JavaPlugin
// Metrics @ https://bstats.org/plugin/bukkit/TotalFreedomMod/2966
new Metrics(this, 2966);
if (getServer().getPluginManager().isPluginEnabled("NetworkManager"))
{
FLog.info("Using NetworkManager's permission handling");
this.permissionHandler = new NMPermissionHandler(this);
} else if (getServer().getPluginManager().isPluginEnabled("Vault"))
{
FLog.info("Using Vault's permission handling");
this.permissionHandler = new VaultPermissionHandler(this);
} else
{
FLog.info("Using Bukkit's native permission handling");
this.permissionHandler = new DefaultPermissionHandler();
}
}
@Override
@ -250,8 +276,7 @@ public class TotalFreedomMod extends JavaPlugin
date = props.getProperty("buildDate", "unknown");
// Need to do this or it will display ${git.commit.id.abbrev}
head = props.getProperty("buildHead", "unknown").replace("${git.commit.id.abbrev}", "unknown");
}
catch (Exception ex)
} catch (Exception ex)
{
FLog.severe("Could not load build properties! Did you compile with NetBeans/Maven?");
FLog.severe(ex);
@ -282,6 +307,7 @@ public class TotalFreedomMod extends JavaPlugin
{
// Start services
wm = new WorldManager();
lv = new LogViewer();
sql = new SQLite();
al = new AdminList();
acl = new ActivityLog();
@ -308,7 +334,9 @@ public class TotalFreedomMod extends JavaPlugin
pem = new PermissionManager();
gr = new GameRuleHandler();
ew = new EntityWiper();
st = new Sitter();
vh = new VanishHandler();
ptero = new Pterodactyl();
}
private void initAdminUtils()
@ -334,6 +362,7 @@ public class TotalFreedomMod extends JavaPlugin
cpb = new CoreProtectBridge();
esb = new EssentialsBridge();
ldb = new LibsDisguisesBridge();
tfg = new TFGuildsBridge();
web = new WorldEditBridge();
wgb = new WorldGuardBridge();
}

View File

@ -1,8 +1,6 @@
package me.totalfreedom.totalfreedommod;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.ChatColor;
@ -15,6 +13,7 @@ import org.bukkit.scheduler.BukkitRunnable;
public class VanishHandler extends FreedomService
{
@Override
public void onStart()
{
@ -30,32 +29,40 @@ public class VanishHandler extends FreedomService
{
Player player = event.getPlayer();
server.getOnlinePlayers().stream().filter(pl -> !plugin.al.isAdmin(player)
&& plugin.al.isVanished(pl.getUniqueId())).forEach(pl -> player.hidePlayer(plugin, pl));
for (Player p : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(player) && plugin.al.isVanished(p.getName()))
{
player.hidePlayer(plugin, p);
}
}
server.getOnlinePlayers().stream().filter(pl -> !plugin.al.isAdmin(pl)
&& plugin.al.isVanished(player.getUniqueId())).forEach(pl -> pl.hidePlayer(plugin, player));
for (Player p : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(p) && plugin.al.isVanished(player.getName()))
{
p.hidePlayer(plugin, player);
}
}
if (plugin.al.isVanished(player.getUniqueId()))
if (plugin.al.isVanished(player.getName()))
{
plugin.esb.setVanished(player.getName(), true);
FLog.info(player.getName() + " joined while still vanished.");
plugin.al.messageAllAdmins(ChatColor.YELLOW + player.getName() + " has joined silently.");
event.joinMessage(null);
event.setJoinMessage(null);
new BukkitRunnable()
{
@Override
public void run()
{
if (plugin.al.isVanished(player.getUniqueId()))
{
player.sendActionBar(Component.text("You are hidden from other players.").color(NamedTextColor.GOLD));
}
else
if (!plugin.al.isVanished(player.getName()))
{
this.cancel();
}
player.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(ChatColor.GOLD + "You are hidden from other players."));
}
}.runTaskTimer(plugin, 0L, 4L);
}
@ -66,9 +73,9 @@ public class VanishHandler extends FreedomService
{
Player player = event.getPlayer();
if (plugin.al.isVanished(player.getUniqueId()))
if (plugin.al.isVanished(player.getName()))
{
event.quitMessage(null);
event.setQuitMessage(null);
FLog.info(player.getName() + " left while still vanished.");
plugin.al.messageAllAdmins(ChatColor.YELLOW + player.getName() + " has left silently.");
}

View File

@ -66,13 +66,8 @@ public class ActivityLogEntry implements IConfig
public void addLogin()
{
this.addLogin(System.currentTimeMillis());
}
public void addLogin(final long timestamp)
{
Date time = Date.from(Instant.ofEpochMilli(timestamp));
timestamps.add("Login: " + FUtil.dateToString(time));
Date currentTime = Date.from(Instant.now());
timestamps.add("Login: " + FUtil.dateToString(currentTime));
}
public void addLogout()

View File

@ -4,14 +4,13 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import me.totalfreedom.totalfreedommod.LogViewer.LogsRegistrationMode;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Server;
import org.bukkit.entity.Player;
public class Admin
@ -24,6 +23,7 @@ public class Admin
private Boolean commandSpy = false;
private Boolean potionSpy = false;
private String acFormat = null;
private String pteroID = null;
public Admin(Player player)
{
@ -44,6 +44,7 @@ public class Admin
this.commandSpy = resultSet.getBoolean("command_spy");
this.potionSpy = resultSet.getBoolean("potion_spy");
this.acFormat = resultSet.getString("ac_format");
this.pteroID = resultSet.getString("ptero_id");
}
catch (SQLException e)
{
@ -56,13 +57,14 @@ public class Admin
{
final StringBuilder output = new StringBuilder();
output.append("Admin: ").append(getName() != null ? getName() : getUuid().toString()).append("\n")
output.append("Admin: ").append(getName()).append("\n")
.append("- IPs: ").append(StringUtils.join(ips, ", ")).append("\n")
.append("- Last Login: ").append(FUtil.dateToString(lastLogin)).append("\n")
.append("- Rank: ").append(rank.getName()).append("\n")
.append("- Is Active: ").append(active).append("\n")
.append("- Potion Spy: ").append(potionSpy).append("\n")
.append("- Admin Chat Format: ").append(acFormat).append("\n");
.append("- Admin Chat Format: ").append(acFormat).append("\n")
.append("- Pterodactyl ID: ").append(pteroID).append("\n");
return output.toString();
}
@ -79,6 +81,7 @@ public class Admin
put("command_spy", commandSpy);
put("potion_spy", potionSpy);
put("ac_format", acFormat);
put("ptero_id", pteroID);
}};
return map;
}
@ -154,35 +157,9 @@ public class Admin
{
plugin.btb.killTelnetSessions(getName());
}
// Ensure admins don't have admin functionality when removed (FS-222)
AdminList.vanished.remove(getUuid());
if (plugin.esb != null)
{
plugin.esb.setVanished(getName(), false);
}
setCommandSpy(false);
setPotionSpy(false);
Server server = Bukkit.getServer();
Player player = server.getPlayer(getUuid());
if (player != null)
{
// Update chats
FPlayer freedomPlayer = plugin.pl.getPlayer(player);
freedomPlayer.removeAdminFunctionality();
// Disable vanish
for (Player player1 : server.getOnlinePlayers())
{
player1.showPlayer(plugin, player);
}
}
}
plugin.lv.updateLogsRegistration(null, getName(), LogsRegistrationMode.DELETE);
}
}
@ -240,4 +217,14 @@ public class Admin
{
this.acFormat = acFormat;
}
public String getPteroID()
{
return pteroID;
}
public void setPteroID(String pteroID)
{
this.pteroID = pteroID;
}
}

View File

@ -2,22 +2,27 @@ package me.totalfreedom.totalfreedommod.admin;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.permissions.handler.NMPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.VaultPermissionHandler;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player;
public class AdminList extends FreedomService
{
public static final List<UUID> vanished = new ArrayList<>();
public static final List<String> vanished = new ArrayList<>();
private final Set<Admin> allAdmins = Sets.newHashSet(); // Includes disabled admins
// Only active admins below
private final Set<Admin> activeAdmins = Sets.newHashSet();
@ -25,6 +30,11 @@ public class AdminList extends FreedomService
private final Map<String, Admin> nameTable = Maps.newHashMap();
private final Map<String, Admin> ipTable = Maps.newHashMap();
public static List<String> getVanished()
{
return vanished;
}
@Override
public void onStart()
{
@ -43,21 +53,14 @@ public class AdminList extends FreedomService
try
{
ResultSet adminSet = plugin.sql.getAdminList();
while (adminSet.next())
{
try
while (adminSet.next())
{
Admin admin = new Admin(adminSet);
allAdmins.add(admin);
}
catch (Throwable ex)
{
FLog.warning("An error occurred whilst reading the admin entry at row #" + adminSet.getRow());
FLog.warning(ex);
}
}
}
catch (SQLException e)
} catch (SQLException e)
{
FLog.severe("Failed to load admin list: " + e.getMessage());
}
@ -94,6 +97,16 @@ public class AdminList extends FreedomService
return isAdmin(sender);
}
public List<String> getActiveAdminNames()
{
List<String> names = new ArrayList();
for (Admin admin : activeAdmins)
{
names.add(admin.getName());
}
return names;
}
public boolean isAdmin(CommandSender sender)
{
if (!(sender instanceof Player))
@ -101,7 +114,7 @@ public class AdminList extends FreedomService
return true;
}
Admin admin = getAdmin((Player)sender);
Admin admin = getAdmin((Player) sender);
return admin != null && admin.isActive();
}
@ -112,28 +125,48 @@ public class AdminList extends FreedomService
{
return true;
}
if (plugin.permissionHandler instanceof NMPermissionHandler || plugin.permissionHandler instanceof VaultPermissionHandler)
{
// FLog.debug("Using " + plugin.permissionHandler.getClass().getSimpleName() + " for AdminList#isAdmin");
return plugin.permissionHandler.inGroup(player, ConfigEntry.PERMISSIONS_GROUPS_ADMIN.getString());
}
// FLog.debug("AdminList#isAdmin: Returning false because there is no permissions plugin that supports groups on the server");
return false;
Admin admin = getAdmin(player);
/*Admin admin = getAdmin(player);
return admin != null && admin.isActive();
return admin != null && admin.isActive();*/
}
public boolean isSeniorAdmin(CommandSender sender)
{
Admin admin = getAdmin(sender);
//TODO: BukkitTelnet checks, but fuck that plugin
if (sender instanceof ConsoleCommandSender)
{
return true;
}
if (sender instanceof Player player && (plugin.permissionHandler instanceof NMPermissionHandler || plugin.permissionHandler instanceof VaultPermissionHandler))
{
// FLog.debug("Using " + plugin.permissionHandler.getClass().getSimpleName() + " for AdminList#isSeniorAdmin");
return plugin.permissionHandler.inGroup(player, ConfigEntry.PERMISSIONS_GROUPS_SENIOR.getString());
}
// FLog.debug("AdminList#isSeniorAdmin: Returning false because there is no permissions plugin that supports groups on the server");
return false;
// return plugin.permissionHandler.hasPermission(sender, "totalfreedommod.admin");
/*Admin admin = getAdmin(sender);
if (admin == null)
{
return false;
}
return admin.getRank().ordinal() >= Rank.SENIOR_ADMIN.ordinal();
return admin.getRank().ordinal() >= Rank.SENIOR_ADMIN.ordinal();*/
}
public Admin getAdmin(CommandSender sender)
{
if (sender instanceof Player)
{
return getAdmin((Player)sender);
return getAdmin((Player) sender);
}
return getEntryByName(sender.getName());
@ -194,15 +227,6 @@ public class AdminList extends FreedomService
// Save admin
plugin.sql.addAdmin(admin);
// Add login time
UUID uuid = admin.getUuid();
Player player = Bukkit.getPlayer(uuid);
if (player != null)
{
plugin.acl.getActivityLog(player).addLogin(player.getLastLogin());
}
return true;
}
@ -245,10 +269,7 @@ public class AdminList extends FreedomService
activeAdmins.add(admin);
uuidTable.put(admin.getUuid(), admin);
if (admin.getName() != null)
{
nameTable.put(admin.getName().toLowerCase(), admin);
}
nameTable.put(admin.getName().toLowerCase(), admin);
for (String ip : admin.getIps())
{
@ -280,8 +301,7 @@ public class AdminList extends FreedomService
plugin.sql.setAdminValue(admin, entry.getKey(), entry.getValue());
}
}
}
catch (SQLException e)
} catch (SQLException e)
{
FLog.severe("Failed to save admin: " + e.getMessage());
}
@ -316,9 +336,9 @@ public class AdminList extends FreedomService
updateTables();
}
public boolean isVanished(UUID uuid)
public boolean isVanished(String player)
{
return vanished.contains(uuid);
return vanished.contains(player);
}
public Set<Admin> getAllAdmins()

View File

@ -121,6 +121,17 @@ public class Ban
reason);
}
public static Ban forPlayerFuzzy(Player player, CommandSender by, Date expiry, String reason)
{
return new Ban(player.getName(),
player.getUniqueId(),
FUtil.getFuzzyIp(FUtil.getIp(player)),
by.getName(),
Date.from(Instant.now()),
expiry,
reason);
}
public static SimpleDateFormat getDateFormat()
{
return DATE_FORMAT;

View File

@ -1,5 +1,6 @@
package me.totalfreedom.totalfreedommod.banning;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import java.sql.ResultSet;
@ -13,6 +14,7 @@ import java.util.Map;
import java.util.Set;
import java.util.UUID;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.entity.Player;
@ -28,6 +30,8 @@ public class BanManager extends FreedomService
private final Map<String, Ban> nameBans = Maps.newHashMap();
private final Map<UUID, Ban> uuidBans = Maps.newHashMap();
private final Map<String, Ban> ipBans = Maps.newHashMap();
private final List<String> unbannableUsernames = Lists.newArrayList();
//
@Override
@ -66,6 +70,11 @@ public class BanManager extends FreedomService
updateViews();
FLog.info("Loaded " + ipBans.size() + " IP bans and " + nameBans.size() + " username bans.");
// Load unbannable usernames
unbannableUsernames.clear();
unbannableUsernames.addAll(ConfigEntry.FAMOUS_PLAYERS.getStringList());
FLog.info("Loaded " + unbannableUsernames.size() + " unbannable usernames.");
}
@Override

View File

@ -1,14 +1,10 @@
package me.totalfreedom.totalfreedommod.banning;
import com.google.common.collect.Lists;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import me.totalfreedom.totalfreedommod.config.IConfig;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.configuration.ConfigurationSection;
public class IndefiniteBan implements IConfig
@ -17,7 +13,6 @@ public class IndefiniteBan implements IConfig
private String username = null;
private UUID uuid = null;
private String reason = null;
private Date expiry = null;
public IndefiniteBan()
{
@ -27,7 +22,6 @@ public class IndefiniteBan implements IConfig
public void loadFrom(ConfigurationSection cs)
{
this.username = cs.getName();
try
{
String strUUID = cs.getString("uuid", null);
@ -41,20 +35,9 @@ public class IndefiniteBan implements IConfig
{
FLog.warning("Failed to load indefinite banned UUID for " + this.username + ". Make sure the UUID is in the correct format with dashes.");
}
this.ips.clear();
this.ips.addAll(cs.getStringList("ips"));
this.reason = cs.getString("reason", null);
String date = cs.getString("expiry", null);
try
{
this.expiry = date != null ? new SimpleDateFormat("yyyy-MM-dd").parse(date) : null;
}
catch (ParseException ex)
{
FLog.warning("Failed to load indefinite banned expiry for " + this.username + ". Make sure the expiry is in the correct format (yyyy-MM-dd).");
}
}
@Override
@ -103,24 +86,4 @@ public class IndefiniteBan implements IConfig
{
this.reason = reason;
}
public Date getExpiry()
{
return expiry;
}
public void setExpiry(Date date)
{
this.expiry = date;
}
public boolean hasExpiry()
{
return this.expiry != null;
}
public boolean isExpired()
{
return hasExpiry() && expiry.before(new Date(FUtil.getUnixTime()));
}
}

View File

@ -2,8 +2,6 @@ package me.totalfreedom.totalfreedommod.banning;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Set;
import java.util.UUID;
import me.totalfreedom.totalfreedommod.FreedomService;
@ -21,24 +19,30 @@ public class IndefiniteBanList extends FreedomService
{
public static final String CONFIG_FILENAME = "indefinitebans.yml";
private YamlConfig config;
private final Set<IndefiniteBan> indefBans = Sets.newHashSet();
private int nameBanCount = 0;
private int uuidBanCount = 0;
private int ipBanCount = 0;
private final SimpleDateFormat dateFormat = new SimpleDateFormat("dd MMM yyyy, zzzz");
public static String getConfigFilename()
{
return CONFIG_FILENAME;
}
@Override
public void onStart()
{
indefBans.clear();
config = new YamlConfig(plugin, CONFIG_FILENAME, true);
final YamlConfig config = new YamlConfig(plugin, CONFIG_FILENAME, true);
config.load();
for (String name : config.getKeys(false))
@ -60,18 +64,10 @@ public class IndefiniteBanList extends FreedomService
continue;
}
if (indefBan.isExpired())
{
FLog.info("Removing " + name + " from indefinite ban list as the entry has expired!");
config.set(name, null);
continue;
}
indefBans.add(indefBan);
}
updateCount();
config.save();
FLog.info("Loaded " + nameBanCount + " indefinite name bans, " + uuidBanCount + " UUID bans, and " + ipBanCount + " ip bans");
}
@ -115,28 +111,12 @@ public class IndefiniteBanList extends FreedomService
if (ban != null)
{
if (ban.isExpired())
{
config.set(ban.getUsername(), null);
config.save();
return;
}
String kickMessage = ChatColor.RED + "Your " + bannedBy + " is "
+ (ban.hasExpiry() ? "" : "indefinitely ")
+ "banned from this server.";
String kickMessage = ChatColor.RED + "Your " + bannedBy + " is indefinitely banned from this server.";
String reason = ban.getReason();
if (!Strings.isNullOrEmpty(reason))
{
kickMessage += "\nReason: " + ChatColor.GOLD + reason;
}
Date expiry = ban.getExpiry();
if (expiry != null)
{
kickMessage += ChatColor.RED + "\nExpiry: " + ChatColor.GOLD + dateFormat.format(expiry);
}
String appealURL = ConfigEntry.SERVER_INDEFBAN_URL.getString();
if (!Strings.isNullOrEmpty(appealURL))
{

View File

@ -1,10 +1,14 @@
package me.totalfreedom.totalfreedommod.blocking;
import java.util.List;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.Groups;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.block.Banner;
import org.bukkit.block.Skull;
import org.bukkit.block.banner.Pattern;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -67,7 +71,7 @@ public class BlockBlocker extends FreedomService
}
case STRUCTURE_BLOCK:
{
if (!ConfigEntry.ALLOW_MASTERBLOCKS.getBoolean())
if (!ConfigEntry.ALLOW_STRUCTURE_BLOCKS.getBoolean())
{
player.sendMessage(ChatColor.GRAY + "Structure blocks are disabled.");
player.getInventory().setItem(player.getInventory().getHeldItemSlot(), new ItemStack(Material.COOKIE, 1));
@ -77,7 +81,7 @@ public class BlockBlocker extends FreedomService
}
case JIGSAW:
{
if (!ConfigEntry.ALLOW_MASTERBLOCKS.getBoolean())
if (!ConfigEntry.ALLOW_JIGSAWS.getBoolean())
{
player.sendMessage(ChatColor.GRAY + "Jigsaws are disabled.");
player.getInventory().setItem(player.getInventory().getHeldItemSlot(), new ItemStack(Material.COOKIE, 1));
@ -85,16 +89,6 @@ public class BlockBlocker extends FreedomService
}
break;
}
case REPEATING_COMMAND_BLOCK:
case CHAIN_COMMAND_BLOCK:
case COMMAND_BLOCK:
if (!ConfigEntry.ALLOW_MASTERBLOCKS.getBoolean())
{
player.sendMessage(ChatColor.GRAY + "Command blocks are disabled.");
player.getInventory().setItem(player.getInventory().getHeldItemSlot(), new ItemStack(Material.COOKIE, 1));
event.setCancelled(true);
}
break;
case GRINDSTONE:
{
if (!ConfigEntry.ALLOW_GRINDSTONES.getBoolean())
@ -183,5 +177,17 @@ public class BlockBlocker extends FreedomService
break;
}
}
if (Groups.BANNERS.contains(event.getBlockPlaced().getType()))
{
Banner banner = (Banner)event.getBlockPlaced().getState();
List<Pattern> patterns = banner.getPatterns();
if (patterns.size() >= 2)
{
banner.setPatterns(patterns.subList(0, 2));
player.sendMessage(ChatColor.GRAY + "Your banner had too many patterns on it, so some were removed.");
}
}
}
}

View File

@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import me.totalfreedom.scissors.event.block.MasterBlockFireEvent;
import io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -20,7 +20,15 @@ import org.bukkit.entity.FallingBlock;
import org.bukkit.entity.Tameable;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.*;
import org.bukkit.event.block.BlockBurnEvent;
import org.bukkit.event.block.BlockDispenseEvent;
import org.bukkit.event.block.BlockFromToEvent;
import org.bukkit.event.block.BlockGrowEvent;
import org.bukkit.event.block.BlockIgniteEvent;
import org.bukkit.event.block.BlockPhysicsEvent;
import org.bukkit.event.block.BlockPistonExtendEvent;
import org.bukkit.event.block.BlockPistonRetractEvent;
import org.bukkit.event.block.LeavesDecayEvent;
import org.bukkit.event.entity.EntityCombustEvent;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDeathEvent;
@ -109,28 +117,6 @@ public class EventBlocker extends FreedomService
event.setRadius(ConfigEntry.EXPLOSIVE_RADIUS.getDouble().floatValue());
}
@EventHandler(priority = EventPriority.HIGH)
public void onBlockExplode(BlockExplodeEvent event)
{
if (!ConfigEntry.ALLOW_EXPLOSIONS.getBoolean())
{
event.setCancelled(true);
return;
}
event.setYield(ConfigEntry.EXPLOSIVE_RADIUS.getDouble().floatValue());
}
@EventHandler(priority = EventPriority.HIGHEST)
public void onMasterBlockFire(MasterBlockFireEvent event)
{
if (!ConfigEntry.ALLOW_MASTERBLOCKS.getBoolean())
{
event.setCancelled(true);
event.getAt().getBlock().setType(Material.CAKE);
}
}
@EventHandler(priority = EventPriority.HIGH)
public void onEntityCombust(EntityCombustEvent event)
{
@ -162,9 +148,12 @@ public class EventBlocker extends FreedomService
if (ConfigEntry.ENABLE_PET_PROTECT.getBoolean())
{
Entity entity = event.getEntity();
if (entity instanceof Tameable tameable && tameable.isTamed())
if (entity instanceof Tameable)
{
event.setCancelled(true);
if (((Tameable)entity).isTamed())
{
event.setCancelled(true);
}
}
}
}
@ -172,7 +161,7 @@ public class EventBlocker extends FreedomService
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerDropItem(PlayerDropItemEvent event)
{
if (!plugin.al.isAdmin(event.getPlayer()) && !ConfigEntry.ALLOW_ITEM_DROPS.getBoolean())
if (!plugin.al.isAdmin(event.getPlayer()))
{
event.setCancelled(true);
}

View File

@ -4,10 +4,7 @@ import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.Groups;
import org.bukkit.ChatColor;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -27,7 +24,7 @@ public class InteractBlocker extends FreedomService
{
}
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
@EventHandler(priority = EventPriority.HIGH)
public void onPlayerInteract(PlayerInteractEvent event)
{
switch (event.getAction())
@ -70,42 +67,21 @@ public class InteractBlocker extends FreedomService
private void handleRightClick(PlayerInteractEvent event)
{
final Player player = event.getPlayer();
if (player.getGameMode().equals(GameMode.SPECTATOR)) {
return;
}
final Block clickedBlock = event.getClickedBlock();
if (clickedBlock != null && clickedBlock.getType() == Material.RESPAWN_ANCHOR && !ConfigEntry.ALLOW_RESPAWN_ANCHORS.getBoolean())
if (event.getClickedBlock() != null)
{
event.setCancelled(true);
return;
if (event.getClickedBlock().getType().equals(Material.STRUCTURE_BLOCK) || event.getClickedBlock().getType().equals(Material.JIGSAW) || event.getClickedBlock().getType().equals(Material.RESPAWN_ANCHOR))
{
event.setCancelled(true);
event.getPlayer().closeInventory();
}
}
if (Groups.SPAWN_EGGS.contains(event.getMaterial()))
{
player.getInventory().clear(player.getInventory().getHeldItemSlot());
player.sendMessage(ChatColor.GRAY + "Spawn eggs are currently disabled.");
event.setCancelled(true);
EntityType eggType = null;
try
{
Material mat = event.getMaterial();
if (mat == Material.MOOSHROOM_SPAWN_EGG)
{
eggType = EntityType.MUSHROOM_COW;
}
else
{
eggType = EntityType.valueOf(mat.name().substring(0, mat.name().length() - 10));
}
}
catch (IllegalArgumentException ignored)
{
//
}
if (eggType != null && clickedBlock != null)
{
clickedBlock.getWorld().spawnEntity(clickedBlock.getLocation().add(event.getBlockFace().getDirection()).add(0.5, 0.5, 0.5), eggType);
}
return;
}
@ -176,11 +152,6 @@ public class InteractBlocker extends FreedomService
}
case WRITTEN_BOOK:
{
if (ConfigEntry.ALLOW_BOOKS.getBoolean())
{
break;
}
player.getInventory().clear(player.getInventory().getHeldItemSlot());
player.sendMessage(ChatColor.GRAY + "Books are currently disabled.");
event.setCancelled(true);

View File

@ -24,12 +24,30 @@ import org.bukkit.plugin.SimplePluginManager;
public class CommandBlocker extends FreedomService
{
private final Pattern whitespacePattern = Pattern.compile("^/?( +)(.*)?");
private final Pattern flagPattern = Pattern.compile("(:([0-9]){5,})");
//
private final Map<String, CommandBlockerEntry> entryList = Maps.newHashMap();
private final List<String> unknownCommands = Lists.newArrayList();
public static CommandMap getCommandMap()
{
try
{
SimplePluginManager simplePluginManager = (SimplePluginManager)Bukkit.getServer().getPluginManager();
Field commandMapField = SimplePluginManager.class.getDeclaredField("commandMap");
commandMapField.setAccessible(true);
return (SimpleCommandMap)commandMapField.get(simplePluginManager);
}
catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e)
{
FLog.severe("Failed to get command map field (" + e.getMessage() + ")");
}
return null;
}
@Override
public void onStart()
{
@ -47,7 +65,7 @@ public class CommandBlocker extends FreedomService
entryList.clear();
unknownCommands.clear();
final CommandMap commandMap = Bukkit.getCommandMap();
final CommandMap commandMap = getCommandMap();
@SuppressWarnings("unchecked")
List<String> blockedCommands = (List<String>)ConfigEntry.BLOCKED_COMMANDS.getList();
@ -138,14 +156,6 @@ public class CommandBlocker extends FreedomService
// Format
command = command.toLowerCase().trim();
// Whitespaces
Matcher whitespaceMatcher = whitespacePattern.matcher(command);
if (whitespaceMatcher.matches() && whitespaceMatcher.groupCount() == 2)
{
command = whitespaceMatcher.group(2);
}
command = command.startsWith("/") ? command.substring(1) : command;
// Check for plugin specific commands
@ -193,9 +203,12 @@ public class CommandBlocker extends FreedomService
}
// Validate sub command
if (entry.getSubCommand() != null && (subCommand == null || !subCommand.startsWith(entry.getSubCommand())))
if (entry.getSubCommand() != null)
{
return false;
if (subCommand == null || !subCommand.startsWith(entry.getSubCommand()))
{
return false;
}
}
if (entry.getRank().hasPermission(sender))

View File

@ -90,10 +90,7 @@ public class BukkitTelnetBridge extends FreedomService
playerTags.put("tfm.playerdata.getTag", plugin.pl.getPlayer(player).getTag());
if (server.getPluginManager().isPluginEnabled("Essentials"))
{
playerTags.put("tfm.essentialsBridge.getNickname", plugin.esb.getNickname(player.getName()));
}
playerTags.put("tfm.essentialsBridge.getNickname", plugin.esb.getNickname(player.getName()));
}
}
@ -104,9 +101,12 @@ public class BukkitTelnetBridge extends FreedomService
try
{
final Plugin bukkitTelnet = server.getPluginManager().getPlugin("BukkitTelnet");
if (bukkitTelnet instanceof BukkitTelnet)
if (bukkitTelnet != null)
{
bukkitTelnetPlugin = (BukkitTelnet)bukkitTelnet;
if (bukkitTelnet instanceof BukkitTelnet)
{
bukkitTelnetPlugin = (BukkitTelnet)bukkitTelnet;
}
}
}
catch (Exception ex)

View File

@ -1,58 +1,81 @@
package me.totalfreedom.totalfreedommod.bridge;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.io.File;
import java.sql.*;
import java.text.DecimalFormat;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.coreprotect.CoreProtect;
import net.coreprotect.CoreProtectAPI;
import net.coreprotect.utility.Util;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.TextComponent;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.Material;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.block.Action;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.Plugin;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
public class CoreProtectBridge extends FreedomService
{
//-- Block Inspector --//
private static final Component name = Component.text("Block Inspector").color(TextColor.color(0x30ade4));
private static final Component header = Component.text("---- ").append(name)
.append(Component.text(" ---- ")).colorIfAbsent(NamedTextColor.WHITE);
private static final Component prefix = name.append(Component.text(" - ").color(NamedTextColor.WHITE))
.colorIfAbsent(NamedTextColor.WHITE);
//--
private final HashMap<UUID, Long> cooldownMap = new HashMap<>();
private HashMap<UUID, FUtil.PaginationList<CoreProtectAPI.ParseResult>> historyMap;
public static Map<Player, FUtil.PaginationList<String>> HISTORY_MAP = new HashMap<>();
private final List<String> tables = Arrays.asList("co_sign", "co_session", "co_container", "co_block");
//---------------------//
private final HashMap<String, Long> cooldown = new HashMap<>();
private CoreProtectAPI coreProtectAPI = null;
private BukkitTask wiper;
public static Long getSecondsLeft(long prevTime, int timeAdd)
{
return prevTime / 1000L + timeAdd - System.currentTimeMillis() / 1000L;
}
// Unix timestamp converter taken from Functions class in CoreProtect, not my code
public static String getTimeAgo(int logTime, int currentTime)
{
StringBuilder message = new StringBuilder();
double timeSince = (double)currentTime - ((double)logTime + 0.0D);
timeSince /= 60.0D;
if (timeSince < 60.0D)
{
message.append((new DecimalFormat("0.00")).format(timeSince)).append("/m ago");
}
if (message.length() == 0)
{
timeSince /= 60.0D;
if (timeSince < 24.0D)
{
message.append((new DecimalFormat("0.00")).format(timeSince)).append("/h ago");
}
}
if (message.length() == 0)
{
timeSince /= 24.0D;
message.append((new DecimalFormat("0.00")).format(timeSince)).append("/d ago");
}
return message.toString();
}
@Override
public void onStart()
{
if (isEnabled())
{
historyMap = new HashMap<>();
}
}
@Override
@ -65,7 +88,7 @@ public class CoreProtectBridge extends FreedomService
CoreProtect coreProtect = null;
try
{
final Plugin coreProtectPlugin = server.getPluginManager().getPlugin("CoreProtect");
final Plugin coreProtectPlugin = Bukkit.getServer().getPluginManager().getPlugin("CoreProtect");
assert coreProtectPlugin != null;
if (coreProtectPlugin instanceof CoreProtect)
{
@ -106,11 +129,6 @@ public class CoreProtectBridge extends FreedomService
public boolean isEnabled()
{
if (!server.getPluginManager().isPluginEnabled("CoreProtect"))
{
return false;
}
final CoreProtect coreProtect = getCoreProtect();
return coreProtect != null && coreProtect.isEnabled();
@ -119,13 +137,13 @@ public class CoreProtectBridge extends FreedomService
// Rollback the specified player's edits that were in the last 24 hours.
public void rollback(final String name)
{
final CoreProtectAPI coreProtect = getCoreProtectAPI();
if (!isEnabled())
{
return;
}
final CoreProtectAPI coreProtect = getCoreProtectAPI();
new BukkitRunnable()
{
@Override
@ -139,13 +157,13 @@ public class CoreProtectBridge extends FreedomService
// Reverts a rollback for the specified player's edits that were in the last 24 hours.
public void restore(final String name)
{
final CoreProtectAPI coreProtect = getCoreProtectAPI();
if (!isEnabled())
{
return;
}
final CoreProtectAPI coreProtect = getCoreProtectAPI();
new BukkitRunnable()
{
@Override
@ -156,182 +174,264 @@ public class CoreProtectBridge extends FreedomService
}.runTaskAsynchronously(plugin);
}
public boolean hasHistory(Player player)
public File getDatabase()
{
return historyMap.containsKey(player.getUniqueId());
}
public FUtil.PaginationList<CoreProtectAPI.ParseResult> getHistoryForPlayer(Player player)
{
return historyMap.get(player.getUniqueId());
}
public void showPageToPlayer(Player player, FUtil.PaginationList<CoreProtectAPI.ParseResult> results, int pageNum)
{
if (player == null || !player.isOnline())
{
return;
}
List<CoreProtectAPI.ParseResult> page = results.getPage(pageNum);
if (page == null || page.isEmpty())
{
player.sendMessage(prefix.append(Component.text("No results were found.", NamedTextColor.WHITE)));
}
else
{
// This shouldn't change at all in any of the other entries, so this should be safe
Component location = Component.text(String.format("(%s, %s, %s)", results.get(0).getX(),
results.get(0).getY(), results.get(0).getZ()));
final long time = System.currentTimeMillis() / 1000;
player.sendMessage(header.append(location.color(NamedTextColor.GRAY).decorate(TextDecoration.ITALIC)));
page.forEach(entry ->
{
TextComponent.Builder line = Component.text();
// Time
line.append(Component.text(Util.getTimeSince(entry.getTime(), time, false))
.color(NamedTextColor.GRAY));
// Action
Component action = Component.text(" interacted with ");
Component symbol = Component.text(" - ", NamedTextColor.WHITE);
switch (entry.getActionId())
{
case 0 ->
{
action = Component.text(" broke ");
symbol = Component.text(" - ", NamedTextColor.RED);
}
case 1 ->
{
action = Component.text(" placed ");
symbol = Component.text(" + ", NamedTextColor.GREEN);
}
case 2 -> action = Component.text(" clicked ");
default ->
{
// Do nothing (shuts Codacy up)
}
}
// Symbol, player, action, block
line.append(symbol).append(Component.text(entry.getPlayer()).color(TextColor.color(0x30ade4)))
.append(action.color(NamedTextColor.WHITE)).append(
Component.text(entry.getBlockData().getMaterial().name().toLowerCase())
.color(TextColor.color(0x30ade4)));
// Rolled back?
if (entry.isRolledBack())
{
line.decorate(TextDecoration.STRIKETHROUGH);
}
player.sendMessage(line.append(Component.text(".", NamedTextColor.WHITE)).build());
});
if (results.getPageCount() > 1)
{
player.sendMessage(Component.text("-----", NamedTextColor.WHITE));
// Page indicator
TextComponent.Builder indicator = Component.text();
// <-
if (pageNum > 1)
{
indicator.append(Component.text("", NamedTextColor.WHITE).clickEvent(
ClickEvent.runCommand("/ins history " + (pageNum - 1))));
}
// Page <current>/<total>
indicator.append(Component.text("Page ", TextColor.color(0x30ade4)).append(Component.text(pageNum + "/"
+ results.getPageCount(), NamedTextColor.WHITE)));
// ->
if (pageNum < results.getPageCount())
{
indicator.append(Component.text("", NamedTextColor.WHITE).clickEvent(
ClickEvent.runCommand("/ins history " + (pageNum + 1))));
}
// | Use /ins history <page> for advanced navigation
indicator.append(Component.text(" | ", NamedTextColor.GRAY).append(Component.text("Use ", NamedTextColor.WHITE)
.append(Component.text("/ins history <page>", TextColor.color(0x30ade4))
.clickEvent(ClickEvent.suggestCommand("/ins history ")))
.append(Component.text(" for advanced navigation", NamedTextColor.WHITE))));
player.sendMessage(indicator.build());
}
}
}
public CompletableFuture<FUtil.PaginationList<CoreProtectAPI.ParseResult>> lookupForPlayer(Block block, Player player)
{
cooldownMap.put(player.getUniqueId(), System.currentTimeMillis());
CoreProtectAPI api = getCoreProtectAPI();
return CompletableFuture.supplyAsync(() ->
{
historyMap.remove(player.getUniqueId());
FUtil.PaginationList<CoreProtectAPI.ParseResult> pages = new FUtil.PaginationList<>(10);
api.blockLookup(block, -1).forEach(stringArray -> pages.add(api.parseResult(stringArray)));
historyMap.put(player.getUniqueId(), pages);
return pages;
});
}
@EventHandler(priority = EventPriority.MONITOR)
public void onInteract(PlayerInteractEvent event)
{
// The inspector only works if we have CoreProtect installed
if (!isEnabled())
{
return null;
}
return (new File(getCoreProtect().getDataFolder(), "database.db"));
}
public double getDBSize()
{
double bytes = getDatabase().length();
double kilobytes = (bytes / 1024);
double megabytes = (kilobytes / 1024);
return (megabytes / 1024);
}
public void clearDatabase(World world)
{
clearDatabase(world, false);
}
// Wipes DB for the specified world
public void clearDatabase(World world, Boolean shutdown)
{
if (!ConfigEntry.COREPROTECT_MYSQL_ENABLED.getBoolean())
{
return;
}
final CoreProtect coreProtect = getCoreProtect();
if (coreProtect == null)
{
return;
}
Player player = event.getPlayer();
if ((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)
&& plugin.pl.getData(player.getUniqueId()).hasInspection())
/* As CoreProtect doesn't have an API method for deleting all of the data for a specific world
we have to do this manually via SQL */
Connection connection;
try
{
event.setCancelled(true);
Block block = event.getClickedBlock();
Optional<Long> cooldown = Optional.ofNullable(cooldownMap.get(player.getUniqueId()));
String host = ConfigEntry.COREPROTECT_MYSQL_HOST.getString();
String port = ConfigEntry.COREPROTECT_MYSQL_PORT.getString();
String username = ConfigEntry.COREPROTECT_MYSQL_USERNAME.getString();
String password = ConfigEntry.COREPROTECT_MYSQL_PASSWORD.getString();
String database = ConfigEntry.COREPROTECT_MYSQL_DATABASE.getString();
String url = host + ":" + port + "/" + database + "?user=" + username + "&password=" + password + "&useSSL=false";
connection = DriverManager.getConnection("jdbc:sql://" + url);
final PreparedStatement statement = connection.prepareStatement("SELECT id FROM co_world WHERE world = ?");
statement.setQueryTimeout(30);
if (cooldown.isPresent() && getSecondsLeft(cooldown.get(), 3) > 0L)
// Obtain world ID from CoreProtect database
statement.setString(1, world.getName());
ResultSet resultSet = statement.executeQuery();
String worldID = null;
while (resultSet.next())
{
player.sendMessage(prefix.append(Component.text("You need to wait ")
.append(Component.text(getSecondsLeft(cooldown.get(), 3)))
.append(Component.text(" seconds before you can make another query."))
.color(NamedTextColor.WHITE)));
worldID = String.valueOf(resultSet.getInt("id"));
}
// Ensure the world ID is not null
if (worldID == null)
{
FLog.warning("Failed to obtain the world ID for the " + world.getName());
return;
}
// Time to do a look-up.
if (block != null)
// Iterate through each table and delete their data if the world ID matches
for (String table : tables)
{
/* This is a hack to make it so that when you right-click, the coordinates that get used depend on
* what's in your hand. Non-blocks use the block you clicked directly, but blocks use wherever the
* block was supposed to be placed. */
ItemStack hand = player.getInventory().getItemInMainHand();
if (event.getAction() == Action.RIGHT_CLICK_BLOCK && hand.getType().isBlock() && hand.getType() != Material.AIR)
{
block = block.getRelative(event.getBlockFace()).getState().getBlock();
}
final PreparedStatement statement1 = connection.prepareStatement("DELETE FROM ? WHERE wid = ?");
statement1.setString(1, table);
statement1.setString(2, worldID);
statement1.executeQuery();
}
lookupForPlayer(block, player).thenAccept(results ->
connection.close();
}
catch (SQLException e)
{
FLog.warning("Failed to delete the CoreProtect data for the " + world.getName());
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerInteract(PlayerInteractEvent event)
{
Player player = event.getPlayer();
PlayerData data = plugin.pl.getData(player);
Block block = event.getClickedBlock();
final CoreProtectAPI coreProtect = getCoreProtectAPI();
// TODO: Rewrite this
if (data.hasInspection())
{
int cooldownTime = 3;
// Cooldown check
if ((event.getAction() == Action.LEFT_CLICK_BLOCK || event.getAction() == Action.RIGHT_CLICK_BLOCK)
&& cooldown.containsKey(player.getName()))
{
long secondsLeft = getSecondsLeft(cooldown.get(player.getName()), cooldownTime);
if (secondsLeft > 0L)
{
if (results.isEmpty())
event.setCancelled(true);
player.sendMessage(ChatColor.RED + String.valueOf(secondsLeft) + " seconds left before next query.");
return;
}
}
// Actual lookup time
if (event.getAction() == Action.LEFT_CLICK_BLOCK)
{
if (block != null)
{
event.setCancelled(true);
List<String[]> lookup = coreProtect.blockLookup(block, -1);
if (!plugin.al.isAdmin(player))
{
player.sendMessage(prefix.append(Component.text("No results were found.").color(NamedTextColor.WHITE)));
cooldown.put(player.getName(), System.currentTimeMillis());
}
else
if (lookup != null)
{
showPageToPlayer(player, results, 1);
if (lookup.isEmpty())
{
player.sendMessage(net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector " + ChatColor.WHITE + "- " + "No block data found for this location");
return;
}
HISTORY_MAP.remove(event.getPlayer());
HISTORY_MAP.put(event.getPlayer(), new FUtil.PaginationList<>(10));
FUtil.PaginationList<String> paged = HISTORY_MAP.get(event.getPlayer());
player.sendMessage("---- " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector" + ChatColor.WHITE + " ---- " +
ChatColor.GRAY + "(x" + block.getX() + "/" + "y" + block.getY() + "/" + "z" + block.getZ() + ")");
for (String[] value : lookup)
{
CoreProtectAPI.ParseResult result = coreProtect.parseResult(value);
BlockData bl = result.getBlockData();
String s;
String st = "";
if (result.getActionString().equals("Placement"))
{
s = " placed ";
}
else if (result.getActionString().equals("Removal"))
{
s = " broke ";
}
else
{
s = " interacted with ";
}
if (result.isRolledBack())
{
st += "§m";
}
int time = (int)(System.currentTimeMillis() / 1000L);
paged.add(ChatColor.GRAY + getTimeAgo(result.getTime(), time) + ChatColor.WHITE + " - " + net.md_5.bungee.api.ChatColor.of("#30ade4") +
st + result.getPlayer() + ChatColor.WHITE + st + s + net.md_5.bungee.api.ChatColor.of("#30ade4") + st + bl.getMaterial().toString().toLowerCase());
}
List<String> page = paged.getPage(1);
for (String entries : page)
{
player.sendMessage(entries);
}
player.sendMessage("Page 1/" + paged.getPageCount() + " | To index through the pages, type " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "/ins history <page>");
}
});
}
}
else if (event.getAction() == Action.RIGHT_CLICK_BLOCK)
{
if (block != null)
{
BlockState blockState = block.getRelative(event.getBlockFace()).getState();
Block placedBlock = blockState.getBlock();
event.setCancelled(true);
List<String[]> lookup = coreProtect.blockLookup(placedBlock, -1);
if (lookup.isEmpty())
{
lookup = coreProtect.blockLookup(block, -1);
}
if (!plugin.al.isAdmin(player))
{
cooldown.put(player.getName(), System.currentTimeMillis());
}
if (lookup != null)
{
if (lookup.isEmpty())
{
player.sendMessage(net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector " + ChatColor.WHITE + "- " + "No block data found for this location");
return;
}
HISTORY_MAP.remove(event.getPlayer());
HISTORY_MAP.put(event.getPlayer(), new FUtil.PaginationList<>(10));
FUtil.PaginationList<String> paged = HISTORY_MAP.get(event.getPlayer());
player.sendMessage("---- " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector" + ChatColor.WHITE + " ---- " +
ChatColor.GRAY + "(x" + block.getX() + "/" + "y" + block.getY() + "/" + "z" + block.getZ() + ")");
for (String[] value : lookup)
{
CoreProtectAPI.ParseResult result = coreProtect.parseResult(value);
BlockData bl = result.getBlockData();
String s;
String st = "";
if (result.getActionString().equals("Placement"))
{
s = " placed ";
}
else if (result.getActionString().equals("Removal"))
{
s = " broke ";
}
else
{
s = " interacted with ";
}
if (result.isRolledBack())
{
st += "§m";
}
int time = (int)(System.currentTimeMillis() / 1000L);
paged.add(ChatColor.GRAY + getTimeAgo(result.getTime(), time) + ChatColor.WHITE + " - " + net.md_5.bungee.api.ChatColor.of("#30ade4") +
st + result.getPlayer() + ChatColor.WHITE + st + s + net.md_5.bungee.api.ChatColor.of("#30ade4") + st + bl.getMaterial().toString().toLowerCase());
}
List<String> page = paged.getPage(1);
for (String entries : page)
{
player.sendMessage(entries);
}
player.sendMessage("Page 1/" + paged.getPageCount() + " | To index through the pages, type " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "/ins history <page>");
}
}
}
}
}

View File

@ -6,6 +6,7 @@ import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -13,6 +14,7 @@ import org.bukkit.event.EventPriority;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.inventory.Inventory;
import org.bukkit.inventory.InventoryHolder;
import org.bukkit.plugin.Plugin;
@ -127,7 +129,7 @@ public class EssentialsBridge extends FreedomService
try
{
User user = getEssentialsUser(username);
if (user != null && user.getBase().isOnline())
if (user != null)
{
user.setVanished(vanished);
}
@ -202,10 +204,17 @@ public class EssentialsBridge extends FreedomService
}
}
// TODO: Actually use this for something or remove it.
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerQuit(PlayerQuitEvent event)
{
Player player = event.getPlayer();
}
public boolean isEnabled()
{
final Essentials ess = getEssentialsPlugin();
return ess != null && ess.isEnabled();
}
}
}

View File

@ -0,0 +1,58 @@
package me.totalfreedom.totalfreedommod.bridge;
import me.totalfreedom.tfguilds.Common;
import me.totalfreedom.tfguilds.TFGuilds;
import me.totalfreedom.totalfreedommod.FreedomService;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
public class TFGuildsBridge extends FreedomService
{
public boolean enabled = false;
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
public boolean isTFGuildsEnabled()
{
if (enabled)
{
return true;
}
try
{
final Plugin tfGuilds = server.getPluginManager().getPlugin("TFGuilds");
if (tfGuilds != null && tfGuilds.isEnabled())
{
if (tfGuilds instanceof TFGuilds)
{
enabled = true;
return true;
}
}
}
catch (NoClassDefFoundError ex)
{
return false;
}
return false;
}
public boolean inGuildChat(Player player)
{
if (!isTFGuildsEnabled())
{
return false;
}
return Common.GUILD_CHAT.contains(player);
}
}

View File

@ -10,9 +10,12 @@ public @interface CommandPermissions
Rank level() default Rank.NON_OP;
String permission() default "";
SourceType source() default SourceType.BOTH;
boolean blockHostConsole() default false;
int cooldown() default 0;
}

View File

@ -6,7 +6,6 @@ import java.util.List;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.kyori.adventure.text.Component;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -34,8 +33,13 @@ public class Command_adminmode extends FreedomCommand
{
ConfigEntry.ADMIN_ONLY_MODE.setBoolean(true);
FUtil.adminAction(sender.getName(), "Closing the server to non-admins", true);
server.getOnlinePlayers().stream().filter(player -> !isAdmin(player)).forEach(player ->
player.kick(Component.text("The server is now closed to non-admins.")));
for (Player player : server.getOnlinePlayers())
{
if (!isAdmin(player))
{
player.kickPlayer("Server is now closed to non-admins.");
}
}
return true;
}

View File

@ -1,21 +1,30 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.attribute.Attribute;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Arrays;
@CommandPermissions(level = Rank.OP, source = SourceType.BOTH)
@CommandParameters(description = "Lists all possible attributes.", usage = "/<command>")
public class Command_attributelist extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
msg("All possible attributes: " + FUtil.listToString(Arrays.stream(Attribute.values()).map(Enum::name).toList()));
StringBuilder list = new StringBuilder("All possible attributes: ");
for (Attribute attribute : Attribute.values())
{
list.append(attribute.name()).append(", ");
}
// Remove extra comma at the end of the list
list = new StringBuilder(list.substring(0, list.length() - 2));
msg(list.toString());
return true;
}
}

View File

@ -5,106 +5,134 @@ import me.totalfreedom.totalfreedommod.punishments.Punishment;
import me.totalfreedom.totalfreedommod.punishments.PunishmentType;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.List;
import java.util.Optional;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Restricts/restores block modification abilities for everyone on the server or a certain player.", usage = "/<command> [<player> [reason] | list | purge | all]")
@CommandParameters(description = "Restricts/unrestricts block modification abilities for everyone on the server or a certain player.", usage = "/<command> [[-s] <player> [reason] | list | purge | all]")
public class Command_blockedit extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, String[] args, final boolean senderIsConsole)
{
if (args.length > 0)
{
switch (args[0].toLowerCase())
{
case "list" ->
{
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
plugin.pl.getPlayer(player).isEditBlocked()).sorted().toList();
// Oh dear god, why do I have to do it like this?
msg("There " + (list.size() != 1 ? "are " : "is ") + list.size() + " player"
+ (list.size() != 1 ? "s" : "") + " online with restricted block modification abilities"
+ (list.size() > 0 ? ":" : "."));
list.forEach(player -> msg("- " + player.getName()));
}
case "purge" ->
{
FUtil.adminAction(sender.getName(), "Restoring block modification abilities for all players", true);
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
plugin.pl.getPlayer(player).isEditBlocked()).toList();
list.forEach(player ->
{
plugin.pl.getPlayer(player).setEditBlocked(false);
msg(player, "Your block modification abilities have been restored.", ChatColor.GREEN);
});
msg("Restored block modification abilities for " + list.size() + " player"
+ (list.size() != 1 ? "s" : "") + ".");
}
case "all", "-a" ->
{
FUtil.adminAction(sender.getName(), "Restricting block modification abilities for all non-admins", true);
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
!plugin.al.isAdmin(player)).toList();
list.forEach(player ->
{
plugin.pl.getPlayer(player).setEditBlocked(true);
msg(player, "Your block modification abilities have been restricted.", ChatColor.RED);
});
msg("Restricted block modification abilities for " + list.size() + " player"
+ (list.size() != 1 ? "s" : "") + ".");
}
default -> Optional.ofNullable(getPlayer(args[0])).ifPresentOrElse(player ->
{
FPlayer fPlayer = plugin.pl.getPlayer(player);
if (fPlayer.isEditBlocked())
{
FUtil.adminAction(sender.getName(), "Restoring block modification abilities for " + player.getName(), true);
fPlayer.setEditBlocked(false);
msg("Restored block modification abilities for " + player.getName() + ".");
msg(player, "Your block modification abilities have been restored.", ChatColor.GREEN);
}
else
{
if (plugin.al.isAdmin(player))
{
msg(player.getName() + " is an admin, and as such cannot have their block modification abilities restricted.", ChatColor.RED);
}
else
{
FUtil.adminAction(sender.getName(), "Restricting block modification abilities for " + player.getName(), true);
fPlayer.setEditBlocked(true);
msg("Restricted block modification abilities for " + player.getName() + ".");
msg(player, "Your block modification abilities have been restricted.", ChatColor.RED);
plugin.pul.logPunishment(new Punishment(player.getName(), FUtil.getIp(player),
sender.getName(), PunishmentType.BLOCKEDIT, null));
}
}
}, () -> msg(PLAYER_NOT_FOUND));
}
return true;
}
else
if (args.length == 0)
{
return false;
}
if (args[0].equals("list"))
{
msg("The following have block modification abilities restricted:");
int count = 0;
for (Player player : server.getOnlinePlayers())
{
final FPlayer info = plugin.pl.getPlayer(player);
if (info.isEditBlocked())
{
msg("- " + player.getName());
++count;
}
}
if (count == 0)
{
msg("- none");
}
return true;
}
if (args[0].equals("purge"))
{
FUtil.adminAction(sender.getName(), "Unblocking block modification abilities for all players", true);
int count = 0;
for (final Player player : this.server.getOnlinePlayers())
{
final FPlayer info = plugin.pl.getPlayer(player);
if (info.isEditBlocked())
{
info.setEditBlocked(false);
++count;
}
}
msg("Unblocked all block modification abilities for " + count + " players.");
return true;
}
if (args[0].equals("all"))
{
FUtil.adminAction(sender.getName(), "Blocking block modification abilities for all non-admins", true);
int counter = 0;
for (final Player player : this.server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(player))
{
final FPlayer playerdata = plugin.pl.getPlayer(player);
playerdata.setEditBlocked(true);
++counter;
}
}
msg("Blocked block modification abilities for " + counter + " players.");
return true;
}
final boolean smite = args[0].equals("-s");
if (smite)
{
args = (String[])ArrayUtils.subarray(args, 1, args.length);
if (args.length < 1)
{
return false;
}
}
final Player player2 = getPlayer(args[0]);
if (player2 == null)
{
msg(PLAYER_NOT_FOUND);
return true;
}
String reason = null;
if (args.length > 1)
{
reason = StringUtils.join(args, " ", 1, args.length);
}
final FPlayer pd = plugin.pl.getPlayer(player2);
if (pd.isEditBlocked())
{
FUtil.adminAction(sender.getName(), "Unblocking block modification abilities for " + player2.getName(), true);
pd.setEditBlocked(false);
msg("Unblocking block modification abilities for " + player2.getName());
msg(player2, "Your block modification abilities have been restored.", ChatColor.RED);
}
else
{
if (plugin.al.isAdmin(player2))
{
msg(player2.getName() + " is an admin, and cannot have their block edits blocked.");
return true;
}
FUtil.adminAction(sender.getName(), "Blocking block modification abilities for " + player2.getName(), true);
pd.setEditBlocked(true);
if (smite)
{
Command_smite.smite(sender, player2, reason);
}
msg(player2, "Your block modification abilities have been blocked.", ChatColor.RED);
msg("Blocked all block modification abilities for " + player2.getName());
plugin.pul.logPunishment(new Punishment(player2.getName(), FUtil.getIp(player2), sender.getName(), PunishmentType.BLOCKEDIT, null));
}
return true;
}
}

View File

@ -21,7 +21,7 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Place a cage around someone with certain blocks, or someone's player head.", usage = "/<command> <purge | <partialname> [head | block] [playername | blockname]")
public class Command_cage extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
if (args.length == 0)
@ -33,8 +33,11 @@ public class Command_cage extends FreedomCommand
if (args[0].equalsIgnoreCase("purge"))
{
FUtil.adminAction(sender.getName(), "Uncaging all players", true);
server.getOnlinePlayers().stream().map(player -> plugin.pl.getPlayer(player)).forEach(fPlayer ->
fPlayer.getCageData().setCaged(false));
for (Player player : server.getOnlinePlayers())
{
final FPlayer fPlayer = plugin.pl.getPlayer(player);
fPlayer.getCageData().setCaged(false);
}
return true;
}
@ -59,7 +62,7 @@ public class Command_cage extends FreedomCommand
final String s = args[1];
switch (s)
{
case "head" ->
case "head":
{
outerMaterial = Material.PLAYER_HEAD;
if (args.length >= 3)
@ -70,8 +73,9 @@ public class Command_cage extends FreedomCommand
{
outerMaterial = Material.SKELETON_SKULL;
}
break;
}
case "block" ->
case "block":
{
if (args.length >= 3)
{
@ -81,6 +85,7 @@ public class Command_cage extends FreedomCommand
if (Material.matchMaterial(args[2]) != null && Material.matchMaterial(args[2]).isBlock())
{
outerMaterial = Material.matchMaterial(args[2]);
break;
}
else
{
@ -93,7 +98,7 @@ public class Command_cage extends FreedomCommand
return false;
}
}
default ->
default:
{
return false;
}
@ -151,7 +156,7 @@ public class Command_cage extends FreedomCommand
{
if (args[1].equals("block"))
{
return Arrays.stream(Material.values()).map(Enum::name).toList();
return FUtil.getAllMaterialNames();
}
else if (args[1].equals("head"))
{

View File

@ -10,17 +10,20 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Clears the chat.", usage = "/<command>", aliases = "cc")
public class Command_cleanchat extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
server.getOnlinePlayers().stream().filter(player -> !plugin.al.isAdmin(player)).forEach(player ->
for (Player player : server.getOnlinePlayers())
{
for (int i = 0; i < 100; i++)
if (!plugin.al.isAdmin(player))
{
msg(player, "");
for (int i = 0; i < 100; i++)
{
msg(player, "");
}
}
});
}
FUtil.adminAction(sender.getName(), "Cleared chat", true);
return true;
}

View File

@ -112,9 +112,6 @@ public class Command_coins extends FreedomCommand
+ ChatColor.GOLD + coinsToTransfer
+ ChatColor.GREEN + " coin" + (coinsToTransfer > 1 ? "s" : "")
+ " to " + ChatColor.GOLD + target.getName() + ChatColor.GREEN + ".", ChatColor.GREEN);
plugin.pl.save(playerData);
plugin.pl.save(senderData);
}
return true;

View File

@ -3,9 +3,6 @@ package me.totalfreedom.totalfreedommod.command;
import java.util.Arrays;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.TextDecoration;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.command.Command;
@ -18,19 +15,20 @@ import org.bukkit.inventory.meta.ItemMeta;
@CommandParameters(description = "Get a stick of happiness.", usage = "/<command>")
public class Command_debugstick extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
ItemStack itemStack = new ItemStack(Material.DEBUG_STICK);
ItemMeta itemMeta = itemStack.getItemMeta();
assert itemMeta != null;
itemMeta.displayName(Component.text("Stick of Happiness", NamedTextColor.GOLD).decorate(TextDecoration.BOLD));
itemMeta.lore(Arrays.asList(
Component.text("This is the most powerful stick in the game.", NamedTextColor.RED),
Component.text("You can left click to select what you want to change.", NamedTextColor.DARK_BLUE),
Component.text("And then you can right click to change it!", NamedTextColor.DARK_GREEN),
Component.text("Isn't technology amazing?", NamedTextColor.DARK_PURPLE)
));
itemMeta.setDisplayName(ChatColor.GOLD.toString() + ChatColor.BOLD.toString() + "Stick of Happiness");
List<String> lore = Arrays.asList(
ChatColor.RED + "This is the most powerful stick in the game.",
ChatColor.DARK_BLUE + "You can left click to select what you want to change.",
ChatColor.DARK_GREEN + "And then you can right click to change it!",
ChatColor.DARK_PURPLE + "Isn't technology amazing?");
itemMeta.setLore(lore);
itemStack.setItemMeta(itemMeta);
playerSender.getInventory().addItem(itemStack);
return true;

View File

@ -21,7 +21,12 @@ public class Command_denick extends FreedomCommand
}
FUtil.adminAction(sender.getName(), "Removing all nicknames", false);
server.getOnlinePlayers().forEach(player -> plugin.esb.setNickname(player.getName(), null));
for (Player player : server.getOnlinePlayers())
{
plugin.esb.setNickname(player.getName(), null);
}
return true;
}
}

View File

@ -32,14 +32,16 @@ public class Command_deop extends FreedomCommand
final List<String> matchedPlayerNames = new ArrayList<>();
for (Player player : server.getOnlinePlayers())
{
if ((player.getName().toLowerCase().contains(targetName) || player.getDisplayName().toLowerCase().contains(targetName)
|| player.getName().contains(targetName) || player.getDisplayName().contains(targetName)) &&
player.isOp() && !plugin.al.isVanished(player.getUniqueId()))
if (player.getName().toLowerCase().contains(targetName) || player.getDisplayName().toLowerCase().contains(targetName)
|| player.getName().contains(targetName) || player.getDisplayName().contains(targetName))
{
matchedPlayerNames.add(player.getName());
player.setOp(false);
msg(player, YOU_ARE_NOT_OP);
plugin.rm.updateDisplay(player);
if (player.isOp() && !plugin.al.isVanished(player.getName()))
{
matchedPlayerNames.add(player.getName());
player.setOp(false);
msg(player, YOU_ARE_NOT_OP);
plugin.rm.updateDisplay(player);
}
}
}

View File

@ -52,6 +52,7 @@ public class Command_doom extends FreedomCommand
admin.setActive(false);
plugin.al.save(admin);
plugin.al.updateTables();
plugin.ptero.updateAccountStatus(admin);
if (plugin.dc.enabled && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean())
{
Discord.syncRoles(admin, plugin.pl.getData(admin.getName()).getDiscordID());

View File

@ -5,8 +5,6 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.IntStream;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.ChatColor;
@ -21,6 +19,18 @@ import org.bukkit.inventory.ItemStack;
@CommandParameters(description = "Enchant items.", usage = "/<command> <list | addall | reset | add <name> [level] | remove <name>>")
public class Command_enchant extends FreedomCommand
{
public static List<String> stringNumberRange(int min, int max)
{
List<String> range = new ArrayList<>();
for (int i = min; i <= max; i++)
{
range.add(String.valueOf(i));
}
return range;
}
@SuppressWarnings("deprecation")
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
@ -63,23 +73,30 @@ public class Command_enchant extends FreedomCommand
}
else if (args[0].equalsIgnoreCase("addall"))
{
Arrays.stream(Enchantment.values()).filter(enchantment -> enchantment.canEnchantItem(item)).forEach(ench ->
for (Enchantment ench : Enchantment.values())
{
try
{
item.addEnchantment(ench, ench.getMaxLevel());
if (ench.canEnchantItem(item))
{
item.addEnchantment(ench, ench.getMaxLevel());
}
}
catch (Exception ex)
{
msg("Could not add enchantment: " + ench.getName());
}
});
}
msg("Added all possible enchantments for this item.");
}
else if (args[0].equalsIgnoreCase("reset"))
{
item.getEnchantments().keySet().forEach(item::removeEnchantment);
for (Enchantment ench : item.getEnchantments().keySet())
{
item.removeEnchantment(ench);
}
msg("Removed all enchantments.");
}
else
@ -234,18 +251,21 @@ public class Command_enchant extends FreedomCommand
return getEnchantments(item);
}
}
else if (args.length == 3 && args[0].equals("add"))
else if (args.length == 3)
{
Enchantment enchantment = Enchantment.getByName(args[1].toUpperCase());
if (enchantment != null)
if (args[0].equals("add"))
{
if (!unsafe)
Enchantment enchantment = Enchantment.getByName(args[1].toUpperCase());
if (enchantment != null)
{
return IntStream.rangeClosed(1, enchantment.getMaxLevel()).mapToObj(String::valueOf).toList();
}
else
{
return Collections.singletonList("[level]");
if (!unsafe)
{
return stringNumberRange(1, enchantment.getMaxLevel());
}
else
{
return Collections.singletonList("[level]");
}
}
}
}

View File

@ -1,30 +1,23 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.IntStream;
import me.totalfreedom.totalfreedommod.bridge.CoreProtectBridge;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Block inspector tool for operators.", usage = "/<command> [history] [page]", aliases = "ins")
@CommandParameters(description = "Block inspector tool for operators", usage = "/<command> [history] <page>", aliases = "ins")
public class Command_inspect extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!plugin.cpb.isEnabled())
{
msg("CoreProtect is not enabled on this server.");
return true;
}
if (args.length == 0)
{
PlayerData playerData = plugin.pl.getData(playerSender);
@ -46,40 +39,31 @@ public class Command_inspect extends FreedomCommand
}
catch (NumberFormatException e)
{
msg("Invalid number.", ChatColor.RED);
return true;
msg("Invalid number", ChatColor.RED);
}
}
int godDammit = pageIndex;
Optional.ofNullable(plugin.cpb.getHistoryForPlayer(playerSender)).ifPresentOrElse(page ->
plugin.cpb.showPageToPlayer(playerSender, page, godDammit),
() -> msg("You haven't inspected anything yet!", ChatColor.RED));
FUtil.PaginationList<String> paged = CoreProtectBridge.HISTORY_MAP.get(playerSender);
if (paged != null)
{
if (pageIndex < 1 || pageIndex > paged.getPageCount())
{
msg("Not a valid page number", ChatColor.RED);
return true;
}
return true;
}
else
{
return false;
}
}
msg("---- " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector" + ChatColor.WHITE + " ---- ", ChatColor.WHITE);
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1)
{
return Collections.singletonList("history");
}
else if (args.length == 2 && args[0].equalsIgnoreCase("history") && plugin.cpb.isEnabled()
&& sender instanceof Player player && plugin.cpb.hasHistory(player))
{
return IntStream.rangeClosed(1, plugin.cpb.getHistoryForPlayer(player).getPageCount()).limit(50)
.mapToObj(String::valueOf).toList();
}
else
{
return Collections.emptyList();
List<String> page = paged.getPage(pageIndex);
for (String entries : page)
{
msg(entries);
}
msg("Page " + pageIndex + "/" + paged.getPageCount() + " | To index through the pages, type " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "/ins history <page>", ChatColor.WHITE);
return true;
}
}
return true;
}
}

View File

@ -46,7 +46,7 @@ public class Command_invis extends FreedomCommand
for (Player player : server.getOnlinePlayers())
{
if (player.hasPotionEffect(PotionEffectType.INVISIBILITY) && !plugin.al.isVanished(player.getUniqueId()))
if (player.hasPotionEffect(PotionEffectType.INVISIBILITY) && !plugin.al.isVanished(player.getName()))
{
players.add(player.getName());
if (clear && !plugin.al.isAdmin(player))

View File

@ -2,8 +2,7 @@ package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@ -12,13 +11,20 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Kick all non-admins on server.", usage = "/<command>", aliases = "kickall")
public class Command_kicknoob extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
FUtil.adminAction(sender.getName(), "Disconnecting all non-admins", true);
server.getOnlinePlayers().stream().filter(player -> !plugin.al.isAdmin(player)).forEach(player ->
player.kick(Component.text("All non-admins were kicked by " + sender.getName() + ".", NamedTextColor.RED)));
for (Player player : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(player))
{
player.kickPlayer(ChatColor.RED + "All non-admins were kicked by " + sender.getName() + ".");
}
}
return true;
}
}

View File

@ -1,6 +1,9 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Displayable;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.md_5.bungee.api.ChatColor;
@ -9,37 +12,63 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
@CommandPermissions(level = Rank.NON_OP, source = SourceType.BOTH)
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command> [-a | -v]", aliases = "who,lsit")
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command> [-s | -f | -v]", aliases = "who,lsit")
public class Command_list extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
if (args.length > 1)
{
return false;
}
if (FUtil.isFromHostConsole(sender.getName()))
{
List<String> names = new ArrayList<>();
for (Player player : server.getOnlinePlayers())
{
if (!plugin.al.isVanished(player.getName()))
{
names.add(player.getName());
}
}
msg("There are " + names.size() + "/" + server.getMaxPlayers() + " players online:\n" + StringUtils.join(names, ", "), ChatColor.WHITE);
return true;
}
ListFilter listFilter;
if (args.length == 1)
{
switch (args[0].toLowerCase())
String s = args[0];
switch (s)
{
case "-s", "-a" -> listFilter = ListFilter.ADMINS;
case "-v" ->
case "-s":
case "-a":
{
listFilter = ListFilter.ADMINS;
break;
}
case "-v":
{
checkRank(Rank.ADMIN);
listFilter = ListFilter.VANISHED_ADMINS;
break;
}
case "-t" ->
case "-t":
{
checkRank(Rank.ADMIN);
listFilter = ListFilter.TELNET_SESSIONS;
break;
}
default ->
case "-f":
{
listFilter = ListFilter.FAMOUS_PLAYERS;
break;
}
default:
{
return false;
}
@ -49,42 +78,74 @@ public class Command_list extends FreedomCommand
{
listFilter = ListFilter.PLAYERS;
}
StringBuilder onlineStats = new StringBuilder();
StringBuilder onlineUsers = new StringBuilder();
String onlineStats;
List<String> players;
List<String> n = new ArrayList<>();
if (listFilter == ListFilter.TELNET_SESSIONS && plugin.al.isAdmin(sender))
{
players = plugin.btb.getConnectedAdmins().stream().map(Admin::getName).toList();
onlineStats = ChatColor.BLUE + "There are " + ChatColor.RED + players.size() + ChatColor.BLUE
+ " admins connected to telnet.";
List<Admin> connectedAdmins = plugin.btb.getConnectedAdmins();
onlineStats.append(ChatColor.BLUE).append("There are ").append(ChatColor.RED).append(connectedAdmins.size())
.append(ChatColor.BLUE)
.append(" admins connected to telnet.");
for (Admin admin : connectedAdmins)
{
n.add(admin.getName());
}
}
else
{
onlineStats = ChatColor.BLUE + "There are " + ChatColor.RED + FUtil.getFakePlayerCount() + ChatColor.BLUE
+ " out of a maximum " + ChatColor.RED + server.getMaxPlayers() + ChatColor.BLUE + " players online.";
onlineStats.append(ChatColor.BLUE).append("There are ").append(ChatColor.RED).append(FUtil.getFakePlayerCount())
.append(ChatColor.BLUE)
.append(" out of a maximum ")
.append(ChatColor.RED)
.append(server.getMaxPlayers())
.append(ChatColor.BLUE)
.append(" players online.");
for (Player p : server.getOnlinePlayers())
{
if (listFilter == ListFilter.ADMINS && !plugin.al.isAdmin(p))
{
continue;
}
if (listFilter == ListFilter.ADMINS && plugin.al.isVanished(p.getName()))
{
continue;
}
if (listFilter == ListFilter.VANISHED_ADMINS && !plugin.al.isVanished(p.getName()))
{
continue;
}
if (listFilter == ListFilter.FAMOUS_PLAYERS && !ConfigEntry.FAMOUS_PLAYERS.getList().contains(p.getName().toLowerCase()))
{
continue;
}
if (listFilter == ListFilter.PLAYERS && plugin.al.isVanished(p.getName()))
{
continue;
}
players = server.getOnlinePlayers().stream().filter(pl ->
(listFilter == ListFilter.ADMINS && plugin.al.isAdmin(pl) && !plugin.al.isVanished(pl.getUniqueId()))
|| (listFilter == ListFilter.VANISHED_ADMINS && plugin.al.isVanished(pl.getUniqueId()))
|| (listFilter == ListFilter.PLAYERS && !plugin.al.isVanished(pl.getUniqueId()))).map(player ->
plugin.rm.getDisplay(player).getColoredTag() + player.getName()).toList();
final Displayable display = plugin.rm.getDisplay(p);
n.add(display.getColoredTag() + p.getName());
}
}
String onlineUsers = "Connected " + listFilter.name().toLowerCase().replace('_', ' ') + ": " + ChatColor.WHITE +
StringUtils.join(players, ChatColor.WHITE + ", " + ChatColor.WHITE);
String playerType = listFilter.toString().toLowerCase().replace('_', ' ');
onlineUsers.append("Connected ")
.append(playerType)
.append(": ")
.append(StringUtils.join(n, ChatColor.WHITE + ", "));
if (senderIsConsole)
{
msg(ChatColor.stripColor(onlineStats));
msg(ChatColor.stripColor(onlineUsers));
msg(ChatColor.stripColor(onlineStats.toString()));
msg(ChatColor.stripColor(onlineUsers.toString()));
}
else
{
msg(onlineStats);
msg(onlineUsers);
msg(onlineStats.toString());
msg(onlineUsers.toString());
}
n.clear();
return true;
}
@ -93,6 +154,7 @@ public class Command_list extends FreedomCommand
PLAYERS,
ADMINS,
VANISHED_ADMINS,
TELNET_SESSIONS
TELNET_SESSIONS,
FAMOUS_PLAYERS
}
}

View File

@ -0,0 +1,26 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.LogViewer.LogsRegistrationMode;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Register your connection with the TFM logviewer.", usage = "/<command> [off]")
public class Command_logs extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
LogsRegistrationMode mode = LogsRegistrationMode.ADD;
if (args.length == 1 && "off".equalsIgnoreCase(args[0]))
{
mode = LogsRegistrationMode.DELETE;
}
plugin.lv.updateLogsRegistration(sender, playerSender, mode);
return true;
}
}

View File

@ -3,15 +3,15 @@ package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.GameRuleHandler;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Control mob limiting parameters.", usage = "/<command> <on | off | setmax <count> | dragon | giant | ghast | slime>")
@CommandParameters(description = "Control mob limiting parameters.", usage = "/<command> <on|off|setmax <count>|dragon|giant|ghast|slime>")
public class Command_moblimiter extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -20,35 +20,47 @@ public class Command_moblimiter extends FreedomCommand
return false;
}
switch (args[0].toLowerCase())
if (args[0].equalsIgnoreCase("on"))
{
case "on" -> ConfigEntry.MOB_LIMITER_ENABLED.setBoolean(true);
case "off" -> ConfigEntry.MOB_LIMITER_ENABLED.setBoolean(false);
case "dragon" -> ConfigEntry.MOB_LIMITER_DISABLE_DRAGON.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_DRAGON.getBoolean());
case "giant" -> ConfigEntry.MOB_LIMITER_DISABLE_GIANT.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_GIANT.getBoolean());
case "slime" -> ConfigEntry.MOB_LIMITER_DISABLE_SLIME.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_SLIME.getBoolean());
case "ghast" -> ConfigEntry.MOB_LIMITER_DISABLE_GHAST.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_GHAST.getBoolean());
case "setmax" ->
ConfigEntry.MOB_LIMITER_ENABLED.setBoolean(true);
}
else if (args[0].equalsIgnoreCase("off"))
{
ConfigEntry.MOB_LIMITER_ENABLED.setBoolean(false);
}
else if (args[0].equalsIgnoreCase("dragon"))
{
ConfigEntry.MOB_LIMITER_DISABLE_DRAGON.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_DRAGON.getBoolean());
}
else if (args[0].equalsIgnoreCase("giant"))
{
ConfigEntry.MOB_LIMITER_DISABLE_GIANT.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_GIANT.getBoolean());
}
else if (args[0].equalsIgnoreCase("slime"))
{
ConfigEntry.MOB_LIMITER_DISABLE_SLIME.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_SLIME.getBoolean());
}
else if (args[0].equalsIgnoreCase("ghast"))
{
ConfigEntry.MOB_LIMITER_DISABLE_GHAST.setBoolean(!ConfigEntry.MOB_LIMITER_DISABLE_GHAST.getBoolean());
}
else
{
if (args.length < 2)
{
if (args.length < 2)
{
return false;
}
return false;
}
if (args[0].equalsIgnoreCase("setmax"))
{
try
{
ConfigEntry.MOB_LIMITER_MAX.setInteger(Math.max(0, Math.min(2000, Integer.parseInt(args[1]))));
}
catch (Exception ex)
catch (NumberFormatException ignored)
{
msg("Invalid number: " + args[1], ChatColor.RED);
return true;
}
}
default ->
{
// Shut the fuck up Codacy!
}
}
if (ConfigEntry.MOB_LIMITER_ENABLED.getBoolean())
@ -66,6 +78,7 @@ public class Command_moblimiter extends FreedomCommand
}
plugin.gr.setGameRule(GameRuleHandler.GameRule.DO_MOB_SPAWNING, !ConfigEntry.MOB_LIMITER_ENABLED.getBoolean());
return true;
}
}

View File

@ -1,5 +1,6 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
@ -15,6 +16,17 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Purge all mobs in all worlds.", usage = "/<command> [name]", aliases = "mp")
public class Command_mobpurge extends FreedomCommand
{
public static List<String> getAllMobNames()
{
List<String> names = new ArrayList<>();
for (EntityType entityType : Groups.MOB_TYPES)
{
names.add(entityType.name());
}
return names;
}
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -55,7 +67,7 @@ public class Command_mobpurge extends FreedomCommand
{
if (args.length == 1)
{
return Groups.MOB_TYPES.stream().map(Enum::name).toList();
return getAllMobNames();
}
return Collections.emptyList();

View File

@ -1,6 +1,10 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.punishments.Punishment;
import me.totalfreedom.totalfreedommod.punishments.PunishmentType;
import me.totalfreedom.totalfreedommod.rank.Rank;
@ -16,6 +20,7 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Mutes a player with brute force.", usage = "/<command> <[-s | -q] <player> [reason] | list | purge | all>", aliases = "stfu")
public class Command_mute extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -24,110 +29,134 @@ public class Command_mute extends FreedomCommand
return false;
}
switch (args[0].toLowerCase())
if (args[0].equalsIgnoreCase("list"))
{
case "list" ->
msg("Muted players:");
FPlayer info;
int count = 0;
for (Player mp : server.getOnlinePlayers())
{
msg("Muted players:");
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
plugin.pl.getPlayer(player).isMuted()).toList();
if (list.size() > 0)
list.forEach(player -> msg("- " + player.getName()));
else
msg("- none");
}
case "purge" ->
{
FUtil.adminAction(sender.getName(), "Unmuting all players", true);
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
plugin.pl.getPlayer(player).isMuted()).toList();
list.forEach(player ->
info = plugin.pl.getPlayer(mp);
if (info.isMuted())
{
plugin.pl.getPlayer(player).setMuted(false);
player.sendTitle(ChatColor.RED + "You have been unmuted.",
ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
});
msg("Unmuted " + list.size() + " player" + (list.size() != 1 ? "s" : "") + ".");
}
case "all" ->
{
FUtil.adminAction(sender.getName(), "Muting all non-admins", true);
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
!plugin.al.isAdmin(player)).toList();
list.forEach(player ->
{
plugin.pl.getPlayer(player).setMuted(true);
player.sendTitle(ChatColor.RED + "You've been muted globally.",
ChatColor.YELLOW + "Please be patient and you will be unmuted shortly.", 20, 100, 60);
});
msg("Muted " + list.size() + " player" + (list.size() != 1 ? "s" : "") + ".");
}
default ->
{
boolean quiet = args[0].equalsIgnoreCase("-q");
boolean smite = args[0].equalsIgnoreCase("-s");
// Handling the -q parameter
if (quiet || smite)
{
if (args.length == 1) return false;
args = ArrayUtils.subarray(args, 1, args.length);
msg("- " + mp.getName());
count++;
}
// Handling the (optional) reason
String reason = args.length > 1 ? StringUtils.join(args, " ", 1, args.length) : null;
// Showtime
Optional.ofNullable(getPlayer(args[0])).ifPresentOrElse(player ->
{
if (plugin.al.isAdmin(player))
{
msg(player.getName() + " is an admin, and as such can't be muted.", ChatColor.RED);
return;
}
else if (plugin.pl.getPlayer(player).isMuted())
{
msg(player.getName() + " is already muted.", ChatColor.RED);
return;
}
// Don't broadcast the mute if it was quiet
if (!quiet)
{
FUtil.adminAction(sender.getName(), "Muting " + player.getName(), true);
}
// Smite the player if we're supposed to
if (smite)
{
Command_smite.smite(sender, player, reason, true, false);
}
// Mutes the player
plugin.pl.getPlayer(player).setMuted(true);
// Notify the player that they have been muted
player.sendTitle(ChatColor.RED + "You've been muted.",
ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
msg(player, "You have been muted by " + ChatColor.YELLOW + sender.getName()
+ ChatColor.RED + ".", ChatColor.RED);
// Give them the reason if one is present.
if (reason != null)
{
msg(player, "Reason: " + ChatColor.YELLOW + reason, ChatColor.RED);
}
msg((quiet ? "Quietly m" : "M") + "uted " + player.getName() + ".");
plugin.pul.logPunishment(new Punishment(player.getName(), FUtil.getIp(player), sender.getName(),
PunishmentType.MUTE, reason));
}, () -> msg(PLAYER_NOT_FOUND));
}
if (count == 0)
{
msg("- none");
}
return true;
}
if (args[0].equalsIgnoreCase("purge"))
{
FUtil.adminAction(sender.getName(), "Unmuting all players.", true);
FPlayer info;
int count = 0;
for (Player mp : server.getOnlinePlayers())
{
info = plugin.pl.getPlayer(mp);
if (info.isMuted())
{
info.setMuted(false);
mp.sendTitle(ChatColor.RED + "You've been unmuted.", ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
count++;
}
}
plugin.mu.MUTED_PLAYERS.clear();
msg("Unmuted " + count + " players.");
return true;
}
if (args[0].equalsIgnoreCase("all"))
{
FUtil.adminAction(sender.getName(), "Muting all non-admins", true);
FPlayer playerdata;
int counter = 0;
for (Player player : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(player))
{
player.sendTitle(ChatColor.RED + "You've been muted globally.", ChatColor.YELLOW + "Please be patient and you will be unmuted shortly.", 20, 100, 60);
playerdata = plugin.pl.getPlayer(player);
playerdata.setMuted(true);
counter++;
}
}
msg("Muted " + counter + " players.");
return true;
}
// -s option (smite)
boolean smite = args[0].equals("-s");
// -q option (shadowmute)
boolean quiet = args[0].equals("-q");
if (smite || quiet)
{
args = ArrayUtils.subarray(args, 1, args.length);
if (args.length < 1)
{
return false;
}
}
final Player player = getPlayer(args[0]);
if (player == null)
{
msg(PLAYER_NOT_FOUND);
return true;
}
String reason = null;
if (args.length > 1)
{
reason = StringUtils.join(args, " ", 1, args.length);
}
FPlayer playerdata = plugin.pl.getPlayer(player);
if (plugin.al.isAdmin(player))
{
msg(player.getName() + " is an admin, and can't be muted.");
return true;
}
if (!playerdata.isMuted())
{
playerdata.setMuted(true);
player.sendTitle(ChatColor.RED + "You've been muted.", ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
if (quiet)
{
msg("Muted " + player.getName() + " quietly");
return true; // doesn't announce reason
}
FUtil.adminAction(sender.getName(), "Muting " + player.getName(), true);
if (reason != null)
{
msg(player, ChatColor.RED + "Reason: " + ChatColor.YELLOW + reason);
}
if (smite)
{
Command_smite.smite(sender, player, reason);
}
msg(player, "You have been muted by " + ChatColor.YELLOW + sender.getName(), ChatColor.RED);
msg("Muted " + player.getName());
plugin.pul.logPunishment(new Punishment(player.getName(), FUtil.getIp(player), sender.getName(), PunishmentType.MUTE, reason));
}
else
{
msg(ChatColor.RED + "That player is already muted.");
}
return true;

View File

@ -217,33 +217,42 @@ public class Command_myadmin extends FreedomCommand
}
else if (args.length == 2)
{
if (args[0].equalsIgnoreCase("-o"))
if (args[0].equals("-o"))
{
return FUtil.getPlayerList();
}
else
{
if (doubleArguments.contains(args[0]) && args[0].equalsIgnoreCase("clearip"))
if (doubleArguments.contains(args[0]))
{
List<String> ips = plugin.al.getAdmin(sender).getIps();
ips.remove(FUtil.getIp((Player)sender));
return ips;
if (args[0].equals("clearip"))
{
List<String> ips = plugin.al.getAdmin(sender).getIps();
ips.remove(FUtil.getIp((Player)sender));
return ips;
}
}
}
}
else if (args.length == 3 && args[0].equalsIgnoreCase("-o"))
else if (args.length == 3)
{
List<String> options = new ArrayList<>();
options.addAll(singleArguments);
options.addAll(doubleArguments);
return options;
}
else if (args.length == 4 && args[0].equalsIgnoreCase("-o") && args[2].equalsIgnoreCase("clearip"))
{
Admin admin = plugin.al.getEntryByName(args[1]);
if (admin != null)
if (args[0].equals("-o"))
{
return admin.getIps();
List<String> options = new ArrayList<>();
options.addAll(singleArguments);
options.addAll(doubleArguments);
return options;
}
}
else if (args.length == 4)
{
if (args[0].equals("-o") && args[2].equals("clearip"))
{
Admin admin = plugin.al.getEntryByName(args[1]);
if (admin != null)
{
return admin.getIps();
}
}
}
return FUtil.getPlayerList();

View File

@ -0,0 +1,23 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.History;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.BOTH)
@CommandParameters(description = "Check the name history of a specified player.", usage = "/<command> <username>", aliases = "nh")
public class Command_namehistory extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 1)
{
return false;
}
History.reportHistory(sender, args[0]);
return true;
}
}

View File

@ -74,11 +74,11 @@ public class Command_nickfilter extends FreedomCommand
player = getPlayerByDisplayName(displayName);
if (player == null || plugin.al.isVanished(player.getUniqueId()) && !plugin.al.isAdmin(sender))
if (player == null || plugin.al.isVanished(player.getName()) && !plugin.al.isAdmin(sender))
{
player = getPlayerByDisplayNameAlt(displayName);
if (player == null || !plugin.al.isVanished(player.getUniqueId()) && !plugin.al.isAdmin(sender))
if (player == null || !plugin.al.isVanished(player.getName()) && !plugin.al.isAdmin(sender))
{
msg("Can't find player by nickname: " + displayName);
return true;

View File

@ -15,15 +15,10 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Essentials Interface Command - Rainbowify your nickname.", usage = "/<command> <hex> <hex> <nick>", aliases = "nickgr")
public class Command_nickgradient extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!server.getPluginManager().isPluginEnabled("Essentials"))
{
msg("Essentials is not enabled on this server.");
return true;
}
if (args.length != 3)
{
return false;

View File

@ -2,25 +2,20 @@ package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.Arrays;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Essentials Interface Command - Randomize the colors of your nickname.", usage = "/<command> <<nick> | off>")
public class Command_nicknyan extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!server.getPluginManager().isPluginEnabled("Essentials"))
{
msg("Essentials is not enabled on this server.");
return true;
}
if (args.length != 1)
{
return false;
@ -46,24 +41,32 @@ public class Command_nicknyan extends FreedomCommand
return true;
}
if (server.getOnlinePlayers().stream().anyMatch(player -> player != playerSender
&& (player.getName().equalsIgnoreCase(nickPlain)
|| ChatColor.stripColor(plugin.esb.getNickname(player.getName())).trim().equalsIgnoreCase(nickPlain))))
for (Player player : Bukkit.getOnlinePlayers())
{
msg("That nickname is already in use.");
return true;
if (player == playerSender)
{
continue;
}
if (player.getName().equalsIgnoreCase(nickPlain) || ChatColor.stripColor(player.getDisplayName()).trim().equalsIgnoreCase(nickPlain))
{
msg("That nickname is already in use.");
return true;
}
}
final StringBuilder newNick = new StringBuilder();
Arrays.stream(nickPlain.chars().toArray()).forEach(character -> newNick.append(FUtil.randomChatColor())
.append(Character.toString(character)));
final char[] chars = nickPlain.toCharArray();
for (char c : chars)
{
newNick.append(FUtil.randomChatColor()).append(c);
}
newNick.append(ChatColor.WHITE);
plugin.esb.setNickname(sender.getName(), newNick.toString());
msg("Your nickname is now: " + newNick);
msg("Your nickname is now: " + newNick.toString());
return true;
}
}

View File

@ -12,15 +12,10 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Essentials Interface Command - Rainbowify your nickname.", usage = "/<command> <nick>")
public class Command_nickrainbow extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!server.getPluginManager().isPluginEnabled("Essentials"))
{
msg("Essentials is not enabled on this server.");
return true;
}
if (args.length != 1)
{
return false;

View File

@ -33,14 +33,16 @@ public class Command_op extends FreedomCommand
List<String> matchedPlayerNames = new ArrayList<>();
for (final Player player : server.getOnlinePlayers())
{
if ((player.getName().toLowerCase().contains(targetName) || player.getDisplayName().toLowerCase().contains(targetName)
|| player.getName().contains(targetName) || player.getDisplayName().contains(targetName)) &&
!player.isOp() && !plugin.al.isVanished(player.getUniqueId()))
if (player.getName().toLowerCase().contains(targetName) || player.getDisplayName().toLowerCase().contains(targetName)
|| player.getName().contains(targetName) || player.getDisplayName().contains(targetName))
{
matchedPlayerNames.add(player.getName());
player.setOp(true);
msg(player, YOU_ARE_OP);
plugin.rm.updateDisplay(player);
if (!player.isOp() && !plugin.al.isVanished(player.getName()))
{
matchedPlayerNames.add(player.getName());
player.setOp(true);
msg(player, YOU_ARE_OP);
plugin.rm.updateDisplay(player);
}
}
}

View File

@ -10,12 +10,13 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "OP everyone on the server.", usage = "/<command>")
public class Command_opall extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
FUtil.adminAction(sender.getName(), "Opping all players on the server", false);
server.getOnlinePlayers().forEach(player ->
for (Player player : server.getOnlinePlayers())
{
if (!player.isOp())
{
@ -27,7 +28,7 @@ public class Command_opall extends FreedomCommand
{
player.recalculatePermissions();
}
});
}
return true;
}

View File

@ -0,0 +1,114 @@
package me.totalfreedom.totalfreedommod.command;
import com.google.common.base.Strings;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.SENIOR_ADMIN, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Manage your Pterodactyl panel account", usage = "/<command> <create | delete>")
public class Command_panel extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!plugin.ptero.isEnabled())
{
msg("Pterodactyl integration is currently disabled.", ChatColor.RED);
return true;
}
PlayerData playerData = getData(playerSender);
if (playerData.getDiscordID() == null)
{
msg("You must have a linked discord account.", ChatColor.RED);
return true;
}
if (args.length == 0)
{
return false;
}
if (args[0].equalsIgnoreCase("create"))
{
msg("Creating your Pterodactyl account...", ChatColor.GREEN);
Admin admin = getAdmin(playerSender);
if (admin.getPteroID() != null)
{
msg("You already have a Pterodactyl account.", ChatColor.RED);
return true;
}
String username = sender.getName();
String password = FUtil.randomString(30);
String id = plugin.ptero.createAccount(username, password);
if (Strings.isNullOrEmpty(id))
{
msg("Failed to create your Pterodactyl account.", ChatColor.RED);
return true;
}
plugin.ptero.addAccountToServer(id);
admin.setPteroID(id);
plugin.al.save(admin);
plugin.al.updateTables();
plugin.dc.sendPteroInfo(playerData, username, password);
msg("Successfully created your Pterodactyl account. Check your DMs from " + plugin.dc.formatBotTag() + " on discord to get your credentials.", ChatColor.GREEN);
return true;
}
else if (args[0].equalsIgnoreCase("delete"))
{
msg("Deleting your Pterodactyl account...", ChatColor.GREEN);
Admin admin = getAdmin(playerSender);
if (admin.getPteroID() == null)
{
msg("You do not have a Pterodactyl account.", ChatColor.RED);
return true;
}
boolean deleted = plugin.ptero.deleteAccount(admin.getPteroID());
if (!deleted)
{
msg("Failed to delete your Pterodactyl account.", ChatColor.RED);
return true;
}
admin.setPteroID(null);
plugin.al.save(admin);
plugin.al.updateTables();
msg("Successfully deleted your Pterodactyl account.", ChatColor.GREEN);
return true;
}
return false;
}
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1 && plugin.al.isSeniorAdmin(sender))
{
return Arrays.asList("create", "delete");
}
return Collections.emptyList();
}
}

View File

@ -1,6 +1,9 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
@ -14,109 +17,116 @@ import org.bukkit.plugin.PluginManager;
@CommandParameters(description = "Enable, disable, or reload a specified plugin, as well as list all plugins on the server.", usage = "/<command> <<enable | disable | reload> <pluginname>> | list>", aliases = "plc")
public class Command_plugincontrol extends FreedomCommand
{
private final List<String> UNTOUCHABLE_PLUGINS = Arrays.asList(plugin.getName());
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length == 0 || args.length > 2)
{
return false;
}
final PluginManager pm = server.getPluginManager();
/* This is the way it is because there was too much "if the arguments aren't enough then return false" in the
* original code in addition to the stupid amount of "if something isn't right then do some boilerplate stuff
* then return true". Codacy complained, so I aggressively optimized this to keep it quiet. */
switch (args.length)
if (args.length == 1)
{
case 1 ->
if (args[0].equalsIgnoreCase("list"))
{
if (args[0].equalsIgnoreCase("list"))
for (Plugin serverPlugin : pm.getPlugins())
{
Arrays.stream(pm.getPlugins()).forEach(pl ->
{
final String version = pl.getDescription().getVersion();
msg(ChatColor.GRAY + "- " + (pl.isEnabled() ? ChatColor.GREEN : ChatColor.RED) + pl.getName()
+ ChatColor.GOLD + (!version.isEmpty() ? " v" + version : "") + " by "
+ StringUtils.join(pl.getDescription().getAuthors(), ", "));
});
return true;
final String version = serverPlugin.getDescription().getVersion();
msg(ChatColor.GRAY + "- " + (serverPlugin.isEnabled() ? ChatColor.GREEN : ChatColor.RED) + serverPlugin.getName()
+ ChatColor.GOLD + (!version.isEmpty() ? " v" + version : "") + " by "
+ StringUtils.join(serverPlugin.getDescription().getAuthors(), ", "));
}
return true;
}
case 2 ->
return false;
}
if (args[0].equals("enable"))
{
final Plugin target = getPlugin(args[1]);
if (target == null)
{
Plugin pl = pm.getPlugin(args[1]);
if (pl != null)
{
switch (args[0].toLowerCase())
{
case "enable" ->
{
if (pl.isEnabled())
{
msg(pl.getName() + " is already enabled.");
return true;
}
pm.enablePlugin(pl);
if (pl.isEnabled())
{
msg(pl.getName() + " is now enabled.");
}
else
{
msg("An error occurred whilst attempting to enable " + pl.getName() + ".");
}
return true;
}
case "disable" ->
{
if (!pl.isEnabled())
{
msg(pl.getName() + " is already disabled.");
return true;
}
else if (UNTOUCHABLE_PLUGINS.contains(pl.getName()))
{
msg(pl.getName() + " can't be disabled.");
return true;
}
pm.disablePlugin(pl);
msg(pl.getName() + " is now disabled.");
return true;
}
case "reload" ->
{
if (UNTOUCHABLE_PLUGINS.contains(pl.getName()))
{
msg(pl.getName() + " can't be reloaded.");
return true;
}
pm.disablePlugin(pl);
pm.enablePlugin(pl);
msg(pl.getName() + " has been reloaded.");
return true;
}
default ->
{
// Do nothing. This is here to please Codacy.
}
}
}
else
{
msg("Plugin not found!");
return true;
}
msg("Plugin not found!");
return true;
}
default ->
if (target.isEnabled())
{
// Ditto
msg("Plugin is already enabled.");
return true;
}
pm.enablePlugin(target);
if (!pm.isPluginEnabled(target))
{
msg("Error enabling plugin " + target.getName());
return true;
}
msg(target.getName() + " is now enabled.");
return true;
}
if (args[0].equals("disable"))
{
final Plugin target = getPlugin(args[1]);
if (target == null)
{
msg("Plugin not found!");
return true;
}
if (!target.isEnabled())
{
msg("Plugin is already disabled.");
return true;
}
if (UNTOUCHABLE_PLUGINS.contains(target.getName()))
{
msg("You cannot disable " + target.getName());
return true;
}
pm.disablePlugin(target);
if (pm.isPluginEnabled(target))
{
msg("Error disabling plugin " + target.getName());
return true;
}
msg(target.getName() + " is now disabled.");
return true;
}
if (args[0].equals("reload"))
{
final Plugin target = getPlugin(args[1]);
if (target == null)
{
msg("Plugin not found!");
return true;
}
if (UNTOUCHABLE_PLUGINS.contains(target.getName()))
{
msg("You cannot reload " + target.getName());
return true;
}
pm.disablePlugin(target);
pm.enablePlugin(target);
msg(target.getName() + " reloaded.");
return true;
}
return false;
@ -133,12 +143,51 @@ public class Command_plugincontrol extends FreedomCommand
{
return Arrays.asList("enable", "disable", "reload", "list");
}
else if (args.length == 2 && !args[0].equalsIgnoreCase("list"))
else if (args.length == 2)
{
return Arrays.stream(server.getPluginManager().getPlugins()).map(Plugin::getName)
.filter(pl -> !UNTOUCHABLE_PLUGINS.contains(pl)).toList();
if (!args[0].equals("list"))
{
return getAllPluginNames();
}
}
return Collections.emptyList();
}
}
public List<String> getAllPluginNames()
{
List<String> names = new ArrayList<>();
for (Plugin plugin : server.getPluginManager().getPlugins())
{
if (!UNTOUCHABLE_PLUGINS.contains(plugin.getName()))
{
names.add(plugin.getName());
}
}
names.remove(plugin.getName());
return names;
}
public Plugin getPlugin(String name)
{
for (Plugin serverPlugin : server.getPluginManager().getPlugins())
{
if (serverPlugin.getName().equalsIgnoreCase(name))
{
return serverPlugin;
}
}
if (name.length() >= 3)
{
for (Plugin serverPlugin : server.getPluginManager().getPlugins())
{
if (serverPlugin.getName().toLowerCase().contains(name.toLowerCase()))
{
return serverPlugin;
}
}
}
return null;
}
}

View File

@ -6,6 +6,7 @@ import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -20,6 +21,8 @@ import org.bukkit.potion.PotionEffectType;
aliases = "effect")
public class Command_potion extends FreedomCommand
{
@SuppressWarnings("deprecation")
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -29,8 +32,15 @@ public class Command_potion extends FreedomCommand
{
if (args[0].equalsIgnoreCase("list"))
{
msg("Potion effect types: " + FUtil.listToString(Arrays.stream(PotionEffectType.values())
.map(PotionEffectType::getName).toList()), ChatColor.AQUA);
List<String> potionEffectTypeNames = new ArrayList<>();
for (PotionEffectType potion_effect_type : PotionEffectType.values())
{
if (potion_effect_type != null)
{
potionEffectTypeNames.add(potion_effect_type.getName());
}
}
msg("Potion effect types: " + StringUtils.join(potionEffectTypeNames, ", "), ChatColor.AQUA);
}
else if (args[0].equalsIgnoreCase("clearall"))
{
@ -40,9 +50,14 @@ public class Command_potion extends FreedomCommand
return true;
}
FUtil.adminAction(sender.getName(), "Clearing all potion effects from all players", true);
server.getOnlinePlayers().forEach(target -> target.getActivePotionEffects().forEach(effect ->
target.removePotionEffect(effect.getType())));
FUtil.adminAction(sender.getName(), "Cleared all potion effects from all players", true);
for (Player target : server.getOnlinePlayers())
{
for (PotionEffect potion_effect : target.getActivePotionEffects())
{
target.removePotionEffect(potion_effect.getType());
}
}
}
}
@ -71,7 +86,7 @@ public class Command_potion extends FreedomCommand
if (target == null)
{
msg(PLAYER_NOT_FOUND, ChatColor.RED);
msg(FreedomCommand.PLAYER_NOT_FOUND, ChatColor.RED);
return true;
}
@ -80,8 +95,7 @@ public class Command_potion extends FreedomCommand
target.removePotionEffect(potion_effect.getType());
}
msg("Cleared all active potion effects " + (!target.equals(playerSender) ? "from player "
+ target.getName() + "." : "from yourself."), ChatColor.AQUA);
msg("Cleared all active potion effects " + (!target.equals(playerSender) ? "from player " + target.getName() + "." : "from yourself."), ChatColor.AQUA);
}
break;
}
@ -103,7 +117,7 @@ public class Command_potion extends FreedomCommand
target = getPlayer(args[4]);
if (target == null || plugin.al.isVanished(target.getUniqueId()) && !plugin.al.isAdmin(sender))
if (target == null || plugin.al.isVanished(target.getName()) && !plugin.al.isAdmin(sender))
{
msg(PLAYER_NOT_FOUND);
return true;
@ -118,41 +132,44 @@ public class Command_potion extends FreedomCommand
}
}
PotionEffectType effectType = PotionEffectType.getByName(args[1]);
if (effectType == null)
PotionEffectType potion_effect_type = PotionEffectType.getByName(args[1]);
if (potion_effect_type == null)
{
msg("Invalid potion effect: " + args[1], ChatColor.AQUA);
msg("Invalid potion effect type.", ChatColor.AQUA);
return true;
}
int duration;
try
{
duration = Math.min(Integer.parseInt(args[2]), 100000);
duration = Integer.parseInt(args[2]);
duration = Math.min(duration, 100000);
}
catch (NumberFormatException ex)
{
msg("Invalid duration: " + args[2], ChatColor.RED);
msg("Invalid potion duration.", ChatColor.RED);
return true;
}
int amplifier;
try
{
amplifier = Math.min(Integer.parseInt(args[3]), 100000);
amplifier = Integer.parseInt(args[3]);
amplifier = Math.min(amplifier, 100000);
}
catch (NumberFormatException ex)
{
msg("Invalid potion amplifier: " + args[3], ChatColor.RED);
msg("Invalid potion amplifier.", ChatColor.RED);
return true;
}
PotionEffect new_effect = effectType.createEffect(duration, amplifier);
target.addPotionEffect(new_effect);
msg("Added potion effect: " + new_effect.getType().getName()
+ ", Duration: " + new_effect.getDuration()
+ ", Amplifier: " + new_effect.getAmplifier()
+ (!target.equals(playerSender) ? " to player " + target.getName() + "." : " to yourself."), ChatColor.AQUA);
PotionEffect new_effect = potion_effect_type.createEffect(duration, amplifier);
target.addPotionEffect(new_effect, true);
msg(
"Added potion effect: " + new_effect.getType().getName()
+ ", Duration: " + new_effect.getDuration()
+ ", Amplifier: " + new_effect.getAmplifier()
+ (!target.equals(playerSender) ? " to player " + target.getName() + "." : " to yourself."), ChatColor.AQUA);
}
break;
}
@ -169,7 +186,7 @@ public class Command_potion extends FreedomCommand
{
switch (args.length)
{
case 1 ->
case 1:
{
List<String> arguments = new ArrayList<>(Arrays.asList("list", "clear", "add"));
if (plugin.al.isAdmin(sender))
@ -178,46 +195,72 @@ public class Command_potion extends FreedomCommand
}
return arguments;
}
case 2 ->
case 2:
{
if (args[0].equalsIgnoreCase("clear"))
if (args[0].equals("clear"))
{
if (plugin.al.isAdmin(sender))
{
return FUtil.getPlayerList();
}
}
else if (args[0].equalsIgnoreCase("add"))
else if (args[0].equals("add"))
{
return Arrays.stream(PotionEffectType.values()).map(PotionEffectType::getName).toList();
return getAllPotionTypes();
}
break;
}
case 3 ->
case 3:
{
if (args[0].equalsIgnoreCase("add"))
if (args[0].equals("add"))
{
return Collections.singletonList("<duration>");
}
break;
}
case 4 ->
case 4:
{
if (args[0].equalsIgnoreCase("add"))
if (args[0].equals("add"))
{
return Collections.singletonList("<amplifier>");
}
break;
}
case 5 ->
case 5:
{
if (plugin.al.isAdmin(sender) && args[0].equalsIgnoreCase("add"))
if (plugin.al.isAdmin(sender))
{
return FUtil.getPlayerList();
if (args[0].equals("add"))
{
return FUtil.getPlayerList();
}
}
break;
}
default ->
default:
{
break;
}
}
return Collections.emptyList();
}
public List<String> getAllPotionTypes()
{
List<String> types = new ArrayList<>();
for (PotionEffectType potionEffectType : PotionEffectType.values())
{
if (potionEffectType != null)
{
types.add(potionEffectType.getName());
}
}
return types;
}
}

View File

@ -1,37 +1,17 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME, blockHostConsole = true)
@CommandParameters(description = "Report a player for all admins to see.", usage = "/<command> <player> <reason>")
public class Command_report extends FreedomCommand
{
private void handleLog(final @Nullable Boolean value, final @Nullable Throwable ex, final CommandSender sender)
{
if (ex != null)
{
sender.sendMessage(Component.text("An error occurred while attempting to log your previously filed report to a Discord channel.", NamedTextColor.RED));
ex.printStackTrace();
return;
}
if (Boolean.FALSE.equals(value))
{
return;
}
sender.sendMessage(Component.text("The report you previously filed has been successfully logged to a Discord channel. Please note that spamming reports is not allowed, and you will be sanctioned if you are found to be doing it.", NamedTextColor.GRAY));
}
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
@ -42,43 +22,41 @@ public class Command_report extends FreedomCommand
}
Player player = getPlayer(args[0], true);
OfflinePlayer offlinePlayer = getOfflinePlayer(args[0]);
if (player == null && offlinePlayer == null)
if (player == null)
{
msg(PLAYER_NOT_FOUND);
return true;
}
else if (player != null)
{
if (sender instanceof Player)
{
if (player.equals(playerSender))
{
msg(ChatColor.RED + "Please, don't try to report yourself.");
return true;
}
}
if (plugin.al.isAdmin(player))
if (sender instanceof Player)
{
if (player.equals(playerSender))
{
msg(ChatColor.RED + "You can not report admins.");
msg(ChatColor.RED + "Please, don't try to report yourself.");
return true;
}
}
if (plugin.al.isAdmin(player))
{
msg(ChatColor.RED + "You can not report admins.");
return true;
}
String report = StringUtils.join(ArrayUtils.subarray(args, 1, args.length), " ");
String reportedUsername = (player == null) ? offlinePlayer.getName() : player.getName();
plugin.cm.reportAction(playerSender, reportedUsername, report);
plugin.cm.reportAction(playerSender, player, report);
msg(ChatColor.GREEN + "Thank you, your report is being processed.");
boolean logged = false;
if (plugin.dc.enabled)
{
plugin.dc.sendReport(playerSender.getName(), reportedUsername, report).whenCompleteAsync((logged, ex) -> handleLog(logged, ex, sender));
logged = plugin.dc.sendReport(playerSender, player, report);
}
msg(ChatColor.GREEN + "Thank you, your report has been successfully logged."
+ (logged ? ChatColor.RED + "\nNote: This report has been logged to a discord channel, as with any report system, spamming reports can lead to you getting banned." : ""));
return true;
}
}

View File

@ -84,22 +84,19 @@ public class Command_ride extends FreedomCommand
return true;
}
if (args.length >= 2 && args[0].equalsIgnoreCase("mode"))
if (args.length >= 2)
{
try
if (args[0].equalsIgnoreCase("mode"))
{
PlayerData.RideMode mode = PlayerData.RideMode.valueOf(args[1].toUpperCase());
PlayerData playerDataSender = plugin.pl.getData(playerSender);
playerDataSender.setRideMode(mode);
plugin.pl.save(playerDataSender);
msg("Ride mode is now set to " + mode.name().toLowerCase() + ".");
if (args[1].equalsIgnoreCase("normal") || args[1].equalsIgnoreCase("off") || args[1].equalsIgnoreCase("ask"))
{
PlayerData playerDataSender = plugin.pl.getData(playerSender);
playerDataSender.setRideMode(args[1].toLowerCase());
plugin.pl.save(playerDataSender);
msg("Ride mode is now set to " + args[1].toLowerCase() + ".");
return true;
}
}
catch (IllegalArgumentException ex)
{
msg("Invalid mode.", ChatColor.RED);
}
return true;
}
final Player player = getPlayer(args[0], true);
@ -117,13 +114,13 @@ public class Command_ride extends FreedomCommand
return true;
}
if (playerData.getRideMode() == PlayerData.RideMode.OFF && !isAdmin(sender))
if (playerData.getRideMode().equals("off") && !isAdmin(sender))
{
msg("That player cannot be ridden.", ChatColor.RED);
return true;
}
if (playerData.getRideMode() == PlayerData.RideMode.ASK && !FUtil.isExecutive(playerSender.getName()))
if (playerData.getRideMode().equals("ask") && !FUtil.isExecutive(playerSender.getName()))
{
msg("Sent a request to the player.", ChatColor.GREEN);
msg(player, sender.getName() + " has requested to ride you.", ChatColor.AQUA);

View File

@ -5,7 +5,6 @@ import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import me.totalfreedom.totalfreedommod.util.Groups;
import net.coreprotect.CoreProtectAPI;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location;
@ -23,7 +22,7 @@ import org.bukkit.entity.Player;
public class Command_ro extends FreedomCommand
{
private int removeBlocks(Location center, Material material, int radius, String user)
public static int replaceBlocks(Location center, Material fromMaterial, Material toMaterial, int radius)
{
int affected = 0;
@ -36,17 +35,11 @@ public class Command_ro extends FreedomCommand
{
Block block = centerBlock.getRelative(xOffset, yOffset, zOffset);
BlockData data = block.getBlockData();
CoreProtectAPI cpAPI = plugin.cpb.getCoreProtectAPI();
if (block.getLocation().distanceSquared(center) < (radius * radius))
{
if (material.equals(Material.WATER) && data instanceof Waterlogged waterloggedData)
if (fromMaterial.equals(Material.WATER) && data instanceof Waterlogged)
{
if (cpAPI != null)
{
cpAPI.logRemoval(user, block.getLocation(), material, data);
}
Waterlogged waterloggedData = (Waterlogged)data;
if (waterloggedData.isWaterlogged())
{
waterloggedData.setWaterlogged(false);
@ -54,18 +47,12 @@ public class Command_ro extends FreedomCommand
affected++;
continue;
}
block.setType(Material.AIR);
block.setType(toMaterial);
affected++;
}
else if (block.getType().equals(material))
else if (block.getType().equals(fromMaterial))
{
if (cpAPI != null)
{
cpAPI.logRemoval(user, block.getLocation(), material, data);
}
block.setType(Material.AIR);
block.setType(toMaterial);
affected++;
}
}
@ -168,7 +155,7 @@ public class Command_ro extends FreedomCommand
for (final Material material : materials)
{
affected += removeBlocks(player.getLocation(), material, radius, sender.getName());
affected += replaceBlocks(player.getLocation(), material, Material.AIR, radius);
}
}
}
@ -179,7 +166,7 @@ public class Command_ro extends FreedomCommand
FUtil.adminAction(sender.getName(), "Removing all " + names + " within " + radius + " blocks of " + targetPlayer.getName(), false);
for (Material material : materials)
{
affected += removeBlocks(targetPlayer.getLocation(), material, radius, sender.getName());
affected += replaceBlocks(targetPlayer.getLocation(), material, Material.AIR, radius);
}
}
}

View File

@ -112,6 +112,8 @@ public class Command_saconfig extends FreedomCommand
Discord.syncRoles(admin, plugin.pl.getData(admin.getName()).getDiscordID());
}
plugin.ptero.updateAccountStatus(admin);
msg("Set " + admin.getName() + "'s rank to " + rank.getName());
return true;
}
@ -174,10 +176,11 @@ public class Command_saconfig extends FreedomCommand
}
// Find the old admin entry
String name = player.getName();
Admin admin = null;
for (Admin loopAdmin : plugin.al.getAllAdmins())
{
if (loopAdmin.getUuid().equals(player.getUniqueId()))
if (loopAdmin.getName().equalsIgnoreCase(name) || loopAdmin.getIps().contains(FUtil.getIp(player)))
{
admin = loopAdmin;
break;
@ -186,6 +189,7 @@ public class Command_saconfig extends FreedomCommand
if (admin == null) // New admin
{
FUtil.adminAction(sender.getName(), "Adding " + player.getName() + " to the admin list", true);
admin = new Admin(player);
@ -208,6 +212,7 @@ public class Command_saconfig extends FreedomCommand
Discord.syncRoles(admin, plugin.pl.getData(player).getDiscordID());
}
}
plugin.ptero.updateAccountStatus(admin);
final FPlayer fPlayer = plugin.pl.getPlayer(player);
if (fPlayer.getFreezeData().isFrozen())
@ -235,7 +240,6 @@ public class Command_saconfig extends FreedomCommand
checkRank(Rank.ADMIN);
Player player = getPlayer(args[1]);
Admin admin = player != null ? plugin.al.getAdmin(player) : plugin.al.getEntryByName(args[1]);
if (admin == null)
@ -244,24 +248,24 @@ public class Command_saconfig extends FreedomCommand
return true;
}
String adminName = admin.getName();
FUtil.adminAction(sender.getName(), "Removing " + admin.getName() + " from the admin list", true);
admin.setActive(false);
plugin.al.save(admin);
plugin.al.updateTables();
if (player != null)
{
plugin.rm.updateDisplay(player);
plugin.pl.getPlayer(player).setAdminChat(false);
}
if (plugin.dc.enabled && ConfigEntry.DISCORD_ROLE_SYNC.getBoolean())
{
Discord.syncRoles(admin, plugin.pl.getData(adminName).getDiscordID());
Discord.syncRoles(admin, plugin.pl.getData(admin.getName()).getDiscordID());
}
plugin.ptero.updateAccountStatus(admin);
return true;
}

View File

@ -1,17 +1,19 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.event.ClickEvent;
import net.kyori.adventure.text.event.HoverEvent;
import net.kyori.adventure.text.format.NamedTextColor;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.TranslatableComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.ChatColor;
import org.bukkit.World;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.generator.WorldInfo;
import java.util.ArrayList;
import java.util.List;
@CommandPermissions(level = Rank.NON_OP, source = SourceType.BOTH)
@ -45,11 +47,34 @@ public class Command_seed extends FreedomCommand
}
}
sender.sendMessage(Component.translatable("commands.seed.success",
Component.text("[", NamedTextColor.WHITE).append(Component.text(world.getSeed(), NamedTextColor.GREEN)
.clickEvent(ClickEvent.copyToClipboard(String.valueOf(world.getSeed())))
.hoverEvent(HoverEvent.showText(Component.translatable("chat.copy"))))
.append(Component.text("]"))));
// If the sender is not a Player, use the usual msg method to
if (senderIsConsole)
{
msg("Seed: [" + ChatColor.GREEN + world.getSeed() + ChatColor.WHITE + "]", ChatColor.WHITE);
}
else
{
// Gets the seed for later uses
String seed = String.valueOf(world.getSeed());
// This is a really stupid hack to get things to play nicely, but it works so I don't give a damn
BaseComponent[] components = {new TranslatableComponent("chat.copy.click")};
TextComponent seedAsComponent = new TextComponent(seed);
// Style the message like in vanilla Minecraft.
seedAsComponent.setColor(ChatColor.GREEN.asBungee());
seedAsComponent.setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, seed));
seedAsComponent.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(components)));
// Enclose the seed with brackets
TextComponent seedString = new TextComponent("[");
seedString.addExtra(seedAsComponent);
seedString.addExtra("]");
// Send the message to the player.
TranslatableComponent response = new TranslatableComponent("commands.seed.success", seedString);
playerSender.spigot().sendMessage(response);
}
return true;
}
@ -58,7 +83,13 @@ public class Command_seed extends FreedomCommand
{
if (args.length == 1)
{
return server.getWorlds().stream().map(WorldInfo::getName).toList();
// Returns a list of worlds on the server and returns it
List<String> worlds = new ArrayList<>();
for (World world : server.getWorlds())
{
worlds.add(world.getName());
}
return worlds;
}
return null;

View File

@ -1,6 +1,7 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.Optional;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.Location;
import org.bukkit.Material;
@ -14,9 +15,10 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.NON_OP, source = SourceType.BOTH)
@CommandParameters(description = "Set the on/off state of the lever at position x, y, z in world 'worldname'.", usage = "/<command> <x> <y> <z> <worldname> <on | off>")
@CommandParameters(description = "Set the on/off state of the lever at position x, y, z in world 'worldname'.", usage = "/<command> <x> <y> <z> <worldname> <on|off>")
public class Command_setlever extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -31,38 +33,50 @@ public class Command_setlever extends FreedomCommand
x = Double.parseDouble(args[0]);
y = Double.parseDouble(args[1]);
z = Double.parseDouble(args[2]);
// Shows the "Invalid coordinates" message without having to do boilerplate bullshit
if (Math.abs(x) > 29999998 || Math.abs(y) > 29999998 || Math.abs(z) > 29999998)
{
throw new IllegalArgumentException();
}
}
catch (IllegalArgumentException ex)
catch (NumberFormatException ex)
{
msg("Invalid coordinates.");
return true;
}
Optional<World> optionalWorld = server.getWorlds().stream().filter(world ->
world.getName().equalsIgnoreCase(args[3])).findAny();
if (optionalWorld.isEmpty())
if (x > 29999998 || x < -29999998 || y > 29999998 || y < -29999998 || z > 29999998 || z < -29999998)
{
msg("Invalid world: " + args[3]);
msg("Coordinates cannot be larger than 29999998 or smaller than -29999998 blocks.");
return true;
}
final Location leverLocation = new Location(optionalWorld.get(), x, y, z);
World world = null;
final String needleWorldName = args[3].trim();
final List<World> worlds = server.getWorlds();
for (final World testWorld : worlds)
{
if (testWorld.getName().trim().equalsIgnoreCase(needleWorldName))
{
world = testWorld;
break;
}
}
if (world == null)
{
msg("Invalid world name.");
return true;
}
final Location leverLocation = new Location(world, x, y, z);
final boolean leverOn = (args[4].trim().equalsIgnoreCase("on") || args[4].trim().equalsIgnoreCase("1"));
final Block targetBlock = leverLocation.getBlock();
if (targetBlock.getType() == Material.LEVER)
{
BlockState state = targetBlock.getState();
BlockData data = state.getBlockData();
Switch caster = (Switch) data;
Switch caster = (Switch)data;
caster.setPowered(args[4].trim().equalsIgnoreCase("on") || args[4].trim().equalsIgnoreCase("1"));
caster.setPowered(leverOn);
state.setBlockData(data);
state.update();
@ -70,7 +84,8 @@ public class Command_setlever extends FreedomCommand
}
else
{
msg("That block isn't a lever.");
msg("Target block " + targetBlock + " is not a lever.");
return true;
}
return true;

View File

@ -0,0 +1,35 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Sit at the current place you are at.", usage = "/<command>")
public class Command_sit extends FreedomCommand
{
public static List<ArmorStand> STANDS = new ArrayList<>();
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
if (args.length != 0)
{
return false;
}
ArmorStand stand = (ArmorStand)playerSender.getWorld().spawnEntity(playerSender.getLocation().clone().subtract(0.0, 1.7, 0.0), EntityType.ARMOR_STAND);
stand.setGravity(false);
stand.setAI(false);
stand.setVisible(false);
stand.setInvulnerable(true);
stand.addPassenger(playerSender);
STANDS.add(stand);
msg("You are now sitting.");
return true;
}
}

View File

@ -1,11 +1,11 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.Arrays;
import java.util.List;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.EnumUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.World;
@ -24,7 +24,7 @@ public class Command_spawnmob extends FreedomCommand
{
if (args.length > 0 && args[0].equalsIgnoreCase("list"))
{
List<EntityType> types = Arrays.stream(EntityType.values()).toList();
List<EntityType> types = EnumUtils.getEnumList(EntityType.class);
String typeList = StringUtils.join(types, ", ").toLowerCase();
msg(typeList);
return true;

View File

@ -1,5 +1,7 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.HashMap;
import java.util.Map;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.ChatColor;
import org.bukkit.World;
@ -11,6 +13,19 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Shows Minecraft server info, such as authentication status.", usage = "/<command>")
public class Command_status extends FreedomCommand
{
public static final Map<String, String> SERVICE_MAP = new HashMap<>();
static
{
SERVICE_MAP.put("minecraft.net", "Minecraft.net");
SERVICE_MAP.put("login.minecraft.net", "Minecraft Logins");
SERVICE_MAP.put("session.minecraft.net", "Minecraft Multiplayer Sessions");
SERVICE_MAP.put("account.mojang.com", "Mojang Accounts Website");
SERVICE_MAP.put("auth.mojang.com", "Mojang Accounts Login");
SERVICE_MAP.put("skins.minecraft.net", "Minecraft Skins");
}
@Override
public boolean run(final CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{

View File

@ -47,7 +47,7 @@ public class Command_tag extends FreedomCommand
for (final Player player : server.getOnlinePlayers())
{
if (plugin.al.isVanished(player.getUniqueId()) && !plugin.al.isAdmin(sender))
if (plugin.al.isVanished(player.getName()) && !plugin.al.isAdmin(sender))
{
continue;
}

View File

@ -19,9 +19,9 @@ public class Command_toggle extends FreedomCommand
private final List<String> toggles = Arrays.asList(
"waterplace", "fireplace", "lavaplace", "fluidspread", "lavadmg", "firespread", "frostwalk",
"firework", "prelog", "lockdown", "petprotect", "entitywipe", "nonuke [range] [count]",
"explosives [radius]", "unsafeenchs", "bells", "armorstands", "masterblocks", "item_drops",
"grindstones", "jukeboxes", "spawners", "4chan", "beehives", "respawnanchors", "autotp", "autoclear", "minecarts",
"mp44", "landmines", "tossmob", "gravity");
"explosives [radius]", "unsafeenchs", "bells", "armorstands", "structureblocks", "jigsaws", "grindstones",
"jukeboxes", "spawners", "4chan", "beehives", "respawnanchors", "autotp", "autoclear", "minecarts", "mp44",
"landmines", "tossmob", "gravity");
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
@ -193,21 +193,15 @@ public class Command_toggle extends FreedomCommand
break;
}
case "masterblocks":
case "structureblocks":
{
toggle("Master blocks are", ConfigEntry.ALLOW_MASTERBLOCKS);
toggle("Structure blocks are", ConfigEntry.ALLOW_STRUCTURE_BLOCKS);
break;
}
case "books":
case "jigsaws":
{
toggle("Books are", ConfigEntry.ALLOW_BOOKS);
break;
}
case "item_drops":
{
toggle("Item drops are", ConfigEntry.ALLOW_ITEM_DROPS);
toggle("Jigsaws are", ConfigEntry.ALLOW_JIGSAWS);
break;
}
@ -325,4 +319,4 @@ public class Command_toggle extends FreedomCommand
}
return Collections.emptyList();
}
}
}

View File

@ -1,5 +1,7 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
@ -19,6 +21,17 @@ import org.bukkit.inventory.ItemStack;
usage = "/<command> <mobtype [speed] | off | list>")
public class Command_tossmob extends FreedomCommand
{
public static List<String> getAllMobNames()
{
List<String> names = new ArrayList<>();
for (EntityType entityType : Groups.MOB_TYPES)
{
names.add(entityType.name());
}
return names;
}
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -45,7 +58,7 @@ public class Command_tossmob extends FreedomCommand
if (args[0].equalsIgnoreCase("list"))
{
msg("Supported mobs: " + Groups.MOB_TYPES.stream().map(Enum::name).toList(), ChatColor.GREEN);
msg("Supported mobs: " + getAllMobNames(), ChatColor.GREEN);
return true;
}

View File

@ -6,8 +6,8 @@ import me.totalfreedom.totalfreedommod.rank.Displayable;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.format.NamedTextColor;
import net.md_5.bungee.api.ChatMessageType;
import net.md_5.bungee.api.chat.TextComponent;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
@ -19,7 +19,7 @@ import org.bukkit.scheduler.BukkitRunnable;
@CommandParameters(description = "Vanish/unvanish yourself.", usage = "/<command> [-s[ilent]]", aliases = "v")
public class Command_vanish extends FreedomCommand
{
@Override
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
Displayable display = plugin.rm.getDisplay(playerSender);
@ -34,7 +34,7 @@ public class Command_vanish extends FreedomCommand
}
}
if (plugin.al.isVanished(playerSender.getUniqueId()))
if (plugin.al.isVanished(playerSender.getName()))
{
if (silent)
{
@ -44,9 +44,8 @@ public class Command_vanish extends FreedomCommand
{
msg("You have unvanished.", ChatColor.GOLD);
FUtil.bcastMsg(plugin.rm.craftLoginMessage(playerSender, null));
server.broadcast(Component.translatable("multiplayer.player.joined", Component.text(playerSender.getName()))
.color(NamedTextColor.YELLOW));
plugin.dc.messageChatChannel("**" + playerSender.getName() + " joined the server" + "**", true);
FUtil.bcastMsg(playerSender.getName() + " joined the game.", ChatColor.YELLOW);
plugin.dc.messageChatChannel("**" + playerSender.getName() + " joined the server" + "**");
}
PlayerData playerData = plugin.pl.getData(playerSender);
@ -68,7 +67,7 @@ public class Command_vanish extends FreedomCommand
}
plugin.esb.setVanished(playerSender.getName(), false);
playerSender.setPlayerListName(StringUtils.substring(displayName, 0, 16));
AdminList.vanished.remove(playerSender.getUniqueId());
AdminList.vanished.remove(playerSender.getName());
}
else
{
@ -77,13 +76,9 @@ public class Command_vanish extends FreedomCommand
@Override
public void run()
{
if (plugin.al.isVanished(playerSender.getUniqueId()))
if (plugin.al.isVanished(playerSender.getName()))
{
sender.sendActionBar(Component.text("You are hidden from other players.").color(NamedTextColor.GOLD));
}
else
{
cancel();
playerSender.spigot().sendMessage(ChatMessageType.ACTION_BAR, TextComponent.fromLegacyText(ChatColor.GOLD + "You are hidden from other players."));
}
}
}.runTaskTimer(plugin, 0L, 4L);
@ -95,19 +90,23 @@ public class Command_vanish extends FreedomCommand
else
{
msg("You have vanished.", ChatColor.GOLD);
server.broadcast(Component.translatable("multiplayer.player.left", Component.text(playerSender.getName()))
.color(NamedTextColor.YELLOW));
plugin.dc.messageChatChannel("**" + playerSender.getName() + " left the server" + "**", true);
FUtil.bcastMsg(playerSender.getName() + " left the game.", ChatColor.YELLOW);
plugin.dc.messageChatChannel("**" + playerSender.getName() + " left the server" + "**");
}
FLog.info(playerSender.getName() + " is now vanished.");
plugin.al.messageAllAdmins(ChatColor.YELLOW + sender.getName() + " has vanished and is now only visible to admins.");
server.getOnlinePlayers().stream().filter(player -> !plugin.al.isAdmin(player)).forEach(player ->
player.hidePlayer(plugin,playerSender));
for (Player player : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(player))
{
player.hidePlayer(plugin, playerSender);
}
}
plugin.esb.setVanished(playerSender.getName(), true);
AdminList.vanished.add(playerSender.getUniqueId());
AdminList.vanished.add(playerSender.getName());
}
return true;
}

View File

@ -1,10 +1,11 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang3.StringUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
@ -30,8 +31,7 @@ public class Command_whitelist extends FreedomCommand
msg("There are no whitelisted players.");
return true;
}
msg("Whitelisted players: " + FUtil.listToString(server.getWhitelistedPlayers().stream().map(player ->
player.getName() != null ? player.getName() : player.getUniqueId().toString()).toList()));
msg("Whitelisted players: " + FUtil.playerListToNames(server.getWhitelistedPlayers()));
return true;
}
@ -187,13 +187,23 @@ public class Command_whitelist extends FreedomCommand
}
else if (args[0].equals("remove"))
{
return server.getWhitelistedPlayers().stream().map(OfflinePlayer::getName).filter(Objects::nonNull).toList();
return getWhitelistedNames();
}
}
return Collections.emptyList();
}
public List<String> getWhitelistedNames()
{
List<String> names = new ArrayList<>();
for (OfflinePlayer player : server.getWhitelistedPlayers())
{
names.add(player.getName());
}
return names;
}
public int purge()
{
int removed = 0;

View File

@ -1,7 +1,6 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank;
@ -16,6 +15,17 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "See who has an item and optionally clear the specified item.", usage = "/<command> <item> [clear]", aliases = "wh")
public class Command_whohas extends FreedomCommand
{
public static List<String> getAllMaterials()
{
List<String> names = new ArrayList<>();
for (Material material : Material.values())
{
names.add(material.name());
}
return names;
}
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
@ -39,16 +49,19 @@ public class Command_whohas extends FreedomCommand
for (final Player player : server.getOnlinePlayers())
{
if (!plugin.al.isAdmin(sender) && plugin.al.isVanished(player.getUniqueId()))
if (!plugin.al.isAdmin(sender) && plugin.al.isVanished(player.getName()))
{
continue;
}
if (player.getInventory().contains(material))
{
players.add(player.getName());
if (plugin.al.isAdmin(sender) && doClear && !plugin.al.isAdmin(player))
if (plugin.al.isAdmin(sender))
{
player.getInventory().remove(material);
if (doClear && !plugin.al.isAdmin(player))
{
player.getInventory().remove(material);
}
}
}
}
@ -70,7 +83,7 @@ public class Command_whohas extends FreedomCommand
{
if (args.length == 1)
{
return Arrays.stream(Material.values()).map(Enum::name).toList();
return getAllMaterials();
}
if (args.length == 2 && plugin.al.isAdmin(sender))

View File

@ -1,10 +1,14 @@
package me.totalfreedom.totalfreedommod.command;
import com.google.common.collect.Lists;
import java.lang.reflect.Field;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.player.PlayerData;
@ -14,14 +18,12 @@ import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.command.*;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class FreedomCommand implements CommandExecutor, TabCompleter
{
@ -41,6 +43,8 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
private final String usage;
private final String aliases;
private final Rank level;
private final String permission;
private final SourceType source;
private final boolean blockHostConsole;
private final int cooldown;
@ -57,6 +61,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
this.usage = params.usage();
this.aliases = params.aliases();
this.level = perms.level();
this.permission = perms.permission().isEmpty() ? "totalfreedommod." + this.name.toLowerCase() : perms.permission();
this.source = perms.source();
this.blockHostConsole = perms.blockHostConsole();
this.cooldown = perms.cooldown();
@ -160,8 +165,65 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
}
}
@Deprecated
protected void checkRank(@Deprecated Rank rank, String permission)
{
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
if (!plugin.permissionHandler.hasPermission(player, permission))
{
noPerms();
return;
}
}
if (!plugin.rm.getRank(sender).isAtLeast(rank))
{
noPerms();
}
}
protected void checkPermissions(String permission)
{
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
if (!plugin.permissionHandler.hasPermission(player, permission))
{
noPerms();
}
}
}
protected boolean checkPermissionsSilent(String permission)
{
//TODO: Not bothering with BukkitTelnet now.
// FLog.debug("Using checkPermissionsSilent");
if (sender instanceof ConsoleCommandSender)
{
return true;
}
if (sender instanceof Player player)
{
// FLog.debug("Checking player permission for " + player.getUniqueId() + " - " + permission);
return plugin.permissionHandler.hasPermission(player, permission);
}
return false;
}
@Deprecated
protected void checkRank(Rank rank)
{
// FLog.debug("Using checkRank");
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
// FLog.debug("Checking player permission for " + player.getUniqueId() + " - " + this.permission);
if (!plugin.permissionHandler.hasPermission(player, this.permission))
{
noPerms();
return;
}
}
if (!plugin.rm.getRank(sender).isAtLeast(rank))
{
noPerms();
@ -217,23 +279,16 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
protected Player getPlayer(String name, Boolean nullVanished)
{
Player player = Bukkit.getPlayer(name);
if (player != null && nullVanished && plugin.al.isVanished(player.getUniqueId()) && !plugin.al.isAdmin(sender))
if (player != null)
{
return null;
if (nullVanished && plugin.al.isVanished(player.getName()) && !plugin.al.isAdmin(sender))
{
return null;
}
}
return player;
}
@Nullable
protected OfflinePlayer getOfflinePlayer(String name)
{
return Arrays.stream(Bukkit.getOfflinePlayers())
.filter(player -> player.getName() != null)
.filter(player -> player.getName().equalsIgnoreCase(name))
.findFirst()
.orElse(null);
}
protected Admin getAdmin(CommandSender sender)
{
return plugin.al.getAdmin(sender);
@ -370,7 +425,15 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
public boolean func2()
{
if (!plugin.rm.getRank(sender).isAtLeast(perms.level()))
/*if (!plugin.rm.getRank(sender).isAtLeast(perms.level()))
{
msg(NO_PERMISSION);
return true;
}*/
FLog.debug("Result of check perms: " + (!checkPermissionsSilent(cmd.permission)));
if (!checkPermissionsSilent(cmd.permission))
{
msg(NO_PERMISSION);
return true;

View File

@ -25,6 +25,8 @@ public enum ConfigEntry
ALLOW_BELLS(Boolean.class, "allow.bells"),
ALLOW_ARMOR_STANDS(Boolean.class, "allow.armorstands"),
ALLOW_MINECARTS(Boolean.class, "allow.minecarts"),
ALLOW_STRUCTURE_BLOCKS(Boolean.class, "allow.structureblocks"),
ALLOW_JIGSAWS(Boolean.class, "allow.jigsaws"),
ALLOW_GRINDSTONES(Boolean.class, "allow.grindstones"),
ALLOW_JUKEBOXES(Boolean.class, "allow.jukeboxes"),
ALLOW_SPAWNERS(Boolean.class, "allow.spawners"),
@ -33,9 +35,6 @@ public enum ConfigEntry
AUTO_TP(Boolean.class, "allow.auto_tp"),
AUTO_CLEAR(Boolean.class, "allow.auto_clear"),
ALLOW_GRAVITY(Boolean.class, "allow.gravity"),
ALLOW_MASTERBLOCKS(Boolean.class, "allow.masterblocks"),
ALLOW_BOOKS(Boolean.class, "allow.books"),
ALLOW_ITEM_DROPS(Boolean.class, "allow.item_drops"),
//
BLOCKED_CHATCODES(String.class, "blocked_chatcodes"),
//
@ -74,10 +73,12 @@ public enum ConfigEntry
SERVER_WHITELIST_MOTD(String.class, "server.motds.whitelist"),
SERVER_FULL_MOTD(String.class, "server.motds.full"),
//
PERMISSIONS_GROUPS_ADMIN(String.class, "permissions.groups.admin"),
PERMISSIONS_GROUPS_SENIOR(String.class, "permissions.groups.senior_admin"),
PERMISSIONS_GROUPS_DEFAULT(String.class, "permissions.groups.default"),
DISCORD_TOKEN(String.class, "discord.token"),
DISCORD_PREFIX(String.class, "discord.prefix"),
DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"),
DISCORD_REPORT_ARCHIVE_CHANNEL_ID(String.class, "discord.report_archive_channel_id"),
DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"),
DISCORD_ADMINCHAT_CHANNEL_ID(String.class, "discord.adminchat_channel_id"),
@ -92,6 +93,12 @@ public enum ConfigEntry
DISCORD_SERVER_OWNER_ROLE_ID(String.class, "discord.server_owner_role_id"),
DISCORD_INVITE_LINK(String.class, "discord.invite_link"),
//
PTERO_URL(String.class, "ptero.url"),
PTERO_DEFAULT_EMAIL_DOMAIN(String.class, "ptero.default_email_domain"),
PTERO_SERVER_UUID(String.class, "ptero.server_uuid"),
PTERO_ADMIN_KEY(String.class, "ptero.admin_key"),
PTERO_SERVER_KEY(String.class, "ptero.server_key"),
//
SHOP_ENABLED(Boolean.class, "shop.enabled"),
SHOP_TITLE(String.class, "shop.title"),
SHOP_PREFIX(String.class, "shop.prefix"),
@ -141,6 +148,9 @@ public enum ConfigEntry
AUTOKICK_THRESHOLD(Double.class, "autokick.threshold"),
AUTOKICK_TIME(Integer.class, "autokick.time"),
//
LOGS_SECRET(String.class, "logs.secret"),
LOGS_URL(String.class, "logs.url"),
//
FLATLANDS_GENERATE(Boolean.class, "flatlands.generate"),
FLATLANDS_GENERATE_PARAMS(String.class, "flatlands.generate_params"),
//
@ -157,6 +167,7 @@ public enum ConfigEntry
WILDCARD_BLOCKED_COMMANDS(List.class, "blocked_commands.wildcard"),
FORBIDDEN_WORDS(List.class, "forbidden_words"),
HOST_SENDER_NAMES(List.class, "host_sender_names"),
FAMOUS_PLAYERS(List.class, "famous_players"),
ADMIN_ONLY_MODE(Boolean.class, "admin_only_mode"),
ADMIN_INFO(List.class, "admininfo"),
VOTING_INFO(List.class, "votinginfo"),
@ -177,6 +188,19 @@ public enum ConfigEntry
this.configName = configName;
}
public static ConfigEntry findConfigEntry(String name)
{
name = name.toLowerCase().replace("_", "");
for (ConfigEntry entry : values())
{
if (entry.toString().toLowerCase().replace("_", "").equals(name))
{
return entry;
}
}
return null;
}
public Class<?> getType()
{
return type;

View File

@ -3,16 +3,19 @@ package me.totalfreedom.totalfreedommod.discord;
import com.google.common.base.Strings;
import java.time.Instant;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.SplittableRandom;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.security.auth.login.LoginException;
import com.google.common.collect.ImmutableList;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
@ -23,24 +26,20 @@ import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.PrivateChannel;
import net.dv8tion.jda.api.entities.Role;
import net.dv8tion.jda.api.entities.SelfUser;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.entities.User;
import net.dv8tion.jda.api.events.ReadyEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.ChunkingFilter;
import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.internal.utils.concurrent.CountingThreadFactory;
import net.kyori.adventure.text.Component;
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
import net.md_5.bungee.api.ChatColor;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.GameRule;
import org.bukkit.Location;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
@ -48,18 +47,16 @@ import org.bukkit.event.entity.PlayerDeathEvent;
import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Discord extends FreedomService
{
public static HashMap<String, PlayerData> LINK_CODES = new HashMap<>();
public static JDA bot = null;
public static DiscordCommandManager DISCORD_COMMAND_MANAGER;
public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR;
public List<CompletableFuture<Message>> sentMessages = new ArrayList<>();
public Boolean enabled = false;
private static final ImmutableList<String> DISCORD_SUBDOMAINS = ImmutableList.of("discordapp.com", "discord.com", "discord.gg");
private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)");
public static String getCode(PlayerData playerData)
{
@ -149,9 +146,6 @@ public class Discord extends FreedomService
public void startBot()
{
DISCORD_COMMAND_MANAGER = new DiscordCommandManager();
DISCORD_COMMAND_MANAGER.init(this);
enabled = !Strings.isNullOrEmpty(ConfigEntry.DISCORD_TOKEN.getString());
if (!enabled)
{
@ -174,7 +168,6 @@ public class Discord extends FreedomService
.addEventListeners(new PrivateMessageListener(),
new DiscordToMinecraftListener(),
new DiscordToAdminChatListener(),
new MessageReactionListener(),
new ListenerAdapter()
{
@Override
@ -194,18 +187,15 @@ public class Discord extends FreedomService
catch (LoginException e)
{
FLog.warning("An invalid token for Discord integration was provided, the bot will not enable.");
enabled = false;
}
catch (IllegalArgumentException e)
{
FLog.warning("Discord integration failed to start.");
enabled = false;
}
catch (NoClassDefFoundError e)
{
FLog.warning("The JDA plugin is not installed, therefore the discord bot cannot start.");
FLog.warning("To resolve this error, please download the latest JDA from: https://github.com/AtlasMediaGroup/Minecraft-JDA/releases");
enabled = false;
FLog.warning("To resolve this error, please download the latest JDA from: https://github.com/TFPatches/Minecraft-JDA/releases");
}
}
@ -225,12 +215,44 @@ public class Discord extends FreedomService
}
}
sentMessages.clear();
messageChatChannel("**Message queue cleared**", true);
messageChatChannel("**Message queue cleared**");
}
public void sendPteroInfo(PlayerData playerData, String username, String password)
{
User user = getUser(playerData.getDiscordID());
String message = "The following are your Pterodactyl details:\n\nUsername: " + username + "\nPassword: " + password + "\n\nYou can connect to the panel at " + plugin.ptero.URL;
PrivateChannel privateChannel = user.openPrivateChannel().complete();
privateChannel.sendMessage(message).complete();
}
public User getUser(String id)
{
Guild guild = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());
if (guild == null)
{
FLog.severe("Either the bot is not in the Discord server or it doesn't exist. Check the server ID.");
return null;
}
Member member = guild.getMemberById(id);
if (member == null)
{
return null;
}
return member.getUser();
}
public String generateCode(int size)
{
return RandomStringUtils.randomNumeric(size);
StringBuilder code = new StringBuilder();
SplittableRandom random = new SplittableRandom();
for (int i = 0; i < size; i++)
{
code.append(random.nextInt(10));
}
return code.toString();
}
@EventHandler(priority = EventPriority.MONITOR)
@ -243,11 +265,9 @@ public class Discord extends FreedomService
return;
}
Component deathMessage = event.deathMessage();
if (deathMessage != null)
if (event.getDeathMessage() != null)
{
messageChatChannel("**" + deformat(PlainTextComponentSerializer.plainText().serialize(deathMessage)) + "**", true);
messageChatChannel("**" + event.getDeathMessage() + "**");
}
}
@ -260,82 +280,85 @@ public class Discord extends FreedomService
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event)
{
if (!plugin.al.isVanished(event.getPlayer().getUniqueId()))
if (!plugin.al.isVanished(event.getPlayer().getName()))
{
messageChatChannel("**" + deformat(event.getPlayer().getName()) + " joined the server" + "**", true);
messageChatChannel("**" + event.getPlayer().getName() + " joined the server" + "**");
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerLeave(PlayerQuitEvent event)
{
if (!plugin.al.isVanished(event.getPlayer().getUniqueId()))
if (!plugin.al.isVanished(event.getPlayer().getName()))
{
messageChatChannel("**" + deformat(event.getPlayer().getName()) + " left the server" + "**", true);
messageChatChannel("**" + event.getPlayer().getName() + " left the server" + "**");
}
}
public static String sanitizeChatMessage(String message)
{
String newMessage = message;
if (message.toLowerCase().contains("discord.gg")) // discord.gg/invite works as an invite
{
return "";
}
for (String subdomain : DISCORD_SUBDOMAINS)
{
if (message.toLowerCase().contains(subdomain + "/invite"))
{
return "";
}
}
if (message.contains("§"))
{
newMessage = message.replace("§", "");
}
return newMessage;
}
public void messageChatChannel(String message)
{
messageChatChannel(message, false);
}
public void messageChatChannel(String message, boolean system)
{
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
if (message.contains("@everyone") || message.contains("@here"))
{
message = StringUtils.remove(message, "@");
}
String sanitizedMessage = (system) ? message : sanitizeChatMessage(message);
if (message.toLowerCase().contains("discord.gg"))
{
return;
}
if (message.contains("§"))
{
message = StringUtils.remove(message, "§");
}
if (sanitizedMessage.isBlank()) return;
Matcher DISCORD_MENTION_MATCHER = DISCORD_MENTION_PATTERN.matcher(message);
while (DISCORD_MENTION_MATCHER.find())
{
String mention = DISCORD_MENTION_MATCHER.group(1);
message = message.replace(mention, mention.replace("@",""));
}
if (enabled && !chat_channel_id.isEmpty())
{
CompletableFuture<Message> sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(sanitizedMessage).allowedMentions(Collections.emptyList()).submit(true);
CompletableFuture<Message> sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(deformat(message)).submit(true);
sentMessages.add(sentMessage);
}
}
public void messageAdminChatChannel(String message)
{
messageAdminChatChannel(message, false);
}
public void messageAdminChatChannel(String message, boolean system)
{
String chat_channel_id = ConfigEntry.DISCORD_ADMINCHAT_CHANNEL_ID.getString();
if (message.contains("@everyone") || message.contains("@here"))
{
message = StringUtils.remove(message, "@");
}
String sanitizedMessage = sanitizeChatMessage(message);
if (message.toLowerCase().contains("discord.gg"))
{
return;
}
if (message.contains("§"))
{
message = StringUtils.remove(message, "§");
}
if (sanitizedMessage.isBlank()) return;
Matcher DISCORD_MENTION_MATCHER = DISCORD_MENTION_PATTERN.matcher(message);
while (DISCORD_MENTION_MATCHER.find())
{
String mention = DISCORD_MENTION_MATCHER.group(1);
message = message.replace(mention, mention.replace("@",""));
}
if (enabled && !chat_channel_id.isEmpty())
{
CompletableFuture<Message> sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(sanitizedMessage).allowedMentions(Collections.emptyList()).submit(true);
CompletableFuture<Message> sentMessage = Objects.requireNonNull(bot.getTextChannelById(chat_channel_id)).sendMessage(deformat(message)).submit(true);
sentMessages.add(sentMessage);
}
}
@ -343,7 +366,7 @@ public class Discord extends FreedomService
public String formatBotTag()
{
SelfUser user = bot.getSelfUser();
return user.getAsTag();
return user.getName() + "#" + user.getDiscriminator();
}
@Override
@ -351,18 +374,18 @@ public class Discord extends FreedomService
{
if (bot != null)
{
messageChatChannel("**Server has stopped**", true);
messageChatChannel("**Server has stopped**");
}
FLog.info("Discord integration has successfully shutdown.");
}
public static String deformat(String input)
public String deformat(String input)
{
return input.replaceAll("([_\\\\`*>|])", "\\\\$1");
return input.replace("_", "\\_");
}
public boolean shouldISendReport()
public boolean sendReport(Player reporter, Player reported, String reason)
{
if (ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString().isEmpty())
{
@ -377,7 +400,6 @@ public class Discord extends FreedomService
Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());
if (server == null)
{
FLog.severe("The Discord server ID specified is invalid, or the bot is not on the server.");
return false;
@ -390,89 +412,23 @@ public class Discord extends FreedomService
return false;
}
return true;
}
public CompletableFuture<Boolean> sendReport(String reporterName, String reportedName, String reason)
{
return CompletableFuture.supplyAsync(() ->
EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Report for " + reported.getName());
embedBuilder.setDescription(reason);
embedBuilder.setFooter("Reported by " + reporter.getName(), "https://minotar.net/helm/" + reporter.getName() + ".png");
embedBuilder.setTimestamp(Instant.from(ZonedDateTime.now()));
String location = "World: " + Objects.requireNonNull(reported.getLocation().getWorld()).getName() + ", X: " + reported.getLocation().getBlockX() + ", Y: " + reported.getLocation().getBlockY() + ", Z: " + reported.getLocation().getBlockZ();
embedBuilder.addField("Location", location, true);
embedBuilder.addField("Game Mode", WordUtils.capitalizeFully(reported.getGameMode().name()), true);
com.earth2me.essentials.User user = plugin.esb.getEssentialsUser(reported.getName());
embedBuilder.addField("God Mode", WordUtils.capitalizeFully(String.valueOf(user.isGodModeEnabled())), true);
if (user.getNickname() != null)
{
if (!shouldISendReport())
{
return false;
}
final Guild server = bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());
if (server == null)
{
FLog.severe("The guild ID specified in the config is invalid.");
return false;
}
final TextChannel channel = server.getTextChannelById(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString());
if (channel == null)
{
FLog.severe("The report channel ID specified in the config is invalid.");
return false;
}
Player onlinePlayer = Bukkit.getPlayer(reportedName);
boolean online = onlinePlayer != null;
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Report for " + reportedName + (online ? "" : " (offline)"));
embedBuilder.setDescription(reason);
embedBuilder.setFooter("Reported by " + reporterName, "https://minotar.net/helm/" + reporterName + ".png");
embedBuilder.setTimestamp(Instant.from(ZonedDateTime.now()));
Location location = null;
Boolean godMode = null;
String nickName = null;
if (plugin.esb.isEnabled())
{
com.earth2me.essentials.User user = plugin.esb.getEssentialsUser(reportedName);
if (!online)
{
location = user.getLastLocation();
}
godMode = user.isGodModeEnabled();
nickName = user.getNickname();
}
if (location == null && online)
{
location = onlinePlayer.getLocation();
}
if (location != null)
{
embedBuilder.addField("Location", "World: " + location.getWorld().getName() + ", X: " + location.getBlockX() + ", Y: " + location.getBlockY() + ", Z: " + location.getBlockZ(), true);
}
if (godMode != null)
{
embedBuilder.addField("God Mode", WordUtils.capitalizeFully(godMode.toString()), true);
}
if (nickName != null)
{
embedBuilder.addField("Nickname", nickName, true);
}
MessageEmbed embed = embedBuilder.build();
Message message = channel.sendMessageEmbeds(embed).complete();
if (!ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString().isEmpty())
{
message.addReaction("\uD83D\uDCCB").complete();
}
return true;
}, t -> Bukkit.getScheduler().runTaskAsynchronously(plugin, t));
embedBuilder.addField("Nickname", user.getNickname(), true);
}
MessageEmbed embed = embedBuilder.build();
channel.sendMessage(embed).complete();
return true;
}
// Do no ask why this is here. I spent two hours trying to make a simple thing work
@ -480,32 +436,7 @@ public class Discord extends FreedomService
{
public void start()
{
messageChatChannel("**Server has started**", true);
messageChatChannel("**Server has started**");
}
}
public void onPlayerChat(Player player, String message)
{
if (ConfigEntry.ADMIN_ONLY_MODE.getBoolean())
{
return;
}
if (server.hasWhitelist())
{
return;
}
if (plugin.pl.getPlayer(player).isMuted())
{
return;
}
if (bot == null)
{
return;
}
messageChatChannel(deformat(player.getName()) + " \u00BB " + ChatColor.stripColor(message));
}
}

View File

@ -5,8 +5,9 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.rank.Title;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.entities.*;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.md_5.bungee.api.chat.BaseComponent;
@ -23,107 +24,77 @@ public class DiscordToMinecraftListener extends ListenerAdapter
{
public void onMessageReceived(MessageReceivedEvent event)
{
final String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
final MessageChannel genericChannel = event.getChannel();
if (event.getMember() == null)
String chat_channel_id = ConfigEntry.DISCORD_CHAT_CHANNEL_ID.getString();
if (event.getMember() != null && !chat_channel_id.isEmpty() && event.getChannel().getId().equals(chat_channel_id))
{
return;
}
if (!event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()))
{
Member member = event.getMember();
String tag = getDisplay(member);
Message msg = event.getMessage();
if (chat_channel_id.isEmpty())
{
return;
}
ComponentBuilder emsg = new ComponentBuilder();
if (event.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()))
{
return;
}
// Prefix
emsg.append(ChatColor.DARK_GRAY + "[");
TextComponent inviteLink = new TextComponent("Discord");
inviteLink.setColor(ChatColor.DARK_AQUA.asBungee());
inviteLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
new Text("Click here to get the invite link!")));
inviteLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
ConfigEntry.DISCORD_INVITE_LINK.getString()));
emsg.append(inviteLink);
emsg.append(ChatColor.DARK_GRAY + "] ", ComponentBuilder.FormatRetention.NONE);
if (!genericChannel.getId().equals(chat_channel_id))
{
return;
}
// Tag (if they have one)
if (tag != null)
{
emsg.append(tag);
}
if (!(genericChannel instanceof TextChannel))
{
return;
}
final TextChannel textChannel = (TextChannel) genericChannel;
final Member member = event.getMember();
final String tag = getDisplay(member);
final Message msg = event.getMessage();
final String content = msg.getContentStripped();
if (content.toLowerCase().startsWith(ConfigEntry.DISCORD_PREFIX.getString().toLowerCase()) && Discord.DISCORD_COMMAND_MANAGER.parse(content, member, textChannel))
{
return;
}
ComponentBuilder emsg = new ComponentBuilder();
// Prefix
emsg.append(ChatColor.DARK_GRAY + "[");
TextComponent inviteLink = new TextComponent("Discord");
inviteLink.setColor(ChatColor.DARK_AQUA.asBungee());
inviteLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
new Text("Click here to get the invite link!")));
inviteLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
ConfigEntry.DISCORD_INVITE_LINK.getString()));
emsg.append(inviteLink);
emsg.append(ChatColor.DARK_GRAY + "] ", ComponentBuilder.FormatRetention.NONE);
// Tag (if they have one)
if (tag != null)
{
emsg.append(tag);
}
emsg.append(" ");
// User
TextComponent user = new TextComponent(FUtil.stripColors(member.getEffectiveName()));
user.setColor(ChatColor.RED.asBungee());
emsg.append(user);
// Message
emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET
+ FUtil.stripColors(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE);
// Attachments
if (!msg.getAttachments().isEmpty())
{
if (!msg.getContentDisplay().isEmpty())
emsg.append(" ");
for (Message.Attachment attachment : msg.getAttachments())
{
TextComponent media = new TextComponent("[Media] ");
media.setColor(ChatColor.YELLOW.asBungee());
media.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl()));
media.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(attachment.getUrl())));
// User
TextComponent user = new TextComponent(ChatColor.stripColor(member.getEffectiveName()));
user.setColor(ChatColor.RED.asBungee());
emsg.append(user);
emsg.append(media, ComponentBuilder.FormatRetention.NONE);
// Message
emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET
+ ChatColor.stripColor(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE);
// Attachments
if (!msg.getAttachments().isEmpty())
{
if (!msg.getContentDisplay().isEmpty())
emsg.append(" ");
for (Message.Attachment attachment : msg.getAttachments())
{
TextComponent media = new TextComponent("[Media] ");
media.setColor(ChatColor.YELLOW.asBungee());
media.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl()));
media.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(attachment.getUrl())));
emsg.append(media, ComponentBuilder.FormatRetention.NONE);
}
}
BaseComponent[] components = emsg.create();
for (Player player : Bukkit.getOnlinePlayers())
{
if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord())
{
player.spigot().sendMessage(components);
}
}
FLog.info(TextComponent.toLegacyText(components), true);
}
}
BaseComponent[] components = emsg.create();
for (Player player : Bukkit.getOnlinePlayers())
{
if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord())
{
player.sendMessage(components);
}
}
FLog.info(TextComponent.toLegacyText(components), true);
}
public String getDisplay(Member member)
{
Guild server = Discord.bot.getGuildById(ConfigEntry.DISCORD_SERVER_ID.getString());

View File

@ -1,71 +0,0 @@
package me.totalfreedom.totalfreedommod.discord;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.MessageEmbed;
import net.dv8tion.jda.api.entities.TextChannel;
import net.dv8tion.jda.api.events.message.react.MessageReactionAddEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter;
import java.util.Collections;
public class MessageReactionListener extends ListenerAdapter
{
public void onMessageReactionAdd(MessageReactionAddEvent messageReactionAddEvent)
{
if (!messageReactionAddEvent.isFromGuild())
{
return;
}
if (messageReactionAddEvent.getMember() == null)
{
return;
}
if (messageReactionAddEvent.getMember().getUser().getId().equals(Discord.bot.getSelfUser().getId()))
{
return;
}
if (!messageReactionAddEvent.getChannel().getId().equals(ConfigEntry.DISCORD_REPORT_CHANNEL_ID.getString()))
{
return;
}
if (!messageReactionAddEvent.getReactionEmote().getEmoji().equals("\uD83D\uDCCB"))
{
return;
}
final TextChannel archiveChannel = Discord.bot.getTextChannelById(ConfigEntry.DISCORD_REPORT_ARCHIVE_CHANNEL_ID.getString());
if (archiveChannel == null)
{
FLog.warning("Report archive channel is defined in the config, yet doesn't actually exist!");
return;
}
final Message message = messageReactionAddEvent.retrieveMessage().complete();
final Member completer = messageReactionAddEvent.getMember();
if (!message.getAuthor().getId().equals(Discord.bot.getSelfUser().getId()))
{
return;
}
// We don't need other embeds... yet?
final MessageEmbed embed = message.getEmbeds().get(0);
final MessageBuilder archiveMessageBuilder = new MessageBuilder();
archiveMessageBuilder.setContent("Report completed by " + completer.getUser().getAsMention() + " (" + Discord.deformat(completer.getUser().getAsTag() + ")"));
archiveMessageBuilder.setAllowedMentions(Collections.emptyList());
archiveMessageBuilder.setEmbeds(embed);
final Message archiveMessage = archiveMessageBuilder.build();
archiveChannel.sendMessage(archiveMessage).complete();
message.delete().complete();
}
}

View File

@ -1,25 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.command;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Guild;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.User;
import java.util.List;
public interface DiscordCommand
{
String getCommandName();
String getDescription();
String getCategory();
List<String> getAliases();
boolean isAdmin();
boolean canExecute(Member member);
MessageBuilder execute(Member member, List<String> args);
}

View File

@ -1,13 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.command;
import net.dv8tion.jda.api.entities.Member;
public abstract class DiscordCommandImpl implements DiscordCommand
{
@Override
public boolean canExecute(Member member)
{
// TODO Implement administrator checks if/when any administrative Discord commands are added to the bot
return !isAdmin();
}
}

View File

@ -1,98 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.command;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.entities.TextChannel;
import org.reflections.Reflections;
import java.awt.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
public class DiscordCommandManager
{
public static final String PREFIX = ConfigEntry.DISCORD_PREFIX.getString();
private Discord discord;
public final List<DiscordCommand> commands = new ArrayList<>();
public void init(Discord discord)
{
this.discord = discord;
final Reflections discordCommandsDir = new Reflections("me.totalfreedom.totalfreedommod.discord.commands");
final Set<Class<? extends DiscordCommand>> commandClasses = discordCommandsDir.getSubTypesOf(DiscordCommand.class);
for (Class<? extends DiscordCommand> commandClass : commandClasses)
{
try
{
commands.add(commandClass.getDeclaredConstructor().newInstance());
}
catch (Exception e)
{
FLog.warning("Failed to load Discord command: " + commandClass.getName());
}
}
FLog.info("Loaded " + commands.size() + " Discord commands.");
}
public boolean parse(String content, Member member, TextChannel channel)
{
final String actualContent = content.substring(PREFIX.length()).trim();
List<String> args = new ArrayList<>(Arrays.asList(actualContent.split(" ")));
if (args.isEmpty())
{
return false;
}
final String alias = args.get(0);
if (alias.isEmpty())
{
return false;
}
for (DiscordCommand command : commands)
{
if (command.getCommandName().equalsIgnoreCase(alias) || command.getAliases().contains(alias.toLowerCase()))
{
if (command.canExecute(member))
{
final MessageBuilder messageBuilder = command.execute(member, args);
final Message message = messageBuilder.build();
final CompletableFuture<Message> futureMessage = channel.sendMessage(message).submit(true);
this.discord.sentMessages.add(futureMessage);
return true;
}
else
{
final MessageBuilder messageBuilder = new MessageBuilder();
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setTitle("Command error");
embedBuilder.setColor(Color.RED);
embedBuilder.setDescription("You don't have permission to execute this command.");
messageBuilder.setEmbeds(embedBuilder.build());
final Message message = messageBuilder.build();
final CompletableFuture<Message> futureMessage = channel.sendMessage(message).submit(true);
this.discord.sentMessages.add(futureMessage);
return true;
}
}
}
return false;
}
}

View File

@ -1,86 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommand;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandManager;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import java.awt.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class HelpCommand extends DiscordCommandImpl
{
@Override
public String getCommandName()
{
return "help";
}
@Override
public String getDescription()
{
return "Displays the help command";
}
@Override
public String getCategory()
{
return "Help";
}
@Override
public List<String> getAliases()
{
return List.of("cmds", "commands", "elp");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
final EmbedBuilder embedBuilder = new EmbedBuilder();
embedBuilder.setColor(Color.GREEN);
embedBuilder.setTitle("Help Command");
final Map<String, List<DiscordCommand>> commandCategories = new HashMap<>();
for (DiscordCommand command : Discord.DISCORD_COMMAND_MANAGER.commands)
{
if (!commandCategories.containsKey(command.getCategory()))
{
commandCategories.put(command.getCategory(), new ArrayList<>(List.of(command)));
}
else
{
commandCategories.get(command.getCategory()).add(command);
}
}
for (Map.Entry<String, List<DiscordCommand>> entry : commandCategories.entrySet())
{
final String category = entry.getKey();
final List<DiscordCommand> commands = entry.getValue();
final StringBuilder fieldValue = new StringBuilder();
for (DiscordCommand command : commands)
{
fieldValue.append("**").append(DiscordCommandManager.PREFIX).append(command.getCommandName()).append("** - ").append(command.getDescription()).append("\n");
}
embedBuilder.addField(category, fieldValue.toString().trim(), false);
}
return new MessageBuilder().setEmbeds(embedBuilder.build());
}
}

View File

@ -1,99 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.rank.Displayable;
import me.totalfreedom.totalfreedommod.rank.RankManager;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListCommand extends DiscordCommandImpl
{
private static final TotalFreedomMod PLUGIN = TotalFreedomMod.plugin();
@Override
public String getCommandName()
{
return "list";
}
@Override
public String getDescription()
{
return "Gives a list of online players.";
}
@Override
public String getCategory()
{
return "Server Commands";
}
@Override
public List<String> getAliases()
{
return List.of("online", "who", "l", "lsit");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
if (PLUGIN == null)
{
throw new IllegalStateException("TotalFreedomMod somehow null while executing a command!");
}
final AdminList adminList = PLUGIN.al;
final RankManager rankManager = PLUGIN.rm;
EmbedBuilder embedBuilder = new EmbedBuilder()
.setTitle("Player List - " + ConfigEntry.SERVER_NAME.getString())
.setDescription("There are " + FUtil.getFakePlayerCount() + " / " + Bukkit.getMaxPlayers() + " online players");
Map<Displayable, List<String>> displayables = new HashMap<>();
Bukkit.getOnlinePlayers().stream().filter(player -> !adminList.isVanished(player.getUniqueId())).forEach(player ->
{
final Displayable displayable = rankManager.getDisplay(player);
final String name = Discord.deformat(player.getName());
if (displayables.containsKey(displayable))
{
displayables.get(displayable).add(name);
}
else
{
displayables.put(displayable, new ArrayList<>(List.of(name)));
}
});
for (Map.Entry<Displayable, List<String>> entry : displayables.entrySet())
{
final Displayable displayable = entry.getKey();
final List<String> players = entry.getValue();
embedBuilder.addField(displayable.getPlural() + " (" + players.size() + ")",
String.join(", ", players), false);
}
return new MessageBuilder().setEmbeds(embedBuilder.build());
}
}

View File

@ -1,58 +0,0 @@
package me.totalfreedom.totalfreedommod.discord.commands;
import me.totalfreedom.totalfreedommod.discord.command.DiscordCommandImpl;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.MessageBuilder;
import net.dv8tion.jda.api.entities.Member;
import org.bukkit.Bukkit;
import java.util.Collections;
import java.util.List;
public class TPSCommand extends DiscordCommandImpl
{
@Override
public String getCommandName()
{
return "tps";
}
@Override
public String getDescription()
{
return "Lag information regarding the server.";
}
@Override
public String getCategory()
{
return "Server Commands";
}
@Override
public List<String> getAliases()
{
return Collections.singletonList("lag");
}
@Override
public boolean isAdmin()
{
return false;
}
@Override
public MessageBuilder execute(Member member, List<String> args)
{
final EmbedBuilder builder = new EmbedBuilder();
builder.setTitle("Server lag information");
builder.addField("TPS", String.valueOf(Math.round(FUtil.getMeanAverageDouble(Bukkit.getServer().getTPS()))), false);
builder.addField("Uptime", FUtil.getUptime(), false);
builder.addField("Maximum Memory", Math.ceil(FUtil.getMaxMem()) + " MB", false);
builder.addField("Allocated Memory", Math.ceil(FUtil.getTotalMem()) + " MB", false);
builder.addField("Free Memory", Math.ceil(FUtil.getFreeMem()) + " MB", false);
return new MessageBuilder().setEmbeds(builder.build());
}
}

View File

@ -13,7 +13,13 @@ import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.shop.ShopItem;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.*;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.FireworkEffect;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.Sound;
import org.bukkit.SoundCategory;
import org.bukkit.block.Block;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.EnderPearl;
@ -89,16 +95,11 @@ public class ItemFun extends FreedomService
{
}
@EventHandler(ignoreCancelled = true)
@EventHandler
public void onPlayerEntityInteract(PlayerInteractEntityEvent event)
{
Player player = event.getPlayer();
if (player.getGameMode().equals(GameMode.SPECTATOR))
{
return;
}
Entity entity = event.getRightClicked();
FPlayer fPlayer = plugin.pl.getPlayer(player);

View File

@ -20,6 +20,7 @@ import me.totalfreedom.totalfreedommod.httpd.module.Module_indefbans;
import me.totalfreedom.totalfreedommod.httpd.module.Module_index;
import me.totalfreedom.totalfreedommod.httpd.module.Module_list;
import me.totalfreedom.totalfreedommod.httpd.module.Module_logfile;
import me.totalfreedom.totalfreedommod.httpd.module.Module_logs;
import me.totalfreedom.totalfreedommod.httpd.module.Module_players;
import me.totalfreedom.totalfreedommod.httpd.module.Module_punishments;
import me.totalfreedom.totalfreedommod.httpd.module.Module_schematic;
@ -95,6 +96,7 @@ public class HTTPDaemon extends FreedomService
module("help", Module_help.class, false);
module("list", Module_list.class, false);
module("logfile", Module_logfile.class, true);
module("logs", Module_logs.class, true);
module("indefbans", Module_indefbans.class, true);
module("players", Module_players.class, false);
module("punishments", Module_punishments.class, true);

View File

@ -337,12 +337,12 @@ public abstract class NanoHTTPD
*/
protected String decodePercent(String str)
{
String decoded = str;
String decoded = null;
try
{
decoded = URLDecoder.decode(str, "UTF8");
}
catch (UnsupportedEncodingException | IllegalArgumentException ignored)
catch (UnsupportedEncodingException ignored)
{
}
return decoded;

View File

@ -4,12 +4,16 @@ import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD;
import me.totalfreedom.totalfreedommod.permissions.handler.DefaultPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.IPermissionHandler;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.JSONArray;
import org.json.JSONObject;
import java.util.Arrays;
import java.util.Collection;
public class Module_list extends HTTPDModule
@ -25,7 +29,32 @@ public class Module_list extends HTTPDModule
{
if (params.get("json") != null && params.get("json").equals("true"))
{
FLog.debug("Swapping to JSON View!");
final JSONObject responseObject = new JSONObject();
if (!(plugin.permissionHandler instanceof DefaultPermissionHandler))
{
FLog.debug("Displaying custom list on HTTPD!");
IPermissionHandler handler = plugin.permissionHandler;
final JSONObject players = new JSONObject();
Arrays.stream(handler.getGroups()).forEach(s ->
{
JSONArray array = new JSONArray();
Bukkit.getOnlinePlayers().stream().filter(player -> !plugin.al.isVanished(player.getName())).filter(player -> handler.getPrimaryGroup(player).equalsIgnoreCase(s)).forEach(player ->
{
array.put(player.getName());
});
players.put(s.toLowerCase(), array);
});
responseObject.put("players", players);
responseObject.put("online", Bukkit.getOnlinePlayers().stream().filter(player -> !plugin.al.isVanished(player.getName())).count());
responseObject.put("max", Bukkit.getMaxPlayers());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString(4));
response.addHeader("Access-Control-Allow-Origin", "*");
return response;
}
final JSONArray owners = new JSONArray();
final JSONArray executives = new JSONArray();
@ -37,49 +66,49 @@ public class Module_list extends HTTPDModule
for (Player player : Bukkit.getOnlinePlayers())
{
if (plugin.al.isVanished(player.getUniqueId()))
if (plugin.al.isVanished(player.getName()))
{
continue;
}
if (plugin.pl.getData(player).isMasterBuilder())
{
masterbuilders.add(player.getName());
masterbuilders.put(player.getName());
}
if (FUtil.DEVELOPER_NAMES.contains(player.getName()))
{
developers.add(player.getName());
developers.put(player.getName());
}
if (ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) && !FUtil.DEVELOPERS.contains(player.getName()))
{
executives.add(player.getName());
executives.put(player.getName());
}
if (ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()))
{
owners.add(player.getName());
owners.put(player.getName());
}
if (!plugin.al.isAdmin(player) && hasSpecialTitle(player))
{
operators.add(player.getName());
operators.put(player.getName());
}
if (hasSpecialTitle(player) && plugin.al.isAdmin(player) && !plugin.al.isVanished(player.getUniqueId()))
if (hasSpecialTitle(player) && plugin.al.isAdmin(player) && !plugin.al.isVanished(player.getName()))
{
Admin admin = plugin.al.getAdmin(player);
switch (admin.getRank())
{
case ADMIN:
{
admins.add(player.getName());
admins.put(player.getName());
break;
}
case SENIOR_ADMIN:
{
senioradmins.add(player.getName());
senioradmins.put(player.getName());
break;
}
default:
@ -102,23 +131,31 @@ public class Module_list extends HTTPDModule
responseObject.put("online", FUtil.getFakePlayerCount());
responseObject.put("max", server.getMaxPlayers());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString(4));
response.addHeader("Access-Control-Allow-Origin", "*");
return response;
}
else
} else
{
final StringBuilder body = new StringBuilder();
final Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
body.append("<p>There are ").append(FUtil.getFakePlayerCount()).append("/")
int count = onlinePlayers.size() - AdminList.vanished.size();
body.append("<p>There are ").append(count < 0 ? 0 : count).append("/")
.append(Bukkit.getMaxPlayers()).append(" players online:</p>\r\n");
body.append("<ul>\r\n");
onlinePlayers.stream().filter(player -> !plugin.al.isVanished(player.getUniqueId())).forEach(player ->
body.append("<li>").append(plugin.rm.getDisplay(player).getTag()).append(player.getName()).append("</li>\r\n"));
for (Player player : onlinePlayers)
{
if (plugin.al.isVanished(player.getName()))
{
continue;
}
String tag = plugin.rm.getDisplay(player).getTag();
body.append("<li>").append(tag).append(player.getName()).append("</li>\r\n");
}
body.append("</ul>\r\n");
@ -136,4 +173,5 @@ public class Module_list extends HTTPDModule
{
return "TotalFreedom - Online Players";
}
}

View File

@ -0,0 +1,29 @@
package me.totalfreedom.totalfreedommod.httpd.module;
import java.io.File;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD;
import me.totalfreedom.totalfreedommod.util.FLog;
public class Module_logs extends Module_file
{
public Module_logs(NanoHTTPD.HTTPSession session)
{
super(session);
}
@Override
public NanoHTTPD.Response getResponse()
{
if (ConfigEntry.LOGS_SECRET.getString().equals(params.get("password")) && !ConfigEntry.LOGS_SECRET.getString().isEmpty())
{
FLog.info(session.getSocket().getInetAddress() + " is downloading latest.log.");
return serveFile("latest.log", params, new File("./logs"));
}
else
{
return new NanoHTTPD.Response(NanoHTTPD.Response.Status.FORBIDDEN, NanoHTTPD.MIME_PLAINTEXT, "Incorrect password.");
}
}
}

View File

@ -1,59 +1,89 @@
package me.totalfreedom.totalfreedommod.httpd.module;
import com.google.gson.Gson;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.entity.HumanEntity;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Module_players extends HTTPDModule
{
private static final Gson gson = new Gson();
{
public Module_players(NanoHTTPD.HTTPSession session)
{
super(session);
}
@Override
@SuppressWarnings("unchecked")
public NanoHTTPD.Response getResponse()
{
final Map<String, List<String>> responseMap = new HashMap<>();
final JSONObject responseObject = new JSONObject();
final List<String> admins = new ArrayList<>();
final List<String> senioradmins = new ArrayList<>();
final JSONArray players = new JSONArray();
final JSONArray onlineadmins = new JSONArray(); // updated, never queried.
final JSONArray masterbuilders = new JSONArray();
final JSONArray admins = new JSONArray();
final JSONArray senioradmins = new JSONArray();
final JSONArray developers = new JSONArray();
final JSONArray executives = new JSONArray();
plugin.al.getActiveAdmins().stream().filter(admin -> admin.getName() != null).forEach(admin ->
// All online players
for (Player player : Bukkit.getOnlinePlayers())
{
switch (admin.getRank())
if (!plugin.al.isVanished(player.getName()))
{
case ADMIN -> admins.add(admin.getName());
case SENIOR_ADMIN -> senioradmins.add(admin.getName());
default ->
players.add(player.getName());
if (plugin.al.isAdmin(player))
{
// Do nothing, keeps Codacy quiet
onlineadmins.add(player.getName());
}
}
});
}
responseMap.put("players", server.getOnlinePlayers().stream().filter(player ->
!plugin.al.isVanished(player.getUniqueId())).map(HumanEntity::getName).toList());
responseMap.put("masterbuilders", plugin.pl.getMasterBuilderNames());
responseMap.put("admins", admins);
responseMap.put("senioradmins", senioradmins);
responseMap.put("developers", FUtil.DEVELOPER_NAMES);
responseMap.put("assistantexecutives", ConfigEntry.SERVER_ASSISTANT_EXECUTIVES.getStringList());
responseMap.put("executives", ConfigEntry.SERVER_EXECUTIVES.getStringList());
// Admins
for (Admin admin : plugin.al.getActiveAdmins())
{
final String username = admin.getName();
switch (admin.getRank())
{
case ADMIN:
{
admins.add(username);
break;
}
case SENIOR_ADMIN:
{
senioradmins.add(username);
break;
}
default:
{
// Do nothing
break;
}
}
}
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON,
gson.toJson(responseMap));
masterbuilders.addAll(plugin.pl.getMasterBuilderNames());
// Developers
developers.addAll(FUtil.DEVELOPER_NAMES);
// Executives
executives.addAll(ConfigEntry.SERVER_EXECUTIVES.getList());
responseObject.put("players", players);
responseObject.put("masterbuilders", masterbuilders);
responseObject.put("admins", admins);
responseObject.put("senioradmins", senioradmins);
responseObject.put("developers", developers);
responseObject.put("executives", executives);
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString());
response.addHeader("Access-Control-Allow-Origin", "*");
return response;
}

Some files were not shown because too many files have changed in this diff Show More