Compare commits

..

2 Commits

Author SHA1 Message Date
8949ee75eb fix requested by packs
apparently some pterodactyl installations don't like short UUIDs so this changes the config to say "use long uuids, not short uuids" instead
2021-06-29 20:36:23 -06:00
d88509bf11 Rewrite Pterodactyl integration (#86)
* Update Command_ride.java

* ok, done (FS-156)

* Fixes FS-137

* grammar fix

* Remove a number of wipe commands we don't want anyway

We shouldn't be wiping any of this data within the server now anyway so let's not tempt fate again.

* Why overcomplicating things is a horrifically bad idea (#55)

The longer I look into this plugin's code, the angrier I will become.

This fixes 2 bugs in the /potion command:
- Fixes non-admins being able to clear other players
- Fixes NPE caused when trying to add potion effects to players who are not on the server as a non-admin.

Both of these issues are caused by overcomplicating seemingly simple solutions, hence the name of this commit.

Co-authored-by: Ryan <Wild1145@users.noreply.github.com>
Co-authored-by: Nathan Curran <30569566+Focusvity@users.noreply.github.com>

* Bug fixes, improvements, and removals (FS-192) (#46)

* Three fixes

* Fixes /tempban throwing a NullPointerException when trying to get a player who isn't on the server but was in the past
* Fixes /tempban banning players for 24 hours regardless of the duration defined
* Fixes /list -t throwing a NullPointerException when performed from a non-player source (such as Telnet)

* Removes hubworld entriely

* Configurable blacklists for tag, muted commands, and wildcard

Changes:
* Moves globally blocked commands to the `global` subsection of the original `blocked_commands` section. You *will* need to update your configurations
* /wildcard's command blacklist is now configurable under the `wildcard` section in `blocked_commands`.
* The commands muted players can't use are now configurable under the `muted` section in `blocked_commands`.
* Removes some commented-out globally blocked command entries.

Co-authored-by: Ryan <Wild1145@users.noreply.github.com>

* Switched from -c to -ci (#63)

Resolves FS-219

* Added new dependency to allow TFM to compile (#65)

* Name change for Fleek (#64)

* Add //g to blocked commands (#62)

Co-authored-by: Nathan Curran <30569566+Focusvity@users.noreply.github.com>

* Small modification to new TFGuilds (FS-255) (#67)

* Calculate the player count without offline players (FS-247) (#68)

Co-authored-by: Ryan <Wild1145@users.noreply.github.com>

* Use long instead of int and use offset to check time (FS-181) (#69)

* Use long instead of int and use offset to check time (FS-181)

* Remove star import

* Addresses FS-224 (#70)

* Bump version

* TotalFreedomMod May Update

* Retired support for 2021.02 fully. (#72)

* Rewrite Pterodactyl integration

- Rewrite Pterodactyl integration
- Bring back the restart command and fix the stop command to gracefully stop the server now
- I had to update for Java 16, sorry. I can't get it to compile on 11 anymore anyway

* Codacy

* Actually document how you set it up

Also, rename server key to client key. That was from the old API, renamed it to be consistent with 1.x API

* Be even clearer

* Update Command_restart.java

* Update pom.xml

Co-authored-by: Video <videogamesm12@gmail.com>
Co-authored-by: Elmon11 <elmon11bussiness@gmail.com>
Co-authored-by: Ryan <Wild1145@users.noreply.github.com>
Co-authored-by: Nathan Curran <30569566+Focusvity@users.noreply.github.com>
2021-06-29 20:28:30 +10:00
88 changed files with 3022 additions and 1812 deletions

View File

@ -1,23 +0,0 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
# Maintain Maven Updates
- package-ecosystem: "maven" # See documentation for possible values
directory: "/" # Location of package manifests
target-branch: "development"
open-pull-requests-limit: 50
schedule:
interval: "daily"
# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
target-branch: "development"
open-pull-requests-limit: 50
schedule:
interval: "daily"

View File

@ -25,7 +25,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis # Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI - name: Run Codacy Analysis CLI
uses: codacy/codacy-analysis-cli-action@4.0.0 uses: codacy/codacy-analysis-cli-action@1.1.0
with: with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository # 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 # You can also omit the token and run the tools that support default configurations

View File

@ -38,11 +38,10 @@ jobs:
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Setup Java JDK - name: Setup Java JDK
uses: actions/setup-java@v2.3.0 uses: actions/setup-java@v1.4.3
with: 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 # 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. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@ -26,11 +26,11 @@ jobs:
# Step 2: run this sync action - specify the upstream repo, upstream branch to sync with, and target sync branch # 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 - name: Pull (Fast-Forward) upstream changes
id: sync id: sync
uses: aormsby/Fork-Sync-With-Upstream-action@v3.3 uses: aormsby/Fork-Sync-With-Upstream-action@v2.1
with: with:
upstream_repository: AtlasMediaGroup/TotalFreedomMod upstream_repository: AtlasMediaGroup/TotalFreedomMod
upstream_branch: main upstream_branch: main
target_branch: development target_branch: main
git_pull_args: --ff-only # optional arg use, defaults to simple 'pull' 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) # Step 3: Display a message if 'sync' step had new commits (simple test)

View File

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

17
.github/workflows/maven.yml vendored Normal file
View File

@ -0,0 +1,17 @@
name: Maven-Build
on: [push]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v1
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 11
- name: Build with Maven
run: mvn -B package --file pom.xml

13
.travis.yml Normal file
View File

@ -0,0 +1,13 @@
language: java
jdk:
- oraclejdk11
- openjdk11
notifications:
email: false
addons:
apt:
packages:
- sshpass
script: mvn clean install
after_success:
- ./travis-upload.sh

View File

@ -1,4 +1,4 @@
# 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 [![Build Status](https://travis-ci.com/AtlasMediaGroup/TotalFreedomMod.svg?branch=development)](https://travis-ci.com/AtlasMediaGroup/TotalFreedomMod) [![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)
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. 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.
@ -14,4 +14,4 @@ For information on our security policy and reporting an issue, please see [SECUR
### Compiling ### Compiling
You need Maven to build. You'd also need to set the JDK version to Java 11 as that is the current standard as of now. You need Maven to build. You'd also need to set the JDK version to Java 8 as that is the current standard as of now.

View File

@ -11,23 +11,20 @@ These versions are currently actively supported by our team, and you should expe
| Version | Supported | Support End: | | Version | Supported | Support End: |
| ------------------- | ------------------ | ------------------------------ | | ------------------- | ------------------ | ------------------------------ |
| 2021.09 | :white_check_mark: | No Earlier than December 2021 | | 2021.05 | :white_check_mark: | No Earlier than August 2021 |
### Legacy Supported ### Legacy Supported
These versions are no longer under active development, however we will look to release critical secuirty patches where appropriate. These versions are no longer under active development, however we will look to release critical secuirty patches where appropriate.
| Version | Supported | Support End: | | Version | Supported | Support End: |
| ------------------- | ------------------ | ------------ | | ------------------- | ------------------ | ------------ |
| 2021.06 | :white_check_mark: | October 2021 | | 2021.04 | :white_check_mark: | July 2021 |
### No Longer Supported ### No Longer Supported
These versions are no longer supported at all. It is strongly advised to update if you are running any of these versions. These versions are no longer supported at all. It is strongly advised to update if you are running any of these versions.
| Version | Supported | Support Ended: | | Version | Supported | Support Ended: |
| ------------------- | ------------------ | ------------------- | | ------------------- | ------------------ | ------------------- |
| 2021.05 | :white_check_mark: | September 2021 |
| 2021.04 | :white_check_mark: | July 2021 |
| 2021.02 | :x: | 6 June 2021 | | 2021.02 | :x: | 6 June 2021 |
| 2020.11 | :x: | 3 May 2021 | | 2020.11 | :x: | 3 May 2021 |
| 6.0.x (Pre-Release) | :x: | December 2020 | | 6.0.x (Pre-Release) | :x: | December 2020 |

169
pom.xml
View File

@ -5,7 +5,7 @@
<groupId>me.totalfreedom</groupId> <groupId>me.totalfreedom</groupId>
<artifactId>TotalFreedomMod</artifactId> <artifactId>TotalFreedomMod</artifactId>
<version>2022.02-RC01</version> <version>2021.05</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
@ -39,27 +39,26 @@
</scm> </scm>
<repositories> <repositories>
<repository>
<id>apache-snapshots</id>
<url>https://repository.apache.org/content/repositories/snapshots/</url>
</repository>
<repository> <repository>
<id>jitpack.io</id> <id>jitpack.io</id>
<url>https://jitpack.io</url> <url>https://jitpack.io</url>
</repository> </repository>
<repository>
<id>networkmanager-repo</id>
<url>https://repo.networkmanager.xyz/repository/maven-public/</url>
</repository>
<repository>
<id>atlas-nexus-01-totalfreedom-development</id>
<url>https://nexus-01.core.atlas-media.co.uk/repository/totalfreedom-development/</url>
</repository>
<repository> <repository>
<id>CodeMC</id> <id>CodeMC</id>
<url>https://repo.codemc.org/repository/maven-public/</url> <url>https://repo.codemc.org/repository/maven-public/</url>
</repository> </repository>
<repository>
<id>nms-repo</id>
<url>https://repo.codemc.org/repository/nms/</url>
</repository>
<repository> <repository>
<id>spigot-repo</id> <id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url> <url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
@ -107,11 +106,19 @@
</repository> </repository>
<repository> <repository>
<id>esentialsx-repo</id> <id>papermc</id>
<url>https://repo.essentialsx.net/releases/</url> <url>https://papermc.io/repo/repository/maven-public/</url>
</repository> </repository>
<repository>
<id>ess-repo</id>
<url>https://ci.ender.zone/plugin/repository/everything/</url>
</repository>
<repository>
<id>mattmalec-repo</id>
<url>https://repo.mattmalec.com/repository/releases</url>
</repository>
</repositories> </repositories>
<dependencies> <dependencies>
@ -119,14 +126,28 @@
<dependency> <dependency>
<groupId>commons-io</groupId> <groupId>commons-io</groupId>
<artifactId>commons-io</artifactId> <artifactId>commons-io</artifactId>
<version>2.11.0</version> <version>2.8.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.commons</groupId> <groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId> <artifactId>commons-lang3</artifactId>
<version>3.12.0</version> <version>3.11</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.15</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.speedxx</groupId>
<artifactId>Mojangson</artifactId>
<version>1957eef8d6</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@ -138,9 +159,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.papermc.paper</groupId> <groupId>org.spigotmc</groupId>
<artifactId>paper-api</artifactId> <artifactId>spigot</artifactId>
<version>1.17.1-R0.1-SNAPSHOT</version> <version>1.16.5-R0.1-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -152,37 +173,44 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.github.AtlasMediaGroup</groupId> <groupId>com.github.TotalFreedomMC</groupId>
<artifactId>TF-LibsDisguises</artifactId> <artifactId>TF-LibsDisguises</artifactId>
<version>5a340341b0</version> <version>48f01cf2fe</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sk89q.worldedit</groupId> <groupId>com.sk89q.worldedit</groupId>
<artifactId>worldedit-bukkit</artifactId> <artifactId>worldedit-bukkit</artifactId>
<version>7.2.8</version> <version>7.3.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.ess3</groupId>
<artifactId>EssentialsX</artifactId>
<version>2.18.2</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.dv8tion</groupId> <groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId> <artifactId>JDA</artifactId>
<version>4.2.1_255</version> <version>4.3.0_277</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.coreprotect</groupId> <groupId>net.coreprotect</groupId>
<artifactId>coreprotect</artifactId> <artifactId>coreprotect</artifactId>
<version>21.2</version> <version>19.5</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.sk89q.worldguard</groupId> <groupId>com.sk89q.worldguard</groupId>
<artifactId>worldguard-bukkit</artifactId> <artifactId>worldguard-bukkit</artifactId>
<version>7.0.6</version> <version>7.0.5</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -201,9 +229,9 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>net.essentialsx</groupId> <groupId>net.goldtreeservers</groupId>
<artifactId>EssentialsX</artifactId> <artifactId>worldguardextraflags</artifactId>
<version>2.19.0</version> <version>4.0.0</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
@ -217,35 +245,47 @@
<dependency> <dependency>
<groupId>org.javassist</groupId> <groupId>org.javassist</groupId>
<artifactId>javassist</artifactId> <artifactId>javassist</artifactId>
<version>3.28.0-GA</version> <version>3.27.0-GA</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>me.totalfreedom</groupId> <groupId>com.github.AtlasMediaGroup</groupId>
<artifactId>tfguilds</artifactId> <artifactId>TFGuilds</artifactId>
<version>2021.06-RC2</version> <version>master-SNAPSHOT</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jetbrains</groupId> <groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId> <artifactId>annotations</artifactId>
<version>22.0.0</version> <version>20.1.0</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version> <version>3.1.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.mattmalec</groupId>
<artifactId>Pterodactyl4J</artifactId>
<version>2.BETA_47</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.3.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.junit.jupiter</groupId> <groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId> <artifactId>junit-jupiter</artifactId>
<version>5.8.0</version> <version>5.4.2</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@ -254,46 +294,8 @@
<artifactId>org.eclipse.sisu.inject</artifactId> <artifactId>org.eclipse.sisu.inject</artifactId>
<version>0.3.4</version> <version>0.3.4</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.MilkBowl</groupId>
<artifactId>VaultAPI</artifactId>
<version>1.7</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.bstats</groupId>
<artifactId>bstats</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>nl.chimpgamer.networkmanager</groupId>
<artifactId>api</artifactId>
<version>2.11.4</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>io.github.slimjar</groupId>
<artifactId>slimjar</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220320</version>
</dependency>
</dependencies> </dependencies>
<pluginRepositories>
<pluginRepository>
<id>apache.snapshots</id>
<url>https://repository.apache.org/snapshots/</url>
</pluginRepository>
</pluginRepositories>
<build> <build>
<!-- Filter resources for build.properties --> <!-- Filter resources for build.properties -->
<resources> <resources>
@ -311,9 +313,9 @@
<version>3.8.1</version> <version>3.8.1</version>
<configuration> <configuration>
<outputFileName>TotalFreedomMod.jar</outputFileName> <outputFileName>TotalFreedomMod.jar</outputFileName>
<compilerVersion>17</compilerVersion> <compilerVersion>11</compilerVersion>
<source>17</source> <source>11</source>
<target>17</target> <target>11</target>
</configuration> </configuration>
</plugin> </plugin>
@ -321,7 +323,7 @@
<plugin> <plugin>
<groupId>pl.project13.maven</groupId> <groupId>pl.project13.maven</groupId>
<artifactId>git-commit-id-plugin</artifactId> <artifactId>git-commit-id-plugin</artifactId>
<version>4.9.10</version> <version>4.0.5</version>
<executions> <executions>
<execution> <execution>
<id>get-the-git-infos</id> <id>get-the-git-infos</id>
@ -362,7 +364,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId> <artifactId>maven-antrun-plugin</artifactId>
<version>3.0.0</version> <version>1.8</version>
<executions> <executions>
<execution> <execution>
<id>default-cli</id> <id>default-cli</id>
@ -434,10 +436,12 @@
</plugin> </plugin>
<!-- Shade --> <!-- Shade -->
<!-- NOTE: This should only be temporary. This will need to be updated when a stable build comes out
that supports Java 16 -->
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId> <artifactId>maven-shade-plugin</artifactId>
<version>3.3.1-SNAPSHOT</version> <version>3.3.0-SNAPSHOT</version>
<executions> <executions>
<execution> <execution>
<phase>package</phase> <phase>package</phase>
@ -449,8 +453,7 @@
<relocations> <relocations>
<relocation> <relocation>
<pattern>io.papermc.lib</pattern> <pattern>io.papermc.lib</pattern>
<shadedPattern>me.totalfreedom.totalfreedommod.paperlib <shadedPattern>me.totalfreedom.totalfreedommod.paperlib</shadedPattern>
</shadedPattern> <!-- Replace this -->
</relocation> </relocation>
<relocation> <relocation>
<pattern>org.bstats</pattern> <pattern>org.bstats</pattern>
@ -461,12 +464,14 @@
<includes> <includes>
<include>commons-io:commons-io</include> <include>commons-io:commons-io</include>
<include>org.apache.commons:commons-lang3</include> <include>org.apache.commons:commons-lang3</include>
<include>commons-codec:commons-codec</include>
<include>org.reflections:reflections</include> <include>org.reflections:reflections</include>
<include>org.javassist:javassist</include> <include>org.javassist:javassist</include>
<include>io.papermc:paperlib</include> <include>io.papermc:paperlib</include>
<include>com.github.speedxx:Mojangson</include>
<include>org.bstats:bstats-bukkit</include> <include>org.bstats:bstats-bukkit</include>
<include>org.bstats:bstats-base</include>
<include>org.jetbrains:annotations</include> <include>org.jetbrains:annotations</include>
<include>com.mattmalec:Pterodactyl4J</include>
</includes> </includes>
</artifactSet> </artifactSet>
</configuration> </configuration>
@ -483,7 +488,7 @@
<plugin> <plugin>
<groupId>org.apache.maven.plugins</groupId> <groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId> <artifactId>maven-checkstyle-plugin</artifactId>
<version>3.1.2</version> <version>3.1.1</version>
<configuration> <configuration>
<configLocation>checkstyle.xml</configLocation> <configLocation>checkstyle.xml</configLocation>
<failOnViolation>true</failOnViolation> <failOnViolation>true</failOnViolation>

View File

@ -3,10 +3,7 @@ package me.totalfreedom.totalfreedommod;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.FPlayer; import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
@ -22,7 +19,6 @@ import org.bukkit.event.player.AsyncPlayerPreLoginEvent;
import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerJoinEvent;
import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
public class LoginProcess extends FreedomService public class LoginProcess extends FreedomService
{ {
@ -61,13 +57,13 @@ public class LoginProcess extends FreedomService
@EventHandler(priority = EventPriority.NORMAL) @EventHandler(priority = EventPriority.NORMAL)
public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event) public void onPlayerPreLogin(AsyncPlayerPreLoginEvent event)
{ {
final Admin entry = plugin.al.getEntryByUuid(event.getUniqueId()); final String ip = event.getAddress().getHostAddress().trim();
final boolean isAdmin = entry != null && entry.isActive(); final boolean isAdmin = plugin.al.getEntryByIp(ip) != null;
// Check if the player is already online // Check if the player is already online
for (Player onlinePlayer : server.getOnlinePlayers()) for (Player onlinePlayer : server.getOnlinePlayers())
{ {
if (!onlinePlayer.getUniqueId().equals(event.getUniqueId())) if (!onlinePlayer.getName().equalsIgnoreCase(event.getName()))
{ {
continue; continue;
} }
@ -89,7 +85,7 @@ public class LoginProcess extends FreedomService
{ {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final String username = player.getName(); final String username = player.getName();
final UUID uuid = player.getUniqueId(); final String ip = event.getAddress().getHostAddress().trim();
// Check username length // Check username length
if (username.length() < MIN_USERNAME_LENGTH || username.length() > MAX_USERNAME_LENGTH) if (username.length() < MIN_USERNAME_LENGTH || username.length() > MAX_USERNAME_LENGTH)
@ -123,8 +119,7 @@ public class LoginProcess extends FreedomService
} }
// Validation below this point // Validation below this point
final Admin entry = plugin.al.getEntryByUuid(uuid); if (plugin.al.getEntryByIp(ip) != null) // Check if player is admin
if (entry != null && entry.isActive()) // Check if player is admin
{ {
// Force-allow log in // Force-allow log in
event.allow(); event.allow();
@ -179,11 +174,14 @@ public class LoginProcess extends FreedomService
} }
// Whitelist // Whitelist
if (server.isWhitelistEnforced() && !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."); event.disallow(PlayerLoginEvent.Result.KICK_OTHER, "You are not whitelisted on this server.");
} }
} }
}
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerJoin(PlayerJoinEvent event) public void onPlayerJoin(PlayerJoinEvent event)
@ -192,22 +190,6 @@ public class LoginProcess extends FreedomService
final FPlayer fPlayer = plugin.pl.getPlayer(player); final FPlayer fPlayer = plugin.pl.getPlayer(player);
final PlayerData playerData = plugin.pl.getData(player); final PlayerData playerData = plugin.pl.getData(player);
// Sends a message to the player if they have never joined before (or simply lack player data).
if (!event.getPlayer().hasPlayedBefore() && ConfigEntry.FIRST_JOIN_INFO_ENABLED.getBoolean())
{
new BukkitRunnable()
{
@Override
public void run()
{
for (String line : ConfigEntry.FIRST_JOIN_INFO.getStringList())
{
player.sendMessage(FUtil.colorize(line));
}
}
}.runTaskLater(plugin, 20);
}
player.sendTitle(FUtil.colorize(ConfigEntry.SERVER_LOGIN_TITLE.getString()), FUtil.colorize(ConfigEntry.SERVER_LOGIN_SUBTITLE.getString()), 20, 100, 60); player.sendTitle(FUtil.colorize(ConfigEntry.SERVER_LOGIN_TITLE.getString()), FUtil.colorize(ConfigEntry.SERVER_LOGIN_SUBTITLE.getString()), 20, 100, 60);
player.setOp(true); player.setOp(true);
@ -222,7 +204,7 @@ public class LoginProcess extends FreedomService
return; return;
} }
if (!playerData.getIps().contains(FUtil.getIp(player))) if (!playerData.hasVerification() && !playerData.getIps().contains(FUtil.getIp(player)))
{ {
playerData.addIp(FUtil.getIp(player)); playerData.addIp(FUtil.getIp(player));
plugin.pl.save(playerData); plugin.pl.save(playerData);

View File

@ -1,16 +1,17 @@
package me.totalfreedom.totalfreedommod; package me.totalfreedom.totalfreedommod;
import com.google.common.collect.Multimap; import ca.momothereal.mojangson.ex.MojangsonParseException;
import ca.momothereal.mojangson.value.MojangsonCompound;
import ca.momothereal.mojangson.value.MojangsonValue;
import io.papermc.lib.PaperLib; import io.papermc.lib.PaperLib;
import java.util.List;
import java.util.Collection;
import java.util.Map;
import java.util.Objects; import java.util.Objects;
import net.minecraft.server.v1_16_R3.NBTTagCompound;
import net.minecraft.server.v1_16_R3.NBTTagList;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
import org.bukkit.attribute.Attribute; import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack;
import org.bukkit.attribute.AttributeModifier;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler; import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
@ -19,7 +20,6 @@ import org.bukkit.event.player.PlayerLoginEvent;
import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerMoveEvent;
import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerTeleportEvent;
import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
public class MovementValidator extends FreedomService public class MovementValidator extends FreedomService
{ {
@ -133,49 +133,55 @@ public class MovementValidator extends FreedomService
private Boolean exploitItem(ItemStack item) private Boolean exploitItem(ItemStack item)
{ {
if (item == null) net.minecraft.server.v1_16_R3.ItemStack nmsStack = CraftItemStack.asNMSCopy(item);
NBTTagList modifiers = getAttributeList(nmsStack);
MojangsonCompound compound = new MojangsonCompound();
boolean foundNegative = false;
boolean foundPositive = false;
try
{ {
return false; String mod = modifiers.toString();
String fancy = ("{" + (mod.substring(1, mod.length() - 1).replace("{", "").replace("}", "")) + "}");
compound.read(fancy);
for (String key : compound.keySet())
{
if (Objects.equals(key, "Amount")) //null-safe .equals()
{
@SuppressWarnings("rawtypes")
List<MojangsonValue> values = compound.get(key);
for (MojangsonValue<?> val : values)
{
if (val.getValue().toString().equals("Infinityd"))
{
foundPositive = true;
}
if (val.getValue().toString().equals("-Infinityd"))
{
foundNegative = true;
}
}
}
}
}
catch (MojangsonParseException e)
{
e.printStackTrace();
}
return foundNegative && foundPositive;
} }
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... private NBTTagList getAttributeList(net.minecraft.server.v1_16_R3.ItemStack stack)
for (Attribute attr : attributes.keySet())
{ {
// Default values if (stack.getTag() == null)
boolean posInf = false;
boolean negInf = false;
// For every AttributeModifier...
for (AttributeModifier modifier : attrMap.get(attr))
{ {
// Are they ∞ or -∞? stack.setTag(new NBTTagCompound());
if (modifier.getAmount() == Double.POSITIVE_INFINITY) }
NBTTagList attr = stack.getTag().getList("AttributeModifiers", 10);
if (attr == null)
{ {
posInf = true; stack.getTag().set("AttributeModifiers", new NBTTagList());
} }
else if (modifier.getAmount() == Double.NEGATIVE_INFINITY) return stack.getTag().getList("AttributeModifiers", 10);
{
negInf = true;
}
}
// Are both values set as true?
if (posInf && negInf)
{
return true;
}
}
}
}
return false;
} }
} }

View File

@ -1,26 +1,30 @@
package me.totalfreedom.totalfreedommod; package me.totalfreedom.totalfreedommod;
import java.io.IOException; import com.mattmalec.pterodactyl4j.Permission;
import java.util.Arrays; import com.mattmalec.pterodactyl4j.PowerAction;
import java.util.List; import com.mattmalec.pterodactyl4j.PteroAction;
import com.google.common.base.Strings; import com.mattmalec.pterodactyl4j.PteroBuilder;
import com.mattmalec.pterodactyl4j.application.entities.ApplicationUser;
import com.mattmalec.pterodactyl4j.application.entities.PteroApplication;
import com.mattmalec.pterodactyl4j.application.managers.UserAction;
import com.mattmalec.pterodactyl4j.client.entities.ClientServer;
import com.mattmalec.pterodactyl4j.client.entities.ClientSubuser;
import com.mattmalec.pterodactyl4j.client.entities.PteroClient;
import joptsimple.internal.Strings;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog; 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 class Pterodactyl extends FreedomService
{ {
public final String URL = ConfigEntry.PTERO_URL.getString(); 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 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 String CLIENT_KEY = ConfigEntry.PTERO_CLIENT_KEY.getString();
private final List<String> ADMIN_HEADERS = Arrays.asList("Accept:Application/vnd.pterodactyl.v1+json", "Content-Type:application/json", "Authorization:Bearer " + ADMIN_KEY); private final String IDENTIFIER = ConfigEntry.PTERO_SERVER_UUID.getString();
private final PteroApplication adminAPI = PteroBuilder.createApplication(URL, ADMIN_KEY);
private final PteroClient clientAPI = PteroBuilder.createClient(URL, CLIENT_KEY);
private final ClientServer server = clientAPI.retrieveServerByIdentifier(IDENTIFIER).execute();
private boolean enabled = !Strings.isNullOrEmpty(URL); private boolean enabled = !Strings.isNullOrEmpty(URL);
@ -43,163 +47,60 @@ public class Pterodactyl extends FreedomService
if (!admin.isActive() || admin.getRank() != Rank.SENIOR_ADMIN) if (!admin.isActive() || admin.getRank() != Rank.SENIOR_ADMIN)
{ {
FLog.debug("Disabling ptero acc"); FLog.debug("Disabling Pterodactyl account");
removeAccountFromServer(id); removeAccountFromServer(id);
return; return;
} }
FLog.debug("Enabling ptero acc"); FLog.debug("Enabling Pterodactyl account");
addAccountToServer(id); addAccountToServer(id);
} }
@SuppressWarnings("unchecked")
public String createAccount(String username, String password) public String createAccount(String username, String password)
{ {
JSONObject json = new JSONObject(); UserAction action = adminAPI.getUserManager().createUser()
json.put("username", username); .setUserName(username)
json.put("password", password); .setEmail(username.toLowerCase() + "@" + ConfigEntry.PTERO_DEFAULT_EMAIL_DOMAIN.getString())
json.put("email", username.toLowerCase() + "@" + ConfigEntry.PTERO_DEFAULT_EMAIL_DOMAIN.getString()); .setFirstName(username)
json.put("first_name", username); .setLastName("\u200E") // Required - make it appear empty
json.put("last_name", "\u200E"); // required, so I made it appear empty .setPassword(password);
Response response; return action.execute().getId();
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 void deleteAccount(String id)
{
ApplicationUser username = adminAPI.retrieveUserById(id).execute();
PteroAction<Void> action = adminAPI.getUserManager().deleteUser(username);
action.execute();
} }
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) public void addAccountToServer(String id)
{ {
String url = URL + "/api/client/servers/" + ConfigEntry.PTERO_SERVER_UUID.getString() + "/users"; ApplicationUser username = adminAPI.retrieveUserById(id).execute();
String email = username.getEmail();
JSONObject userData = getUserData(id); PteroAction<ClientServer> server = clientAPI.retrieveServerByIdentifier(IDENTIFIER);
if (userData == null) server.execute().getSubuserManager().createUser()
{ .setEmail(email)
FLog.severe("The Pterodactyl user with the ID of " + id + " was not found"); .setPermissions(Permission.CONTROL_PERMISSIONS).execute();
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) public void removeAccountFromServer(String id)
{ {
JSONObject userData = getUserData(id); ApplicationUser username = adminAPI.retrieveUserById(id).execute();
if (userData == null) PteroAction<ClientServer> server = clientAPI.retrieveServerByIdentifier(IDENTIFIER);
{ ClientSubuser clientSubuser = server.execute().getSubuser(username.getUUID()).retrieve().execute();
FLog.severe("The Pterodactyl user with the ID of " + id + " was not found"); server.execute().getSubuserManager().deleteUser(clientSubuser).execute();
return;
} }
String url = URL + "/api/client/servers/" + ConfigEntry.PTERO_SERVER_UUID.getString() + "/users/" + userData.get("uuid"); public void stopServer()
try
{ {
FUtil.sendRequest(url, "DELETE", SERVER_HEADERS, null); clientAPI.setPower(server, PowerAction.STOP).execute();
}
catch (IOException e)
{
FLog.severe(e);
}
} }
public JSONObject getUserData(String id) public void restartServer()
{ {
Response response; clientAPI.setPower(server, PowerAction.RESTART).execute();
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() public boolean isEnabled()

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; package me.totalfreedom.totalfreedommod;
import com.google.gson.Gson;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
@ -8,13 +7,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority; import org.bukkit.event.EventPriority;
import org.bukkit.event.server.ServerListPingEvent; import org.bukkit.event.server.ServerListPingEvent;
import java.io.InputStreamReader;
public class ServerPing extends FreedomService 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 @Override
public void onStart() public void onStart()
{ {
@ -60,7 +54,7 @@ public class ServerPing extends FreedomService
return; 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 = baseMotd.replace("\\n", "\n");
baseMotd = FUtil.colorize(baseMotd); baseMotd = FUtil.colorize(baseMotd);
@ -79,9 +73,4 @@ public class ServerPing extends FreedomService
event.setMotd(motd.toString().trim()); event.setMotd(motd.toString().trim());
} }
private static class VersionMeta
{
private String id;
}
} }

View File

@ -3,7 +3,6 @@ package me.totalfreedom.totalfreedommod;
import java.io.File; import java.io.File;
import java.io.InputStream; import java.io.InputStream;
import java.util.Properties; import java.util.Properties;
import me.totalfreedom.totalfreedommod.admin.ActivityLog; import me.totalfreedom.totalfreedommod.admin.ActivityLog;
import me.totalfreedom.totalfreedommod.admin.AdminList; import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.banning.BanManager; import me.totalfreedom.totalfreedommod.banning.BanManager;
@ -15,6 +14,7 @@ import me.totalfreedom.totalfreedommod.blocking.InteractBlocker;
import me.totalfreedom.totalfreedommod.blocking.MobBlocker; import me.totalfreedom.totalfreedommod.blocking.MobBlocker;
import me.totalfreedom.totalfreedommod.blocking.PVPBlocker; import me.totalfreedom.totalfreedommod.blocking.PVPBlocker;
import me.totalfreedom.totalfreedommod.blocking.PotionBlocker; import me.totalfreedom.totalfreedommod.blocking.PotionBlocker;
import me.totalfreedom.totalfreedommod.blocking.SignBlocker;
import me.totalfreedom.totalfreedommod.blocking.command.CommandBlocker; import me.totalfreedom.totalfreedommod.blocking.command.CommandBlocker;
import me.totalfreedom.totalfreedommod.bridge.BukkitTelnetBridge; import me.totalfreedom.totalfreedommod.bridge.BukkitTelnetBridge;
import me.totalfreedom.totalfreedommod.bridge.CoreProtectBridge; import me.totalfreedom.totalfreedommod.bridge.CoreProtectBridge;
@ -36,10 +36,6 @@ import me.totalfreedom.totalfreedommod.fun.Trailer;
import me.totalfreedom.totalfreedommod.httpd.HTTPDaemon; import me.totalfreedom.totalfreedommod.httpd.HTTPDaemon;
import me.totalfreedom.totalfreedommod.permissions.PermissionConfig; import me.totalfreedom.totalfreedommod.permissions.PermissionConfig;
import me.totalfreedom.totalfreedommod.permissions.PermissionManager; import me.totalfreedom.totalfreedommod.permissions.PermissionManager;
import me.totalfreedom.totalfreedommod.permissions.handler.DefaultPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.IPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.NMPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.VaultPermissionHandler;
import me.totalfreedom.totalfreedommod.player.PlayerList; import me.totalfreedom.totalfreedommod.player.PlayerList;
import me.totalfreedom.totalfreedommod.punishments.PunishmentList; import me.totalfreedom.totalfreedommod.punishments.PunishmentList;
import me.totalfreedom.totalfreedommod.rank.RankManager; import me.totalfreedom.totalfreedommod.rank.RankManager;
@ -58,6 +54,7 @@ import org.bukkit.generator.ChunkGenerator;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.java.JavaPlugin; import org.bukkit.plugin.java.JavaPlugin;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.spigotmc.SpigotConfig;
public class TotalFreedomMod extends JavaPlugin public class TotalFreedomMod extends JavaPlugin
{ {
@ -77,6 +74,8 @@ public class TotalFreedomMod extends JavaPlugin
// Command Loader // Command Loader
public CommandLoader cl; public CommandLoader cl;
// Services // Services
public ServerInterface si;
public SavedFlags sf;
public WorldManager wm; public WorldManager wm;
public LogViewer lv; public LogViewer lv;
public AdminList al; public AdminList al;
@ -123,6 +122,7 @@ public class TotalFreedomMod extends JavaPlugin
public Trailer tr; public Trailer tr;
public HTTPDaemon hd; public HTTPDaemon hd;
public WorldRestrictions wr; public WorldRestrictions wr;
public SignBlocker snp;
public EntityWiper ew; public EntityWiper ew;
public Sitter st; public Sitter st;
public VanishHandler vh; public VanishHandler vh;
@ -137,8 +137,6 @@ public class TotalFreedomMod extends JavaPlugin
public WorldEditBridge web; public WorldEditBridge web;
public WorldGuardBridge wgb; public WorldGuardBridge wgb;
public IPermissionHandler permissionHandler;
public static TotalFreedomMod getPlugin() public static TotalFreedomMod getPlugin()
{ {
return plugin; return plugin;
@ -150,7 +148,7 @@ public class TotalFreedomMod extends JavaPlugin
{ {
if (plugin.getName().equalsIgnoreCase(pluginName)) if (plugin.getName().equalsIgnoreCase(pluginName))
{ {
return (TotalFreedomMod) plugin; return (TotalFreedomMod)plugin;
} }
} }
return null; return null;
@ -179,6 +177,9 @@ public class TotalFreedomMod extends JavaPlugin
final MethodTimer timer = new MethodTimer(); final MethodTimer timer = new MethodTimer();
timer.start(); timer.start();
// Warn if we're running on a wrong version
ServerInterface.warnVersion();
// Delete unused files // Delete unused files
FUtil.deleteCoreDumps(); FUtil.deleteCoreDumps();
FUtil.deleteFolder(new File("./_deleteme")); FUtil.deleteFolder(new File("./_deleteme"));
@ -186,6 +187,7 @@ public class TotalFreedomMod extends JavaPlugin
fsh = new FreedomServiceHandler(); fsh = new FreedomServiceHandler();
config = new MainConfig(); config = new MainConfig();
config.load();
if (FUtil.inDeveloperMode()) if (FUtil.inDeveloperMode())
{ {
@ -211,24 +213,13 @@ public class TotalFreedomMod extends JavaPlugin
FLog.info("Started " + fsh.getServiceAmount() + " services."); FLog.info("Started " + fsh.getServiceAmount() + " services.");
timer.update(); 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 // Metrics @ https://bstats.org/plugin/bukkit/TotalFreedomMod/2966
new Metrics(this, 2966); new Metrics(this, 2966);
if (getServer().getPluginManager().isPluginEnabled("NetworkManager")) // little workaround to stop spigot from autorestarting - causing AMP to detach from process.
{ SpigotConfig.config.set("settings.restart-on-crash", false);
FLog.info("Using NetworkManager's permission handling");
this.permissionHandler = new NMPermissionHandler(this);
} else if (getServer().getPluginManager().isPluginEnabled("Vault"))
{
FLog.info("Using Vault's permission handling");
this.permissionHandler = new VaultPermissionHandler(this);
} else
{
FLog.info("Using Bukkit's native permission handling");
this.permissionHandler = new DefaultPermissionHandler();
}
} }
@Override @Override
@ -276,7 +267,8 @@ public class TotalFreedomMod extends JavaPlugin
date = props.getProperty("buildDate", "unknown"); date = props.getProperty("buildDate", "unknown");
// Need to do this or it will display ${git.commit.id.abbrev} // Need to do this or it will display ${git.commit.id.abbrev}
head = props.getProperty("buildHead", "unknown").replace("${git.commit.id.abbrev}", "unknown"); head = props.getProperty("buildHead", "unknown").replace("${git.commit.id.abbrev}", "unknown");
} catch (Exception ex) }
catch (Exception ex)
{ {
FLog.severe("Could not load build properties! Did you compile with NetBeans/Maven?"); FLog.severe("Could not load build properties! Did you compile with NetBeans/Maven?");
FLog.severe(ex); FLog.severe(ex);
@ -306,6 +298,8 @@ public class TotalFreedomMod extends JavaPlugin
private void initServices() private void initServices()
{ {
// Start services // Start services
si = new ServerInterface();
sf = new SavedFlags();
wm = new WorldManager(); wm = new WorldManager();
lv = new LogViewer(); lv = new LogViewer();
sql = new SQLite(); sql = new SQLite();
@ -333,6 +327,7 @@ public class TotalFreedomMod extends JavaPlugin
im = new IndefiniteBanList(); im = new IndefiniteBanList();
pem = new PermissionManager(); pem = new PermissionManager();
gr = new GameRuleHandler(); gr = new GameRuleHandler();
snp = new SignBlocker();
ew = new EntityWiper(); ew = new EntityWiper();
st = new Sitter(); st = new Sitter();
vh = new VanishHandler(); vh = new VanishHandler();

View File

@ -2,8 +2,11 @@ package me.totalfreedom.totalfreedommod.admin;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; 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.LogViewer.LogsRegistrationMode;
import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
@ -15,8 +18,10 @@ import org.bukkit.entity.Player;
public class Admin public class Admin
{ {
private final List<String> ips = new ArrayList<>(); private final List<String> ips = new ArrayList<>();
private UUID uuid; private String name;
private boolean active = true; private boolean active = true;
private Rank rank = Rank.ADMIN; private Rank rank = Rank.ADMIN;
private Date lastLogin = new Date(); private Date lastLogin = new Date();
@ -27,7 +32,7 @@ public class Admin
public Admin(Player player) public Admin(Player player)
{ {
uuid = player.getUniqueId(); this.name = player.getName();
this.ips.add(FUtil.getIp(player)); this.ips.add(FUtil.getIp(player));
} }
@ -35,7 +40,7 @@ public class Admin
{ {
try try
{ {
this.uuid = UUID.fromString(resultSet.getString("uuid")); this.name = resultSet.getString("username");
this.active = resultSet.getBoolean("active"); this.active = resultSet.getBoolean("active");
this.rank = Rank.findRank(resultSet.getString("rank")); this.rank = Rank.findRank(resultSet.getString("rank"));
this.ips.clear(); this.ips.clear();
@ -57,7 +62,7 @@ public class Admin
{ {
final StringBuilder output = new StringBuilder(); final StringBuilder output = new StringBuilder();
output.append("Admin: ").append(getName()).append("\n") output.append("Admin: ").append(name).append("\n")
.append("- IPs: ").append(StringUtils.join(ips, ", ")).append("\n") .append("- IPs: ").append(StringUtils.join(ips, ", ")).append("\n")
.append("- Last Login: ").append(FUtil.dateToString(lastLogin)).append("\n") .append("- Last Login: ").append(FUtil.dateToString(lastLogin)).append("\n")
.append("- Rank: ").append(rank.getName()).append("\n") .append("- Rank: ").append(rank.getName()).append("\n")
@ -73,7 +78,7 @@ public class Admin
{ {
Map<String, Object> map = new HashMap<String, Object>() Map<String, Object> map = new HashMap<String, Object>()
{{ {{
put("uuid", uuid.toString()); put("username", name);
put("active", active); put("active", active);
put("rank", rank.toString()); put("rank", rank.toString());
put("ips", FUtil.listToString(ips)); put("ips", FUtil.listToString(ips));
@ -115,20 +120,20 @@ public class Admin
public boolean isValid() public boolean isValid()
{ {
return uuid != null return name != null
&& rank != null && rank != null
&& !ips.isEmpty() && !ips.isEmpty()
&& lastLogin != null; && lastLogin != null;
} }
public UUID getUuid()
{
return uuid;
}
public String getName() public String getName()
{ {
return Bukkit.getOfflinePlayer(uuid).getName(); return name;
}
public void setName(String name)
{
this.name = name;
} }
public boolean isActive() public boolean isActive()

View File

@ -2,31 +2,30 @@ package me.totalfreedom.totalfreedommod.admin;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; 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 java.util.concurrent.TimeUnit;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.permissions.handler.NMPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.VaultPermissionHandler;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.command.ConsoleCommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class AdminList extends FreedomService public class AdminList extends FreedomService
{ {
public static final List<String> 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 private final Set<Admin> allAdmins = Sets.newHashSet(); // Includes disabled admins
// Only active admins below // Only active admins below
private final Set<Admin> activeAdmins = Sets.newHashSet(); 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> nameTable = Maps.newHashMap();
private final Map<String, Admin> ipTable = Maps.newHashMap(); private final Map<String, Admin> ipTable = Maps.newHashMap();
@ -60,13 +59,14 @@ public class AdminList extends FreedomService
allAdmins.add(admin); allAdmins.add(admin);
} }
} }
} catch (SQLException e) }
catch (SQLException e)
{ {
FLog.severe("Failed to load admin list: " + e.getMessage()); FLog.severe("Failed to load admin list: " + e.getMessage());
} }
updateTables(); 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) public void messageAllAdmins(String message)
@ -114,7 +114,7 @@ public class AdminList extends FreedomService
return true; return true;
} }
Admin admin = getAdmin((Player) sender); Admin admin = getAdmin((Player)sender);
return admin != null && admin.isActive(); return admin != null && admin.isActive();
} }
@ -125,48 +125,28 @@ public class AdminList extends FreedomService
{ {
return true; return true;
} }
if (plugin.permissionHandler instanceof NMPermissionHandler || plugin.permissionHandler instanceof VaultPermissionHandler)
{
// FLog.debug("Using " + plugin.permissionHandler.getClass().getSimpleName() + " for AdminList#isAdmin");
return plugin.permissionHandler.inGroup(player, ConfigEntry.PERMISSIONS_GROUPS_ADMIN.getString());
}
// FLog.debug("AdminList#isAdmin: Returning false because there is no permissions plugin that supports groups on the server");
return false;
/*Admin admin = getAdmin(player); Admin admin = getAdmin(player);
return admin != null && admin.isActive();*/ return admin != null && admin.isActive();
} }
public boolean isSeniorAdmin(CommandSender sender) public boolean isSeniorAdmin(CommandSender sender)
{ {
//TODO: BukkitTelnet checks, but fuck that plugin Admin admin = getAdmin(sender);
if (sender instanceof ConsoleCommandSender)
{
return true;
}
if (sender instanceof Player player && (plugin.permissionHandler instanceof NMPermissionHandler || plugin.permissionHandler instanceof VaultPermissionHandler))
{
// FLog.debug("Using " + plugin.permissionHandler.getClass().getSimpleName() + " for AdminList#isSeniorAdmin");
return plugin.permissionHandler.inGroup(player, ConfigEntry.PERMISSIONS_GROUPS_SENIOR.getString());
}
// FLog.debug("AdminList#isSeniorAdmin: Returning false because there is no permissions plugin that supports groups on the server");
return false;
// return plugin.permissionHandler.hasPermission(sender, "totalfreedommod.admin");
/*Admin admin = getAdmin(sender);
if (admin == null) if (admin == null)
{ {
return false; return false;
} }
return admin.getRank().ordinal() >= Rank.SENIOR_ADMIN.ordinal();*/ return admin.getRank().ordinal() >= Rank.SENIOR_ADMIN.ordinal();
} }
public Admin getAdmin(CommandSender sender) public Admin getAdmin(CommandSender sender)
{ {
if (sender instanceof Player) if (sender instanceof Player)
{ {
return getAdmin((Player) sender); return getAdmin((Player)sender);
} }
return getEntryByName(sender.getName()); return getEntryByName(sender.getName());
@ -174,20 +154,40 @@ public class AdminList extends FreedomService
public Admin getAdmin(Player player) public Admin getAdmin(Player player)
{ {
final String ip = FUtil.getIp(player); // Find admin
final Admin entry = getEntryByUuid(player.getUniqueId()); 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 null;
{
return uuidTable.get(uuid);
} }
public Admin getEntryByName(String name) public Admin getEntryByName(String name)
@ -200,6 +200,25 @@ public class AdminList extends FreedomService
return ipTable.get(ip); 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) public void updateLastLogin(Player player)
{ {
final Admin admin = getAdmin(player); final Admin admin = getAdmin(player);
@ -209,9 +228,31 @@ public class AdminList extends FreedomService
} }
admin.setLastLogin(new Date()); admin.setLastLogin(new Date());
admin.setName(player.getName());
save(admin); 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) public boolean addAdmin(Admin admin)
{ {
if (!admin.isValid()) if (!admin.isValid())
@ -256,7 +297,6 @@ public class AdminList extends FreedomService
public void updateTables() public void updateTables()
{ {
activeAdmins.clear(); activeAdmins.clear();
uuidTable.clear();
nameTable.clear(); nameTable.clear();
ipTable.clear(); ipTable.clear();
@ -268,13 +308,13 @@ public class AdminList extends FreedomService
} }
activeAdmins.add(admin); activeAdmins.add(admin);
uuidTable.put(admin.getUuid(), admin);
nameTable.put(admin.getName().toLowerCase(), admin); nameTable.put(admin.getName().toLowerCase(), admin);
for (String ip : admin.getIps()) for (String ip : admin.getIps())
{ {
ipTable.put(ip, admin); ipTable.put(ip, admin);
} }
} }
} }
@ -292,7 +332,7 @@ public class AdminList extends FreedomService
{ {
try try
{ {
ResultSet currentSave = plugin.sql.getAdminByUuid(admin.getUuid()); ResultSet currentSave = plugin.sql.getAdminByName(admin.getName());
for (Map.Entry<String, Object> entry : admin.toSQLStorable().entrySet()) for (Map.Entry<String, Object> entry : admin.toSQLStorable().entrySet())
{ {
Object storedValue = plugin.sql.getValue(currentSave, entry.getKey(), entry.getValue()); Object storedValue = plugin.sql.getValue(currentSave, entry.getKey(), entry.getValue());
@ -301,7 +341,8 @@ public class AdminList extends FreedomService
plugin.sql.setAdminValue(admin, entry.getKey(), entry.getValue()); plugin.sql.setAdminValue(admin, entry.getKey(), entry.getValue());
} }
} }
} catch (SQLException e) }
catch (SQLException e)
{ {
FLog.severe("Failed to save admin: " + e.getMessage()); FLog.severe("Failed to save admin: " + e.getMessage());
} }
@ -360,4 +401,9 @@ public class AdminList extends FreedomService
{ {
return ipTable; return ipTable;
} }
public Map<String, List<String>> getVerifiedNoAdmin()
{
return verifiedNoAdmin;
}
} }

View File

@ -4,8 +4,6 @@ import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import io.papermc.paper.event.player.PlayerSignCommandPreprocessEvent;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
@ -267,10 +265,4 @@ public class EventBlocker extends FreedomService
FUtil.fixCommandVoid(event.getEntity()); FUtil.fixCommandVoid(event.getEntity());
event.setDeathMessage(event.getDeathMessage()); event.setDeathMessage(event.getDeathMessage());
} }
@EventHandler
public void onSignInteract(PlayerSignCommandPreprocessEvent event)
{
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

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

View File

@ -42,7 +42,7 @@ public class BukkitTelnetBridge extends FreedomService
return; return;
} }
final Admin admin = plugin.al.getEntryByIp(ip); final Admin admin = plugin.al.getEntryByIpFuzzy(ip);
if (admin == null || !admin.isActive() || !admin.getRank().hasConsoleVariant()) if (admin == null || !admin.isActive() || !admin.getRank().hasConsoleVariant())
{ {

View File

@ -192,6 +192,7 @@ public class CoreProtectBridge extends FreedomService
return (megabytes / 1024); return (megabytes / 1024);
} }
// Wipes DB for the specified world
public void clearDatabase(World world) public void clearDatabase(World world)
{ {
clearDatabase(world, false); clearDatabase(world, false);
@ -259,6 +260,12 @@ public class CoreProtectBridge extends FreedomService
{ {
FLog.warning("Failed to delete the CoreProtect data for the " + world.getName()); FLog.warning("Failed to delete the CoreProtect data for the " + world.getName());
} }
// This exits for flatlands wipes
if (shutdown)
{
server.shutdown();
}
} }
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
@ -269,14 +276,18 @@ public class CoreProtectBridge extends FreedomService
Block block = event.getClickedBlock(); Block block = event.getClickedBlock();
final CoreProtectAPI coreProtect = getCoreProtectAPI(); final CoreProtectAPI coreProtect = getCoreProtectAPI();
// TODO: Rewrite this
if (data.hasInspection()) if (data.hasInspection())
{ {
if (event.getAction() == Action.LEFT_CLICK_BLOCK)
{
if (block != null)
{
event.setCancelled(true);
List<String[]> lookup = coreProtect.blockLookup(block, -1);
int cooldownTime = 3; int cooldownTime = 3;
// Cooldown check if (cooldown.containsKey(player.getName()))
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); long secondsLeft = getSecondsLeft(cooldown.get(player.getName()), cooldownTime);
if (secondsLeft > 0L) if (secondsLeft > 0L)
@ -287,14 +298,6 @@ public class CoreProtectBridge extends FreedomService
} }
} }
// Actual lookup time
if (event.getAction() == Action.LEFT_CLICK_BLOCK)
{
if (block != null)
{
event.setCancelled(true);
List<String[]> lookup = coreProtect.blockLookup(block, -1);
if (!plugin.al.isAdmin(player)) if (!plugin.al.isAdmin(player))
{ {
cooldown.put(player.getName(), System.currentTimeMillis()); cooldown.put(player.getName(), System.currentTimeMillis());
@ -360,6 +363,8 @@ public class CoreProtectBridge extends FreedomService
else if (event.getAction() == Action.RIGHT_CLICK_BLOCK) else if (event.getAction() == Action.RIGHT_CLICK_BLOCK)
{ {
if (block != null) if (block != null)
{
if (data.hasInspection())
{ {
BlockState blockState = block.getRelative(event.getBlockFace()).getState(); BlockState blockState = block.getRelative(event.getBlockFace()).getState();
Block placedBlock = blockState.getBlock(); Block placedBlock = blockState.getBlock();
@ -371,6 +376,19 @@ public class CoreProtectBridge extends FreedomService
lookup = coreProtect.blockLookup(block, -1); lookup = coreProtect.blockLookup(block, -1);
} }
int cooldownTime = 3;
if (cooldown.containsKey(player.getName()))
{
long secondsLeft = getSecondsLeft(cooldown.get(player.getName()), cooldownTime);
if (secondsLeft > 0L)
{
event.setCancelled(true);
player.sendMessage(ChatColor.RED + String.valueOf(secondsLeft) + " seconds left before next query.");
return;
}
}
if (!plugin.al.isAdmin(player)) if (!plugin.al.isAdmin(player))
{ {
cooldown.put(player.getName(), System.currentTimeMillis()); cooldown.put(player.getName(), System.currentTimeMillis());
@ -435,4 +453,5 @@ public class CoreProtectBridge extends FreedomService
} }
} }
} }
}
} }

View File

@ -114,7 +114,8 @@ public class EssentialsBridge extends FreedomService
User user = getEssentialsUser(username); User user = getEssentialsUser(username);
if (user != null) if (user != null)
{ {
return user.getLastOnlineActivity(); Long l = FUtil.getField(user, "lastActivity");
return (l != null) ? l : 0L;
} }
} }
catch (Exception ex) catch (Exception ex)

View File

@ -48,6 +48,52 @@ public class WorldEditBridge extends FreedomService
return worldeditPlugin; 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) public void setLimit(Player player, int limit)
{ {
try try
@ -107,4 +153,23 @@ public class WorldEditBridge extends FreedomService
return null; 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; 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.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.RegionContainer;
import java.util.Map;
import com.sk89q.worldguard.protection.regions.RegionQuery;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import org.bukkit.entity.Player; import org.bukkit.World;
import org.bukkit.plugin.Plugin; import org.bukkit.plugin.Plugin;
public class WorldGuardBridge extends FreedomService public class WorldGuardBridge extends FreedomService
@ -15,6 +15,7 @@ public class WorldGuardBridge extends FreedomService
@Override @Override
public void onStart() public void onStart()
{ {
plugin.wr.protectWorld(plugin.wm.masterBuilderWorld.getWorld());
} }
@Override @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(); RegionContainer container = WorldGuard.getInstance().getPlatform().getRegionContainer();
RegionQuery query = container.createQuery(); return container.get(BukkitAdapter.adapt(world));
return query.testBuild(localPlayer.getLocation(), localPlayer);
} }
// If the plugin isn't present, return true. public int wipeRegions(World world)
return true; {
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() public boolean isEnabled()

View File

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

View File

@ -1,8 +1,8 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import com.earth2me.essentials.User;
import me.totalfreedom.totalfreedommod.banning.Ban; import me.totalfreedom.totalfreedommod.banning.Ban;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.punishments.Punishment; import me.totalfreedom.totalfreedommod.punishments.Punishment;
@ -60,39 +60,28 @@ public class Command_ban extends FreedomCommand
} }
final String username; final String username;
final String ip; final List<String> ips = new ArrayList<>();
final Player player = getPlayer(args[0]); final Player player = getPlayer(args[0]);
if (player == null) if (player == null)
{ {
// Gets the IP using Essentials data if available final PlayerData entry = plugin.pl.getData(args[0]);
if (plugin.esb.isEnabled() && plugin.esb.getEssentialsUser(args[0]) != null)
{
User essUser = plugin.esb.getEssentialsUser(args[0]);
//
username = essUser.getName();
ip = essUser.getLastLoginAddress();
}
// Last resort - Getting the first result from the username itself
else
{
PlayerData entry = plugin.pl.getData(args[0]);
if (entry == null) if (entry == null)
{ {
msg(PLAYER_NOT_FOUND); msg("Can't find that user. If target is not logged in, make sure that you spelled the name exactly.");
return true; return true;
} }
else
{
username = entry.getName(); username = entry.getName();
ip = entry.getIps().get(0); ips.addAll(entry.getIps());
}
}
} }
else else
{ {
final PlayerData entry = plugin.pl.getData(player);
username = player.getName(); username = player.getName();
ip = FUtil.getIp(player); //ips.addAll(entry.getIps());/
ips.add(FUtil.getIp(player));
// Deop // Deop
player.setOp(false); player.setOp(false);
@ -137,6 +126,7 @@ public class Command_ban extends FreedomCommand
// Ban player // Ban player
Ban ban; Ban ban;
if (player != null) if (player != null)
{ {
ban = Ban.forPlayer(player, sender, null, reason); ban = Ban.forPlayer(player, sender, null, reason);
@ -145,8 +135,12 @@ public class Command_ban extends FreedomCommand
{ {
ban = Ban.forPlayerName(username, sender, null, reason); ban = Ban.forPlayerName(username, sender, null, reason);
} }
ban.addIp(ip);
for (String ip : ips)
{
ban.addIp(ip);
ban.addIp(FUtil.getFuzzyIp(ip));
}
plugin.bm.addBan(ban); plugin.bm.addBan(ban);
@ -160,7 +154,7 @@ public class Command_ban extends FreedomCommand
{ {
bcast.append(" - Reason: ").append(ChatColor.YELLOW).append(reason); bcast.append(" - Reason: ").append(ChatColor.YELLOW).append(reason);
} }
msg(sender, ChatColor.GRAY + username + " has been banned and IP is: " + ip); msg(sender, ChatColor.GRAY + username + " has been banned and IP is: " + StringUtils.join(ips, ", "));
FUtil.adminAction(sender.getName(), bcast.toString(), true); FUtil.adminAction(sender.getName(), bcast.toString(), true);
} }
@ -178,7 +172,7 @@ public class Command_ban extends FreedomCommand
} }
// Log ban // Log ban
plugin.pul.logPunishment(new Punishment(username, ip, sender.getName(), PunishmentType.BAN, reason)); plugin.pul.logPunishment(new Punishment(username, ips.get(0), sender.getName(), PunishmentType.BAN, reason));
return true; return true;
} }

View File

@ -77,26 +77,13 @@ public class Command_cage extends FreedomCommand
} }
case "block": case "block":
{ {
if (args.length >= 3) if (Material.matchMaterial(args[2]) != null)
{
// Checks the validity of the Material and checks if it's a block.
// This is incredibly inefficient, as Spigot's isBlock() method in Material is an actual
// nightmare of switch-cases.
if (Material.matchMaterial(args[2]) != null && Material.matchMaterial(args[2]).isBlock())
{ {
outerMaterial = Material.matchMaterial(args[2]); outerMaterial = Material.matchMaterial(args[2]);
break; break;
} }
else
{
msg("Invalid block!", ChatColor.RED); msg("Invalid block!", ChatColor.RED);
return true; break;
}
}
else
{
return false;
}
} }
default: default:
{ {

View File

@ -8,7 +8,7 @@ import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH) @CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Clears the chat.", usage = "/<command>", aliases = "cc") @CommandParameters(description = "Clears the chat.", usage = "/<command>", aliases = "cc")
public class Command_cleanchat extends FreedomCommand public class Command_clearchat extends FreedomCommand
{ {
@Override @Override

View File

@ -9,11 +9,8 @@ import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.List;
@CommandPermissions(level = Rank.OP, source = SourceType.BOTH) @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 public class Command_coins extends FreedomCommand
{ {
@Override @Override
@ -24,119 +21,34 @@ public class Command_coins extends FreedomCommand
msg("The shop is currently disabled!", ChatColor.RED); msg("The shop is currently disabled!", ChatColor.RED);
return true; return true;
} }
Player p;
final String prefix = FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " "); final String prefix = FUtil.colorize(ConfigEntry.SHOP_PREFIX.getString() + " ");
if (args.length > 0)
switch (args.length)
{ {
// Mode for seeing how many coins the sender has (doesn't work from console) if (getPlayer(args[0]) != null)
case 0: {
p = getPlayer(args[0]);
}
else
{
msg(PLAYER_NOT_FOUND);
return true;
}
}
else
{ {
if (senderIsConsole) 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 else
{ {
PlayerData playerData = getData(playerSender); p = playerSender;
msg(prefix + ChatColor.GREEN + "You have " + ChatColor.RED + playerData.getCoins() + ChatColor.GREEN
+ " coins.");
} }
}
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; 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);
}
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

@ -1,5 +1,6 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import java.util.Objects;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.banning.Ban; import me.totalfreedom.totalfreedommod.banning.Ban;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -42,7 +43,7 @@ public class Command_doom extends FreedomCommand
FUtil.adminAction(sender.getName(), "Casting oblivion over " + player.getName(), true); FUtil.adminAction(sender.getName(), "Casting oblivion over " + player.getName(), true);
FUtil.bcastMsg(player.getName() + " will be completely obliviated!", ChatColor.RED); FUtil.bcastMsg(player.getName() + " will be completely obliviated!", ChatColor.RED);
final String ip = FUtil.getIp(player); final String ip = Objects.requireNonNull(player.getAddress()).getAddress().getHostAddress().trim();
// Remove from admin // Remove from admin
Admin admin = getAdmin(player); Admin admin = getAdmin(player);
@ -75,7 +76,10 @@ public class Command_doom extends FreedomCommand
// Ban player // Ban player
Ban ban = Ban.forPlayer(player, sender); Ban ban = Ban.forPlayer(player, sender);
ban.setReason((reason == null ? "FUCKOFF" : reason)); ban.setReason((reason == null ? "FUCKOFF" : reason));
ban.addIp(ip); for (String playerIp : plugin.pl.getData(player).getIps())
{
ban.addIp(playerIp);
}
plugin.bm.addBan(ban); plugin.bm.addBan(ban);
// Set gamemode to survival // Set gamemode to survival

View File

@ -1,50 +1,40 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import org.apache.commons.lang.StringUtils;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME) @CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Eject any entities that are riding you.", usage = "/<command>") @CommandParameters(description = "Eject players that are riding you.", usage = "/<command>")
public class Command_eject extends FreedomCommand public class Command_eject extends FreedomCommand
{ {
/* Player.getShoulderEntityLeft() and Player.getShoulderEntityRight() are deprecated, however unless
Player.getPassengers() also includes shoulders (which isn't likely, given the official documentation doesn't
state an alternative method to use instead), these methods will continue to be used here. */
@SuppressWarnings("deprecation")
@Override @Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{ {
// Uses the size of the return value of Player.getPassengers() as the starting number of entities ejected
int count = playerSender.getPassengers().size();
// Removes any entities from the sender's shoulders List<String> names = new ArrayList<>();
if (playerSender.getShoulderEntityLeft() != null)
for (Entity entity : playerSender.getPassengers())
{ {
playerSender.setShoulderEntityLeft(null); names.add(entity.getName());
count++;
}
if (playerSender.getShoulderEntityRight() != null)
{
playerSender.setShoulderEntityLeft(null);
count++;
} }
// Removes anything riding the sender if (names.isEmpty())
playerSender.eject();
if (count != 0)
{
msg(count + " entit" + (count == 1 ? "y was" : "ies were") + " ejected.", ChatColor.GREEN);
}
else
{ {
msg("Nothing was ejected.", ChatColor.GREEN); msg("Nothing was ejected.", ChatColor.GREEN);
return true;
} }
msg("Ejecting " + StringUtils.join(names, ", ") + ".", ChatColor.GREEN);
playerSender.eject();
return true; return true;
} }
} }

View File

@ -18,7 +18,7 @@ public class Command_linkdiscord extends FreedomCommand
{ {
if (!plugin.dc.enabled) 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; return true;
} }
@ -32,7 +32,7 @@ public class Command_linkdiscord extends FreedomCommand
} }
playerData.setDiscordID(args[1]); playerData.setDiscordID(args[1]);
msg("Linked " + args[0] + "'s Discord account.", ChatColor.GREEN); msg("Linked " + args[0] + "'s discord account.", ChatColor.GREEN);
return true; return true;
} }

View File

@ -15,8 +15,8 @@ import org.bukkit.entity.Player;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@CommandPermissions(level = Rank.NON_OP, source = SourceType.BOTH) @CommandPermissions(level = Rank.IMPOSTOR, source = SourceType.BOTH)
@CommandParameters(description = "Lists the real names of all online players.", usage = "/<command> [-s | -f | -v]", aliases = "who,lsit") @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 public class Command_list extends FreedomCommand
{ {
@ -63,6 +63,11 @@ public class Command_list extends FreedomCommand
listFilter = ListFilter.TELNET_SESSIONS; listFilter = ListFilter.TELNET_SESSIONS;
break; break;
} }
case "-i":
{
listFilter = ListFilter.IMPOSTORS;
break;
}
case "-f": case "-f":
{ {
listFilter = ListFilter.FAMOUS_PLAYERS; listFilter = ListFilter.FAMOUS_PLAYERS;
@ -117,6 +122,10 @@ public class Command_list extends FreedomCommand
{ {
continue; continue;
} }
if (listFilter == ListFilter.IMPOSTORS && !plugin.al.isAdminImpostor(p))
{
continue;
}
if (listFilter == ListFilter.FAMOUS_PLAYERS && !ConfigEntry.FAMOUS_PLAYERS.getList().contains(p.getName().toLowerCase())) if (listFilter == ListFilter.FAMOUS_PLAYERS && !ConfigEntry.FAMOUS_PLAYERS.getList().contains(p.getName().toLowerCase()))
{ {
continue; continue;
@ -155,6 +164,7 @@ public class Command_list extends FreedomCommand
ADMINS, ADMINS,
VANISHED_ADMINS, VANISHED_ADMINS,
TELNET_SESSIONS, TELNET_SESSIONS,
FAMOUS_PLAYERS FAMOUS_PLAYERS,
IMPOSTORS
} }
} }

View File

@ -0,0 +1,96 @@
package me.totalfreedom.totalfreedommod.command;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldguard.domains.DefaultDomain;
import com.sk89q.worldguard.protection.flags.Flag;
import com.sk89q.worldguard.protection.flags.Flags;
import com.sk89q.worldguard.protection.flags.RegionGroup;
import com.sk89q.worldguard.protection.flags.StateFlag;
import com.sk89q.worldguard.protection.managers.RegionManager;
import com.sk89q.worldguard.protection.regions.ProtectedCuboidRegion;
import com.sk89q.worldguard.protection.regions.ProtectedRegion;
import java.util.HashMap;
import java.util.Map;
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.ONLY_IN_GAME)
@CommandParameters(description = "Make a WorldGuard region for an OP.", usage = "/<command> <playername> <name>", aliases = "mor")
public class Command_makeopregion extends FreedomCommand
{
final Map<Flag<?>, Object> flags = new HashMap<Flag<?>, Object>()
{{
put(Flags.BLOCK_PLACE, StateFlag.State.ALLOW);
put(Flags.BLOCK_BREAK, StateFlag.State.ALLOW);
put(Flags.BUILD, StateFlag.State.ALLOW);
put(Flags.PLACE_VEHICLE, StateFlag.State.ALLOW);
put(Flags.DESTROY_VEHICLE, StateFlag.State.ALLOW);
put(Flags.ENTITY_ITEM_FRAME_DESTROY, StateFlag.State.ALLOW);
put(Flags.ENTITY_PAINTING_DESTROY, StateFlag.State.ALLOW);
put(net.goldtreeservers.worldguardextraflags.flags.Flags.WORLDEDIT, StateFlag.State.ALLOW);
}};
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
if (args.length < 2)
{
return false;
}
final Player player = getPlayer(args[0]);
if (player == null)
{
msg(FreedomCommand.PLAYER_NOT_FOUND);
return true;
}
String name = args[1];
LocalSession session = plugin.web.getWorldEditPlugin().getSession(playerSender);
Region selection;
try
{
selection = session.getSelection(session.getSelectionWorld());
}
catch (IncompleteRegionException e)
{
msg("Please make a WorldEdit selection", ChatColor.RED);
return true;
}
if (selection == null)
{
msg("Please make a WorldEdit selection", ChatColor.RED);
return true;
}
ProtectedRegion region = new ProtectedCuboidRegion(name, selection.getMinimumPoint(), selection.getMaximumPoint());
DefaultDomain owners = new DefaultDomain();
owners.addPlayer(playerSender.getName());
owners.addPlayer(player.getName());
region.setOwners(owners);
region.setFlags(flags);
for (Flag<?> flag : flags.keySet())
{
region.setFlag(flag.getRegionGroupFlag(), RegionGroup.MEMBERS);
}
RegionManager regionManager = plugin.wgb.getRegionManager(playerSender.getWorld());
regionManager.addRegion(region);
msg("Successfully created the region '" + name + "' for " + player.getName(), ChatColor.GREEN);
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; 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); FUtil.adminAction(sender.getName(), "Adding " + data.getName() + " to the Master Builder list", true);
data.setMasterBuilder(true); data.setMasterBuilder(true);
data.setVerification(true);
plugin.pl.save(data); plugin.pl.save(data);
if (player != null) if (player != null)
{ {
plugin.rm.updateDisplay(player); plugin.rm.updateDisplay(player);
} }
return true;
} }
else else
{ {
msg("That player is already on the Master Builder list."); msg("That player is already on the Master Builder list.");
}
return true; return true;
} }
}
case "remove": case "remove":
{ {
if (args.length < 2) 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); FUtil.adminAction(sender.getName(), "Removing " + data.getName() + " from the Master Builder list", true);
data.setMasterBuilder(false); data.setMasterBuilder(false);
if (data.getDiscordID() == null)
{
data.setVerification(false);
}
plugin.pl.save(data); plugin.pl.save(data);
if (player != null) if (player != null)
{ {

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

@ -130,19 +130,17 @@ public class Command_mute extends FreedomCommand
{ {
playerdata.setMuted(true); playerdata.setMuted(true);
player.sendTitle(ChatColor.RED + "You've been muted.", ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60); player.sendTitle(ChatColor.RED + "You've been muted.", ChatColor.YELLOW + "Be sure to follow the rules!", 20, 100, 60);
if (quiet)
{
msg("Muted " + player.getName() + " quietly");
return true; // doesn't announce reason
}
FUtil.adminAction(sender.getName(), "Muting " + player.getName(), true);
if (reason != null) if (reason != null)
{ {
msg(player, ChatColor.RED + "Reason: " + ChatColor.YELLOW + reason); msg(player, ChatColor.RED + "Reason: " + ChatColor.YELLOW + reason);
} }
if (quiet)
{
msg("Muted " + player.getName() + " quietly");
return true;
}
FUtil.adminAction(sender.getName(), "Muting " + player.getName(), true);
if (smite) if (smite)
{ {

View File

@ -24,10 +24,6 @@ public class Command_opall extends FreedomCommand
msg(player, YOU_ARE_OP); msg(player, YOU_ARE_OP);
plugin.rm.updateDisplay(player); plugin.rm.updateDisplay(player);
} }
else
{
player.recalculatePermissions();
}
} }
return true; return true;

View File

@ -17,11 +17,9 @@ import org.bukkit.entity.Player;
@CommandParameters(description = "Manage your Pterodactyl panel account", usage = "/<command> <create | delete>") @CommandParameters(description = "Manage your Pterodactyl panel account", usage = "/<command> <create | delete>")
public class Command_panel extends FreedomCommand public class Command_panel extends FreedomCommand
{ {
@Override @Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{ {
if (!plugin.ptero.isEnabled()) if (!plugin.ptero.isEnabled())
{ {
msg("Pterodactyl integration is currently disabled.", ChatColor.RED); msg("Pterodactyl integration is currently disabled.", ChatColor.RED);
@ -32,7 +30,7 @@ public class Command_panel extends FreedomCommand
if (playerData.getDiscordID() == null) if (playerData.getDiscordID() == null)
{ {
msg("You must have a linked discord account.", ChatColor.RED); msg("You must have a linked Discord account.", ChatColor.RED);
return true; return true;
} }
@ -63,13 +61,11 @@ public class Command_panel extends FreedomCommand
} }
plugin.ptero.addAccountToServer(id); plugin.ptero.addAccountToServer(id);
admin.setPteroID(id); admin.setPteroID(id);
plugin.al.save(admin); plugin.al.save(admin);
plugin.al.updateTables(); plugin.al.updateTables();
plugin.dc.sendPteroInfo(playerData, username, password); 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); msg("Successfully created your Pterodactyl account. Check your DMs from " + plugin.dc.formatBotTag() + " on Discord to get your credentials.", ChatColor.GREEN);
return true; return true;
} }
else if (args[0].equalsIgnoreCase("delete")) else if (args[0].equalsIgnoreCase("delete"))
@ -83,18 +79,10 @@ public class Command_panel extends FreedomCommand
return true; return true;
} }
boolean deleted = plugin.ptero.deleteAccount(admin.getPteroID()); plugin.ptero.deleteAccount(admin.getPteroID());
if (!deleted)
{
msg("Failed to delete your Pterodactyl account.", ChatColor.RED);
return true;
}
admin.setPteroID(null); admin.setPteroID(null);
plugin.al.save(admin); plugin.al.save(admin);
plugin.al.updateTables(); plugin.al.updateTables();
msg("Successfully deleted your Pterodactyl account.", ChatColor.GREEN); msg("Successfully deleted your Pterodactyl account.", ChatColor.GREEN);
return true; return true;
} }

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

