Compare commits

..

No commits in common. "main" and "2021.09-RC03" have entirely different histories.

142 changed files with 5913 additions and 2774 deletions

View File

@ -21,11 +21,11 @@ jobs:
steps:
# Checkout the repository to the GitHub Actions runner
- name: Checkout code
uses: actions/checkout@v3
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,18 +35,18 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v3
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
java-version: 11
distribution: 'adopt'
# 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@v2.1
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

21
.github/workflows/java11-maven.yml vendored Normal file
View File

@ -0,0 +1,21 @@
name: Java11-Maven-Build
on: [push]
jobs:
build-java-11:
runs-on: ubuntu-latest
steps:
# Checkout the code
- uses: actions/checkout@v1
# Java 11 Builds
- name: Set up JDK 11
uses: actions/setup-java@v2.3.0
with:
java-version: 11
distribution: 'adopt'
- name: Build with Maven
run: mvn -B package --file pom.xml

View File

@ -9,11 +9,11 @@ jobs:
steps:
# Checkout the code
- uses: actions/checkout@v3
- 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

@ -10,15 +10,15 @@ In terms of plugin releases, our support matrix is as follows:
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 |
| ------------------- | ------------------ | ------------------------------ |
| 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 |
| ------------------- | ------------------ | ------------ |
| 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>