@ -0,0 +1,41 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Release parrots from your shoulders.", usage = "/<command>", aliases = "removeparrots")
public class Command_releaseparrots extends FreedomCommand
{
@SuppressWarnings("deprecation")
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
Entity leftShoulderEntity = playerSender.getShoulderEntityLeft();
Entity rightShoulderEntity = playerSender.getShoulderEntityRight();
if (rightShoulderEntity == null && leftShoulderEntity == null)
{
msg("No parrots were detected on either of your shoulders.");
return true;
}
if (leftShoulderEntity != null && leftShoulderEntity.getType().equals(EntityType.PARROT))
{
playerSender.setShoulderEntityLeft(null);
msg("Removed the parrot on your left shoulder.");
}
if (rightShoulderEntity != null && rightShoulderEntity.getType().equals(EntityType.PARROT))
{
playerSender.setShoulderEntityRight(null);
msg("Removed the parrot on your right shoulder.");
}
return true;
}
}

View File

@ -0,0 +1,77 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.HashMap;
import java.util.Map;
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;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Restart the server", usage = "/<command> [reason]")
public class Command_restart extends FreedomCommand
{
private static final Map<CommandSender, String> RESTART_CONFIRM = new HashMap<>();
@Override
public boolean run(final CommandSender sender, final Player playerSender, final Command cmd, final String commandLabel, final String[] args, final boolean senderIsConsole)
{
if (!plugin.ptero.isEnabled())
{
msg("Pterodactyl integration is currently disabled.", ChatColor.RED);
return true;
}
String reason = "Server is restarting!";
if (args.length != 0)
{
reason = StringUtils.join(args, " ");
}
if (sender.getName().equals("CONSOLE"))
{
restart(reason);
return true;
}
else if (RESTART_CONFIRM.containsKey(sender))
{
restart(RESTART_CONFIRM.get(sender));
return true;
}
msg("Warning: You're about to restart the server. Type /restart again to confirm you want to do this.");
RESTART_CONFIRM.put(sender, reason);
new BukkitRunnable()
{
@Override
public void run()
{
if (RESTART_CONFIRM.containsKey(sender))
{
RESTART_CONFIRM.remove(sender);
msg("Restart request expired.");
}
}
}.runTaskLater(plugin, 15 * 20);
return true;
}
public void restart(String reason)
{
FUtil.bcastMsg("Server is restarting!", ChatColor.LIGHT_PURPLE);
for (Player player : server.getOnlinePlayers())
{
player.kickPlayer(ChatColor.LIGHT_PURPLE + reason);
}
RESTART_CONFIRM.remove(sender);
plugin.ptero.restartServer();
}
}

View File

@ -187,6 +187,12 @@ public class Command_saconfig extends FreedomCommand
} }
} }
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 if (admin == null) // New admin
{ {
@ -199,10 +205,23 @@ public class Command_saconfig extends FreedomCommand
else // Existing admin else // Existing admin
{ {
FUtil.adminAction(sender.getName(), "Re-adding " + player.getName() + " to the admin list", true); 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.addIp(FUtil.getIp(player));
admin.setActive(true); admin.setActive(true);
admin.setLastLogin(new Date()); admin.setLastLogin(new Date());
if (plugin.al.isVerifiedAdmin(player))
{
plugin.al.verifiedNoAdmin.remove(player.getName());
}
plugin.al.save(admin); plugin.al.save(admin);
plugin.al.updateTables(); plugin.al.updateTables();
plugin.rm.updateDisplay(player); plugin.rm.updateDisplay(player);

View File

@ -1,97 +0,0 @@
package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank;
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 java.util.ArrayList;
import java.util.List;
@CommandPermissions(level = Rank.NON_OP, source = SourceType.BOTH)
@CommandParameters(description = "Get the seed of the world you are currently in.", usage = "/seed [world]")
public class Command_seed extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
World world;
if (args.length > 0)
{
world = server.getWorld(args[0]);
if (world == null)
{
msg("That world could not be found", ChatColor.RED);
return true;
}
}
else
{
// If the sender is a Player, use that world. Otherwise, use the overworld as a fallback.
if (!senderIsConsole)
{
world = playerSender.getWorld();
}
else
{
world = server.getWorlds().get(0);
}
}
// 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;
}
@Override
public List<String> getTabCompleteOptions(CommandSender sender, Command command, String alias, String[] args)
{
if (args.length == 1)
{
// 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

@ -0,0 +1,49 @@
package me.totalfreedom.totalfreedommod.command;
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.OP, source = SourceType.ONLY_IN_GAME)
@CommandParameters(description = "Sets your experience level (XP).", usage = "/<command> [level]")
public class Command_setlevel extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length != 1)
{
return false;
}
int new_level;
try
{
new_level = Integer.parseInt(args[0]);
if (new_level < 0)
{
new_level = 0;
}
else if (new_level > 50)
{
new_level = 50;
}
}
catch (NumberFormatException ex)
{
msg("Invalid level.", ChatColor.RED);
return true;
}
playerSender.setLevel(new_level);
msg("Your XP level is now set to " + ChatColor.GOLD + new_level);
return true;
}
}

View File

@ -1,8 +1,6 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import java.util.List; import java.util.List;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang3.EnumUtils; import org.apache.commons.lang3.EnumUtils;
@ -57,7 +55,6 @@ public class Command_spawnmob extends FreedomCommand
return true; return true;
} }
int max = ConfigEntry.SPAWNMOB_MAX.getInteger();
int amount = 1; int amount = 1;
if (args.length > 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; return true;
} }