102
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>me.totalfreedom</groupId>
<artifactId>TotalFreedomMod</artifactId>
<version>2022.06.1</version>
<version>2021.09-RC03</version>
<packaging>jar</packaging>
<properties>
@ -50,6 +50,11 @@
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<repository>
<id>nms-repo</id>
<url>https://repo.codemc.org/repository/nms/</url>
</repository>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
@ -65,6 +70,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 +96,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,7 +114,7 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.13.0</version>
<version>2.11.0</version>
<scope>compile</scope>
</dependency>
@ -110,16 +126,23 @@
</dependency>
<dependency>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>3.0.2</version>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>me.totalfreedom.scissors</groupId>
<artifactId>Scissors-API</artifactId>
<version>1.19.4-R0.1-SNAPSHOT</version>
<groupId>org.bstats</groupId>
<artifactId>bstats-bukkit</artifactId>
<version>2.2.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
@ -140,35 +163,35 @@
<dependency>
<groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId>
<version>7.2.15</version>
<version>7.2.4</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>19.5</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId>
<version>7.0.8</version>
<version>7.0.4</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>
@ -180,61 +203,61 @@
</dependency>
<dependency>
<groupId>net.essentialsx</groupId>
<groupId>net.ess3</groupId>
<artifactId>EssentialsX</artifactId>
<version>2.20.0</version>
<scope>provided</scope>
<version>2.18.2</version>
<scope>compile</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>compile</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>
</dependencies>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<build>
<!-- Filter resources for build.properties -->
<resources>
@ -249,12 +272,12 @@
<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>
<source>17</source>
<target>17</target>
<compilerVersion>11</compilerVersion>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
@ -303,7 +326,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 +356,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 +376,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 +401,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.4.1</version>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
@ -400,10 +423,15 @@
</relocations>
<artifactSet>
<includes>
<include>commons-io:commons-io</include>
<include>org.apache.commons:commons-lang3</include>
<include>commons-codec:commons-codec</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
if (ConfigEntry.FOURCHAN_ENABLED.getBoolean())
{
boolean green = ChatColor.stripColor(message).toLowerCase().startsWith(">");
boolean orange = ChatColor.stripColor(message).toLowerCase().endsWith("<");
if (ConfigEntry.FOURCHAN_ENABLED.getBoolean())
{
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

@ -3,10 +3,7 @@ package me.totalfreedom.totalfreedommod;
import io.papermc.lib.PaperLib;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData;
@ -61,13 +58,13 @@ public class LoginProcess extends FreedomService
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event)
{
final Admin entry = plugin.al.getEntryByUuid(event.getUniqueId());
final boolean isAdmin = entry != null && entry.isActive();
final String ip = event.getAddress().getHostAddress().trim();
final boolean isAdmin = plugin.al.getEntryByIp(ip) != null;
// Check if the player is already online
for (Player onlinePlayer : server.getOnlinePlayers())
{
if (!onlinePlayer.getUniqueId().equals(event.getUniqueId()))
if (!onlinePlayer.getName().equalsIgnoreCase(event.getName()))
{
continue;
}
@ -89,7 +86,7 @@ public class LoginProcess extends FreedomService
{
final Player player = event.getPlayer();
final String username = player.getName();
final UUID uuid = player.getUniqueId();
final String ip = event.getAddress().getHostAddress().trim();
// Check username length
if (username.length() < MIN_USERNAME_LENGTH || username.length() > MAX_USERNAME_LENGTH)
@ -123,8 +120,7 @@ public class LoginProcess extends FreedomService
}
// Validation below this point
final Admin entry = plugin.al.getEntryByUuid(uuid);
if (entry != null && entry.isActive()) // Check if player is admin
if (plugin.al.getEntryByIp(ip) != null) // Check if player is admin
{
// Force-allow log in
event.allow();
@ -179,11 +175,14 @@ public class LoginProcess extends FreedomService
}
// Whitelist
if (server.hasWhitelist() && !player.isWhitelisted())
if (plugin.si.isWhitelisted())
{
if (!plugin.si.getWhitelisted().contains(username.toLowerCase()))
{
event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "You are not whitelisted on this server.");
}
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event)
@ -222,7 +221,7 @@ public class LoginProcess extends FreedomService
return;
}
if (!playerData.getIps().contains(FUtil.getIp(player)))
if (!playerData.hasVerification() && !playerData.getIps().contains(FUtil.getIp(player)))
{
playerData.addIp(FUtil.getIp(player));
plugin.pl.save(playerData);

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 (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.");
}
}
if (isOutOfBounds(worldSpawn))
private Boolean exploitItem(ItemStack item)
{
event.setSpawnLocation(worldSpawn);
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 joptsimple.internal.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,98 @@
package me.totalfreedom.totalfreedommod;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.HashMap;
import java.util.Map;
import me.totalfreedom.totalfreedommod.util.FLog;
import static me.totalfreedom.totalfreedommod.util.FUtil.SAVED_FLAGS_FILENAME;
public class SavedFlags extends FreedomService
{
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
@SuppressWarnings("unchecked")
public Map<String, Boolean> getSavedFlags()
{
Map<String, Boolean> flags = null;
File input = new File(TotalFreedomMod.getPlugin().getDataFolder(), SAVED_FLAGS_FILENAME);
if (input.exists())
{
try
{
try (FileInputStream fis = new FileInputStream(input); ObjectInputStream ois = new ObjectInputStream(fis))
{
flags = (HashMap<String, Boolean>)ois.readObject();
}
}
catch (Exception ex)
{
FLog.severe(ex);
}
}
return flags;
}
public boolean getSavedFlag(String flag) throws Exception
{
Boolean flagValue = null;
Map<String, Boolean> flags = getSavedFlags();
if (flags != null)
{
if (flags.containsKey(flag))
{
flagValue = flags.get(flag);
}
}
if (flagValue != null)
{
return flagValue;
}
else
{
throw new Exception();
}
}
public void setSavedFlag(String flag, boolean value)
{
Map<String, Boolean> flags = getSavedFlags();
if (flags == null)
{
flags = new HashMap<>();
}
flags.put(flag, value);
try
{
final FileOutputStream fos = new FileOutputStream(new File(plugin.getDataFolder(), SAVED_FLAGS_FILENAME));
final ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(flags);
oos.close();
fos.close();
}
catch (Exception ex)
{
FLog.severe(ex);
}
}
}

View File

@ -0,0 +1,83 @@
package me.totalfreedom.totalfreedommod;
import java.util.Arrays;
import java.util.List;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.minecraft.server.v1_16_R3.EntityPlayer;
import net.minecraft.server.v1_16_R3.MinecraftServer;
import org.bukkit.Bukkit;
import org.bukkit.craftbukkit.v1_16_R3.CraftServer;
public class ServerInterface extends FreedomService
{
public static final String COMPILE_NMS_VERSION = "v1_16_R3";
public static void warnVersion()
{
final String nms = FUtil.getNMSVersion();
if (!COMPILE_NMS_VERSION.equals(nms))
{
FLog.warning(TotalFreedomMod.pluginName + " is compiled for " + COMPILE_NMS_VERSION + " but the server is running version " + nms + "!");
FLog.warning("This might result in unexpected behaviour!");
}
}
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
public void setOnlineMode(boolean mode)
{
getServer().setOnlineMode(mode);
}
public int purgeWhitelist()
{
String[] whitelisted = getServer().getPlayerList().getWhitelisted();
int size = whitelisted.length;
for (EntityPlayer player : getServer().getPlayerList().players)
{
getServer().getPlayerList().getWhitelist().remove(player.getProfile());
}
try
{
getServer().getPlayerList().getWhitelist().save();
}
catch (Exception ex)
{
FLog.warning("Could not purge the whitelist!");
FLog.warning(ex);
}
return size;
}
public boolean isWhitelisted()
{
return getServer().getPlayerList().getHasWhitelist();
}
public List<?> getWhitelisted()
{
return Arrays.asList(getServer().getPlayerList().getWhitelisted());
}
public String getVersion()
{
return getServer().getVersion();
}
private MinecraftServer getServer()
{
return ((CraftServer)Bukkit.getServer()).getServer();
}
}

View File

@ -1,6 +1,5 @@
package me.totalfreedom.totalfreedommod;
import com.google.gson.Gson;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit;
@ -8,13 +7,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.server.ServerListPingEvent;
import java.io.InputStreamReader;
public class ServerPing extends FreedomService
{
private final Gson gson = new Gson();
private final VersionMeta meta = gson.fromJson(new InputStreamReader(Bukkit.class.getClassLoader().getResourceAsStream("version.json")),VersionMeta.class);
@Override
public void onStart()
{
@ -60,7 +54,7 @@ public class ServerPing extends FreedomService
return;
}
String baseMotd = ConfigEntry.SERVER_MOTD.getString().replace("%mcversion%", meta.id);
String baseMotd = ConfigEntry.SERVER_MOTD.getString().replace("%mcversion%", plugin.si.getVersion());
baseMotd = baseMotd.replace("\\n", "\n");
baseMotd = FUtil.colorize(baseMotd);
@ -79,9 +73,4 @@ public class ServerPing extends FreedomService
event.setMotd(motd.toString().trim());
}
private static class VersionMeta
{
private String id;
}
}

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

@ -14,11 +14,13 @@ import me.totalfreedom.totalfreedommod.blocking.InteractBlocker;
import me.totalfreedom.totalfreedommod.blocking.MobBlocker;
import me.totalfreedom.totalfreedommod.blocking.PVPBlocker;
import me.totalfreedom.totalfreedommod.blocking.PotionBlocker;
import me.totalfreedom.totalfreedommod.blocking.SignBlocker;
import me.totalfreedom.totalfreedommod.blocking.command.CommandBlocker;
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;
@ -52,6 +54,7 @@ import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull;
import org.spigotmc.SpigotConfig;
public class TotalFreedomMod extends JavaPlugin
{
@ -71,7 +74,10 @@ public class TotalFreedomMod extends JavaPlugin
// Command Loader
public CommandLoader cl;
// Services
public ServerInterface si;
public SavedFlags sf;
public WorldManager wm;
public LogViewer lv;
public AdminList al;
public ActivityLog acl;
public RankManager rm;
@ -116,14 +122,18 @@ public class TotalFreedomMod extends JavaPlugin
public Trailer tr;
public HTTPDaemon hd;
public WorldRestrictions wr;
public SignBlocker snp;
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;
@ -167,6 +177,9 @@ public class TotalFreedomMod extends JavaPlugin
final MethodTimer timer = new MethodTimer();
timer.start();
// Warn if we're running on a wrong version
ServerInterface.warnVersion();
// Delete unused files
FUtil.deleteCoreDumps();
FUtil.deleteFolder(new File("./_deleteme"));
@ -174,6 +187,7 @@ public class TotalFreedomMod extends JavaPlugin
fsh = new FreedomServiceHandler();
config = new MainConfig();
config.load();
if (FUtil.inDeveloperMode())
{
@ -199,10 +213,13 @@ public class TotalFreedomMod extends JavaPlugin
FLog.info("Started " + fsh.getServiceAmount() + " services.");
timer.update();
FLog.info("Version " + pluginVersion + " enabled in " + timer.getTotal() + "ms");
FLog.info("Version " + pluginVersion + " for " + ServerInterface.COMPILE_NMS_VERSION + " enabled in " + timer.getTotal() + "ms");
// Metrics @ https://bstats.org/plugin/bukkit/TotalFreedomMod/2966
new Metrics(this, 2966);
// little workaround to stop spigot from autorestarting - causing AMP to detach from process.
SpigotConfig.config.set("settings.restart-on-crash", false);
}
@Override
@ -281,7 +298,10 @@ public class TotalFreedomMod extends JavaPlugin
private void initServices()
{
// Start services
si = new ServerInterface();
sf = new SavedFlags();
wm = new WorldManager();
lv = new LogViewer();
sql = new SQLite();
al = new AdminList();
acl = new ActivityLog();
@ -307,8 +327,11 @@ public class TotalFreedomMod extends JavaPlugin
im = new IndefiniteBanList();
pem = new PermissionManager();
gr = new GameRuleHandler();
snp = new SignBlocker();
ew = new EntityWiper();
st = new Sitter();
vh = new VanishHandler();
ptero = new Pterodactyl();
}
private void initAdminUtils()
@ -334,6 +357,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

@ -2,32 +2,37 @@ package me.totalfreedom.totalfreedommod.admin;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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
{
private final List<String> ips = new ArrayList<>();
private UUID uuid;
private String name;
private boolean active = true;
private Rank rank = Rank.ADMIN;
private Date lastLogin = new Date();
private Boolean commandSpy = false;
private Boolean potionSpy = false;
private String acFormat = null;
private String pteroID = null;
public Admin(Player player)
{
uuid = player.getUniqueId();
this.name = player.getName();
this.ips.add(FUtil.getIp(player));
}
@ -35,7 +40,7 @@ public class Admin
{
try
{
this.uuid = UUID.fromString(resultSet.getString("uuid"));
this.name = resultSet.getString("username");
this.active = resultSet.getBoolean("active");
this.rank = Rank.findRank(resultSet.getString("rank"));
this.ips.clear();
@ -44,6 +49,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 +62,14 @@ public class Admin
{
final StringBuilder output = new StringBuilder();
output.append("Admin: ").append(getName() != null ? getName() : getUuid().toString()).append("\n")
output.append("Admin: ").append(name).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();
}
@ -71,7 +78,7 @@ public class Admin
{
Map<String, Object> map = new HashMap<String, Object>()
{{
put("uuid", uuid.toString());
put("username", name);
put("active", active);
put("rank", rank.toString());
put("ips", FUtil.listToString(ips));
@ -79,6 +86,7 @@ public class Admin
put("command_spy", commandSpy);
put("potion_spy", potionSpy);
put("ac_format", acFormat);
put("ptero_id", pteroID);
}};
return map;
}
@ -112,20 +120,20 @@ public class Admin
public boolean isValid()
{
return uuid != null
return name != null
&& rank != null
&& !ips.isEmpty()
&& lastLogin != null;
}
public UUID getUuid()
{
return uuid;
}
public String getName()
{
return Bukkit.getOfflinePlayer(uuid).getName();
return name;
}
public void setName(String name)
{
this.name = name;
}
public boolean isActive()
@ -154,35 +162,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 +222,14 @@ public class Admin
{
this.acFormat = acFormat;
}
public String getPteroID()
{
return pteroID;
}
public void setPteroID(String pteroID)
{
this.pteroID = pteroID;
}
}

View File

@ -4,7 +4,11 @@ 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.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -17,14 +21,19 @@ 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<>();
public final Map<String, List<String>> verifiedNoAdmin = Maps.newHashMap();
private final Set<Admin> allAdmins = Sets.newHashSet(); // Includes disabled admins
// Only active admins below
private final Set<Admin> activeAdmins = Sets.newHashSet();
private final Map<UUID, Admin> uuidTable = Maps.newHashMap();
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,18 +52,12 @@ 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)
@ -63,7 +66,7 @@ public class AdminList extends FreedomService
}
updateTables();
FLog.info("Loaded " + allAdmins.size() + " admins (" + uuidTable.size() + " active, " + ipTable.size() + " IPs)");
FLog.info("Loaded " + allAdmins.size() + " admins (" + nameTable.size() + " active, " + ipTable.size() + " IPs)");
}
public void messageAllAdmins(String message)
@ -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))
@ -141,20 +154,40 @@ public class AdminList extends FreedomService
public Admin getAdmin(Player player)
{
final String ip = FUtil.getIp(player);
final Admin entry = getEntryByUuid(player.getUniqueId());
// Find admin
String ip = FUtil.getIp(player);
Admin admin = getEntryByName(player.getName());
if (entry != null && !entry.getIps().contains(ip))
// Admin by name
if (admin != null)
{
entry.addIp(ip);
// Check if we're in online mode,
// Or the players IP is in the admin entry
if (Bukkit.getOnlineMode() || admin.getIps().contains(ip))
{
if (!admin.getIps().contains(ip))
{
// Add the new IP if we have to
admin.addIp(ip);
save(admin);
updateTables();
}
return admin;
}
}
return entry;
// Admin by ip
admin = getEntryByIp(ip);
if (admin != null)
{
// Set the new username
String oldName = admin.getName();
admin.setName(player.getName());
plugin.sql.updateAdminName(oldName, admin.getName());
updateTables();
}
public Admin getEntryByUuid(UUID uuid)
{
return uuidTable.get(uuid);
return null;
}
public Admin getEntryByName(String name)
@ -167,6 +200,25 @@ public class AdminList extends FreedomService
return ipTable.get(ip);
}
public Admin getEntryByIpFuzzy(String needleIp)
{
final Admin directAdmin = getEntryByIp(needleIp);
if (directAdmin != null)
{
return directAdmin;
}
for (String ip : ipTable.keySet())
{
if (FUtil.fuzzyIpMatch(needleIp, ip, 3))
{
return ipTable.get(ip);
}
}
return null;
}
public void updateLastLogin(Player player)
{
final Admin admin = getAdmin(player);
@ -176,9 +228,31 @@ public class AdminList extends FreedomService
}
admin.setLastLogin(new Date());
admin.setName(player.getName());
save(admin);
}
public boolean isAdminImpostor(Player player)
{
return getEntryByName(player.getName()) != null && !isAdmin(player) && !isVerifiedAdmin(player);
}
public boolean isVerifiedAdmin(Player player)
{
return verifiedNoAdmin.containsKey(player.getName()) && verifiedNoAdmin.get(player.getName()).contains(FUtil.getIp(player));
}
public boolean isIdentityMatched(Player player)
{
if (Bukkit.getOnlineMode())
{
return true;
}
Admin admin = getAdmin(player);
return admin != null && admin.getName().equalsIgnoreCase(player.getName());
}
public boolean addAdmin(Admin admin)
{
if (!admin.isValid())
@ -194,15 +268,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;
}
@ -232,7 +297,6 @@ public class AdminList extends FreedomService
public void updateTables()
{
activeAdmins.clear();
uuidTable.clear();
nameTable.clear();
ipTable.clear();
@ -244,16 +308,13 @@ public class AdminList extends FreedomService
}
activeAdmins.add(admin);
uuidTable.put(admin.getUuid(), admin);
if (admin.getName() != null)
{
nameTable.put(admin.getName().toLowerCase(), admin);
}
for (String ip : admin.getIps())
{
ipTable.put(ip, admin);
}
}
}
@ -271,7 +332,7 @@ public class AdminList extends FreedomService
{
try
{
ResultSet currentSave = plugin.sql.getAdminByUuid(admin.getUuid());
ResultSet currentSave = plugin.sql.getAdminByName(admin.getName());
for (Map.Entry<String, Object> entry : admin.toSQLStorable().entrySet())
{
Object storedValue = plugin.sql.getValue(currentSave, entry.getKey(), entry.getValue());
@ -316,9 +377,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()
@ -340,4 +401,9 @@ public class AdminList extends FreedomService
{
return ipTable;
}
public Map<String, List<String>> getVerifiedNoAdmin()
{
return verifiedNoAdmin;
}
}

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,8 +4,6 @@ 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;
import me.totalfreedom.totalfreedommod.util.FUtil;
@ -20,7 +18,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 +115,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,17 +146,20 @@ 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)
{
if (((Tameable)entity).isTamed())
{
event.setCancelled(true);
}
}
}
}
@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);
}
@ -278,10 +265,4 @@ public class EventBlocker extends FreedomService
FUtil.fixCommandVoid(event.getEntity());
event.setDeathMessage(event.getDeathMessage());
}
@EventHandler
public void onSignInteract(PlayerSignCommandPreprocessEvent event)
{
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)
{
if (event.getClickedBlock().getType().equals(Material.STRUCTURE_BLOCK) || event.getClickedBlock().getType().equals(Material.JIGSAW) || event.getClickedBlock().getType().equals(Material.RESPAWN_ANCHOR))
{
event.setCancelled(true);
return;
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

@ -0,0 +1,67 @@
package me.totalfreedom.totalfreedommod.blocking;
import me.totalfreedom.totalfreedommod.FreedomService;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import org.bukkit.ChatColor;
import org.bukkit.Tag;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
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.block.BlockPlaceEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;
//codebeat:disable[LOC,ABC]
public class SignBlocker extends FreedomService
{
@Override
public void onStart()
{
}
@Override
public void onStop()
{
}
@EventHandler(priority = EventPriority.NORMAL)
public void onPlayerPlaceBlock(BlockPlaceEvent event)
{
final Player player = event.getPlayer();
if (Tag.SIGNS.getValues().contains(event.getBlock().getType()))
{
ItemStack sign = event.getItemInHand();
net.minecraft.server.v1_16_R3.ItemStack nmsSign = CraftItemStack.asNMSCopy(sign);
NBTTagCompound compound = (nmsSign.hasTag()) ? nmsSign.getTag() : new NBTTagCompound();
assert compound != null;
NBTTagCompound bet = compound.getCompound("BlockEntityTag");
String line1 = bet.getString("Text1");
String line2 = bet.getString("Text2");
String line3 = bet.getString("Text3");
String line4 = bet.getString("Text4");
if (line1.contains("run_command") || line2.contains("run_command") || line3.contains("run_command") || line4.contains("run_command"))
{
player.sendMessage(ChatColor.GRAY + "You are not allowed to place command signs.");
event.setCancelled(true);
}
}
}
@EventHandler(priority = EventPriority.LOWEST)
public void onPlayerInteractSign(PlayerInteractEvent event)
{
if (event.getAction() != Action.RIGHT_CLICK_BLOCK)
{
return;
}
if (event.getClickedBlock() != null && Tag.SIGNS.getValues().contains(event.getClickedBlock().getType()))
{
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,10 +203,13 @@ public class CommandBlocker extends FreedomService
}
// Validate sub command
if (entry.getSubCommand() != null && (subCommand == null || !subCommand.startsWith(entry.getSubCommand())))
if (entry.getSubCommand() != null)
{
if (subCommand == null || !subCommand.startsWith(entry.getSubCommand()))
{
return false;
}
}
if (entry.getRank().hasPermission(sender))
{

View File

@ -2,10 +2,10 @@ package me.totalfreedom.totalfreedommod.blocking.command;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.spigotmc.SpigotConfig;
public class CommandBlockerEntry
{
@ -45,7 +45,7 @@ public class CommandBlockerEntry
}
if (action == CommandBlockerAction.BLOCK_UNKNOWN)
{
sender.sendMessage(Bukkit.spigot().getSpigotConfig().getString("messages.unknown-command"));
sender.sendMessage(SpigotConfig.unknownCommandMessage);
return;
}
FUtil.playerMsg(sender, FUtil.colorize(message));

View File

@ -42,7 +42,7 @@ public class BukkitTelnetBridge extends FreedomService
return;
}
final Admin admin = plugin.al.getEntryByIp(ip);
final Admin admin = plugin.al.getEntryByIpFuzzy(ip);
if (admin == null || !admin.isActive() || !admin.getRank().hasConsoleVariant())
{
@ -90,12 +90,9 @@ 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()));
}
}
}
public BukkitTelnet getBukkitTelnetPlugin()
{
@ -104,11 +101,14 @@ public class BukkitTelnetBridge extends FreedomService
try
{
final Plugin bukkitTelnet = server.getPluginManager().getPlugin("BukkitTelnet");
if (bukkitTelnet != null)
{
if (bukkitTelnet instanceof BukkitTelnet)
{
bukkitTelnetPlugin = (BukkitTelnet)bukkitTelnet;
}
}
}
catch (Exception ex)
{
FLog.severe(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,271 @@ public class CoreProtectBridge extends FreedomService
}.runTaskAsynchronously(plugin);
}
public boolean hasHistory(Player player)
public File getDatabase()
{
return historyMap.containsKey(player.getUniqueId());
if (!isEnabled())
{
return null;
}
public FUtil.PaginationList<CoreProtectAPI.ParseResult> getHistoryForPlayer(Player player)
{
return historyMap.get(player.getUniqueId());
return (new File(getCoreProtect().getDataFolder(), "database.db"));
}
public void showPageToPlayer(Player player, FUtil.PaginationList<CoreProtectAPI.ParseResult> results, int pageNum)
public double getDBSize()
{
if (player == null || !player.isOnline())
double bytes = getDatabase().length();
double kilobytes = (bytes / 1024);
double megabytes = (kilobytes / 1024);
return (megabytes / 1024);
}
// Wipes DB for the specified world
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;
}
List<CoreProtectAPI.ParseResult> page = results.getPage(pageNum);
/* 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
{
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 (page == null || page.isEmpty())
// 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("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);
worldID = String.valueOf(resultSet.getInt("id"));
}
player.sendMessage(line.append(Component.text(".", NamedTextColor.WHITE)).build());
});
// Ensure the world ID is not null
if (results.getPageCount() > 1)
if (worldID == null)
{
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))));
FLog.warning("Failed to obtain the world ID for the " + world.getName());
return;
}
// Page <current>/<total>
indicator.append(Component.text("Page ", TextColor.color(0x30ade4)).append(Component.text(pageNum + "/"
+ results.getPageCount(), NamedTextColor.WHITE)));
// ->
if (pageNum < results.getPageCount())
// Iterate through each table and delete their data if the world ID matches
for (String table : tables)
{
indicator.append(Component.text("", NamedTextColor.WHITE).clickEvent(
ClickEvent.runCommand("/ins history " + (pageNum + 1))));
final PreparedStatement statement1 = connection.prepareStatement("DELETE FROM ? WHERE wid = ?");
statement1.setString(1, table);
statement1.setString(2, worldID);
statement1.executeQuery();
}
// | 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))));
connection.close();
player.sendMessage(indicator.build());
}
}
}
public CompletableFuture<FUtil.PaginationList<CoreProtectAPI.ParseResult>> lookupForPlayer(Block block, Player player)
catch (SQLException e)
{
cooldownMap.put(player.getUniqueId(), System.currentTimeMillis());
CoreProtectAPI api = getCoreProtectAPI();
FLog.warning("Failed to delete the CoreProtect data for the " + world.getName());
}
return CompletableFuture.supplyAsync(() ->
// This exits for flatlands wipes
if (shutdown)
{
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;
});
server.shutdown();
}
}
@EventHandler(priority = EventPriority.MONITOR)
public void onInteract(PlayerInteractEvent event)
public void onPlayerInteract(PlayerInteractEvent event)
{
// The inspector only works if we have CoreProtect installed
if (!isEnabled())
{
return;
}
Player player = event.getPlayer();
PlayerData data = plugin.pl.getData(player);
Block block = event.getClickedBlock();
final CoreProtectAPI coreProtect = getCoreProtectAPI();
if ((event.getAction() == Action.RIGHT_CLICK_BLOCK || event.getAction() == Action.LEFT_CLICK_BLOCK)
&& plugin.pl.getData(player.getUniqueId()).hasInspection())
// 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)
{
event.setCancelled(true);
Block block = event.getClickedBlock();
Optional<Long> cooldown = Optional.ofNullable(cooldownMap.get(player.getUniqueId()));
player.sendMessage(ChatColor.RED + String.valueOf(secondsLeft) + " seconds left before next query.");
return;
}
}
if (cooldown.isPresent() && getSecondsLeft(cooldown.get(), 3) > 0L)
// Actual lookup time
if (event.getAction() == Action.LEFT_CLICK_BLOCK)
{
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)));
if (block != null)
{
event.setCancelled(true);
List<String[]> 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;
}
// Time to do a look-up.
if (block != null)
{
/* 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();
}
HISTORY_MAP.remove(event.getPlayer());
HISTORY_MAP.put(event.getPlayer(), new FUtil.PaginationList<>(10));
FUtil.PaginationList<String> paged = HISTORY_MAP.get(event.getPlayer());
lookupForPlayer(block, player).thenAccept(results ->
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)
{
if (results.isEmpty())
CoreProtectAPI.ParseResult result = coreProtect.parseResult(value);
BlockData bl = result.getBlockData();
String s;
String st = "";
if (result.getActionString().equals("Placement"))
{
player.sendMessage(prefix.append(Component.text("No results were found.").color(NamedTextColor.WHITE)));
s = " placed ";
}
else if (result.getActionString().equals("Removal"))
{
s = " broke ";
}
else
{
showPageToPlayer(player, results, 1);
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;
@ -112,7 +114,8 @@ public class EssentialsBridge extends FreedomService
User user = getEssentialsUser(username);
if (user != null)
{
return user.getLastOnlineActivity();
Long l = FUtil.getField(user, "lastActivity");
return (l != null) ? l : 0L;
}
}
catch (Exception ex)
@ -127,7 +130,7 @@ public class EssentialsBridge extends FreedomService
try
{
User user = getEssentialsUser(username);
if (user != null && user.getBase().isOnline())
if (user != null)
{
user.setVanished(vanished);
}
@ -202,6 +205,13 @@ 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();

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

@ -48,6 +48,52 @@ public class WorldEditBridge extends FreedomService
return worldeditPlugin;
}
public void undo(Player player, int count)
{
try
{
LocalSession session = getPlayerSession(player);
if (session != null)
{
final BukkitPlayer bukkitPlayer = getBukkitPlayer(player);
if (bukkitPlayer != null)
{
for (int i = 0; i < count; i++)
{
session.undo(session.getBlockBag(bukkitPlayer), bukkitPlayer);
}
}
}
}
catch (Exception ex)
{
FLog.severe(ex);
}
}
public void redo(Player player, int count)
{
try
{
LocalSession session = getPlayerSession(player);
if (session != null)
{
final BukkitPlayer bukkitPlayer = getBukkitPlayer(player);
if (bukkitPlayer != null)
{
for (int i = 0; i < count; i++)
{
session.redo(session.getBlockBag(bukkitPlayer), bukkitPlayer);
}
}
}
}
catch (Exception ex)
{
FLog.severe(ex);
}
}
public void setLimit(Player player, int limit)
{
try
@ -107,4 +153,23 @@ public class WorldEditBridge extends FreedomService
return null;
}
}
private BukkitPlayer getBukkitPlayer(Player player)
{
final WorldEditPlugin wep = getWorldEditPlugin();
if (wep == null)
{
return null;
}
try
{
return wep.wrapPlayer(player);
}
catch (Exception ex)
{
FLog.severe(ex);
return null;
}
}
}

View File

@ -1,13 +1,13 @@
package me.totalfreedom.totalfreedommod.bridge;
import com.sk89q.worldguard.LocalPlayer;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldguard.WorldGuard;
import com.sk89q.worldguard.bukkit.WorldGuardPlugin;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import com.sk89q.worldguard.protection.regions.RegionContainer;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import java.util.Map;
import me.totalfreedom.totalfreedommod.FreedomService;
import org.bukkit.entity.Player;
import org.bukkit.World;
import org.bukkit.plugin.Plugin;
public class WorldGuardBridge extends FreedomService
@ -15,6 +15,7 @@ public class WorldGuardBridge extends FreedomService
@Override
public void onStart()
{
plugin.wr.protectWorld(plugin.wm.masterBuilderWorld.getWorld());
}
@Override
@ -22,21 +23,26 @@ public class WorldGuardBridge extends FreedomService
{
}
public boolean canEditCurrentWorld(Player player)
public RegionManager getRegionManager(World world)
{
// If WorldGuard integration is enabled, do a check with it.
if (isEnabled())
{
LocalPlayer localPlayer = WorldGuardPlugin.inst().wrapPlayer(player);
RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery();
return query.testBuild(localPlayer.getLocation(), localPlayer);
return container.get(BukkitAdapter.adapt(world));
}
// If the plugin isn't present, return true.
return true;
public int wipeRegions(World world)
{
int count = 0;
RegionManager regionManager = getRegionManager(world);
if (regionManager != null)
{
Map<String, ProtectedRegion> regions = regionManager.getRegions();
for (ProtectedRegion region : regions.values())
{
regionManager.removeRegion(region.getId());
count++;
}
}
return count;
}
public boolean isEnabled()

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)
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()));
return false;
}
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 ->
if (args[0].equals("list"))
{
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" ->
msg("The following have block modification abilities restricted:");
int count = 0;
for (Player player : server.getOnlinePlayers())
{
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 ->
final FPlayer info = plugin.pl.getPlayer(player);
if (info.isEditBlocked())
{
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.getName());
++count;
}
}
}, () -> msg(PLAYER_NOT_FOUND));
if (count == 0)
{
msg("- none");
}
return true;
}
else
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())
{
if (!plugin.al.isAdmin(player))
{
for (int i = 0; i < 100; i++)
{
msg(player, "");
}
});
}
}
FUtil.adminAction(sender.getName(), "Cleared chat", true);
return true;
}

View File

@ -9,11 +9,8 @@ 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.OP, source = SourceType.BOTH)
@CommandParameters(description = "Shows the amount of coins you or another player has. Also allows you to give coins to other players.", usage = "/<command> [player] | pay <player> <amount>")
@CommandParameters(description = "Shows the amount of coins you have or another player has", usage = "/<command> [playername]")
public class Command_coins extends FreedomCommand
{
@Override
@ -24,122 +21,34 @@ public class Command_coins extends FreedomCommand
msg("The shop is currently disabled!", ChatColor.RED);
return true;
}
Player p;
final String prefix = FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " ");
switch (args.length)
if (args.length > 0)
{
// Mode for seeing how many coins the sender has (doesn't work from console)
case 0:
if (getPlayer(args[0]) != null)
{
p = getPlayer(args[0]);
}
else
{
msg(PLAYER_NOT_FOUND);
return true;
}
}
else
{
if (senderIsConsole)
{
msg("When used from the console, you must define a target player.");
msg(prefix + ChatColor.RED + "You are not a player, use /coins <playername>");
return true;
}
else
{
PlayerData playerData = getData(playerSender);
msg(prefix + ChatColor.GREEN + "You have " + ChatColor.RED + playerData.getCoins() + ChatColor.GREEN
+ " coins.");
p = playerSender;
}
}
PlayerData playerData = plugin.pl.getData(p);
msg(prefix + ChatColor.GREEN + (args.length > 0 ? p.getName() + " has " : "You have ") + ChatColor.RED + playerData.getCoins() + ChatColor.GREEN + " coins.");
return true;
}
// Mode for seeing how many coins a player has.
case 1:
{
Player target = getPlayer(args[0]);
if (target == null)
{
msg(PLAYER_NOT_FOUND);
}
else
{
PlayerData playerData = getData(target);
msg(prefix + ChatColor.GREEN + target.getName() + " has " + ChatColor.RED + playerData.getCoins() + ChatColor.GREEN + " coins.");
}
return true;
}
// Mode for paying another player coins
case 3:
{
if (args[0].equalsIgnoreCase("pay"))
{
checkPlayer();
final Player target = getPlayer(args[1]);
final PlayerData senderData = getData(playerSender);
int coinsToTransfer;
// Processes args[2]
try
{
// Prevents players from trying to be cheeky with negative numbers.
coinsToTransfer = Math.max(Math.abs(Integer.parseInt(args[2])), 1);
}
catch (NumberFormatException ex)
{
msg("Invalid number: " + args[2], ChatColor.RED);
return true;
}
// Prevents players from performing transactions they can't afford to do.
if (senderData.getCoins() < coinsToTransfer)
{
msg("You don't have enough coins to perform this transaction.", ChatColor.RED);
return true;
}
if (target == null)
{
msg(PLAYER_NOT_FOUND);
}
else
{
PlayerData playerData = getData(target);
playerData.setCoins(playerData.getCoins() + coinsToTransfer);
senderData.setCoins(senderData.getCoins() - coinsToTransfer);
msg(target, sender.getName()
+ ChatColor.GREEN + " has given you "
+ ChatColor.GOLD + coinsToTransfer
+ ChatColor.GREEN + " coin" + (coinsToTransfer > 1 ? "s" : "") + "!", ChatColor.GOLD);
msg("You have given "
+ 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;
}
}
default:
{
return false;
}
}
}
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1)
{
List<String> options = new ArrayList<>(FUtil.getPlayerList());
options.add("pay");
return options;
}
return FUtil.getPlayerList();
}
}

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,9 +32,10 @@ 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))
{
if (player.isOp() && !plugin.al.isVanished(player.getName()))
{
matchedPlayerNames.add(player.getName());
player.setOp(false);
@ -42,6 +43,7 @@ public class Command_deop extends FreedomCommand
plugin.rm.updateDisplay(player);
}
}
}
if (!matchedPlayerNames.isEmpty())
{

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
{
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,14 +251,16 @@ public class Command_enchant extends FreedomCommand
return getEnchantments(item);
}
}
else if (args.length == 3 && args[0].equals("add"))
else if (args.length == 3)
{
if (args[0].equals("add"))
{
Enchantment enchantment = Enchantment.getByName(args[1].toUpperCase());
if (enchantment != null)
{
if (!unsafe)
{
return IntStream.rangeClosed(1, enchantment.getMaxLevel()).mapToObj(String::valueOf).toList();
return stringNumberRange(1, enchantment.getMaxLevel());
}
else
{
@ -249,6 +268,7 @@ public class Command_enchant extends FreedomCommand
}
}
}
}
return Collections.emptyList();
}

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);
msg("Invalid number", 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;
}
msg("---- " + net.md_5.bungee.api.ChatColor.of("#30ade4") + "Block Inspector" + ChatColor.WHITE + " ---- ", ChatColor.WHITE);
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;
}
}
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));
return true;
}
else
{
return false;
}
}
@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();
}
}
}

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

@ -18,7 +18,7 @@ public class Command_linkdiscord extends FreedomCommand
{
if (!plugin.dc.enabled)
{
msg("The Discord integration system is currently disabled.", ChatColor.RED);
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
@ -32,7 +32,7 @@ public class Command_linkdiscord extends FreedomCommand
}
playerData.setDiscordID(args[1]);
msg("Linked " + args[0] + "'s Discord account.", ChatColor.GREEN);
msg("Linked " + args[0] + "'s discord account.", ChatColor.GREEN);
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,68 @@ 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")
@CommandPermissions(level = Rank.IMPOSTOR, source = SourceType.BOTH)
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command> [-s | -i | -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 "-i":
{
listFilter = ListFilter.IMPOSTORS;
break;
}
case "-f":
{
listFilter = ListFilter.FAMOUS_PLAYERS;
break;
}
default:
{
return false;
}
@ -49,42 +83,78 @@ 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.";
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();
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.IMPOSTORS && !plugin.al.isAdminImpostor(p))
{
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;
}
String onlineUsers = "Connected " + listFilter.name().toLowerCase().replace('_', ' ') + ": " + ChatColor.WHITE +
StringUtils.join(players, ChatColor.WHITE + ", " + ChatColor.WHITE);
final Displayable display = plugin.rm.getDisplay(p);
n.add(display.getColoredTag() + p.getName());
}
}
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 +163,8 @@ public class Command_list extends FreedomCommand
PLAYERS,
ADMINS,
VANISHED_ADMINS,
TELNET_SESSIONS
TELNET_SESSIONS,
FAMOUS_PLAYERS,
IMPOSTORS
}
}

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

@ -0,0 +1,63 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
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.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Manually verify someone", usage = "/<command> <playername>", aliases = "mv")
public class Command_manuallyverify extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
boolean verificationEnabled = ConfigEntry.DISCORD_VERIFICATION.getBoolean();
if (!plugin.dc.enabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
if (!verificationEnabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
if (args.length == 0)
{
return false;
}
final Player player = getPlayer(args[0]);
if (player == null)
{
msg(FreedomCommand.PLAYER_NOT_FOUND);
return true;
}
if (!plugin.pl.IsImpostor(player))
{
msg("That player is not an impostor.");
return true;
}
FUtil.adminAction(sender.getName(), "Manually verifying player " + player.getName(), false);
player.setOp(true);
msg(player, YOU_ARE_OP);
if (plugin.pl.getPlayer(player).getFreezeData().isFrozen())
{
plugin.pl.getPlayer(player).getFreezeData().setFrozen(false);
msg(player, "You have been unfrozen.");
}
plugin.pl.verify(player, null);
plugin.rm.updateDisplay(player);
return true;
}
}

View File

@ -116,22 +116,40 @@ public class Command_mbconfig extends FreedomCommand
return true;
}
if (!data.isMasterBuilder())
if (data.isMasterBuilder() && plugin.pl.isPlayerImpostor(player))
{
FUtil.adminAction(sender.getName(), "Re-adding " + data.getName() + " to the Master Builder list", true);
if (plugin.pl.getPlayer(player).getFreezeData().isFrozen())
{
plugin.pl.getPlayer(player).getFreezeData().setFrozen(false);
}
if (player != null)
{
plugin.pl.verify(player, null);
plugin.rm.updateDisplay(player);
player.setOp(true);
msg(player, YOU_ARE_OP);
}
}
else if (!data.isMasterBuilder())
{
FUtil.adminAction(sender.getName(), "Adding " + data.getName() + " to the Master Builder list", true);
data.setMasterBuilder(true);
data.setVerification(true);
plugin.pl.save(data);
if (player != null)
{
plugin.rm.updateDisplay(player);
}
return true;
}
else
{
msg("That player is already on the Master Builder list.");
}
return true;
}
}
case "remove":
{
if (args.length < 2)
@ -155,6 +173,10 @@ public class Command_mbconfig extends FreedomCommand
FUtil.adminAction(sender.getName(), "Removing " + data.getName() + " from the Master Builder list", true);
data.setMasterBuilder(false);
if (data.getDiscordID() == null)
{
data.setVerification(false);
}
plugin.pl.save(data);
if (player != null)
{

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)
{
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

@ -0,0 +1,266 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import java.util.SplittableRandom;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import net.minecraft.server.v1_16_R3.NBTTagList;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Material;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import org.bukkit.inventory.meta.PotionMeta;
import org.bukkit.potion.PotionEffectType;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Modify the current item you are holding.", usage = "/<command> <name <message> | lore <message> | enchant <enchantment> <level> | potion <effect> <duration> <amplifier> | attribute <name> <amount> | clear>", aliases = "mi")
public class Command_modifyitem extends FreedomCommand
{
@SuppressWarnings("deprecation")
@Override
public boolean run(final CommandSender sender, final Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length < 1)
{
return false;
}
ItemStack item = playerSender.getInventory().getItemInMainHand();
if (item.getType().equals(Material.AIR))
{
msg("You must have an item in your hand!");
return true;
}
if (args[0].equalsIgnoreCase("clear"))
{
item.setItemMeta(null);
playerSender.getInventory().setItemInMainHand(item);
return true;
}
if (args.length < 2)
{
return false;
}
ItemMeta meta = item.getItemMeta();
assert meta != null;
switch (args[0])
{
case "name":
String name = FUtil.colorize(StringUtils.join(args, " ", 1, args.length));
meta.setDisplayName(name);
item.setItemMeta(meta);
break;
case "lore":
List<String> lore = new ArrayList<>();
for (String line : StringUtils.join(args, " ", 1, args.length).split("\\\\n"))
{
lore.add(FUtil.colorize(line));
}
meta.setLore(lore);
item.setItemMeta(meta);
break;
case "enchant":
if (args.length < 3)
{
return false;
}
Enchantment enchantment = Enchantment.getByName(args[1].toUpperCase());
if (enchantment == null)
{
msg("Invalid enchantment. Please run /enchant list for a list of valid enchantments.");
return true;
}
int level;
try
{
level = Integer.parseInt(args[2]);
}
catch (NumberFormatException ex)
{
msg("The level specified is not a valid integer.");
return true;
}
meta.addEnchant(enchantment, level, true);
item.setItemMeta(meta);
break;
case "potion":
{
if (!item.getType().equals(Material.POTION) & !item.getType().equals(Material.SPLASH_POTION) & !item.getType().equals(Material.LINGERING_POTION) & !item.getType().equals(Material.TIPPED_ARROW))
{
msg("This item can not have potion effects added to it.");
return true;
}
if (args.length < 4)
{
return false;
}
PotionEffectType type = PotionEffectType.getByName(args[1]);
if (type == null)
{
msg("Invalid potion effect. Please run /potion list for a list of valid potion effects.");
return true;
}
int duration;
try
{
duration = Math.max(1, Math.min(1000000, Integer.parseInt(args[2])));
}
catch (NumberFormatException ex)
{
msg("The duration specified is not a valid integer.");
return true;
}
int amplifier;
try
{
amplifier = Math.max(1, Math.min(256, Integer.parseInt(args[2])));
}
catch (NumberFormatException ex)
{
msg("The amplifier specified is not a valid integer.");
return true;
}
PotionMeta potionMeta = (PotionMeta)meta;
potionMeta.addCustomEffect(type.createEffect(duration, amplifier), true);
item.setItemMeta(potionMeta);
break;
}
case "attribute":
if (args.length < 3)
{
return false;
}
net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
NBTTagCompound compound = (nmsStack.hasTag()) ? nmsStack.getTag() : new NBTTagCompound();
NBTTagList modifiers = getAttributeList(nmsStack);
NBTTagCompound cmpnd = new NBTTagCompound();
Attribute attribute = Attribute.getByName(args[1].toUpperCase());
if (attribute == null)
{
msg("Invalid attribute. Please run /attributelist for a list of valid attributes.");
return true;
}
cmpnd.setString("AttributeName", attribute.getAttribute());
cmpnd.setString("Name", attribute.getAttribute());
double amount;
try
{
amount = Double.parseDouble(args[2]);
}
catch (NumberFormatException ex)
{
msg("The amount specified is not a valid integer.");
return true;
}
if (Double.isNaN(amount))
{
msg("The amount specified is illegal.");
return true;
}
cmpnd.setDouble("Amount", amount);
cmpnd.setInt("Operation", 0);
SplittableRandom random = new SplittableRandom();
cmpnd.setIntArray("UUID", new int[]
{
random.nextInt(),
random.nextInt(),
random.nextInt(),
random.nextInt()
});
cmpnd.setString("Slot", "mainhand");
modifiers.add(cmpnd);
assert compound != null;
compound.set("AttributeModifiers", modifiers);
nmsStack.setTag(compound);
item = CraftItemStack.asBukkitCopy(nmsStack);
break;
default:
return false;
}
playerSender.getInventory().setItemInMainHand(item);
return true;
}
private NBTTagList getAttributeList(net.minecraft.server.v1_16_R3.ItemStack stack)
{
if (stack.getTag() == null)
{
stack.setTag(new NBTTagCompound());
}
NBTTagList attr = stack.getTag().getList("AttributeModifiers", 10);
if (attr == null)
{
stack.getTag().set("AttributeModifiers", new NBTTagList());
}
return stack.getTag().getList("AttributeModifiers", 10);
}
private enum Attribute
{
GENERIC_MAX_HEALTH("GENERIC_MAX_HEALTH", "generic.max_health"),
GENERIC_FOLLOW_RANGE("GENERIC_FOLLOW_RANGE", "generic.follow_range"),
GENERIC_KNOCKBACK_RESISTANCE("GENERIC_KNOCKBACK_RESISTANCE", "generic.knockback_resistance"),
GENERIC_MOVEMENT_SPEED("GENERIC_MOVEMENT_SPEED", "generic.movement_speed"),
GENERIC_FLYING_SPEED("GENERIC_FLYING_SPEED", "generic.flying_speed"),
GENERIC_ATTACK_DAMAGE("GENERIC_ATTACK_DAMAGE", "generic.attack_damage"),
GENERIC_ATTACK_SPEED("GENERIC_ATTACK_SPEED", "generic.attack_speed"),
GENERIC_ARMOR("GENERIC_ARMOR", "generic.armor"),
GENERIC_ARMOR_TOUGHNESS("GENERIC_ARMOR_TOUGHNESS", "generic.armor_toughmess"),
GENERIC_LUCK("GENERIC_LUCK", "generic.luck"),
HORSE_JUMP_STRENGTH("GENERIC_MAX_HEALTH", "horse.jump_strength"),
ZOMBIE_SPAWN_REINFORCEMENTS("ZOMBIE_SPAWN_REINFORCEMENTS", "zombie.spawn_reinforcements");
private final String name;
private final String attribute;
Attribute(String name, String attribute)
{
this.name = name;
this.attribute = attribute;
}
public static Attribute getByName(String name)
{
for (Attribute attr : Attribute.values())
{
if (attr.toString().toUpperCase().equals(name))
{
return attr;
}
}
return null;
}
public String getAttribute()
{
return attribute;
}
@Override
public String toString()
{
return name;
}
}
}

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,132 @@ public class Command_mute extends FreedomCommand
return false;
}
switch (args[0].toLowerCase())
{
case "list" ->
if (args[0].equalsIgnoreCase("list"))
{
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
FPlayer info;
int count = 0;
for (Player mp : server.getOnlinePlayers())
{
info = plugin.pl.getPlayer(mp);
if (info.isMuted())
{
msg("- " + mp.getName());
count++;
}
}
if (count == 0)
{
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 ->
{
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" : "") + ".");
return true;
}
case "all" ->
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);
List<? extends Player> list = server.getOnlinePlayers().stream().filter(player ->
!plugin.al.isAdmin(player)).toList();
list.forEach(player ->
FPlayer playerdata;
int counter = 0;
for (Player player : server.getOnlinePlayers())
{
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" : "") + ".");
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++;
}
}
default ->
{
boolean quiet = args[0].equalsIgnoreCase("-q");
boolean smite = args[0].equalsIgnoreCase("-s");
// Handling the -q parameter
if (quiet || smite)
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)
{
if (args.length == 1) return false;
args = ArrayUtils.subarray(args, 1, args.length);
if (args.length < 1)
{
return false;
}
}
// Handling the (optional) reason
String reason = args.length > 1 ? StringUtils.join(args, " ", 1, args.length) : null;
// Showtime
Optional.ofNullable(getPlayer(args[0])).ifPresentOrElse(player ->
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 as such can't be muted.", ChatColor.RED);
return;
msg(player.getName() + " is an admin, and can't be muted.");
return true;
}
else if (plugin.pl.getPlayer(player).isMuted())
if (!playerdata.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.
playerdata.setMuted(true);
player.sendTitle(ChatColor.RED + "You've been muted.", ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
if (reason != null)
{
msg(player, "Reason: " + ChatColor.YELLOW + reason, ChatColor.RED);
msg(player, ChatColor.RED + "Reason: " + ChatColor.YELLOW + reason);
}
if (quiet)
{
msg("Muted " + player.getName() + " quietly");
return true;
}
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));
FUtil.adminAction(sender.getName(), "Muting " + player.getName(), true);
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,13 +217,15 @@ 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]))
{
if (args[0].equals("clearip"))
{
List<String> ips = plugin.al.getAdmin(sender).getIps();
ips.remove(FUtil.getIp((Player)sender));
@ -231,14 +233,20 @@ public class Command_myadmin extends FreedomCommand
}
}
}
else if (args.length == 3 && args[0].equalsIgnoreCase("-o"))
}
else if (args.length == 3)
{
if (args[0].equals("-o"))
{
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"))
}
else if (args.length == 4)
{
if (args[0].equals("-o") && args[2].equals("clearip"))
{
Admin admin = plugin.al.getEntryByName(args[1]);
if (admin != null)
@ -246,6 +254,7 @@ public class Command_myadmin extends FreedomCommand
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())
{
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,9 +33,10 @@ 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))
{
if (!player.isOp() && !plugin.al.isVanished(player.getName()))
{
matchedPlayerNames.add(player.getName());
player.setOp(true);
@ -43,6 +44,7 @@ public class Command_op extends FreedomCommand
plugin.rm.updateDisplay(player);
}
}
}
if (!matchedPlayerNames.isEmpty())
{

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())
{
@ -23,11 +24,7 @@ public class Command_opall extends FreedomCommand
msg(player, YOU_ARE_OP);
plugin.rm.updateDisplay(player);
}
else
{
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

@ -0,0 +1,158 @@
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.config.ConfigEntry;
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 = "Manage your verification", usage = "/<command> <enable | disable | clearips | clearip <ip> | status | genbackupcodes>", aliases = "playerverify,pv")
public class Command_playerverification extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
PlayerData target = plugin.pl.getData(playerSender);
boolean verificationEnabled = ConfigEntry.DISCORD_VERIFICATION.getBoolean();
List<String> ips = new ArrayList<>(target.getIps());
if (verificationEnabled)
{
if (args.length == 1)
{
if (args[0].equalsIgnoreCase("clearips"))
{
int cleared = 0;
for (String ip : ips)
{
if (!ip.equals(FUtil.getIp(playerSender)))
{
target.removeIp(ip);
cleared++;
}
}
msg("Cleared all IP's except your current IP \"" + FUtil.getIp(playerSender) + "\"");
msg("Cleared " + cleared + " IP's.");
plugin.pl.save(target);
plugin.pl.syncIps(target);
return true;
}
else if (args[0].equalsIgnoreCase("clearip"))
{
return false;
}
}
if (args.length < 1)
{
return false;
}
PlayerData data = plugin.pl.getData(playerSender);
switch (args[0].toLowerCase())
{
case "enable":
{
if (!plugin.dc.enabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
else if (data.hasVerification())
{
msg("Discord verification is already enabled for you.", ChatColor.RED);
return true;
}
else if (data.getDiscordID() == null)
{
msg("Please link a discord account with /linkdiscord.", ChatColor.RED);
return true;
}
data.setVerification(true);
plugin.pl.save(data);
msg("Re-enabled Discord verification.", ChatColor.GREEN);
return true;
}
case "disable":
{
if (!data.hasVerification())
{
msg("Discord verification is already disabled for you.", ChatColor.RED);
return true;
}
data.setVerification(false);
plugin.pl.save(data);
msg("Disabled Discord verification.", ChatColor.GREEN);
return true;
}
case "status":
{
boolean enabled = target.hasVerification();
boolean specified = target.getDiscordID() != null;
msg(ChatColor.GRAY + "Discord Verification Enabled: " + (enabled ? ChatColor.GREEN + "true" : ChatColor.RED + "false"));
msg(ChatColor.GRAY + "Discord ID: " + (specified ? ChatColor.GREEN + target.getDiscordID() : ChatColor.RED + "not set"));
msg(ChatColor.GRAY + "Backup Codes: " + data.getBackupCodes().size() + "/" + "10");
return true;
}
case "genbackupcodes":
{
if (!plugin.dc.enabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
else if (!data.hasVerification())
{
msg("Discord verification is not enabled for you.", ChatColor.RED);
return true;
}
boolean generated = plugin.dc.sendBackupCodes(data);
if (generated)
{
msg("Your backup codes have been sent to your discord account. They can be re-generated at anytime.", ChatColor.GREEN);
}
else
{
msg("Failed to generate backup codes, please contact a developer.", ChatColor.RED);
}
return true;
}
default:
return false;
}
}
else
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
}
return true;
}
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1)
{
return Arrays.asList("enable", "disable", "status", "clearips", "genbackupcodes");
}
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)
{
case 1 ->
if (args.length == 1)
{
if (args[0].equalsIgnoreCase("list"))
{
Arrays.stream(pm.getPlugins()).forEach(pl ->
for (Plugin serverPlugin : pm.getPlugins())
{
final String version = pl.getDescription().getVersion();
msg(ChatColor.GRAY + "- " + (pl.isEnabled() ? ChatColor.GREEN : ChatColor.RED) + pl.getName()
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(pl.getDescription().getAuthors(), ", "));
});
+ StringUtils.join(serverPlugin.getDescription().getAuthors(), ", "));
}
return true;
}
}
case 2 ->
{
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;
return false;
}
pm.enablePlugin(pl);
if (pl.isEnabled())
if (args[0].equals("enable"))
{
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
final Plugin target = getPlugin(args[1]);
if (target == null)
{
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,38 +132,41 @@ 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()
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);
@ -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))
{
if (args[0].equals("add"))
{
return FUtil.getPlayerList();
}
}
default ->
break;
}
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,15 +22,13 @@ 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))
@ -66,19 +44,19 @@ public class Command_report extends FreedomCommand
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,23 +84,20 @@ 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"))
{
if (args[1].equalsIgnoreCase("normal") || args[1].equalsIgnoreCase("off") || args[1].equalsIgnoreCase("ask"))
{
PlayerData.RideMode mode = PlayerData.RideMode.valueOf(args[1].toUpperCase());
PlayerData playerDataSender = plugin.pl.getData(playerSender);
playerDataSender.setRideMode(mode);
playerDataSender.setRideMode(args[1].toLowerCase());
plugin.pl.save(playerDataSender);
msg("Ride mode is now set to " + mode.name().toLowerCase() + ".");
}
catch (IllegalArgumentException ex)
{
msg("Invalid mode.", ChatColor.RED);
}
msg("Ride mode is now set to " + args[1].toLowerCase() + ".");
return true;
}
}
}
final Player player = getPlayer(args[0], true);
if (player == null)
@ -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,18 +176,26 @@ 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;
}
}
if (plugin.pl.isPlayerImpostor(player))
{
msg("This player was labeled as a Player impostor and is not an admin, therefore they cannot be added to the admin list.", ChatColor.RED);
return true;
}
if (admin == null) // New admin
{
FUtil.adminAction(sender.getName(), "Adding " + player.getName() + " to the admin list", true);
admin = new Admin(player);
@ -195,10 +205,23 @@ public class Command_saconfig extends FreedomCommand
else // Existing admin
{
FUtil.adminAction(sender.getName(), "Re-adding " + player.getName() + " to the admin list", true);
String oldName = admin.getName();
if (!oldName.equals(player.getName()))
{
admin.setName(player.getName());
plugin.sql.updateAdminName(oldName, admin.getName());
}
admin.addIp(FUtil.getIp(player));
admin.setActive(true);
admin.setLastLogin(new Date());
if (plugin.al.isVerifiedAdmin(player))
{
plugin.al.verifiedNoAdmin.remove(player.getName());
}
plugin.al.save(admin);
plugin.al.updateTables();
plugin.rm.updateDisplay(player);
@ -208,6 +231,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 +259,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 +267,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,9 @@
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 +22,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;
@ -57,7 +55,6 @@ public class Command_spawnmob extends FreedomCommand
return true;
}
int max = ConfigEntry.SPAWNMOB_MAX.getInteger();
int amount = 1;
if (args.length > 1)
{
@ -72,9 +69,9 @@ public class Command_spawnmob extends FreedomCommand
}
}
if (amount > max || amount < 1)
if (amount > 10 || amount < 1)
{
msg("Invalid amount: " + args[1] + ". Must be 1-" + max + ".", ChatColor.RED);
msg("Invalid amount: " + args[1] + ". Must be 1-10.", ChatColor.RED);
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;
}

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

@ -1,13 +1,11 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.shop.ShopItem;
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)
@CommandPermissions(level = Rank.ADMIN, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Trails rainbow wool behind you as you walk/fly.", usage = "/<command>")
public class Command_trail extends FreedomCommand
{
@ -15,12 +13,6 @@ public class Command_trail extends FreedomCommand
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (!plugin.pl.getData(playerSender).hasItem(ShopItem.RAINBOW_TRAIL))
{
msg("You didn't purchase the ability to have a " + ShopItem.RAINBOW_TRAIL.getName() + "! Purchase it from the shop.", ChatColor.RED);
return true;
}
if (plugin.tr.contains(playerSender))
{
plugin.tr.remove(playerSender);
@ -29,7 +21,7 @@ public class Command_trail extends FreedomCommand
else
{
plugin.tr.add(playerSender);
msg("Trail enabled. Run this command again to disable it.");
msg("Trail enabled. Use \"/trail off\" to disable.");
}
return true;

View File

@ -17,7 +17,7 @@ public class Command_unlinkdiscord extends FreedomCommand
{
if (!plugin.dc.enabled)
{
msg("The Discord integration system is currently disabled.", ChatColor.RED);
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
@ -31,7 +31,7 @@ public class Command_unlinkdiscord extends FreedomCommand
}
playerData.setDiscordID(null);
msg("Unlinked " + args[0] + "'s Discord account.", ChatColor.GREEN);
msg("Unlinked " + args[0] + "'s discord account.", ChatColor.GREEN);
return true;
}
@ -42,6 +42,7 @@ public class Command_unlinkdiscord extends FreedomCommand
return true;
}
data.setDiscordID(null);
data.setVerification(false);
plugin.pl.save(data);
msg("Your Minecraft account has been successfully unlinked from the Discord account.", 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

@ -0,0 +1,101 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.discord.Discord;
import me.totalfreedom.totalfreedommod.player.FPlayer;
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.IMPOSTOR, source = SourceType.BOTH)
@CommandParameters(description = "Sends a verification code to the player, or the player can input the sent code. Admins can manually verify a player impostor.", usage = "/<command> <code | <playername>>")
public class Command_verify extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
boolean verificationEnabled = ConfigEntry.DISCORD_VERIFICATION.getBoolean();
if (!plugin.dc.enabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
if (!verificationEnabled)
{
msg("The Discord verification system is currently disabled.", ChatColor.RED);
return true;
}
if (senderIsConsole)
{
msg("/manuallyverify <playername>", ChatColor.WHITE);
return true;
}
if (!plugin.pl.IsImpostor(playerSender))
{
msg("You are not an impostor, therefore you do not need to verify.", ChatColor.RED);
return true;
}
PlayerData playerData = plugin.pl.getData(playerSender);
String discordId = playerData.getDiscordID();
if (playerData.getDiscordID() == null)
{
msg("You do not have a Discord account linked to your Minecraft account, please verify the manual way.", ChatColor.RED);
return true;
}
if (args.length == 0)
{
String code = plugin.dc.generateCode(10);
plugin.dc.addVerificationCode(code, playerData);
plugin.dc.getUser(discordId).openPrivateChannel().complete().sendMessage("A user with the IP `" + FUtil.getIp(playerSender) + "` has sent a verification request. Please run the following in-game command: `/verify " + code + "`").complete();
msg("A verification code has been sent to your account, please copy the code and run /verify <code>", ChatColor.GREEN);
return true;
}
String code = args[0];
String backupCode = null;
if (plugin.pl.IsImpostor(playerSender))
{
PlayerData mapPlayer = plugin.dc.getVerificationCodes().get(code);
if (mapPlayer == null)
{
if (!playerData.getBackupCodes().contains(Discord.getMD5(code)))
{
msg("You have entered an invalid verification code", ChatColor.RED);
return true;
}
else
{
backupCode = Discord.getMD5(code);
}
}
else
{
plugin.dc.removeVerificationCode(code);
}
final FPlayer fPlayer = plugin.pl.getPlayer(playerSender);
if (fPlayer.getFreezeData().isFrozen())
{
fPlayer.getFreezeData().setFrozen(false);
msg("You have been unfrozen.");
}
FUtil.bcastMsg(playerSender.getName() + " has verified!", ChatColor.GOLD);
playerSender.setOp(true);
plugin.pl.verify(playerSender, backupCode);
return true;
}
return true;
}
}

View File

@ -0,0 +1,92 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import me.totalfreedom.totalfreedommod.player.FPlayer;
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.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Verify an admin without giving them admin permissions.", usage = "/<command> <player>", aliases = "vns,verifynostaff,vna")
public class Command_verifynoadmin extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length < 1)
{
return false;
}
Player player = getPlayer(args[0]);
if (player == null)
{
msg(PLAYER_NOT_FOUND);
return true;
}
if (plugin.al.isAdminImpostor(player))
{
String ip = FUtil.getIp(player);
if (!plugin.al.verifiedNoAdmin.containsKey(player.getName()))
{
List<String> ips = new ArrayList<>();
ips.add(ip);
plugin.al.verifiedNoAdmin.put(player.getName(), ips);
}
else
{
List<String> ips = plugin.al.verifiedNoAdmin.get(player.getName());
if (!ips.contains(ip))
{
ips.add(ip);
plugin.al.verifiedNoAdmin.remove(player.getName());
plugin.al.verifiedNoAdmin.put(player.getName(), ips);
}
}
plugin.rm.updateDisplay(player);
FUtil.adminAction(sender.getName(), "Verified " + player.getName() + ", without admin permissions.", true);
player.setOp(true);
msg(player, YOU_ARE_OP);
final FPlayer fPlayer = plugin.pl.getPlayer(player);
if (fPlayer.getFreezeData().isFrozen())
{
fPlayer.getFreezeData().setFrozen(false);
msg(player, "You have been unfrozen.");
}
msg("Verified " + player.getName() + " but didn't give them admin permissions", ChatColor.GREEN);
}
else
{
msg(player.getName() + " is not an admin imposter.", ChatColor.RED);
}
return true;
}
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1)
{
List<String> adminImposters = new ArrayList<>();
for (Player player : server.getOnlinePlayers())
{
if (plugin.al.isAdminImpostor(player))
{
adminImposters.add(player.getName());
}
}
return adminImposters;
}
return Collections.emptyList();
}
}

View File

@ -1,10 +1,12 @@
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.DepreciationAggregator;
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 +32,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;
}
@ -94,7 +95,7 @@ public class Command_whitelist extends FreedomCommand
if (player == null)
{
player = server.getOfflinePlayer(search_name);
player = DepreciationAggregator.getOfflinePlayer(server, search_name);
}
FUtil.adminAction(sender.getName(), "Adding " + player.getName() + " to the whitelist", false);
@ -116,7 +117,7 @@ public class Command_whitelist extends FreedomCommand
if (player == null)
{
player = server.getOfflinePlayer(search_name);
player = DepreciationAggregator.getOfflinePlayer(server, search_name);
}
if (player.isWhitelisted())
@ -157,7 +158,7 @@ public class Command_whitelist extends FreedomCommand
if (args[0].equalsIgnoreCase("purge"))
{
FUtil.adminAction(sender.getName(), "Removing all players from the whitelist", false);
msg("Removed " + purge() + " players from the whitelist.");
msg("Removed " + plugin.si.purgeWhitelist() + " players from the whitelist.");
return true;
}
return false;
@ -187,21 +188,20 @@ 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 int purge()
public List<String> getWhitelistedNames()
{
int removed = 0;
for (OfflinePlayer player : server.getWhitelistedPlayers())
List<String> names = new ArrayList<>();
for (Object name : plugin.si.getWhitelisted())
{
player.setWhitelisted(false);
removed++;
names.add(String.valueOf(name));
}
return removed;
return names;
}
}

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,19 +49,22 @@ 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))
{
if (doClear && !plugin.al.isAdmin(player))
{
player.getInventory().remove(material);
}
}
}
}
if (players.isEmpty())
{
@ -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,27 +1,33 @@
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;
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.ChatColor;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.command.*;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandMap;
import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.command.PluginCommand;
import org.bukkit.command.TabCompleter;
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
{
@ -34,6 +40,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
public static final String NO_PERMISSION = ChatColor.RED + "You do not have permission to execute this command.";
public static final Timer timer = new Timer();
public static final Map<CommandSender, FreedomCommand> COOLDOWN_TIMERS = new HashMap<>();
private static CommandMap commandMap;
protected final TotalFreedomMod plugin = TotalFreedomMod.getPlugin();
protected final Server server = plugin.getServer();
private final String name;
@ -62,22 +69,34 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
this.cooldown = perms.cooldown();
}
public static CommandMap getCommandMap()
{
if (commandMap == null)
{
try
{
final Field f = Bukkit.getServer().getPluginManager().getClass().getDeclaredField("commandMap");
f.setAccessible(true);
commandMap = (CommandMap)f.get(Bukkit.getServer().getPluginManager());
}
catch (Exception e)
{
e.printStackTrace();
}
}
return commandMap;
}
public static FreedomCommand getFrom(Command command)
{
try
{
if (command instanceof FCommand)
{
return ((FCommand) command).getExecutor();
}
return (FreedomCommand)(((PluginCommand)command).getExecutor());
}
catch (Exception ex)
{
FLog.severe(ex);
return null;
}
return null;
}
public static String getCommandPrefix()
@ -100,7 +119,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
{
cmd.setUsage(this.usage);
}
server.getCommandMap().register("totalfreedommod", cmd);
getCommandMap().register("totalfreedommod", cmd);
cmd.setExecutor(this);
}
@ -217,21 +236,14 @@ 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)
{
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);
return player;
}
protected Admin getAdmin(CommandSender sender)
@ -304,7 +316,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
return perms;
}
public final class FCommand extends Command implements PluginIdentifiableCommand
private final class FCommand extends Command
{
private FreedomCommand cmd = null;
@ -313,11 +325,6 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
super(command);
}
public final FreedomCommand getExecutor()
{
return cmd;
}
public void setExecutor(FreedomCommand cmd)
{
this.cmd = cmd;
@ -420,11 +427,5 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
}
return new ArrayList<>();
}
@Override
public @NotNull Plugin getPlugin()
{
return plugin;
}
}
}

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