View File

@ -20,7 +20,6 @@ public class Command_stop extends FreedomCommand
@Override @Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{ {
String reason = "Server is going offline, come back in about 20 seconds."; String reason = "Server is going offline, come back in about 20 seconds.";
if (args.length != 0) if (args.length != 0)
@ -39,7 +38,6 @@ public class Command_stop extends FreedomCommand
return true; return true;
} }
msg("Warning: You're about to stop the server. Type /stop again to confirm you want to do this."); msg("Warning: You're about to stop the server. Type /stop again to confirm you want to do this.");
STOP_CONFIRM.put(sender, reason); STOP_CONFIRM.put(sender, reason);
@ -69,6 +67,13 @@ public class Command_stop extends FreedomCommand
STOP_CONFIRM.remove(sender); STOP_CONFIRM.remove(sender);
if (plugin.ptero.isEnabled())
{
plugin.ptero.stopServer();
}
else
{
server.shutdown(); server.shutdown();
} }
}
} }

View File

@ -0,0 +1,143 @@
package me.totalfreedom.totalfreedommod.command;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import me.totalfreedom.totalfreedommod.banning.Ban;
import me.totalfreedom.totalfreedommod.player.PlayerData;
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.StringUtils;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH, blockHostConsole = true)
@CommandParameters(description = "Temporarily bans a player for five minutes.", usage = "/<command> [-q] <username> [reason]", aliases = "noob")
public class Command_tban extends FreedomCommand
{
@Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole)
{
if (args.length == 0)
{
return false;
}
boolean quiet = args[0].equalsIgnoreCase("-q");
if (quiet)
{
args = org.apache.commons.lang3.ArrayUtils.subarray(args, 1, args.length);
if (args.length < 1)
{
return false;
}
}
final String username;
final Player player = getPlayer(args[0]);
final PlayerData entry;
if (player == null)
{
entry = plugin.pl.getData(args[0]);
if (entry == null)
{
msg("Can't find that user. If target is not logged in, make sure that you spelled the name exactly.");
return true;
}
username = entry.getName();
}
else
{
entry = plugin.pl.getData(player);
username = player.getName();
}
final List<String> ips = new ArrayList<>(entry.getIps());
String reason = null;
if (args.length > 1)
{
reason = StringUtils.join(args, " ", 1, args.length);
}
StringBuilder kick = new StringBuilder()
.append(ChatColor.RED)
.append("You have been temporarily banned for five minutes. Please read totalfreedom.me for more info.");
if (!quiet)
{
// Strike with lightning
if (player != null)
{
final Location targetPos = player.getLocation();
for (int x = -1; x <= 1; x++)
{
for (int z = -1; z <= 1; z++)
{
final Location strike_pos = new Location(targetPos.getWorld(), targetPos.getBlockX() + x, targetPos.getBlockY(), targetPos.getBlockZ() + z);
Objects.requireNonNull(targetPos.getWorld()).strikeLightning(strike_pos);
}
}
// Kill player
player.setHealth(0.0);
if (reason != null)
{
FUtil.adminAction(sender.getName(), "Tempbanning " + player.getName() + " for 5 minutes - Reason: " + reason, true);
kick.append("\n")
.append(ChatColor.RED)
.append("Reason: ")
.append(ChatColor.GOLD)
.append(reason);
}
else
{
FUtil.adminAction(sender.getName(), "Tempbanning " + player.getName() + " for 5 minutes", true);
}
}
}
else
{
if (player != null)
{
if (reason != null)
{
msg("Quietly temporarily banned " + player.getName() + " for 5 minutes.");
kick.append("\n")
.append(ChatColor.RED)
.append("Reason: ")
.append(ChatColor.GOLD)
.append(reason);
}
}
}
// Ban player
Ban ban = Ban.forPlayerName(username, sender, FUtil.parseDateOffset("5m"), reason);
for (String ip : ips)
{
ban.addIp(ip);
}
plugin.bm.addBan(ban);
// Kick player
if (player != null)
{
player.kickPlayer(kick.toString());
}
// Log ban
plugin.pul.logPunishment(new Punishment(username, ips.get(0), sender.getName(), PunishmentType.TEMPBAN, reason));
return true;
}
}

View File

@ -1,10 +1,10 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import java.util.Objects; import java.util.Objects;
import com.earth2me.essentials.User;
import me.totalfreedom.totalfreedommod.banning.Ban; import me.totalfreedom.totalfreedommod.banning.Ban;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.punishments.Punishment; import me.totalfreedom.totalfreedommod.punishments.Punishment;
@ -21,7 +21,7 @@ import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH) @CommandPermissions(level = Rank.ADMIN, source = SourceType.BOTH)
@CommandParameters(description = "Temporarily ban someone.", usage = "/<command> [-q] <username> [duration] [reason]", aliases = "tban,noob") @CommandParameters(description = "Temporarily ban someone.", usage = "/<command> [-q] <username> [duration] [reason]")
public class Command_tempban extends FreedomCommand public class Command_tempban extends FreedomCommand
{ {
@ -47,72 +47,49 @@ public class Command_tempban extends FreedomCommand
} }
final String username; final String username;
final String ip; final List<String> ips = new ArrayList<>();
final Player player = getPlayer(args[0]); final Player player = getPlayer(args[0]);
PlayerData entry; final PlayerData entry;
if (player == null) if (player == null)
{
// Gets the IP using Essentials data if available
if (plugin.esb.isEnabled() && plugin.esb.getEssentialsUser(args[0]) != null)
{
User essUser = plugin.esb.getEssentialsUser(args[0]);
//
username = essUser.getName();
ip = essUser.getLastLoginAddress();
}
// Last resort - Getting the first result from the username itself
else
{ {
entry = plugin.pl.getData(args[0]); entry = plugin.pl.getData(args[0]);
if (entry == null) if (entry == null)
{ {
msg(PLAYER_NOT_FOUND); msg("Can't find that user. If target is not logged in, make sure that you spelled the name exactly.");
return true; return true;
} }
else
{
username = entry.getName(); username = entry.getName();
ip = entry.getIps().get(0); ips.addAll(entry.getIps());
}
}
} }
else else
{ {
entry = plugin.pl.getData(player);
username = player.getName(); username = player.getName();
ip = FUtil.getIp(player); ips.add(FUtil.getIp(player));
} }
final StringBuilder message = new StringBuilder("Temporarily banned " + username); final StringBuilder message = new StringBuilder("Temporarily banned " + username);
// Default expiration date is 5 minutes Date expires = FUtil.parseDateOffset("30m");
Date expires = FUtil.parseDateOffset("5m");
// Parses what comes after as a duration
if (args.length > 1)
{
try
{
expires = FUtil.parseDateOffset(args[1]);
}
catch (NumberFormatException error)
{
msg("Invalid duration: " + args[1], ChatColor.RED);
return true;
}
}
message.append(" until ").append(date_format.format(expires)); message.append(" until ").append(date_format.format(expires));
// If a reason appears to exist, set it.
String reason = null; String reason = null;
if (args.length > 2) if (args.length >= 2)
{ {
reason = StringUtils.join(ArrayUtils.subarray(args, 2, args.length), " ") + " (" + sender.getName() + ")"; Date parsed_offset = FUtil.parseDateOffset(args[1]);
reason = StringUtils.join(ArrayUtils.subarray(args, parsed_offset == null ? 1 : 2, args.length), " ") + " (" + sender.getName() + ")";
if (parsed_offset != null)
{
expires = parsed_offset;
}
message.append(", Reason: \"").append(reason).append("\""); message.append(", Reason: \"").append(reason).append("\"");
} }
Ban ban; Ban ban;
if (player != null) if (player != null)
{ {
ban = Ban.forPlayer(player, sender, expires, reason); ban = Ban.forPlayer(player, sender, expires, reason);
@ -121,8 +98,11 @@ public class Command_tempban extends FreedomCommand
{ {
ban = Ban.forPlayerName(username, sender, expires, reason); ban = Ban.forPlayerName(username, sender, expires, reason);
} }
ban.addIp(ip);
for (String ip : ips)
{
ban.addIp(ip);
}
plugin.bm.addBan(ban); plugin.bm.addBan(ban);
if (!quiet) if (!quiet)
@ -139,8 +119,6 @@ public class Command_tempban extends FreedomCommand
Objects.requireNonNull(targetPos.getWorld()).strikeLightningEffect(strike_pos); Objects.requireNonNull(targetPos.getWorld()).strikeLightningEffect(strike_pos);
} }
} }
player.kickPlayer(ban.bakeKickMessage());
} }
FUtil.adminAction(sender.getName(), message.toString(), true); FUtil.adminAction(sender.getName(), message.toString(), true);
@ -150,15 +128,19 @@ public class Command_tempban extends FreedomCommand
msg("Quietly temporarily banned " + username + "."); msg("Quietly temporarily banned " + username + ".");
} }
if (player != null)
{
player.kickPlayer(ban.bakeKickMessage());
for (Player p : Bukkit.getOnlinePlayers()) for (Player p : Bukkit.getOnlinePlayers())
{ {
if (FUtil.getIp(p).equals(ip)) if (FUtil.getIp(p).equals(FUtil.getIp(player)))
{ {
p.kickPlayer(ChatColor.RED + "You've been kicked because someone on your IP has been banned."); p.kickPlayer(ChatColor.RED + "You've been kicked because someone on your IP has been banned.");
} }
} }
}
plugin.pul.logPunishment(new Punishment(username, ip, sender.getName(), PunishmentType.TEMPBAN, reason)); plugin.pul.logPunishment(new Punishment(username, ips.get(0), sender.getName(), PunishmentType.TEMPBAN, reason));
return true; return true;
} }
} }

View File

@ -1,13 +1,11 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import me.totalfreedom.totalfreedommod.rank.Rank; 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.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; 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>") @CommandParameters(description = "Trails rainbow wool behind you as you walk/fly.", usage = "/<command>")
public class Command_trail extends FreedomCommand public class Command_trail extends FreedomCommand
{ {
@ -15,12 +13,6 @@ public class Command_trail extends FreedomCommand
@Override @Override
public boolean run(CommandSender sender, Player playerSender, Command cmd, String commandLabel, String[] args, boolean senderIsConsole) 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)) if (plugin.tr.contains(playerSender))
{ {
plugin.tr.remove(playerSender); plugin.tr.remove(playerSender);
@ -29,7 +21,7 @@ public class Command_trail extends FreedomCommand
else else
{ {
plugin.tr.add(playerSender); plugin.tr.add(playerSender);
msg("Trail enabled. Run this command again to disable it."); msg("Trail enabled. Use \"/trail off\" to disable.");
} }
return true; return true;

View File

@ -1,9 +1,12 @@
package me.totalfreedom.totalfreedommod.command; package me.totalfreedom.totalfreedommod.command;
import com.earth2me.essentials.User; import java.util.ArrayList;
import java.util.List;
import me.totalfreedom.totalfreedommod.banning.Ban;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -19,33 +22,20 @@ public class Command_unban extends FreedomCommand
if (args.length > 0) if (args.length > 0)
{ {
String username; String username;
String ip;
// Gets the IP using Essentials data if available
if (plugin.esb.isEnabled() && plugin.esb.getEssentialsUser(args[0]) != null)
{
User essUser = plugin.esb.getEssentialsUser(args[0]);
//
username = essUser.getName();
ip = essUser.getLastLoginAddress();
}
// Secondary method - using Essentials if available
else
{
final PlayerData entry = plugin.pl.getData(args[0]); final PlayerData entry = plugin.pl.getData(args[0]);
if (entry == null) if (entry == null)
{ {
msg(PLAYER_NOT_FOUND); msg("Can't find that user. If target is not logged in, make sure that you spelled the name exactly.");
return true; return true;
} }
username = entry.getName(); username = entry.getName();
ip = entry.getIps().get(0); final List<String> ips = new ArrayList<>(entry.getIps());
}
FUtil.adminAction(sender.getName(), "Unbanning " + username, true); FUtil.adminAction(sender.getName(), "Unbanning " + username, true);
msg(username + " has been unbanned along with the following IPs: " + StringUtils.join(ips, ", "));
plugin.bm.removeBan(plugin.bm.getByUsername(username)); plugin.bm.removeBan(plugin.bm.getByUsername(username));
plugin.bm.removeBan(plugin.bm.getByIp(ip));
msg(username + " has been unbanned along with the IP: " + ip);
if (args.length >= 2) if (args.length >= 2)
{ {
@ -55,6 +45,20 @@ public class Command_unban extends FreedomCommand
msg("Restored edits for: " + username); msg("Restored edits for: " + username);
} }
} }
for (String ip : ips)
{
Ban ban = plugin.bm.getByIp(ip);
if (ban != null)
{
plugin.bm.removeBan(ban);
}
ban = plugin.bm.getByIp(FUtil.getFuzzyIp(ip));
if (ban != null)
{
plugin.bm.removeBan(ban);
}
}
return true; return true;
} }
return false; return false;

View File

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

@ -5,6 +5,7 @@ import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.DepreciationAggregator;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.OfflinePlayer; import org.bukkit.OfflinePlayer;
import org.bukkit.command.Command; import org.bukkit.command.Command;
@ -94,7 +95,7 @@ public class Command_whitelist extends FreedomCommand
if (player == null) 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); FUtil.adminAction(sender.getName(), "Adding " + player.getName() + " to the whitelist", false);
@ -116,7 +117,7 @@ public class Command_whitelist extends FreedomCommand
if (player == null) if (player == null)
{ {
player = server.getOfflinePlayer(search_name); player = DepreciationAggregator.getOfflinePlayer(server, search_name);
} }
if (player.isWhitelisted()) if (player.isWhitelisted())
@ -157,7 +158,7 @@ public class Command_whitelist extends FreedomCommand
if (args[0].equalsIgnoreCase("purge")) if (args[0].equalsIgnoreCase("purge"))
{ {
FUtil.adminAction(sender.getName(), "Removing all players from the whitelist", false); 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 true;
} }
return false; return false;
@ -197,21 +198,10 @@ public class Command_whitelist extends FreedomCommand
public List<String> getWhitelistedNames() public List<String> getWhitelistedNames()
{ {
List<String> names = new ArrayList<>(); List<String> names = new ArrayList<>();
for (OfflinePlayer player : server.getWhitelistedPlayers()) for (Object name : plugin.si.getWhitelisted())
{ {
names.add(player.getName()); names.add(String.valueOf(name));
} }
return names; return names;
} }
public int purge()
{
int removed = 0;
for (OfflinePlayer player : server.getWhitelistedPlayers())
{
player.setWhitelisted(false);
removed++;
}
return removed;
}
} }

View File

@ -13,15 +13,19 @@ import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Server; 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.entity.Player;
import org.bukkit.plugin.Plugin;
import org.bukkit.util.StringUtil; import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@ -36,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 String NO_PERMISSION = ChatColor.RED + "You do not have permission to execute this command.";
public static final Timer timer = new Timer(); public static final Timer timer = new Timer();
public static final Map<CommandSender, FreedomCommand> COOLDOWN_TIMERS = new HashMap<>(); public static final Map<CommandSender, FreedomCommand> COOLDOWN_TIMERS = new HashMap<>();
private static CommandMap commandMap;
protected final TotalFreedomMod plugin = TotalFreedomMod.getPlugin(); protected final TotalFreedomMod plugin = TotalFreedomMod.getPlugin();
protected final Server server = plugin.getServer(); protected final Server server = plugin.getServer();
private final String name; private final String name;
@ -43,8 +48,6 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
private final String usage; private final String usage;
private final String aliases; private final String aliases;
private final Rank level; private final Rank level;
private final String permission;
private final SourceType source; private final SourceType source;
private final boolean blockHostConsole; private final boolean blockHostConsole;
private final int cooldown; private final int cooldown;
@ -61,28 +64,39 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
this.usage = params.usage(); this.usage = params.usage();
this.aliases = params.aliases(); this.aliases = params.aliases();
this.level = perms.level(); this.level = perms.level();
this.permission = perms.permission().isEmpty() ? "totalfreedommod." + this.name.toLowerCase() : perms.permission();
this.source = perms.source(); this.source = perms.source();
this.blockHostConsole = perms.blockHostConsole(); this.blockHostConsole = perms.blockHostConsole();
this.cooldown = perms.cooldown(); 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) public static FreedomCommand getFrom(Command command)
{ {
try try
{ {
if (command instanceof FCommand) return (FreedomCommand)(((PluginCommand)command).getExecutor());
{
return ((FCommand) command).getExecutor();
}
} }
catch (Exception ex) catch (Exception ex)
{ {
FLog.severe(ex);
return null; return null;
} }
return null;
} }
public static String getCommandPrefix() public static String getCommandPrefix()
@ -105,7 +119,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
{ {
cmd.setUsage(this.usage); cmd.setUsage(this.usage);
} }
server.getCommandMap().register("totalfreedommod", cmd); getCommandMap().register("totalfreedommod", cmd);
cmd.setExecutor(this); cmd.setExecutor(this);
} }
@ -165,65 +179,8 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
} }
} }
@Deprecated
protected void checkRank(@Deprecated Rank rank, String permission)
{
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
if (!plugin.permissionHandler.hasPermission(player, permission))
{
noPerms();
return;
}
}
if (!plugin.rm.getRank(sender).isAtLeast(rank))
{
noPerms();
}
}
protected void checkPermissions(String permission)
{
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
if (!plugin.permissionHandler.hasPermission(player, permission))
{
noPerms();
}
}
}
protected boolean checkPermissionsSilent(String permission)
{
//TODO: Not bothering with BukkitTelnet now.
// FLog.debug("Using checkPermissionsSilent");
if (sender instanceof ConsoleCommandSender)
{
return true;
}
if (sender instanceof Player player)
{
// FLog.debug("Checking player permission for " + player.getUniqueId() + " - " + permission);
return plugin.permissionHandler.hasPermission(player, permission);
}
return false;
}
@Deprecated
protected void checkRank(Rank rank) protected void checkRank(Rank rank)
{ {
// FLog.debug("Using checkRank");
//TODO: Not bothering with BukkitTelnet now.
if (sender instanceof Player player)
{
// FLog.debug("Checking player permission for " + player.getUniqueId() + " - " + this.permission);
if (!plugin.permissionHandler.hasPermission(player, this.permission))
{
noPerms();
return;
}
}
if (!plugin.rm.getRank(sender).isAtLeast(rank)) if (!plugin.rm.getRank(sender).isAtLeast(rank))
{ {
noPerms(); noPerms();
@ -359,7 +316,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
return perms; return perms;
} }
public final class FCommand extends Command implements PluginIdentifiableCommand private final class FCommand extends Command
{ {
private FreedomCommand cmd = null; private FreedomCommand cmd = null;
@ -368,11 +325,6 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
super(command); super(command);
} }
public final FreedomCommand getExecutor()
{
return cmd;
}
public void setExecutor(FreedomCommand cmd) public void setExecutor(FreedomCommand cmd)
{ {
this.cmd = cmd; this.cmd = cmd;
@ -425,15 +377,7 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
public boolean func2() public boolean func2()
{ {
/*if (!plugin.rm.getRank(sender).isAtLeast(perms.level())) if (!plugin.rm.getRank(sender).isAtLeast(perms.level()))
{
msg(NO_PERMISSION);
return true;
}*/
FLog.debug("Result of check perms: " + (!checkPermissionsSilent(cmd.permission)));
if (!checkPermissionsSilent(cmd.permission))
{ {
msg(NO_PERMISSION); msg(NO_PERMISSION);
return true; return true;
@ -483,11 +427,5 @@ public abstract class FreedomCommand implements CommandExecutor, TabCompleter
} }
return new ArrayList<>(); return new ArrayList<>();
} }
@Override
public @NotNull Plugin getPlugin()
{
return plugin;
}
} }
} }

View File

@ -45,8 +45,6 @@ public enum ConfigEntry
MOB_LIMITER_DISABLE_GIANT(Boolean.class, "moblimiter.disable.giant"), MOB_LIMITER_DISABLE_GIANT(Boolean.class, "moblimiter.disable.giant"),
MOB_LIMITER_DISABLE_SLIME(Boolean.class, "moblimiter.disable.slime"), MOB_LIMITER_DISABLE_SLIME(Boolean.class, "moblimiter.disable.slime"),
// //
SPAWNMOB_MAX(Integer.class, "spawnmob.max"),
//
HTTPD_ENABLED(Boolean.class, "httpd.enabled"), HTTPD_ENABLED(Boolean.class, "httpd.enabled"),
HTTPD_HOST(String.class, "httpd.host"), HTTPD_HOST(String.class, "httpd.host"),
HTTPD_PORT(Integer.class, "httpd.port"), HTTPD_PORT(Integer.class, "httpd.port"),
@ -73,10 +71,7 @@ public enum ConfigEntry
SERVER_WHITELIST_MOTD(String.class, "server.motds.whitelist"), SERVER_WHITELIST_MOTD(String.class, "server.motds.whitelist"),
SERVER_FULL_MOTD(String.class, "server.motds.full"), SERVER_FULL_MOTD(String.class, "server.motds.full"),
// //
DISCORD_VERIFICATION(Boolean.class, "discord.verification"),
PERMISSIONS_GROUPS_ADMIN(String.class, "permissions.groups.admin"),
PERMISSIONS_GROUPS_SENIOR(String.class, "permissions.groups.senior_admin"),
PERMISSIONS_GROUPS_DEFAULT(String.class, "permissions.groups.default"),
DISCORD_TOKEN(String.class, "discord.token"), DISCORD_TOKEN(String.class, "discord.token"),
DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"), DISCORD_REPORT_CHANNEL_ID(String.class, "discord.report_channel_id"),
DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"), DISCORD_CHAT_CHANNEL_ID(String.class, "discord.chat_channel_id"),
@ -91,13 +86,12 @@ public enum ConfigEntry
DISCORD_ASSISTANT_EXECUTIVE_ROLE_ID(String.class, "discord.assistant_executive_role_id"), DISCORD_ASSISTANT_EXECUTIVE_ROLE_ID(String.class, "discord.assistant_executive_role_id"),
DISCORD_EXECUTIVE_ROLE_ID(String.class, "discord.executive_role_id"), DISCORD_EXECUTIVE_ROLE_ID(String.class, "discord.executive_role_id"),
DISCORD_SERVER_OWNER_ROLE_ID(String.class, "discord.server_owner_role_id"), DISCORD_SERVER_OWNER_ROLE_ID(String.class, "discord.server_owner_role_id"),
DISCORD_INVITE_LINK(String.class, "discord.invite_link"),
// //
PTERO_URL(String.class, "ptero.url"), PTERO_URL(String.class, "ptero.url"),
PTERO_DEFAULT_EMAIL_DOMAIN(String.class, "ptero.default_email_domain"), PTERO_DEFAULT_EMAIL_DOMAIN(String.class, "ptero.default_email_domain"),
PTERO_SERVER_UUID(String.class, "ptero.server_uuid"), PTERO_SERVER_UUID(String.class, "ptero.server_uuid"),
PTERO_ADMIN_KEY(String.class, "ptero.admin_key"), PTERO_ADMIN_KEY(String.class, "ptero.admin_key"),
PTERO_SERVER_KEY(String.class, "ptero.server_key"), PTERO_CLIENT_KEY(String.class, "ptero.client_key"),
// //
SHOP_ENABLED(Boolean.class, "shop.enabled"), SHOP_ENABLED(Boolean.class, "shop.enabled"),
SHOP_TITLE(String.class, "shop.title"), SHOP_TITLE(String.class, "shop.title"),
@ -116,7 +110,6 @@ public enum ConfigEntry
SHOP_PRICES_STACKING_POTATO(Integer.class, "shop.prices.stacking_potato"), SHOP_PRICES_STACKING_POTATO(Integer.class, "shop.prices.stacking_potato"),
SHOP_PRICES_CLOWN_FISH(Integer.class, "shop.prices.clown_fish"), SHOP_PRICES_CLOWN_FISH(Integer.class, "shop.prices.clown_fish"),
SHOP_PRICES_LOGIN_MESSAGES(Integer.class, "shop.prices.login_messages"), SHOP_PRICES_LOGIN_MESSAGES(Integer.class, "shop.prices.login_messages"),
SHOP_PRICES_RAINBOW_TRAIL(Integer.class, "shop.prices.rainbow_trail"),
// //
ADMINLIST_CLEAN_THESHOLD_HOURS(Integer.class, "adminlist.clean_threshold_hours"), ADMINLIST_CLEAN_THESHOLD_HOURS(Integer.class, "adminlist.clean_threshold_hours"),
ADMINLIST_CONSOLE_IS_ADMIN(Boolean.class, "adminlist.console_is_admin"), ADMINLIST_CONSOLE_IS_ADMIN(Boolean.class, "adminlist.console_is_admin"),
@ -172,8 +165,6 @@ public enum ConfigEntry
ADMIN_INFO(List.class, "admininfo"), ADMIN_INFO(List.class, "admininfo"),
VOTING_INFO(List.class, "votinginfo"), VOTING_INFO(List.class, "votinginfo"),
MASTER_BUILDER_INFO(List.class, "masterbuilderinfo"), MASTER_BUILDER_INFO(List.class, "masterbuilderinfo"),
FIRST_JOIN_INFO(List.class, "first_join_info.text"),
FIRST_JOIN_INFO_ENABLED(Boolean.class, "first_join_info.enabled"),
AUTO_ENTITY_WIPE(Boolean.class, "auto_wipe"), AUTO_ENTITY_WIPE(Boolean.class, "auto_wipe"),
TOGGLE_CHAT(Boolean.class, "toggle_chat"), TOGGLE_CHAT(Boolean.class, "toggle_chat"),
DEVELOPER_MODE(Boolean.class, "developer_mode"), DEVELOPER_MODE(Boolean.class, "developer_mode"),

View File

@ -1,6 +1,9 @@
package me.totalfreedom.totalfreedommod.discord; package me.totalfreedom.totalfreedommod.discord;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.time.Instant; import java.time.Instant;
import java.time.ZonedDateTime; import java.time.ZonedDateTime;
import java.util.ArrayList; import java.util.ArrayList;
@ -19,6 +22,7 @@ import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Rank;
import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil;
import net.dv8tion.jda.api.EmbedBuilder; import net.dv8tion.jda.api.EmbedBuilder;
import net.dv8tion.jda.api.JDA; import net.dv8tion.jda.api.JDA;
import net.dv8tion.jda.api.JDABuilder; import net.dv8tion.jda.api.JDABuilder;
@ -37,6 +41,7 @@ import net.dv8tion.jda.api.requests.GatewayIntent;
import net.dv8tion.jda.api.utils.ChunkingFilter; import net.dv8tion.jda.api.utils.ChunkingFilter;
import net.dv8tion.jda.api.utils.MemberCachePolicy; import net.dv8tion.jda.api.utils.MemberCachePolicy;
import net.dv8tion.jda.internal.utils.concurrent.CountingThreadFactory; import net.dv8tion.jda.internal.utils.concurrent.CountingThreadFactory;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils; import org.apache.commons.lang.WordUtils;
import org.bukkit.GameRule; import org.bukkit.GameRule;
@ -52,12 +57,18 @@ public class Discord extends FreedomService
{ {
public static HashMap<String, PlayerData> LINK_CODES = new HashMap<>(); public static HashMap<String, PlayerData> LINK_CODES = new HashMap<>();
public static HashMap<String, PlayerData> VERIFICATION_CODES = new HashMap<>();
public static JDA bot = null; public static JDA bot = null;
public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR; public ScheduledThreadPoolExecutor RATELIMIT_EXECUTOR;
public List<CompletableFuture<Message>> sentMessages = new ArrayList<>(); public List<CompletableFuture<Message>> sentMessages = new ArrayList<>();
public Boolean enabled = false; public Boolean enabled = false;
private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)"); private final Pattern DISCORD_MENTION_PATTERN = Pattern.compile("(<@!?([0-9]{16,20})>)");
public static String getMD5(String string)
{
return DigestUtils.md5Hex(string);
}
public static String getCode(PlayerData playerData) public static String getCode(PlayerData playerData)
{ {
for (String code : LINK_CODES.keySet()) for (String code : LINK_CODES.keySet())
@ -146,6 +157,12 @@ public class Discord extends FreedomService
public void startBot() public void startBot()
{ {
boolean verificationEnabled = ConfigEntry.DISCORD_VERIFICATION.getBoolean();
if (!verificationEnabled)
{
FLog.info("Discord Verification has been manually disabled.");
}
enabled = !Strings.isNullOrEmpty(ConfigEntry.DISCORD_TOKEN.getString()); enabled = !Strings.isNullOrEmpty(ConfigEntry.DISCORD_TOKEN.getString());
if (!enabled) if (!enabled)
{ {
@ -182,15 +199,15 @@ public class Discord extends FreedomService
.setMemberCachePolicy(MemberCachePolicy.ALL) .setMemberCachePolicy(MemberCachePolicy.ALL)
.enableIntents(GatewayIntent.GUILD_MEMBERS) .enableIntents(GatewayIntent.GUILD_MEMBERS)
.build(); .build();
FLog.info("Discord integration has successfully enabled!"); FLog.info("Discord verification bot has successfully enabled!");
} }
catch (LoginException e) catch (LoginException e)
{ {
FLog.warning("An invalid token for Discord integration was provided, the bot will not enable."); FLog.warning("An invalid token for the discord verification bot, the bot will not enable.");
} }
catch (IllegalArgumentException e) catch (IllegalArgumentException e)
{ {
FLog.warning("Discord integration failed to start."); FLog.warning("Discord verification bot failed to start.");
} }
catch (NoClassDefFoundError e) catch (NoClassDefFoundError e)
{ {
@ -244,6 +261,35 @@ public class Discord extends FreedomService
return member.getUser(); return member.getUser();
} }
public boolean sendBackupCodes(PlayerData playerData)
{
List<String> codes = generateBackupCodes();
List<String> encryptedCodes = generateEncryptedBackupCodes(codes);
User user = getUser(playerData.getDiscordID());
File file = generateBackupCodesFile(playerData.getName(), codes);
if (file == null)
{
return false;
}
PrivateChannel privateChannel = user.openPrivateChannel().complete();
privateChannel.sendMessage("Do not share these codes with anyone as they can be used to impose as you.").addFile(file).complete();
playerData.setBackupCodes(encryptedCodes);
plugin.pl.save(playerData);
//noinspection ResultOfMethodCallIgnored
file.delete();
return true;
}
public List<String> generateBackupCodes()
{
List<String> codes = new ArrayList<>();
for (int i = 0; i < 10; i++)
{
codes.add(FUtil.randomAlphanumericString(10));
}
return codes;
}
public String generateCode(int size) public String generateCode(int size)
{ {
StringBuilder code = new StringBuilder(); StringBuilder code = new StringBuilder();
@ -255,6 +301,58 @@ public class Discord extends FreedomService
return code.toString(); return code.toString();
} }
public List<String> generateEncryptedBackupCodes(List<String> codes)
{
List<String> encryptedCodes = new ArrayList<>();
for (String code : codes)
{
encryptedCodes.add(getMD5(code));
}
return encryptedCodes;
}
public File generateBackupCodesFile(String name, List<String> codes)
{
StringBuilder text = new StringBuilder();
text.append("Below are your backup codes for use on TotalFreedom in the event you lose access to your discord account.\n")
.append("Simply pick a code, and run /verify <code> on the server. Each code is one use, so be sure to cross it off once you use it.\n")
.append("To generate new codes, simply run /generatebackupcodes\n\n");
for (String code : codes)
{
text.append(code).append("\n");
}
String fileUrl = plugin.getDataFolder().getAbsolutePath() + "/TF-Backup-Codes-" + name + ".txt";
try
{
FileWriter fileWriter = new FileWriter(fileUrl);
fileWriter.write(text.toString());
fileWriter.close();
}
catch (IOException e)
{
FLog.severe("Failed to generate backup codes file: " + e.toString());
return null;
}
return new File(fileUrl);
}
public void addVerificationCode(String code, PlayerData playerData)
{
VERIFICATION_CODES.put(code, playerData);
}
public void removeVerificationCode(String code)
{
VERIFICATION_CODES.remove(code);
}
public HashMap<String, PlayerData> getVerificationCodes()
{
return VERIFICATION_CODES;
}
@EventHandler(priority = EventPriority.MONITOR) @EventHandler(priority = EventPriority.MONITOR)
public void onPlayerDeath(PlayerDeathEvent event) public void onPlayerDeath(PlayerDeathEvent event)
{ {
@ -377,7 +475,7 @@ public class Discord extends FreedomService
messageChatChannel("**Server has stopped**"); messageChatChannel("**Server has stopped**");
} }
FLog.info("Discord integration has successfully shutdown."); FLog.info("Discord verification bot has successfully shutdown.");
} }
public String deformat(String input) public String deformat(String input)

View File

@ -10,12 +10,9 @@ import net.dv8tion.jda.api.entities.Member;
import net.dv8tion.jda.api.entities.Message; import net.dv8tion.jda.api.entities.Message;
import net.dv8tion.jda.api.events.message.MessageReceivedEvent; import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
import net.dv8tion.jda.api.hooks.ListenerAdapter; import net.dv8tion.jda.api.hooks.ListenerAdapter;
import net.md_5.bungee.api.chat.BaseComponent;
import net.md_5.bungee.api.chat.ClickEvent; import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.ComponentBuilder; import net.md_5.bungee.api.chat.ComponentBuilder;
import net.md_5.bungee.api.chat.HoverEvent;
import net.md_5.bungee.api.chat.TextComponent; import net.md_5.bungee.api.chat.TextComponent;
import net.md_5.bungee.api.chat.hover.content.Text;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
@ -31,66 +28,39 @@ public class DiscordToMinecraftListener extends ListenerAdapter
{ {
Member member = event.getMember(); Member member = event.getMember();
String tag = getDisplay(member); String tag = getDisplay(member);
StringBuilder message = new StringBuilder(ChatColor.DARK_GRAY + "[" + ChatColor.DARK_AQUA + "Discord" + ChatColor.DARK_GRAY + "]");
Message msg = event.getMessage(); Message msg = event.getMessage();
ComponentBuilder emsg = new ComponentBuilder();
// Prefix
emsg.append(ChatColor.DARK_GRAY + "[");
TextComponent inviteLink = new TextComponent("Discord");
inviteLink.setColor(ChatColor.DARK_AQUA.asBungee());
inviteLink.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT,
new Text("Click here to get the invite link!")));
inviteLink.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL,
ConfigEntry.DISCORD_INVITE_LINK.getString()));
emsg.append(inviteLink);
emsg.append(ChatColor.DARK_GRAY + "] ", ComponentBuilder.FormatRetention.NONE);
// Tag (if they have one)
if (tag != null) if (tag != null)
{ {
emsg.append(tag); message.append(" ").append(tag);
}
message.append(" ").append(ChatColor.RED).append(ChatColor.stripColor(member.getEffectiveName())).append(ChatColor.DARK_GRAY).append(":").append(ChatColor.RESET);
ComponentBuilder builder = new ComponentBuilder(message.toString());
if (!msg.getContentDisplay().isEmpty())
{
builder.append(" ").append(ChatColor.stripColor(msg.getContentDisplay()));
message.append(" ").append(ChatColor.stripColor(msg.getContentDisplay())); // for logging
} }
emsg.append(" ");
// User
TextComponent user = new TextComponent(ChatColor.stripColor(member.getEffectiveName()));
user.setColor(ChatColor.RED.asBungee());
emsg.append(user);
// Message
emsg.append(ChatColor.DARK_GRAY + ": " + ChatColor.RESET
+ ChatColor.stripColor(msg.getContentDisplay()), ComponentBuilder.FormatRetention.NONE);
// Attachments
if (!msg.getAttachments().isEmpty()) if (!msg.getAttachments().isEmpty())
{ {
if (!msg.getContentDisplay().isEmpty())
emsg.append(" ");
for (Message.Attachment attachment : msg.getAttachments()) for (Message.Attachment attachment : msg.getAttachments())
{ {
TextComponent media = new TextComponent("[Media] "); attachment.getUrl();
media.setColor(ChatColor.YELLOW.asBungee()); builder.append(" ");
media.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl())); TextComponent text = new TextComponent(ChatColor.YELLOW + "[Media]");
media.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new Text(attachment.getUrl()))); text.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, attachment.getUrl()));
builder.append(text);
emsg.append(media, ComponentBuilder.FormatRetention.NONE); message.append(" [Media]"); // for logging
} }
} }
BaseComponent[] components = emsg.create();
for (Player player : Bukkit.getOnlinePlayers()) for (Player player : Bukkit.getOnlinePlayers())
{ {
if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord()) if (TotalFreedomMod.getPlugin().pl.getData(player).doesDisplayDiscord())
{ {
player.spigot().sendMessage(components); player.spigot().sendMessage(builder.create());
} }
} }
FLog.info(message.toString());
FLog.info(TextComponent.toLegacyText(components), true);
} }
} }
} }

View File

@ -22,8 +22,9 @@ public class PrivateMessageListener extends ListenerAdapter
PlayerData player = Discord.LINK_CODES.get(code); PlayerData player = Discord.LINK_CODES.get(code);
name = player.getName(); name = player.getName();
player.setDiscordID(event.getMessage().getAuthor().getId()); player.setDiscordID(event.getMessage().getAuthor().getId());
player.setVerification(true);
Admin admin = TotalFreedomMod.getPlugin().al.getEntryByUuid(player.getUuid()); Admin admin = TotalFreedomMod.getPlugin().al.getEntryByName(name);
if (admin != null) if (admin != null)
{ {
Discord.syncRoles(admin, player.getDiscordID()); Discord.syncRoles(admin, player.getDiscordID());
@ -36,7 +37,8 @@ public class PrivateMessageListener extends ListenerAdapter
{ {
return; return;
} }
event.getChannel().sendMessage("Link successful. Now this Discord account is linked with your Minecraft account **" + name + "**.").complete(); event.getChannel().sendMessage("Link successful. Now this Discord account is linked with your Minecraft account **" + name + "**.\n"
+ "Now when you are an impostor on the server, you may use `/verify` to verify.").complete();
} }
} }
} }

View File

@ -60,10 +60,13 @@ public class FreezeData
{ {
@Override @Override
public void run() public void run()
{
if (!Objects.requireNonNull(plugin()).al.isAdminImpostor(player) && Objects.requireNonNull(plugin()).pl.isPlayerImpostor(player))
{ {
FUtil.adminAction("TotalFreedom", "Unfreezing " + player.getName(), false); FUtil.adminAction("TotalFreedom", "Unfreezing " + player.getName(), false);
setFrozen(false); setFrozen(false);
} }
}
}.runTaskLater(Objects.requireNonNull(plugin()), AUTO_PURGE_TICKS); }.runTaskLater(Objects.requireNonNull(plugin()), AUTO_PURGE_TICKS);
} }

View File

@ -4,10 +4,7 @@ import java.util.HashSet;
import java.util.Objects; import java.util.Objects;
import java.util.Set; import java.util.Set;
import java.util.SplittableRandom; import java.util.SplittableRandom;
import java.util.UUID;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.shop.ShopItem;
import me.totalfreedom.totalfreedommod.util.Groups; import me.totalfreedom.totalfreedommod.util.Groups;
import org.bukkit.Location; import org.bukkit.Location;
import org.bukkit.Material; import org.bukkit.Material;
@ -21,7 +18,7 @@ import org.bukkit.event.player.PlayerMoveEvent;
public class Trailer extends FreedomService public class Trailer extends FreedomService
{ {
private final SplittableRandom random = new SplittableRandom(); private final SplittableRandom random = new SplittableRandom();
private final Set<UUID> trailPlayers = new HashSet<>(); // player UUID private final Set<String> trailPlayers = new HashSet<>(); // player name
@Override @Override
public void onStart() public void onStart()
@ -36,17 +33,17 @@ public class Trailer extends FreedomService
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMove(PlayerMoveEvent event) public void onPlayerMove(PlayerMoveEvent event)
{ {
/* Doesn't continue any further if... if (trailPlayers.isEmpty())
* - The trail list is empty {
* - The player doesn't have their trail enabled in the first place return;
* - The player doesn't have the trail item in the shop at all }
* - The player doesn't have permission to modify blocks in their current world
*/ if (!trailPlayers.contains(event.getPlayer().getName()))
if (trailPlayers.isEmpty() {
|| !trailPlayers.contains(event.getPlayer().getUniqueId()) return;
|| !plugin.pl.getData(event.getPlayer()).hasItem(ShopItem.RAINBOW_TRAIL) }
|| plugin.wr.doRestrict(event.getPlayer())
|| !plugin.wgb.canEditCurrentWorld(event.getPlayer())) if (event.getPlayer().getWorld().equals(plugin.wm.masterBuilderWorld.getWorld()))
{ {
return; return;
} }
@ -72,7 +69,7 @@ public class Trailer extends FreedomService
{ {
final Location trail_pos; final Location trail_pos;
trail_pos = new Location(event.getPlayer().getWorld(), fromBlock.getX() + x, fromBlock.getY(), fromBlock.getZ() + z); trail_pos = new Location(event.getPlayer().getWorld(), fromBlock.getX() + x, fromBlock.getY(), fromBlock.getZ() + z);
if (trailPlayers.contains(event.getPlayer().getUniqueId()) && plugin.cpb.isEnabled()) if (trailPlayers.contains(event.getPlayer().getName()) && plugin.cpb.isEnabled())
{ {
plugin.cpb.getCoreProtectAPI().logPlacement(event.getPlayer().getName(), trail_pos, material, data); plugin.cpb.getCoreProtectAPI().logPlacement(event.getPlayer().getName(), trail_pos, material, data);
} }
@ -82,16 +79,16 @@ public class Trailer extends FreedomService
public void remove(Player player) public void remove(Player player)
{ {
trailPlayers.remove(player.getUniqueId()); trailPlayers.remove(player.getName());
} }
public void add(Player player) public void add(Player player)
{ {
trailPlayers.add(player.getUniqueId()); trailPlayers.add(player.getName());
} }
public boolean contains(Player player) public boolean contains(Player player)
{ {
return trailPlayers.contains(player.getUniqueId()); return trailPlayers.contains(player.getName());
} }
} }

View File

@ -11,15 +11,9 @@ public class HTMLGenerationTools
return "<p>" + escapeHtml4(data) + "</p>\r\n"; return "<p>" + escapeHtml4(data) + "</p>\r\n";
} }
public static String heading(String data, String id, int level)
{
return "<h" + level + (id != null ? " id=\"" + id + "\"" : "") + ">" + escapeHtml4(data)
+ "</h" + level + ">\r\n";
}
public static String heading(String data, int level) public static String heading(String data, int level)
{ {
return heading(data, null, level); return "<h" + level + ">" + escapeHtml4(data) + "</h" + level + ">\r\n";
} }
public static <K, V> String list(Map<K, V> map) public static <K, V> String list(Map<K, V> map)

View File

@ -1,67 +1,52 @@
package me.totalfreedom.totalfreedommod.httpd.module; package me.totalfreedom.totalfreedommod.httpd.module;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.command.FreedomCommand; import me.totalfreedom.totalfreedommod.command.FreedomCommand;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD; import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD;
import me.totalfreedom.totalfreedommod.rank.Rank; import me.totalfreedom.totalfreedommod.rank.Displayable;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.command.Command; import org.bukkit.command.Command;
import org.bukkit.command.CommandMap; import org.bukkit.command.CommandMap;
import org.bukkit.command.PluginIdentifiableCommand; import org.bukkit.command.PluginIdentifiableCommand;
import org.jetbrains.annotations.NotNull; import org.bukkit.command.SimpleCommandMap;
import org.jetbrains.annotations.Nullable;
import static me.totalfreedom.totalfreedommod.httpd.HTMLGenerationTools.heading; import static me.totalfreedom.totalfreedommod.httpd.HTMLGenerationTools.heading;
import static me.totalfreedom.totalfreedommod.httpd.HTMLGenerationTools.paragraph; import static me.totalfreedom.totalfreedommod.httpd.HTMLGenerationTools.paragraph;
import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4; import static org.apache.commons.lang3.StringEscapeUtils.escapeHtml4;
public class Module_help extends HTTPDModule public class Module_help extends HTTPDModule
{ {
public Module_help(NanoHTTPD.HTTPSession session) public Module_help(NanoHTTPD.HTTPSession session)
{ {
super(session); super(session);
} }
private static String buildDescription(@NotNull Command command) private static String buildDescription(Command command)
{
return buildDescription(command.getName(), command.getDescription(), command.getUsage(), StringUtils.join(command.getAliases(), ", "));
}
private static String buildDescription(@NotNull FreedomCommand command)
{
return buildDescription(command.getName(), command.getDescription(), command.getUsage(), command.getAliases());
}
private static String buildDescription(@NotNull String name, @Nullable String description, @NotNull String usage, @NotNull String aliases)
{ {
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append( sb.append(
"<li><span class=\"commandName\">{$CMD_NAME}</span> - Usage: <span class=\"commandUsage\">{$CMD_USAGE}</span>" "<li><span class=\"commandName\">{$CMD_NAME}</span> - Usage: <span class=\"commandUsage\">{$CMD_USAGE}</span>"
.replace("{$CMD_NAME}", escapeHtml4(name.trim())) .replace("{$CMD_NAME}", escapeHtml4(command.getName().trim()))
.replace("{$CMD_USAGE}", escapeHtml4(usage.trim()))); .replace("{$CMD_USAGE}", escapeHtml4(command.getUsage().trim())));
if (!aliases.isEmpty()) if (!command.getAliases().isEmpty())
{ {
sb.append( sb.append(
" - Aliases: <span class=\"commandAliases\">{$CMD_ALIASES}</span>" " - Aliases: <span class=\"commandAliases\">{$CMD_ALIASES}</span>"
.replace("{$CMD_ALIASES}", escapeHtml4(aliases.trim()))); .replace("{$CMD_ALIASES}", escapeHtml4(StringUtils.join(command.getAliases(), ", "))));
} }
if (description != null)
{
sb.append( sb.append(
"<br><span class=\"commandDescription\">{$CMD_DESC}</span></li>\r\n" "<br><span class=\"commandDescription\">{$CMD_DESC}</span></li>\r\n"
.replace("{$CMD_DESC}", escapeHtml4(description.trim()))); .replace("{$CMD_DESC}", escapeHtml4(command.getDescription().trim())));
}
return sb.toString(); return sb.toString();
} }
@ -69,7 +54,11 @@ public class Module_help extends HTTPDModule
@Override @Override
public String getBody() public String getBody()
{ {
final CommandMap map = Bukkit.getCommandMap(); final CommandMap map = FreedomCommand.getCommandMap();
if (!(map instanceof SimpleCommandMap))
{
return paragraph("Error loading commands.");
}
final StringBuilder responseBody = new StringBuilder() final StringBuilder responseBody = new StringBuilder()
.append(heading("Command Help", 1)) .append(heading("Command Help", 1))
@ -77,7 +66,7 @@ public class Module_help extends HTTPDModule
"This page is an automatically generated listing of all plugin commands that are currently live on the server. " "This page is an automatically generated listing of all plugin commands that are currently live on the server. "
+ "Please note that it does not include vanilla server commands.")); + "Please note that it does not include vanilla server commands."));
final Collection<Command> knownCommands = map.getKnownCommands().values(); final Collection<Command> knownCommands = ((SimpleCommandMap)map).getCommands();
final Map<String, List<Command>> commandsByPlugin = new HashMap<>(); final Map<String, List<Command>> commandsByPlugin = new HashMap<>();
for (Command command : knownCommands) for (Command command : knownCommands)
@ -90,47 +79,34 @@ public class Module_help extends HTTPDModule
List<Command> pluginCommands = commandsByPlugin.computeIfAbsent(pluginName, k -> Lists.newArrayList()); List<Command> pluginCommands = commandsByPlugin.computeIfAbsent(pluginName, k -> Lists.newArrayList());
if (!pluginCommands.contains(command))
{
pluginCommands.add(command); pluginCommands.add(command);
} }
}
final CommandComparator comparator = new CommandComparator();
// For every plugin...
for (Map.Entry<String, List<Command>> entry : commandsByPlugin.entrySet()) for (Map.Entry<String, List<Command>> entry : commandsByPlugin.entrySet())
{ {
final String pluginName = entry.getKey(); final String pluginName = entry.getKey();
final List<Command> commands = entry.getValue(); final List<Command> commands = entry.getValue();
// Sort them alphabetically commands.sort(new CommandComparator());
commands.sort(comparator);
responseBody.append(heading(pluginName, pluginName, 2)).append("<ul>\r\n"); responseBody.append(heading(pluginName, 2)).append("<ul>\r\n");
if (!plugin.getName().equals(pluginName)) Displayable lastTfmCommandLevel = null;
for (Command command : commands)
{ {
commands.forEach((command) -> responseBody.append(buildDescription(command))); if (!TotalFreedomMod.pluginName.equals(pluginName))
{
responseBody.append(buildDescription(command));
continue;
} }
else
Displayable tfmCommandLevel = Objects.requireNonNull(FreedomCommand.getFrom(command)).getPerms().level();
if (lastTfmCommandLevel == null || lastTfmCommandLevel != tfmCommandLevel)
{ {
Map<Rank, List<FreedomCommand>> freedomCommands = new HashMap<>(); responseBody.append("</ul>\r\n").append(heading(tfmCommandLevel.getName(), 3)).append("<ul>\r\n");
}
// Filters out non-TFM commands lastTfmCommandLevel = tfmCommandLevel;
commands.stream().filter((cmd) -> cmd instanceof FreedomCommand.FCommand).forEach((tfmCmd) -> { responseBody.append(buildDescription(command));
Rank rank = FreedomCommand.getFrom(tfmCmd).getLevel();
if (!freedomCommands.containsKey(rank))
freedomCommands.put(rank, new ArrayList<>());
freedomCommands.get(rank).add(FreedomCommand.getFrom(tfmCmd));
});
// Finally dumps them to HTML
Arrays.stream(Rank.values()).filter(freedomCommands::containsKey)
.sorted(comparator::compare).forEach((rank -> {
responseBody.append("</ul>\r\n").append(heading(rank.getName(), 3)).append("<ul>\r\n");
freedomCommands.get(rank).stream().sorted(comparator::compare).forEach((command) -> responseBody.append(buildDescription(command)));
}));
} }
responseBody.append("</ul>\r\n"); responseBody.append("</ul>\r\n");
@ -142,7 +118,7 @@ public class Module_help extends HTTPDModule
@Override @Override
public String getTitle() public String getTitle()
{ {
return plugin.getName() + " :: Command Help"; return "TotalFreedomMod :: Command Help";
} }
@Override @Override
@ -153,23 +129,23 @@ public class Module_help extends HTTPDModule
public static class CommandComparator implements Comparator<Command> public static class CommandComparator implements Comparator<Command>
{ {
@Override @Override
public int compare(Command a, Command b) public int compare(Command a, Command b)
{ {
return a.getName().compareTo(b.getName()); FreedomCommand ca = FreedomCommand.getFrom(a);
} FreedomCommand cb = FreedomCommand.getFrom(b);
public int compare(FreedomCommand a, FreedomCommand b) if (ca == null
|| cb == null
|| ca.getPerms() == null
|| cb.getPerms() == null)
{ {
return a.getName().compareTo(b.getName()); return a.getName().compareTo(b.getName());
} }
public int compare(Rank a, Rank b) return ca.getPerms().level().getName().compareTo(cb.getPerms().level().getName());
{ }
Integer levelA = a.getLevel(); }
Integer levelB = b.getLevel();
return levelB.compareTo(levelA);
}
}
} }

View File

@ -4,16 +4,12 @@ import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.admin.AdminList; import me.totalfreedom.totalfreedommod.admin.AdminList;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD; import me.totalfreedom.totalfreedommod.httpd.NanoHTTPD;
import me.totalfreedom.totalfreedommod.permissions.handler.DefaultPermissionHandler;
import me.totalfreedom.totalfreedommod.permissions.handler.IPermissionHandler;
import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.json.JSONArray; import org.json.simple.JSONArray;
import org.json.JSONObject; import org.json.simple.JSONObject;
import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
public class Module_list extends HTTPDModule public class Module_list extends HTTPDModule
@ -29,32 +25,7 @@ public class Module_list extends HTTPDModule
{ {
if (params.get("json") != null && params.get("json").equals("true")) if (params.get("json") != null && params.get("json").equals("true"))
{ {
FLog.debug("Swapping to JSON View!");
final JSONObject responseObject = new JSONObject(); final JSONObject responseObject = new JSONObject();
if (!(plugin.permissionHandler instanceof DefaultPermissionHandler))
{
FLog.debug("Displaying custom list on HTTPD!");
IPermissionHandler handler = plugin.permissionHandler;
final JSONObject players = new JSONObject();
Arrays.stream(handler.getGroups()).forEach(s ->
{
JSONArray array = new JSONArray();
Bukkit.getOnlinePlayers().stream().filter(player -> !plugin.al.isVanished(player.getName())).filter(player -> handler.getPrimaryGroup(player).equalsIgnoreCase(s)).forEach(player ->
{
array.put(player.getName());
});
players.put(s.toLowerCase(), array);
});
responseObject.put("players", players);
responseObject.put("online", Bukkit.getOnlinePlayers().stream().filter(player -> !plugin.al.isVanished(player.getName())).count());
responseObject.put("max", Bukkit.getMaxPlayers());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString(4));
response.addHeader("Access-Control-Allow-Origin", "*");
return response;
}
final JSONArray owners = new JSONArray(); final JSONArray owners = new JSONArray();
final JSONArray executives = new JSONArray(); final JSONArray executives = new JSONArray();
@ -63,6 +34,7 @@ public class Module_list extends HTTPDModule
final JSONArray admins = new JSONArray(); final JSONArray admins = new JSONArray();
final JSONArray masterbuilders = new JSONArray(); final JSONArray masterbuilders = new JSONArray();
final JSONArray operators = new JSONArray(); final JSONArray operators = new JSONArray();
final JSONArray imposters = new JSONArray();
for (Player player : Bukkit.getOnlinePlayers()) for (Player player : Bukkit.getOnlinePlayers())
{ {
@ -71,29 +43,34 @@ public class Module_list extends HTTPDModule
continue; continue;
} }
if (isImposter(player))
{
imposters.add(player.getName());
}
if (plugin.pl.getData(player).isMasterBuilder()) if (plugin.pl.getData(player).isMasterBuilder())
{ {
masterbuilders.put(player.getName()); masterbuilders.add(player.getName());
} }
if (FUtil.DEVELOPER_NAMES.contains(player.getName())) if (FUtil.DEVELOPER_NAMES.contains(player.getName()))
{ {
developers.put(player.getName()); developers.add(player.getName());
} }
if (ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) && !FUtil.DEVELOPERS.contains(player.getName())) if (ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) && !FUtil.DEVELOPERS.contains(player.getName()))
{ {
executives.put(player.getName()); executives.add(player.getName());
} }
if (ConfigEntry.SERVER_OWNERS.getList().contains(player.getName())) if (ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()))
{ {
owners.put(player.getName()); owners.add(player.getName());
} }
if (!plugin.al.isAdmin(player) && hasSpecialTitle(player)) if (!plugin.al.isAdmin(player) && hasSpecialTitle(player))
{ {
operators.put(player.getName()); operators.add(player.getName());
} }
if (hasSpecialTitle(player) && plugin.al.isAdmin(player) && !plugin.al.isVanished(player.getName())) if (hasSpecialTitle(player) && plugin.al.isAdmin(player) && !plugin.al.isVanished(player.getName()))
@ -103,12 +80,12 @@ public class Module_list extends HTTPDModule
{ {
case ADMIN: case ADMIN:
{ {
admins.put(player.getName()); admins.add(player.getName());
break; break;
} }
case SENIOR_ADMIN: case SENIOR_ADMIN:
{ {
senioradmins.put(player.getName()); senioradmins.add(player.getName());
break; break;
} }
default: default:
@ -128,14 +105,15 @@ public class Module_list extends HTTPDModule
responseObject.put("admins", admins); responseObject.put("admins", admins);
responseObject.put("master_builders", masterbuilders); responseObject.put("master_builders", masterbuilders);
responseObject.put("operators", operators); responseObject.put("operators", operators);
responseObject.put("imposters", imposters);
responseObject.put("online", FUtil.getFakePlayerCount()); responseObject.put("online", FUtil.getFakePlayerCount());
responseObject.put("max", server.getMaxPlayers()); responseObject.put("max", server.getMaxPlayers());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString());
final NanoHTTPD.Response response = new NanoHTTPD.Response(NanoHTTPD.Response.Status.OK, NanoHTTPD.MIME_JSON, responseObject.toString(4));
response.addHeader("Access-Control-Allow-Origin", "*"); response.addHeader("Access-Control-Allow-Origin", "*");
return response; return response;
} else }
else
{ {
final StringBuilder body = new StringBuilder(); final StringBuilder body = new StringBuilder();
@ -163,6 +141,11 @@ public class Module_list extends HTTPDModule
} }
} }
public boolean isImposter(Player player)
{
return plugin.al.isAdminImpostor(player) || plugin.pl.isPlayerImpostor(player);
}
public boolean hasSpecialTitle(Player player) public boolean hasSpecialTitle(Player player)
{ {
return !FUtil.DEVELOPERS.contains(player.getUniqueId().toString()) && !ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) && !ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()); return !FUtil.DEVELOPERS.contains(player.getUniqueId().toString()) && !ConfigEntry.SERVER_EXECUTIVES.getList().contains(player.getName()) && !ConfigEntry.SERVER_OWNERS.getList().contains(player.getName());
@ -173,5 +156,4 @@ public class Module_list extends HTTPDModule
{ {
return "TotalFreedom - Online Players"; return "TotalFreedom - Online Players";
} }
} }

View File

@ -37,7 +37,7 @@ public class Module_players extends HTTPDModule
if (!plugin.al.isVanished(player.getName())) if (!plugin.al.isVanished(player.getName()))
{ {
players.add(player.getName()); players.add(player.getName());
if (plugin.al.isAdmin(player)) if (plugin.al.isAdmin(player) && !plugin.al.isAdminImpostor(player))
{ {
onlineadmins.add(player.getName()); onlineadmins.add(player.getName());
} }

View File

@ -1,61 +0,0 @@
package me.totalfreedom.totalfreedommod.permissions.handler;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Taah
* @project TotalFreedomMod
* @since 9:10 PM [23-05-2022]
*/
public class DefaultPermissionHandler implements IPermissionHandler
{
@Override
public boolean hasPermission(@NotNull OfflinePlayer player, @Nullable String permission)
{
if (permission == null)
{
return true;
}
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for permissions!");
}
@Override
public boolean hasPermission(@NotNull Player player, @Nullable String permission)
{
return permission == null || player.hasPermission(permission);
}
@Override
public boolean inGroup(@NotNull OfflinePlayer player, @Nullable String groupName)
{
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for groups!");
}
@Override
public boolean inGroup(@NotNull Player player, @Nullable String groupName)
{
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for groups!");
}
@Override
public String getPrimaryGroup(@NotNull Player player)
{
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for groups!");
}
@Override
public String getPrefix(@NotNull Player player)
{
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for groups!");
}
@Override
public String[] getGroups()
{
throw new UnsupportedOperationException("Unable to use Bukkit's native permission system for groups!");
}
}

View File

@ -1,26 +0,0 @@
package me.totalfreedom.totalfreedommod.permissions.handler;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Taah
* @project TotalFreedomMod
* @since 9:05 PM [23-05-2022]
*/
public interface IPermissionHandler
{
boolean hasPermission(@NotNull OfflinePlayer player, @Nullable String permission);
boolean hasPermission(@NotNull Player player, @Nullable String permission);
boolean inGroup(@NotNull OfflinePlayer player, @Nullable String groupName);
boolean inGroup(@NotNull Player player, @Nullable String groupName);
String getPrimaryGroup(@NotNull Player player);
String getPrefix(@NotNull Player player);
String[] getGroups();
}

View File

@ -1,150 +0,0 @@
package me.totalfreedom.totalfreedommod.permissions.handler;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.milkbowl.vault.permission.Permission;
import nl.chimpgamer.networkmanager.api.NetworkManagerPlugin;
import nl.chimpgamer.networkmanager.api.NetworkManagerProvider;
import nl.chimpgamer.networkmanager.api.models.permissions.Group;
import nl.chimpgamer.networkmanager.api.models.permissions.PermissionPlayer;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Comparator;
/**
* @author Taah
* @project TotalFreedomMod
* @since 9:10 PM [23-05-2022]
*/
public class NMPermissionHandler implements IPermissionHandler
{
private NetworkManagerPlugin plugin;
public NMPermissionHandler(TotalFreedomMod plugin)
{
if (plugin.permissionHandler != null)
{
return;
}
if (!Bukkit.getPluginManager().isPluginEnabled("NetworkManager"))
{
plugin.permissionHandler = new DefaultPermissionHandler();
return;
}
this.plugin = NetworkManagerProvider.get();
}
@Override
public boolean hasPermission(@NotNull OfflinePlayer player, @Nullable String permission)
{
if (permission == null)
{
FLog.debug("Permission was null!");
return true;
}
PermissionPlayer permissionPlayer = this.plugin.getPermissionManager().getPermissionPlayer(player.getUniqueId());
if (permissionPlayer == null)
{
FLog.debug("Unable to find permissions player in NetworkManager. Returning false.");
return false;
}
if (permissionPlayer.getAllPermissions() == null)
{
FLog.debug("Screw you NetworkManager for telling me all the permissions for player is null.");
return false;
}
Boolean has = permissionPlayer.hasPermission(permission);
if (has == null)
{
// FLog.debug("NetworkManager is idiotic and has a chance of returning null on a Boolean object. Returning false.");
return false;
}
// FLog.debug("Player has perm? " + has);
// FLog.debug("Player permissions for: " + permissionPlayer.getUuid() + "\n" + new GsonBuilder().setPrettyPrinting().create().toJson(permissionPlayer.getAllPermissions()));
// permissionPlayer.getPermissions().forEach(permission1 -> FLog.debug(String.format("%s:%s", permission1.getPermissionString(), permission1.hasExpired())));
return has;
}
@Override
public boolean hasPermission(@NotNull Player player, @Nullable String permission)
{
return hasPermission((OfflinePlayer) player, permission);
}
@Override
public boolean inGroup(@NotNull OfflinePlayer player, @Nullable String groupName)
{
if (groupName == null)
{
FLog.debug("NM Perms: Setting permission access to false, group is null");
return false;
}
PermissionPlayer permissionPlayer = this.plugin.getPermissionManager().getPermissionPlayer(player.getUniqueId());
if (permissionPlayer == null)
{
FLog.debug("NM Perms: Setting permission access to false, player not found in NM for '" + player.getUniqueId() + "'");
return false;
}
if (permissionPlayer.getGroups().isEmpty())
{
FLog.debug("NM Perms: Setting permission access to false, player groups are empty for '" + player.getUniqueId() + "'");
return false;
}
// FLog.debug("Group Name requested for: " + player.getUniqueId() + " - " + groupName);
// FLog.debug("Player has? " + (permissionPlayer.getGroups().stream().anyMatch(group -> group.getName().equals(groupName))));
// permissionPlayer.getGroups().forEach(group -> FLog.debug("Player group: " + group.getName()));
return permissionPlayer.getGroups().stream().anyMatch(group -> group.getName().equals(groupName));
}
@Override
public boolean inGroup(@NotNull Player player, @Nullable String groupName)
{
return this.inGroup((OfflinePlayer) player, groupName);
}
@Override
public String[] getGroups()
{
return this.plugin.getPermissionManager().getGroups().values().stream().map(Group::getName).toArray(String[]::new);
}
@Override
public String getPrimaryGroup(@NotNull Player player)
{
PermissionPlayer permissionPlayer = this.plugin.getPermissionManager().getPermissionPlayer(player.getUniqueId());
if (permissionPlayer == null || permissionPlayer.getPrimaryGroup() == null)
{
FLog.warning("NM Perms: Couldn't find player's primary group due to them not be found our list");
return ConfigEntry.PERMISSIONS_GROUPS_DEFAULT.getString();
}
// permissionPlayer.getGroups().forEach(group -> FLog.debug(String.format("Group for %s: %s", permissionPlayer.getUuid(), group.getName())));
// FLog.debug(String.format("%s Primary Group: %s", permissionPlayer.getUuid(), permissionPlayer.getGroups().stream().sorted(Comparator.comparingInt(Group::getRank)).map(Group::getName).findFirst().orElse(ConfigEntry.PERMISSIONS_GROUPS_DEFAULT.getString())));
return permissionPlayer.getGroups().stream().sorted((o1, o2) -> o1.getRank() - o2.getRank()).map(Group::getName).findFirst().orElse(ConfigEntry.PERMISSIONS_GROUPS_DEFAULT.getString());
}
@Override
public String getPrefix(@NotNull Player player)
{
PermissionPlayer permissionPlayer = this.plugin.getPermissionManager().getPermissionPlayer(player.getUniqueId());
if (permissionPlayer == null)
{
FLog.warning("NM Perms: Couldn't find player's primary group due to them not be found our list");
return "[Error Loading Player]";
}
Group group = this.plugin.getPermissionManager().getGroup(getPrimaryGroup(player));
if (group == null)
{
return "[Error Finding Group]";
}
return group.getPrefix(null);
}
}

View File

@ -1,152 +0,0 @@
package me.totalfreedom.totalfreedommod.permissions.handler;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.util.FLog;
import net.milkbowl.vault.chat.Chat;
import net.milkbowl.vault.permission.Permission;
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.RegisteredServiceProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Taah
* @project TotalFreedomMod
* @since 9:10 PM [23-05-2022]
*/
public class VaultPermissionHandler implements IPermissionHandler
{
private Permission permissions;
private Chat chat;
public VaultPermissionHandler(TotalFreedomMod plugin)
{
if (plugin.permissionHandler != null)
{
return;
}
if (!Bukkit.getPluginManager().isPluginEnabled("Vault"))
{
plugin.permissionHandler = new DefaultPermissionHandler();
return;
}
this.permissions = setupPerms(plugin);
this.chat = setupChat(plugin);
plugin.permissionHandler = this;
}
@Override
public boolean hasPermission(@NotNull OfflinePlayer player, @Nullable String permission)
{
if (this.permissions == null)
{
FLog.debug("Can't use Vault permissions system, there is no plugin using Vault permissions.");
return true;
}
return permission == null || this.permissions.playerHas(null, player, permission);
}
@Override
public boolean hasPermission(@NotNull Player player, @Nullable String permission)
{
if (this.permissions == null)
{
FLog.debug("Can't use Vault permissions system, there is no plugin using Vault permissions.");
return true;
}
return permission == null || this.permissions.playerHas(player, permission);
}
@Override
public boolean inGroup(@NotNull OfflinePlayer player, @Nullable String groupName)
{
if (this.permissions == null)
{
FLog.debug("Can't use Vault permissions system for groups, there is no plugin using Vault permissions.");
return true;
}
if (groupName == null)
{
FLog.debug("Vault Perms: Group name is null, returning false for group check");
return false;
}
return this.permissions.playerInGroup(null, player, groupName);
}
@Override
public boolean inGroup(@NotNull Player player, @Nullable String groupName)
{
if (this.permissions == null)
{
FLog.debug("Can't use Vault permissions system for groups, there is no plugin using Vault permissions.");
return false;
}
if (groupName == null)
{
FLog.debug("Vault Perms: Group name is null, returning false for group check");
return false;
}
return this.permissions.playerInGroup(player, groupName);
}
@Override
public String[] getGroups()
{
if (this.permissions == null)
{
FLog.debug("Can't use Vault permissions system for group listing, there is no plugin using Vault permissions.");
return new String[0];
}
return this.permissions.getGroups();
}
@Override
public String getPrimaryGroup(@NotNull Player player)
{
return this.permissions.getPrimaryGroup(player);
}
@Override
public String getPrefix(@NotNull Player player)
{
if (this.chat == null)
{
return "[No Chat Plugin]";
}
return this.chat.getPlayerPrefix(player);
}
public Permission getPermissions()
{
return permissions;
}
private Permission setupPerms(TotalFreedomMod plugin)
{
RegisteredServiceProvider<Permission> rsp = Bukkit.getServicesManager().getRegistration(Permission.class);
if (rsp == null)
{
FLog.warning("Switching back to Bukkit's default permissions from Vault's due to no permission system found.");
plugin.permissionHandler = new DefaultPermissionHandler();
return null;
}
return rsp.getProvider();
}
private Chat setupChat(TotalFreedomMod plugin)
{
RegisteredServiceProvider<Chat> rsp = Bukkit.getServicesManager().getRegistration(Chat.class);
if (rsp == null)
{
// FLog.warning("Switching back to Bukkit's default permissions from Vault's due to no permission system found.");
// plugin.permissionHandler = new DefaultPermissionHandler();
return null;
}
return rsp.getProvider();
}
}

View File

@ -1,5 +1,7 @@
package me.totalfreedom.totalfreedommod.player; package me.totalfreedom.totalfreedommod.player;
import java.util.ArrayList;
import java.util.List;
import me.totalfreedom.totalfreedommod.TotalFreedomMod; import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.caging.CageData; import me.totalfreedom.totalfreedommod.caging.CageData;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -14,12 +16,8 @@ import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask; import org.bukkit.scheduler.BukkitTask;
import java.util.ArrayList;
import java.util.List;
public class FPlayer public class FPlayer
{ {
public static final long AUTO_PURGE_TICKS = 5L * 60L * 20L; public static final long AUTO_PURGE_TICKS = 5L * 60L * 20L;
@ -54,6 +52,9 @@ public class FPlayer
private String lastMessage = ""; private String lastMessage = "";
private boolean inAdminchat = false; private boolean inAdminchat = false;
private boolean allCommandsBlocked = false; private boolean allCommandsBlocked = false;
private boolean superadminIdVerified = false;
private String lastCommand = ""; private String lastCommand = "";
private boolean cmdspyEnabled = false; private boolean cmdspyEnabled = false;
private String tag = null; private String tag = null;
@ -246,7 +247,7 @@ public class FPlayer
public void startArrowShooter(TotalFreedomMod plugin) public void startArrowShooter(TotalFreedomMod plugin)
{ {
this.stopArrowShooter(); this.stopArrowShooter();
this.mp44ScheduleTask = new ArrowShooter(getPlayer()).runTaskTimer(plugin, 1L, 1L); this.mp44ScheduleTask = new ArrowShooter(this.player).runTaskTimer(plugin, 1L, 1L);
this.mp44Firing = true; this.mp44Firing = true;
} }
@ -645,6 +646,16 @@ public class FPlayer
this.allCommandsBlocked = allCommandsBlocked; this.allCommandsBlocked = allCommandsBlocked;
} }
public boolean isSuperadminIdVerified()
{
return superadminIdVerified;
}
public void setSuperadminIdVerified(boolean superadminIdVerified)
{
this.superadminIdVerified = superadminIdVerified;
}
public boolean isCmdspyEnabled() public boolean isCmdspyEnabled()
{ {
return cmdspyEnabled; return cmdspyEnabled;
@ -697,12 +708,9 @@ public class FPlayer
@Override @Override
public void run() public void run()
{
if (player != null)
{ {
Arrow shot = player.launchProjectile(Arrow.class); Arrow shot = player.launchProjectile(Arrow.class);
shot.setVelocity(shot.getVelocity().multiply(2.0)); shot.setVelocity(shot.getVelocity().multiply(2.0));
} }
} }
}
} }

View File

@ -3,25 +3,30 @@ package me.totalfreedom.totalfreedommod.player;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.*; import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import me.totalfreedom.totalfreedommod.TotalFreedomMod;
import me.totalfreedom.totalfreedommod.shop.ShopItem; import me.totalfreedom.totalfreedommod.shop.ShopItem;
import me.totalfreedom.totalfreedommod.util.FLog; import me.totalfreedom.totalfreedommod.util.FLog;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
public class PlayerData public class PlayerData
{ {
private UUID uuid;
private final List<String> ips = Lists.newArrayList(); private final List<String> ips = Lists.newArrayList();
private final List<String> notes = Lists.newArrayList(); private final List<String> notes = Lists.newArrayList();
private final List<String> backupCodes = Lists.newArrayList();
private String name;
private String tag = null; private String tag = null;
private String discordID = null; private String discordID = null;
private Boolean masterBuilder = false; private Boolean masterBuilder = false;
private Boolean verification = false;
private String rideMode = "ask"; private String rideMode = "ask";
@ -43,14 +48,17 @@ public class PlayerData
{ {
try try
{ {
uuid = UUID.fromString(resultSet.getString("uuid")); name = resultSet.getString("username");
ips.clear(); ips.clear();
ips.addAll(FUtil.stringToList(resultSet.getString("ips"))); ips.addAll(FUtil.stringToList(resultSet.getString("ips")));
notes.clear(); notes.clear();
notes.addAll(FUtil.stringToList(resultSet.getString("notes"))); notes.addAll(FUtil.stringToList(resultSet.getString("notes")));
tag = resultSet.getString("tag"); tag = resultSet.getString("tag");
discordID = resultSet.getString("discord_id"); discordID = resultSet.getString("discord_id");
backupCodes.clear();
backupCodes.addAll(FUtil.stringToList(resultSet.getString("backup_codes")));
masterBuilder = resultSet.getBoolean("master_builder"); masterBuilder = resultSet.getBoolean("master_builder");
verification = resultSet.getBoolean("verification");
rideMode = resultSet.getString("ride_mode"); rideMode = resultSet.getString("ride_mode");
coins = resultSet.getInt("coins"); coins = resultSet.getInt("coins");
items.clear(); items.clear();
@ -64,25 +72,40 @@ public class PlayerData
{ {
FLog.severe("Failed to load player: " + e.getMessage()); FLog.severe("Failed to load player: " + e.getMessage());
} }
// Force verification for Master Builders
if (masterBuilder && !verification)
{
verification = true;
TotalFreedomMod.getPlugin().pl.save(this);
}
else if (!masterBuilder && discordID == null && verification)
{
this.verification = false;
TotalFreedomMod.getPlugin().pl.save(this);
}
} }
public PlayerData(Player player) public PlayerData(Player player)
{ {
this.uuid = player.getUniqueId(); this.name = player.getName();
} }
@Override @Override
public String toString() public String toString()
{ {
return "Player: " + getName() + "\n" +
return "Player: " + name + "\n" +
"- IPs: " + StringUtils.join(ips, ", ") + "\n" + "- IPs: " + StringUtils.join(ips, ", ") + "\n" +
"- Discord ID: " + discordID + "\n" + "- Discord ID: " + discordID + "\n" +
"- Master Builder: " + masterBuilder + "\n" + "- Master Builder: " + masterBuilder + "\n" +
"- Has Verification: " + verification + "\n" +
"- Coins: " + coins + "\n" + "- Coins: " + coins + "\n" +
"- Total Votes: " + totalVotes + "\n" + "- Total Votes: " + totalVotes + "\n" +
"- Display Discord: " + displayDiscord + "\n" + "- Display Discord: " + displayDiscord + "\n" +
"- Tag: " + FUtil.colorize(tag) + ChatColor.GRAY + "\n" + "- Tag: " + FUtil.colorize(tag) + ChatColor.GRAY + "\n" +
"- Ride Mode: " + rideMode + "\n" + "- Ride Mode: " + rideMode + "\n" +
"- Backup Codes: " + backupCodes.size() + "/10" + "\n" +
"- Login Message: " + loginMessage; "- Login Message: " + loginMessage;
} }
@ -131,6 +154,22 @@ public class PlayerData
notes.clear(); notes.clear();
} }
public List<String> getBackupCodes()
{
return Collections.unmodifiableList(backupCodes);
}
public void setBackupCodes(List<String> codes)
{
backupCodes.clear();
backupCodes.addAll(codes);
}
public void removeBackupCode(String code)
{
backupCodes.remove(code);
}
public void addNote(String note) public void addNote(String note)
{ {
notes.add(note); notes.add(note);
@ -174,6 +213,11 @@ public class PlayerData
items.remove(item.getDataName()); items.remove(item.getDataName());
} }
public boolean hasVerification()
{
return verification;
}
public boolean isMasterBuilder() public boolean isMasterBuilder()
{ {
return masterBuilder; return masterBuilder;
@ -188,12 +232,14 @@ public class PlayerData
{ {
return new HashMap<String, Object>() return new HashMap<String, Object>()
{{ {{
put("uuid", uuid.toString()); put("username", name);
put("ips", FUtil.listToString(ips)); put("ips", FUtil.listToString(ips));
put("notes", FUtil.listToString(notes)); put("notes", FUtil.listToString(notes));
put("tag", tag); put("tag", tag);
put("discord_id", discordID); put("discord_id", discordID);
put("backup_codes", FUtil.listToString(backupCodes));
put("master_builder", masterBuilder); put("master_builder", masterBuilder);
put("verification", verification);
put("ride_mode", rideMode); put("ride_mode", rideMode);
put("coins", coins); put("coins", coins);
put("items", FUtil.listToString(items)); put("items", FUtil.listToString(items));
@ -209,14 +255,14 @@ public class PlayerData
return displayDiscord; return displayDiscord;
} }
public UUID getUuid()
{
return uuid;
}
public String getName() public String getName()
{ {
return Bukkit.getOfflinePlayer(uuid).getName(); return name;
}
public void setName(String name)
{
this.name = name;
} }
public String getTag() public String getTag()
@ -249,6 +295,16 @@ public class PlayerData
this.masterBuilder = masterBuilder; this.masterBuilder = masterBuilder;
} }
public Boolean getVerification()
{
return verification;
}
public void setVerification(Boolean verification)
{
this.verification = verification;
}
public String getRideMode() public String getRideMode()
{ {
return rideMode; return rideMode;

View File

@ -3,8 +3,11 @@ package me.totalfreedom.totalfreedommod.player;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; 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.Objects;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
@ -18,7 +21,7 @@ public class PlayerList extends FreedomService
{ {
public final Map<String, FPlayer> playerMap = Maps.newHashMap(); // ip,dataMap public final Map<String, FPlayer> playerMap = Maps.newHashMap(); // ip,dataMap
public final Map<UUID, PlayerData> dataMap = Maps.newHashMap(); // uuid, data public final Map<String, PlayerData> dataMap = Maps.newHashMap(); // username, data
@Override @Override
public void onStart() public void onStart()
@ -54,7 +57,7 @@ public class PlayerList extends FreedomService
while (resultSet.next()) while (resultSet.next())
{ {
PlayerData playerData = load(resultSet); PlayerData playerData = load(resultSet);
dataMap.put(playerData.getUuid(), playerData); dataMap.put(playerData.getName(), playerData);
} }
} }
catch (SQLException e) catch (SQLException e)
@ -100,7 +103,7 @@ public class PlayerList extends FreedomService
public boolean isTelnetMasterBuilder(PlayerData playerData) public boolean isTelnetMasterBuilder(PlayerData playerData)
{ {
Admin admin = plugin.al.getEntryByUuid(playerData.getUuid()); Admin admin = plugin.al.getEntryByName(playerData.getName());
return admin != null && admin.getRank().isAtLeast(Rank.ADMIN) && playerData.isMasterBuilder(); return admin != null && admin.getRank().isAtLeast(Rank.ADMIN) && playerData.isMasterBuilder();
} }
@ -119,9 +122,9 @@ public class PlayerList extends FreedomService
return tPlayer; return tPlayer;
} }
public PlayerData loadByUuid(UUID uuid) public PlayerData loadByName(String name)
{ {
return load(plugin.sql.getPlayerByUuid(uuid)); return load(plugin.sql.getPlayerByName(name));
} }
public PlayerData loadByIp(String ip) public PlayerData loadByIp(String ip)
@ -138,6 +141,43 @@ public class PlayerList extends FreedomService
return new PlayerData(resultSet); return new PlayerData(resultSet);
} }
public Boolean isPlayerImpostor(Player player)
{
PlayerData playerData = getData(player);
return plugin.dc.enabled
&& !plugin.al.isAdmin(player)
&& (playerData.hasVerification())
&& !playerData.getIps().contains(FUtil.getIp(player));
}
public boolean IsImpostor(Player player)
{
return isPlayerImpostor(player) || plugin.al.isAdminImpostor(player);
}
public void verify(Player player, String backupCode)
{
PlayerData playerData = getData(player);
if (backupCode != null)
{
playerData.removeBackupCode(backupCode);
}
playerData.addIp(FUtil.getIp(player));
save(playerData);
if (plugin.al.isAdminImpostor(player))
{
Admin admin = plugin.al.getEntryByName(player.getName());
admin.setLastLogin(new Date());
admin.addIp(FUtil.getIp(player));
plugin.al.updateTables();
plugin.al.save(admin);
}
plugin.rm.updateDisplay(player);
}
public void syncIps(Admin admin) public void syncIps(Admin admin)
{ {
PlayerData playerData = getData(admin.getName()); PlayerData playerData = getData(admin.getName());
@ -146,11 +186,25 @@ public class PlayerList extends FreedomService
plugin.pl.save(playerData); plugin.pl.save(playerData);
} }
public void syncIps(PlayerData playerData)
{
Admin admin = plugin.al.getEntryByName(playerData.getName());
if (admin != null && admin.isActive())
{
admin.clearIPs();
admin.addIps(playerData.getIps());
plugin.al.updateTables();
plugin.al.save(admin);
}
}
public void save(PlayerData player) public void save(PlayerData player)
{ {
try try
{ {
ResultSet currentSave = plugin.sql.getPlayerByUuid(player.getUuid()); ResultSet currentSave = plugin.sql.getPlayerByName(player.getName());
for (Map.Entry<String, Object> entry : player.toSQLStorable().entrySet()) for (Map.Entry<String, Object> entry : player.toSQLStorable().entrySet())
{ {
Object storedValue = plugin.sql.getValue(currentSave, entry.getKey(), entry.getValue()); Object storedValue = plugin.sql.getValue(currentSave, entry.getKey(), entry.getValue());
@ -169,56 +223,69 @@ public class PlayerList extends FreedomService
public PlayerData getData(Player player) public PlayerData getData(Player player)
{ {
// Check for existing data // Check for existing data
PlayerData playerData = dataMap.get(player.getUniqueId()); PlayerData playerData = dataMap.get(player.getName());
if (playerData != null) if (playerData != null)
{ {
return playerData; return playerData;
} }
// Load data // Load data
playerData = loadByUuid(player.getUniqueId()); playerData = loadByName(player.getName());
// Oh you don't have any data? Well now you do
if (playerData == null) if (playerData == null)
{ {
FLog.info("Creating new player data entry for " + player.getName()); playerData = loadByIp(FUtil.getIp(player));
if (playerData != null)
playerData = new PlayerData(player); {
playerData.addIp(FUtil.getIp(player)); plugin.sql.updatePlayerName(playerData.getName(), player.getName());
playerData.setName(player.getName());
dataMap.put(player.getName(), playerData);
return playerData;
} }
}
// Store it in memory. else
dataMap.put(player.getUniqueId(), playerData); {
dataMap.put(player.getName(), playerData);
// Send it to the SQL database.
plugin.sql.addPlayer(playerData);
// Returns it
return playerData; return playerData;
} }
public PlayerData getData(UUID uuid) // Create new data if nonexistent
{ FLog.info("Creating new player verification entry for " + player.getName());
PlayerData data = dataMap.get(uuid);
if (data == null) // Create new player
{ playerData = new PlayerData(player);
data = loadByUuid(uuid); playerData.addIp(FUtil.getIp(player));
}
// Store player
dataMap.put(player.getName(), playerData);
// Save player
plugin.sql.addPlayer(playerData);
return playerData;
return data;
} }
public PlayerData getData(String username) public PlayerData getData(String username)
{ {
OfflinePlayer player = server.getPlayer(username); // Check for existing data
PlayerData playerData = dataMap.get(username);
if (player == null) if (playerData != null)
{ {
player = server.getOfflinePlayer(username); return playerData;
} }
return getData(player.getUniqueId()); playerData = loadByName(username);
if (playerData != null)
{
dataMap.put(username, playerData);
}
else
{
return null;
}
return playerData;
} }
public PlayerData getDataByIp(String ip) public PlayerData getDataByIp(String ip)
@ -227,7 +294,7 @@ public class PlayerList extends FreedomService
if (player != null) if (player != null)
{ {
dataMap.put(player.getUuid(), player); dataMap.put(player.getName(), player);
} }
return player; return player;
@ -238,7 +305,7 @@ public class PlayerList extends FreedomService
return playerMap; return playerMap;
} }
public Map<UUID, PlayerData> getDataMap() public Map<String, PlayerData> getDataMap()
{ {
return dataMap; return dataMap;
} }

View File

@ -4,6 +4,7 @@ import net.md_5.bungee.api.ChatColor;
public enum Rank implements Displayable public enum Rank implements Displayable
{ {
IMPOSTOR("an", "Impostor", Type.PLAYER, "Imp", ChatColor.YELLOW, null, false, false),
NON_OP("a", "Non-Op", Type.PLAYER, "", ChatColor.WHITE, null, false, false), NON_OP("a", "Non-Op", Type.PLAYER, "", ChatColor.WHITE, null, false, false),
OP("an", "Operator", Type.PLAYER, "OP", ChatColor.GREEN, null, false, false), OP("an", "Operator", Type.PLAYER, "OP", ChatColor.GREEN, null, false, false),
ADMIN("an", "Admin", Type.ADMIN, "Admin", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true, true), ADMIN("an", "Admin", Type.ADMIN, "Admin", ChatColor.DARK_GREEN, org.bukkit.ChatColor.DARK_GREEN, true, true),

View File

@ -4,7 +4,6 @@ import java.util.Objects;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.permissions.handler.DefaultPermissionHandler;
import me.totalfreedom.totalfreedommod.player.FPlayer; import me.totalfreedom.totalfreedommod.player.FPlayer;
import me.totalfreedom.totalfreedommod.player.PlayerData; import me.totalfreedom.totalfreedommod.player.PlayerData;
import me.totalfreedom.totalfreedommod.util.FUtil; import me.totalfreedom.totalfreedommod.util.FUtil;
@ -40,6 +39,12 @@ public class RankManager extends FreedomService
final Player player = (Player)sender; final Player player = (Player)sender;
// Display impostors
if (plugin.al.isAdminImpostor(player))
{
return Rank.IMPOSTOR;
}
// If the player's an owner, display that // If the player's an owner, display that
if (ConfigEntry.SERVER_OWNERS.getList().contains(player.getName())) if (ConfigEntry.SERVER_OWNERS.getList().contains(player.getName()))
{ {
@ -62,6 +67,11 @@ public class RankManager extends FreedomService
return Title.ASSTEXEC; return Title.ASSTEXEC;
} }
if (plugin.al.isVerifiedAdmin(player))
{
return Title.VERIFIED_ADMIN;
}
// Master builders show up if they are not an admin // Master builders show up if they are not an admin
if (plugin.pl.getData(player).isMasterBuilder() && !plugin.al.isAdmin(player)) if (plugin.pl.getData(player).isMasterBuilder() && !plugin.al.isAdmin(player))
{ {
@ -127,6 +137,11 @@ public class RankManager extends FreedomService
public Rank getRank(Player player) public Rank getRank(Player player)
{ {
if (plugin.al.isAdminImpostor(player) || plugin.pl.isPlayerImpostor(player))
{
return Rank.IMPOSTOR;
}
final Admin entry = plugin.al.getAdmin(player); final Admin entry = plugin.al.getAdmin(player);
if (entry != null) if (entry != null)
{ {
@ -169,12 +184,7 @@ public class RankManager extends FreedomService
fPlayer.setTag(null); fPlayer.setTag(null);
player.setPlayerListName(null); player.setPlayerListName(null);
} }
if (!(plugin.permissionHandler instanceof DefaultPermissionHandler))
{
fPlayer.setTag(getTag(player, plugin.permissionHandler.getPrefix(player)));
} else {
fPlayer.setTag(getTag(player, display.getColoredTag())); fPlayer.setTag(getTag(player, display.getColoredTag()));
}
updatePlayerTeam(player); updatePlayerTeam(player);
plugin.pem.setPermissions(player); plugin.pem.setPermissions(player);
} }
@ -183,15 +193,53 @@ public class RankManager extends FreedomService
public void onPlayerJoin(PlayerJoinEvent event) public void onPlayerJoin(PlayerJoinEvent event)
{ {
final Player player = event.getPlayer(); final Player player = event.getPlayer();
final FPlayer fPlayer = plugin.pl.getPlayer(player);
PlayerData target = plugin.pl.getData(player); PlayerData target = plugin.pl.getData(player);
// Unban admins
boolean isAdmin = plugin.al.isAdmin(player); boolean isAdmin = plugin.al.isAdmin(player);
// Updates last login time
if (isAdmin) if (isAdmin)
{ {
// Verify strict IP match
if (!plugin.al.isIdentityMatched(player))
{
FUtil.bcastMsg("Warning: " + player.getName() + " is an admin, but is using an account not registered to one of their ip-list.", ChatColor.RED);
fPlayer.setSuperadminIdVerified(false);
}
else
{
fPlayer.setSuperadminIdVerified(true);
plugin.al.updateLastLogin(player); plugin.al.updateLastLogin(player);
} }
}
if (plugin.al.isVerifiedAdmin(player))
{
FUtil.bcastMsg("Warning: " + player.getName() + " is an admin, but does not have any admin permissions.", ChatColor.RED);
}
// Handle impostors
boolean isImpostor = plugin.al.isAdminImpostor(player) || plugin.pl.isPlayerImpostor(player);
if (isImpostor)
{
FUtil.bcastMsg(ChatColor.AQUA + player.getName() + " is " + Rank.IMPOSTOR.getColoredLoginMessage());
if (plugin.al.isAdminImpostor(player))
{
FUtil.bcastMsg("Warning: " + player.getName() + " has been flagged as an admin impostor and has been frozen!", ChatColor.RED);
}
else if (plugin.pl.isPlayerImpostor(player))
{
FUtil.bcastMsg("Warning: " + player.getName() + " has been flagged as a player impostor and has been frozen!", ChatColor.RED);
}
String displayName = Rank.IMPOSTOR.getColor() + player.getName();
player.setPlayerListName(StringUtils.substring(displayName, 0, 16));
player.getInventory().clear();
player.setOp(false);
player.setGameMode(GameMode.SURVIVAL);
plugin.pl.getPlayer(player).getFreezeData().setFrozen(true);
player.sendMessage(ChatColor.RED + "You are marked as an impostor, please verify yourself!");
return;
}
// Broadcast login message // Broadcast login message
if (isAdmin || FUtil.isDeveloper(player) || plugin.pl.getData(player).isMasterBuilder() || plugin.pl.getData(player).hasLoginMessage()) if (isAdmin || FUtil.isDeveloper(player) || plugin.pl.getData(player).isMasterBuilder() || plugin.pl.getData(player).hasLoginMessage())
@ -205,11 +253,14 @@ public class RankManager extends FreedomService
// Set display // Set display
updateDisplay(player); updateDisplay(player);
if (!plugin.pl.isPlayerImpostor(player) && target.hasVerification())
{
if (target.getTag() != null) if (target.getTag() != null)
{ {
plugin.pl.getData(player).setTag(FUtil.colorize(target.getTag())); plugin.pl.getData(player).setTag(FUtil.colorize(target.getTag()));
} }
} }
}
public String craftLoginMessage(Player player, String message) public String craftLoginMessage(Player player, String message)
{ {

View File

@ -6,6 +6,7 @@ public enum Title implements Displayable
{ {
MASTER_BUILDER("a", "Master Builder", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true, true), MASTER_BUILDER("a", "Master Builder", ChatColor.DARK_AQUA, org.bukkit.ChatColor.DARK_AQUA, "MB", true, true),
VERIFIED_ADMIN("a", "Verified Admin", ChatColor.LIGHT_PURPLE, org.bukkit.ChatColor.LIGHT_PURPLE, "VA", false, true),
EXECUTIVE("an", "Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true, true), EXECUTIVE("an", "Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Exec", true, true),
ASSTEXEC("an", "Assistant Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Asst Exec", true, true), ASSTEXEC("an", "Assistant Executive", ChatColor.RED, org.bukkit.ChatColor.RED, "Asst Exec", true, true),
DEVELOPER("a", "Developer", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true, true), DEVELOPER("a", "Developer", ChatColor.DARK_PURPLE, org.bukkit.ChatColor.DARK_PURPLE, "Dev", true, true),

View File

@ -10,29 +10,19 @@ public enum ShopItem
LIGHTNING_ROD("Lightning Rod", Material.BLAZE_ROD, 12, ConfigEntry.SHOP_PRICES_LIGHTNING_ROD, ChatColor.LIGHT_PURPLE, "lightningRod", "/lightningrod"), LIGHTNING_ROD("Lightning Rod", Material.BLAZE_ROD, 12, ConfigEntry.SHOP_PRICES_LIGHTNING_ROD, ChatColor.LIGHT_PURPLE, "lightningRod", "/lightningrod"),
FIRE_BALL("Fire Ball", Material.FIRE_CHARGE, 14, ConfigEntry.SHOP_PRICES_FIRE_BALL, ChatColor.RED, "fireBall", "/fireball"), FIRE_BALL("Fire Ball", Material.FIRE_CHARGE, 14, ConfigEntry.SHOP_PRICES_FIRE_BALL, ChatColor.RED, "fireBall", "/fireball"),
RIDEABLE_PEARL("Rideable Ender Pearl", Material.ENDER_PEARL, 16, ConfigEntry.SHOP_PRICES_RIDEABLE_PEARL, ChatColor.DARK_PURPLE, "rideablePearl", "/rideablepearl"), RIDEABLE_PEARL("Rideable Ender Pearl", Material.ENDER_PEARL, 16, ConfigEntry.SHOP_PRICES_RIDEABLE_PEARL, ChatColor.DARK_PURPLE, "rideablePearl", "/rideablepearl"),
STACKING_POTATO("Stacking Potato", Material.POTATO, 19, ConfigEntry.SHOP_PRICES_STACKING_POTATO, ChatColor.YELLOW, "stackingPotato", "/stackingpotato"), STACKING_POTATO("Stacking Potato", Material.POTATO, 20, ConfigEntry.SHOP_PRICES_STACKING_POTATO, ChatColor.YELLOW, "stackingPotato", "/stackingpotato"),
CLOWN_FISH("Clown Fish", Material.TROPICAL_FISH, 21, ConfigEntry.SHOP_PRICES_CLOWN_FISH, ChatColor.GOLD, "clownFish", "/clownfish"), CLOWN_FISH("Clown Fish", Material.TROPICAL_FISH, 22, ConfigEntry.SHOP_PRICES_CLOWN_FISH, ChatColor.GOLD, "clownFish", "/clownfish"),
LOGIN_MESSAGES("Login Messages", Material.NAME_TAG, 23, ConfigEntry.SHOP_PRICES_LOGIN_MESSAGES, ChatColor.DARK_GREEN, "loginMessages", "/loginmessage"), LOGIN_MESSAGES("Login Messages", Material.NAME_TAG, 24, ConfigEntry.SHOP_PRICES_LOGIN_MESSAGES, ChatColor.DARK_GREEN, "loginMessages", "/loginmessage");
RAINBOW_TRAIL("Rainbow Trail", Material.RED_WOOL, 25, ConfigEntry.SHOP_PRICES_RAINBOW_TRAIL, ChatColor.DARK_RED, "rainbowTrail", "/trail");
/* /*
Shop GUI Layout: Shop GUI Layout:
Dimensions: 9x4 = 36 Dimensions: 9x4 = 36
Key: Key: g = Grappling Hook, l = Lightning Rod, f = Fire Ball, r = Rideable Ender Pearl, s = Stacking Potato, c = Clown Fish, x = Login Messages $ = Coins}
g = Grappling Hook,
l = Lightning Rod
f = Fire Ball
r = Rideable Ender Pearl
s = Stacking Potato
c = Clown Fish
x = Login Messages
t = Rainbow Trail
$ = Coins
--------- ---------
-g-l-f-r- -g-l-f-r-
-s-c-x-t- --s-c-x--
--------$ --------$
*/ */

View File

@ -7,8 +7,6 @@ import java.sql.PreparedStatement;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.UUID;
import me.totalfreedom.totalfreedommod.FreedomService; import me.totalfreedom.totalfreedommod.FreedomService;
import me.totalfreedom.totalfreedommod.admin.Admin; import me.totalfreedom.totalfreedommod.admin.Admin;
import me.totalfreedom.totalfreedommod.banning.Ban; import me.totalfreedom.totalfreedommod.banning.Ban;
@ -84,7 +82,7 @@ public class SQLite extends FreedomService
{ {
try try
{ {
connection.createStatement().execute("CREATE TABLE `admins` (`uuid` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `rank` VARCHAR NOT NULL, `active` BOOLEAN NOT NULL, `last_login` LONG NOT NULL, `command_spy` BOOLEAN NOT NULL, `potion_spy` BOOLEAN NOT NULL, `ac_format` VARCHAR, `ptero_id` VARCHAR);"); connection.createStatement().execute("CREATE TABLE `admins` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `rank` VARCHAR NOT NULL, `active` BOOLEAN NOT NULL, `last_login` LONG NOT NULL, `command_spy` BOOLEAN NOT NULL, `potion_spy` BOOLEAN NOT NULL, `ac_format` VARCHAR, `ptero_id` VARCHAR);");
} }
catch (SQLException e) catch (SQLException e)
{ {
@ -95,7 +93,7 @@ public class SQLite extends FreedomService
{ {
try try
{ {
connection.createStatement().execute("CREATE TABLE `players` (`uuid` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `master_builder` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `login_message` VARCHAR, `inspect` BOOLEAN NOT NULL);"); connection.createStatement().execute("CREATE TABLE `players` (`username` VARCHAR NOT NULL, `ips` VARCHAR NOT NULL, `notes` VARCHAR, `tag` VARCHAR, `discord_id` VARCHAR, `backup_codes` VARCHAR, `master_builder` BOOLEAN NOT NULL,`verification` BOOLEAN NOT NULL, `ride_mode` VARCHAR NOT NULL, `coins` INT, `items` VARCHAR, `total_votes` INT NOT NULL, `display_discord` BOOLEAN NOT NULL, `login_message` VARCHAR, `inspect` BOOLEAN NOT NULL);");
} }
catch (SQLException e) catch (SQLException e)
{ {
@ -135,8 +133,8 @@ public class SQLite extends FreedomService
{ {
try try
{ {
Object[] data = {key, admin.getUuid()}; Object[] data = {key, admin.getName()};
PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE admins SET {0}=? WHERE uuid=''{1}''", data)); PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE admins SET {0}=? WHERE username=''{1}''", data));
statement = setUnknownType(statement, 1, value); statement = setUnknownType(statement, 1, value);
statement.executeUpdate(); statement.executeUpdate();
@ -153,7 +151,7 @@ public class SQLite extends FreedomService
try try
{ {
Object[] data = {key, player.getName()}; Object[] data = {key, player.getName()};
PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE players SET {0}=? WHERE uuid=''{1}''", data)); PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE players SET {0}=? WHERE username=''{1}''", data));
statement = setUnknownType(statement, 1, value); statement = setUnknownType(statement, 1, value);
statement.executeUpdate(); statement.executeUpdate();
@ -164,6 +162,36 @@ public class SQLite extends FreedomService
} }
} }
public void updateAdminName(String oldName, String newName)
{
try
{
PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE admins SET username=? WHERE username=''{0}''", oldName));
statement = setUnknownType(statement, 1, newName);
statement.executeUpdate();
}
catch (SQLException e)
{
FLog.severe("Failed to update admin name: " + e.getMessage());
}
}
public void updatePlayerName(String oldName, String newName)
{
try
{
PreparedStatement statement = connection.prepareStatement(MessageFormat.format("UPDATE players SET username=? WHERE username=''{0}''", oldName));
statement = setUnknownType(statement, 1, newName);
statement.executeUpdate();
}
catch (SQLException e)
{
FLog.severe("Failed to update player name: " + e.getMessage());
}
}
public PreparedStatement setUnknownType(PreparedStatement statement, int index, Object value) throws SQLException public PreparedStatement setUnknownType(PreparedStatement statement, int index, Object value) throws SQLException
{ {
if (value == null) if (value == null)
@ -220,7 +248,7 @@ public class SQLite extends FreedomService
try try
{ {
PreparedStatement statement = connection.prepareStatement("INSERT INTO admins VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); PreparedStatement statement = connection.prepareStatement("INSERT INTO admins VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, admin.getUuid().toString()); statement.setString(1, admin.getName());
statement.setString(2, FUtil.listToString(admin.getIps())); statement.setString(2, FUtil.listToString(admin.getIps()));
statement.setString(3, admin.getRank().toString()); statement.setString(3, admin.getRank().toString());
statement.setBoolean(4, admin.isActive()); statement.setBoolean(4, admin.isActive());
@ -242,20 +270,22 @@ public class SQLite extends FreedomService
{ {
try try
{ {
PreparedStatement statement = connection.prepareStatement("INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); PreparedStatement statement = connection.prepareStatement("INSERT INTO players VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
statement.setString(1, player.getUuid().toString()); statement.setString(1, player.getName());
statement.setString(2, FUtil.listToString(player.getIps())); statement.setString(2, FUtil.listToString(player.getIps()));
statement.setString(3, FUtil.listToString(player.getNotes())); statement.setString(3, FUtil.listToString(player.getNotes()));
statement.setString(4, player.getTag()); statement.setString(4, player.getTag());
statement.setString(5, player.getDiscordID()); statement.setString(5, player.getDiscordID());
statement.setBoolean(6, player.isMasterBuilder()); statement.setString(6, FUtil.listToString(player.getBackupCodes()));
statement.setString(7, player.getRideMode()); statement.setBoolean(7, player.isMasterBuilder());
statement.setInt(8, player.getCoins()); statement.setBoolean(8, player.hasVerification());
statement.setString(9, FUtil.listToString(player.getItems())); statement.setString(9, player.getRideMode());
statement.setInt(10, player.getTotalVotes()); statement.setInt(10, player.getCoins());
statement.setBoolean(11, player.doesDisplayDiscord()); statement.setString(11, FUtil.listToString(player.getItems()));
statement.setString(12, player.getLoginMessage()); statement.setInt(12, player.getTotalVotes());
statement.setBoolean(13, player.hasInspection()); statement.setBoolean(13, player.doesDisplayDiscord());
statement.setString(14, player.getLoginMessage());
statement.setBoolean(15, player.hasInspection());
statement.executeUpdate(); statement.executeUpdate();
} }
catch (SQLException e) catch (SQLException e)
@ -265,11 +295,11 @@ public class SQLite extends FreedomService
} }
} }
public ResultSet getAdminByUuid(UUID uuid) public ResultSet getAdminByName(String name)
{ {
try try
{ {
ResultSet resultSet = connection.createStatement().executeQuery(MessageFormat.format("SELECT * FROM admins WHERE uuid=''{0}''", uuid.toString())); ResultSet resultSet = connection.createStatement().executeQuery(MessageFormat.format("SELECT * FROM admins WHERE username=''{0}''", name));
if (resultSet.next()) if (resultSet.next())
{ {
return resultSet; return resultSet;
@ -284,11 +314,11 @@ public class SQLite extends FreedomService
return null; return null;
} }
public ResultSet getPlayerByUuid(UUID uuid) public ResultSet getPlayerByName(String name)
{ {
try try
{ {
ResultSet resultSet = connection.createStatement().executeQuery(MessageFormat.format("SELECT * FROM players WHERE uuid=''{0}''", uuid.toString())); ResultSet resultSet = connection.createStatement().executeQuery(MessageFormat.format("SELECT * FROM players WHERE username=''{0}''", name));
if (resultSet.next()) if (resultSet.next())
{ {
return resultSet; return resultSet;
@ -296,7 +326,7 @@ public class SQLite extends FreedomService
} }
catch (SQLException e) catch (SQLException e)
{ {
FLog.severe("Failed to get player by UUID:"); FLog.severe("Failed to get player by name:");
FLog.severe(e); FLog.severe(e);
} }

View File

@ -0,0 +1,28 @@
package me.totalfreedom.totalfreedommod.util;
import java.util.HashSet;
import org.bukkit.Material;
import org.bukkit.OfflinePlayer;
import org.bukkit.Server;
import org.bukkit.block.Block;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
@SuppressWarnings("deprecation")
public class DepreciationAggregator
{
public static Block getTargetBlock(LivingEntity entity, HashSet<Material> transparent, int maxDistance)
{
return entity.getTargetBlock(transparent, maxDistance);
}
public static OfflinePlayer getOfflinePlayer(Server server, String name)
{
return server.getOfflinePlayer(name);
}
public static String getName_EntityType(EntityType et)
{
return et.getName();
}
}

View File

@ -36,6 +36,8 @@ import static org.bukkit.Bukkit.getServer;
public class FUtil public class FUtil
{ {
public static final String SAVED_FLAGS_FILENAME = "savedflags.dat";
/* See https://github.com/TotalFreedom/License - None of the listed names may be removed. /* See https://github.com/TotalFreedom/License - None of the listed names may be removed.
Leaving this list here for anyone running TFM on a cracked server: Leaving this list here for anyone running TFM on a cracked server:
public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "Telesphoreo", "CoolJWB"); public static final List<String> DEVELOPERS = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "Telesphoreo", "CoolJWB");
@ -52,12 +54,13 @@ public class FUtil
"d018f2b8-ce60-4672-a45f-e580e0331299", // speednt "d018f2b8-ce60-4672-a45f-e580e0331299", // speednt
"458de06f-36a5-4e1b-aaa6-ec1d1751c5b6", // SupItsDillon "458de06f-36a5-4e1b-aaa6-ec1d1751c5b6", // SupItsDillon
"c8e5af82-6aba-4dd7-83e8-474381380cc9", // Paldiu "c8e5af82-6aba-4dd7-83e8-474381380cc9", // Paldiu
"38ea7c82-7bdc-4f48-b7fd-0e93fc26813d", // AwesomePinch
"ba5aafba-9012-418f-9819-a7020d591068", // TFTWPhoenix "ba5aafba-9012-418f-9819-a7020d591068", // TFTWPhoenix
"d6dd9740-40db-45f5-ab16-4ee16a633009", // Abhi "d6dd9740-40db-45f5-ab16-4ee16a633009", // Abhi
"2e06e049-24c8-42e4-8bcf-d35372af31e6", // NotInSync "2e06e049-24c8-42e4-8bcf-d35372af31e6", // NotInSync
"f97c0d7b-6413-4558-a409-88f09a8f9adb" // videogamesm12 "f97c0d7b-6413-4558-a409-88f09a8f9adb" // videogamesm12
); );
public static final List<String> DEVELOPER_NAMES = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "CoolJWB", "elmon_", "speednt", "SupItsDillon", "Paldiu", "TFTWPhoenix", "abhithedev", "NotInSync", "videogamesm12"); public static final List<String> DEVELOPER_NAMES = Arrays.asList("Madgeek1450", "Prozza", "WickedGamingUK", "Wild1145", "aggelosQQ", "scripthead", "CoolJWB", "elmon_", "speednt", "SupItsDillon", "Paldiu", "AwesomePinch", "TFTWPhoenix", "abhithedev", "NotInSync", "videogamesm12");
public static final Map<String, ChatColor> CHAT_COLOR_NAMES = new HashMap<>(); public static final Map<String, ChatColor> CHAT_COLOR_NAMES = new HashMap<>();
public static final List<ChatColor> CHAT_COLOR_POOL = Arrays.asList( public static final List<ChatColor> CHAT_COLOR_POOL = Arrays.asList(
ChatColor.DARK_RED, ChatColor.DARK_RED,
@ -225,6 +228,33 @@ public class FUtil
return names; return names;
} }
@SuppressWarnings("unchecked")
public static UUID nameToUUID(String name)
{
try
{
JSONArray json = new JSONArray();
json.add(name);
List<String> headers = new ArrayList<>();
headers.add("Accept:application/json");
headers.add("Content-Type:application/json");
Response response = sendRequest("https://api.mojang.com/profiles/minecraft", "POST", headers, json.toString());
// Don't care how stupid this looks, couldn't find anything to parse a json string to something readable in java with something not horrendously huge, maybe im just retarded
Pattern pattern = Pattern.compile("(?<=\"id\":\")[a-f0-9].{31}");
Matcher matcher = pattern.matcher(response.getMessage());
if (matcher.find())
{
String rawUUID = matcher.group(0).replaceFirst("([a-f0-9]{8})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]{4})([a-f0-9]+)", "$1-$2-$3-$4-$5");
return UUID.fromString(rawUUID);
}
}
catch (Exception e)
{
FLog.severe("Failed to convert name to UUID:\n" + e.toString());
}
return null;
}
public static Response sendRequest(String endpoint, String method, List<String> headers, String body) throws IOException public static Response sendRequest(String endpoint, String method, List<String> headers, String body) throws IOException
{ {
URL url = new URL(endpoint); URL url = new URL(endpoint);
@ -510,6 +540,30 @@ public class FUtil
return ip; return ip;
} }
//getField: Borrowed from WorldEdit
@SuppressWarnings("unchecked")
public static <T> T getField(Object from, String name)
{
Class<?> checkClass = from.getClass();
do
{
try
{
Field field = checkClass.getDeclaredField(name);
field.setAccessible(true);
return (T) field.get(from);
}
catch (NoSuchFieldException | IllegalAccessException ignored)
{
}
}
while (checkClass.getSuperclass() != Object.class
&& ((checkClass = checkClass.getSuperclass()) != null));
return null;
}
public static ChatColor randomChatColor() public static ChatColor randomChatColor()
{ {
return CHAT_COLOR_POOL.get(RANDOM.nextInt(CHAT_COLOR_POOL.size())); return CHAT_COLOR_POOL.get(RANDOM.nextInt(CHAT_COLOR_POOL.size()));
@ -701,7 +755,7 @@ public class FUtil
public static String getIp(Player player) public static String getIp(Player player)
{ {
return player.getAddress().getAddress().getHostAddress().trim(); return Objects.requireNonNull(player.getAddress()).getAddress().getHostAddress().trim();
} }
public static String getIp(PlayerLoginEvent event) public static String getIp(PlayerLoginEvent event)

View File

@ -8,11 +8,212 @@ import org.bukkit.entity.EntityType;
public class Groups public class Groups
{ {
public static final List<Material> WOOL_COLORS = Arrays.stream(Material.values()).filter((m) -> m.name().endsWith("_WOOL")).toList(); public static final List<Material> WOOL_COLORS = Arrays.asList(
public static final List<Material> SHULKER_BOXES = Arrays.stream(Material.values()).filter((m) -> m.name().endsWith("SHULKER_BOX")).toList(); Material.WHITE_WOOL,
public static final List<EntityType> MOB_TYPES = Arrays.stream(EntityType.values()).filter(EntityType::isAlive).filter(EntityType::isSpawnable).toList(); Material.RED_WOOL,
public static final List<Material> SPAWN_EGGS = Arrays.stream(Material.values()).filter((mat) -> mat.name().endsWith("_SPAWN_EGG")).toList(); Material.ORANGE_WOOL,
public static final List<Material> BANNERS = Arrays.stream(Material.values()).filter((m) -> m.name().endsWith("_BANNER")).toList(); Material.YELLOW_WOOL,
Material.GREEN_WOOL,
Material.LIME_WOOL,
Material.LIGHT_BLUE_WOOL,
Material.CYAN_WOOL,
Material.BLUE_WOOL,
Material.PURPLE_WOOL,
Material.MAGENTA_WOOL,
Material.PINK_WOOL,
Material.BROWN_WOOL,
Material.GRAY_WOOL,
Material.LIGHT_GRAY_WOOL,
Material.BLACK_WOOL);
public static final List<Material> SHULKER_BOXES = Arrays.asList(
Material.SHULKER_BOX,
Material.WHITE_SHULKER_BOX,
Material.RED_SHULKER_BOX,
Material.ORANGE_SHULKER_BOX,
Material.YELLOW_SHULKER_BOX,
Material.GREEN_SHULKER_BOX,
Material.LIME_SHULKER_BOX,
Material.LIGHT_BLUE_SHULKER_BOX,
Material.CYAN_SHULKER_BOX,
Material.BLUE_SHULKER_BOX,
Material.PURPLE_SHULKER_BOX,
Material.MAGENTA_SHULKER_BOX,
Material.PINK_SHULKER_BOX,
Material.BROWN_SHULKER_BOX,
Material.GRAY_SHULKER_BOX,
Material.LIGHT_GRAY_SHULKER_BOX,
Material.BLACK_SHULKER_BOX);
public static final List<EntityType> MOB_TYPES = Arrays.asList(
EntityType.BAT,
EntityType.BEE,
EntityType.BLAZE,
EntityType.CAVE_SPIDER,
EntityType.CHICKEN,
EntityType.CAT,
EntityType.COD,
EntityType.COW,
EntityType.CREEPER,
EntityType.DOLPHIN,
EntityType.DONKEY,
EntityType.DROWNED,
EntityType.ELDER_GUARDIAN,
EntityType.ENDERMAN,
EntityType.ENDERMITE,
EntityType.EVOKER,
EntityType.FOX,
EntityType.GHAST,
EntityType.GUARDIAN,
EntityType.HOGLIN,
EntityType.HORSE,
EntityType.HUSK,
EntityType.ILLUSIONER,
EntityType.IRON_GOLEM,
EntityType.LLAMA,
EntityType.MAGMA_CUBE,
EntityType.MUSHROOM_COW,
EntityType.MULE,
EntityType.OCELOT,
EntityType.PANDA,
EntityType.PARROT,
EntityType.PHANTOM,
EntityType.PIG,
EntityType.PIGLIN,
EntityType.PIGLIN_BRUTE,
EntityType.PILLAGER,
EntityType.POLAR_BEAR,
EntityType.PUFFERFISH,
EntityType.RABBIT,
EntityType.RAVAGER,
EntityType.SALMON,
EntityType.SHEEP,
EntityType.SHULKER,
EntityType.SILVERFISH,
EntityType.SKELETON,
EntityType.SKELETON_HORSE,
EntityType.SLIME,
EntityType.SNOWMAN,
EntityType.SPIDER,
EntityType.SQUID,
EntityType.STRAY,
EntityType.STRIDER,
EntityType.TRADER_LLAMA,
EntityType.TROPICAL_FISH,
EntityType.TURTLE,
EntityType.VEX,
EntityType.VILLAGER,
EntityType.VINDICATOR,
EntityType.WANDERING_TRADER,
EntityType.WITCH,
EntityType.WITHER_SKELETON,
EntityType.WOLF,
EntityType.ZOGLIN,
EntityType.ZOMBIE,
EntityType.ZOMBIE_HORSE,
EntityType.ZOMBIFIED_PIGLIN,
EntityType.ZOMBIE_VILLAGER);
public static final List<Material> SPAWN_EGGS = Arrays.asList(
Material.BAT_SPAWN_EGG,
Material.BEE_SPAWN_EGG,
Material.BLAZE_SPAWN_EGG,
Material.CAVE_SPIDER_SPAWN_EGG,
Material.CHICKEN_SPAWN_EGG,
Material.CAT_SPAWN_EGG,
Material.COD_SPAWN_EGG,
Material.COW_SPAWN_EGG,
Material.CREEPER_SPAWN_EGG,
Material.DOLPHIN_SPAWN_EGG,
Material.DONKEY_SPAWN_EGG,
Material.DROWNED_SPAWN_EGG,
Material.ELDER_GUARDIAN_SPAWN_EGG,
Material.ENDERMAN_SPAWN_EGG,
Material.ENDERMITE_SPAWN_EGG,
Material.EVOKER_SPAWN_EGG,
Material.FOX_SPAWN_EGG,
Material.GHAST_SPAWN_EGG,
Material.GUARDIAN_SPAWN_EGG,
Material.HOGLIN_SPAWN_EGG,
Material.HORSE_SPAWN_EGG,
Material.HUSK_SPAWN_EGG,
Material.LLAMA_SPAWN_EGG,
Material.MAGMA_CUBE_SPAWN_EGG,
Material.MOOSHROOM_SPAWN_EGG,
Material.MULE_SPAWN_EGG,
Material.OCELOT_SPAWN_EGG,
Material.PANDA_SPAWN_EGG,
Material.PARROT_SPAWN_EGG,
Material.PHANTOM_SPAWN_EGG,
Material.PIG_SPAWN_EGG,
Material.PIGLIN_SPAWN_EGG,
Material.PIGLIN_BRUTE_SPAWN_EGG,
Material.PILLAGER_SPAWN_EGG,
Material.POLAR_BEAR_SPAWN_EGG,
Material.PUFFERFISH_SPAWN_EGG,
Material.RABBIT_SPAWN_EGG,
Material.RAVAGER_SPAWN_EGG,
Material.SALMON_SPAWN_EGG,
Material.SHEEP_SPAWN_EGG,
Material.SHULKER_SPAWN_EGG,
Material.SILVERFISH_SPAWN_EGG,
Material.SKELETON_SPAWN_EGG,
Material.SKELETON_HORSE_SPAWN_EGG,
Material.SLIME_SPAWN_EGG,
Material.SPIDER_SPAWN_EGG,
Material.SQUID_SPAWN_EGG,
Material.STRAY_SPAWN_EGG,
Material.STRIDER_SPAWN_EGG,
Material.TRADER_LLAMA_SPAWN_EGG,
Material.TROPICAL_FISH_SPAWN_EGG,
Material.TURTLE_SPAWN_EGG,
Material.VEX_SPAWN_EGG,
Material.VILLAGER_SPAWN_EGG,
Material.VINDICATOR_SPAWN_EGG,
Material.WANDERING_TRADER_SPAWN_EGG,
Material.WITCH_SPAWN_EGG,
Material.WITHER_SKELETON_SPAWN_EGG,
Material.WOLF_SPAWN_EGG,
Material.ZOGLIN_SPAWN_EGG,
Material.ZOMBIE_SPAWN_EGG,
Material.ZOMBIE_HORSE_SPAWN_EGG,
Material.ZOMBIFIED_PIGLIN_SPAWN_EGG,
Material.ZOMBIE_VILLAGER_SPAWN_EGG);
public static final List<Material> BANNERS = Arrays.asList(
Material.BLACK_BANNER,
Material.BLACK_WALL_BANNER,
Material.BLUE_BANNER,
Material.BLUE_WALL_BANNER,
Material.BROWN_BANNER,
Material.BROWN_WALL_BANNER,
Material.CYAN_BANNER,
Material.CYAN_WALL_BANNER,
Material.GRAY_BANNER,
Material.GRAY_WALL_BANNER,
Material.GREEN_BANNER,
Material.GREEN_WALL_BANNER,
Material.LIGHT_BLUE_BANNER,
Material.LIGHT_BLUE_WALL_BANNER,
Material.LIGHT_GRAY_BANNER,
Material.LIGHT_GRAY_WALL_BANNER,
Material.LIME_BANNER,
Material.LIME_WALL_BANNER,
Material.MAGENTA_BANNER,
Material.MAGENTA_WALL_BANNER,
Material.ORANGE_BANNER,
Material.ORANGE_WALL_BANNER,
Material.PINK_BANNER,
Material.PINK_WALL_BANNER,
Material.PURPLE_BANNER,
Material.PURPLE_WALL_BANNER,
Material.RED_BANNER,
Material.RED_WALL_BANNER,
Material.WHITE_BANNER,
Material.WHITE_WALL_BANNER,
Material.YELLOW_BANNER,
Material.YELLOW_WALL_BANNER);
public static final List<Biome> EXPLOSIVE_BED_BIOMES = Arrays.asList( public static final List<Biome> EXPLOSIVE_BED_BIOMES = Arrays.asList(
Biome.NETHER_WASTES, Biome.NETHER_WASTES,
Biome.CRIMSON_FOREST, Biome.CRIMSON_FOREST,

View File

@ -1,6 +1,9 @@
package me.totalfreedom.totalfreedommod.world; package me.totalfreedom.totalfreedommod.world;
import java.io.File;
import me.totalfreedom.totalfreedommod.config.ConfigEntry; import me.totalfreedom.totalfreedommod.config.ConfigEntry;
import me.totalfreedom.totalfreedommod.util.FLog;
import org.apache.commons.io.FileUtils;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.ChatColor; import org.bukkit.ChatColor;
import org.bukkit.Material; import org.bukkit.Material;
@ -29,6 +32,8 @@ public class Flatlands extends CustomWorld
return null; return null;
} }
wipeFlatlandsIfFlagged();
final WorldCreator worldCreator = new WorldCreator(getName()); final WorldCreator worldCreator = new WorldCreator(getName());
worldCreator.generateStructures(false); worldCreator.generateStructures(false);
worldCreator.type(WorldType.NORMAL); worldCreator.type(WorldType.NORMAL);
@ -58,4 +63,32 @@ public class Flatlands extends CustomWorld
return world; return world;
} }
public void wipeFlatlandsIfFlagged()
{
boolean doFlatlandsWipe = false;
try
{
doFlatlandsWipe = plugin.sf.getSavedFlag("do_wipe_flatlands");
}
catch (Exception ignored)
{
}
if (doFlatlandsWipe)
{
if (Bukkit.getServer().getWorld("flatlands") == null)
{
FLog.info("Wiping flatlands.");
plugin.sf.setSavedFlag("do_wipe_flatlands", false);
FileUtils.deleteQuietly(new File("./flatlands"));
}
else
{
FLog.severe("Can't wipe flatlands, it is already loaded.");
}
}
}
} }

View File

@ -32,6 +32,14 @@ public class WorldRestrictions extends FreedomService
private final List<String> BLOCKED_ESSENTIALS_COMMANDS = Arrays.asList( private final List<String> BLOCKED_ESSENTIALS_COMMANDS = Arrays.asList(
"bigtree", "ebigtree", "largetree", "elargetree"); "bigtree", "ebigtree", "largetree", "elargetree");
private final Map<Flag<?>, Object> flags = new HashMap<Flag<?>, Object>()
{{
put(Flags.PLACE_VEHICLE, StateFlag.State.DENY);
put(Flags.DESTROY_VEHICLE, StateFlag.State.DENY);
put(Flags.ENTITY_ITEM_FRAME_DESTROY, StateFlag.State.DENY);
put(Flags.ENTITY_PAINTING_DESTROY, StateFlag.State.DENY);
}};
@Override @Override
public void onStart() public void onStart()
{ {
@ -147,4 +155,20 @@ public class WorldRestrictions extends FreedomService
} }
} }
} }
public void protectWorld(World world)
{
if (!plugin.wgb.isEnabled())
{
return;
}
RegionManager regionManager = plugin.wgb.getRegionManager(world);
GlobalProtectedRegion region = new GlobalProtectedRegion("__global__");
region.setFlags(flags);
regionManager.addRegion(region);
}
} }

View File

@ -54,15 +54,10 @@ server:
# What to display at the bottom of the tab list # What to display at the bottom of the tab list
tablist_footer: '' tablist_footer: ''
# Permissions System
permissions:
groups:
admin: "Administrator"
senior_admin: "Senior-Administrator"
default: "Guest"
# Discord # Discord
discord: discord:
# Do you want to enable the Discord verification system? (Disabled by default)
verification: false
# If you do not have a token, make a bot account and get one at https://discordapp.com/developers/applications/me # If you do not have a token, make a bot account and get one at https://discordapp.com/developers/applications/me
token: '' token: ''
# The official discord server's ID for this server # The official discord server's ID for this server
@ -89,21 +84,24 @@ discord:
executive_role_id: '' executive_role_id: ''
# Owner role ID # Owner role ID
server_owner_role_id: '' server_owner_role_id: ''
# Invite link for your Discord server
invite_link: 'https://discord.com/invite/PW4savJR9a'
# Pterodactyl # Pterodactyl (requires Discord verification to be enabled)
ptero: ptero:
# URL - do not leave a trailing forward slash # URL - do not leave a trailing forward slash
url: '' url: ''
# The default email domain used to set email addresses for new users - do not include the @ # The default email domain used to set email addresses for new users - do not include the @
default_email_domain: 'example.com' default_email_domain: 'example.com'
# Server UUID # Long Server UUID (for example: abf9a712-6c5a-4504-b4bc-37f1061b8801)
# Do NOT give the short Server UUID
server_uuid: '' server_uuid: ''
# Admin panel API key # Admin panel API key
# Create this key by going to Settings > Application API > Create New
# Make sure you give it Users and Servers permissions
admin_key: '' admin_key: ''
# Server API key # Client API key
server_key: '' # Create a new user and add them as a subuser to the server with all control privileges.
# Then, login to the new user account and go to User Settings. Click on API Credentials and create a new one.
client_key: ''
# The shop # The shop
shop: shop:
@ -166,7 +164,6 @@ shop:
stacking_potato: 300 stacking_potato: 300
clown_fish: 1500 clown_fish: 1500
login_messages: 5000 login_messages: 5000
rainbow_trail: 1500
# Admin list # Admin list
adminlist: adminlist:
@ -214,7 +211,7 @@ allow:
fire_spread: false fire_spread: false
fluid_spread: false fluid_spread: false
lava_place: true lava_place: true
lava_damage: true lava_damage: false
water_place: true water_place: true
tnt_minecarts: false tnt_minecarts: false
explosions: false explosions: false
@ -514,10 +511,6 @@ moblimiter:
slime: true slime: true
giant: true giant: true
# Spawnmob
spawnmob:
max: 25
# Flatlands # Flatlands
flatlands: flatlands:
generate: true generate: true
@ -602,14 +595,6 @@ masterbuilderinfo:
- ' &2- Template:' - ' &2- Template:'
- '&9https://forum.totalfreedom.me/d/336-master-builder-application-process' - '&9https://forum.totalfreedom.me/d/336-master-builder-application-process'
# What new players will see upon joining for the first time.
first_join_info:
enabled: true
text:
- "&6Welcome to TotalFreedom -- the original Free-OP server!"
- "&eThe server's name doesn't mean we have no rules. Do &6/rules &efor a list of them."
- "&aNeed help getting started? Do &2/help &aor a list of commands!"
# Famous players - cannot be banned by username # Famous players - cannot be banned by username
famous_players: famous_players:
- honeydew - honeydew