Compare commits
No commits in common. "main" and "1.0.1-SNAPSHOT" have entirely different histories.
main
...
1.0.1-SNAP
73 changed files with 512 additions and 2575 deletions
|
|
@ -1,43 +0,0 @@
|
||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'src/**'
|
|
||||||
- '.github/**'
|
|
||||||
- 'build.gradle.kts'
|
|
||||||
- 'gradle.properties'
|
|
||||||
- 'settings.gradle'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: arch-linux
|
|
||||||
env:
|
|
||||||
NEMESIS_VERSION_NAME: "autobuild-${{ github.sha }}"
|
|
||||||
NEMESIS_BUILD_CHANNEL: "autobuild"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6.0.1
|
|
||||||
|
|
||||||
- name: Setup Java enviroment
|
|
||||||
uses: actions/setup-java@v5.1.0
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
|
|
||||||
- name: Download CB1060
|
|
||||||
run: |
|
|
||||||
mkdir -p libs
|
|
||||||
curl -L -o libs/craftbukkit-1060.jar https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew buildAll
|
|
||||||
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v6.0.0
|
|
||||||
with:
|
|
||||||
path: build/libs/*.jar
|
|
||||||
|
|
@ -1,40 +0,0 @@
|
||||||
name: Release Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-release:
|
|
||||||
runs-on: arch-linux
|
|
||||||
env:
|
|
||||||
NEMESIS_VERSION_NAME: "${{ github.ref_name }}"
|
|
||||||
NEMESIS_BUILD_CHANNEL: "production"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6.0.1
|
|
||||||
|
|
||||||
- name: Set up Java
|
|
||||||
uses: actions/setup-java@v5.1.0
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: Set up Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
|
|
||||||
- name: Download CB1060
|
|
||||||
run: |
|
|
||||||
mkdir -p libs
|
|
||||||
curl -L -o libs/craftbukkit-1060.jar \
|
|
||||||
https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew buildAll
|
|
||||||
|
|
||||||
- name: Upload JARs to release
|
|
||||||
uses: softprops/action-gh-release@v2.5.0
|
|
||||||
with:
|
|
||||||
files: build/libs/*.jar
|
|
||||||
tag_name: ${{ github.ref_name }}
|
|
||||||
name: ${{ github.ref_name }}
|
|
||||||
15
.github/FUNDING.yml
vendored
15
.github/FUNDING.yml
vendored
|
|
@ -1,15 +0,0 @@
|
||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
github: adrianvic
|
|
||||||
patreon: # Replace with a single Patreon username
|
|
||||||
open_collective: # Replace with a single Open Collective username
|
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
|
||||||
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
liberapay: # Replace with a single Liberapay username
|
|
||||||
issuehunt: # Replace with a single IssueHunt username
|
|
||||||
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
|
|
||||||
polar: # Replace with a single Polar username
|
|
||||||
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
|
|
||||||
thanks_dev: # Replace with a single thanks.dev username
|
|
||||||
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
44
.github/workflows/build.yml
vendored
44
.github/workflows/build.yml
vendored
|
|
@ -1,44 +0,0 @@
|
||||||
name: Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'src/**'
|
|
||||||
- '.github/**'
|
|
||||||
- 'build.gradle.kts'
|
|
||||||
- 'gradle.properties'
|
|
||||||
- 'settings.gradle'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
NEMESIS_VERSION_NAME: "autobuild-${{ github.sha }}"
|
|
||||||
NEMESIS_BUILD_CHANNEL: "autobuild"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6.0.1
|
|
||||||
|
|
||||||
- name: Setup Java enviroment
|
|
||||||
uses: actions/setup-java@v5.1.0
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
|
|
||||||
- name: Download CB1060
|
|
||||||
run: |
|
|
||||||
mkdir -p libs
|
|
||||||
curl -L -o libs/craftbukkit-1060.jar https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew buildAll
|
|
||||||
|
|
||||||
|
|
||||||
- name: Upload artifacts
|
|
||||||
uses: actions/upload-artifact@v3
|
|
||||||
with:
|
|
||||||
path: build/libs/*.jar
|
|
||||||
41
.github/workflows/release-build.yml
vendored
41
.github/workflows/release-build.yml
vendored
|
|
@ -1,41 +0,0 @@
|
||||||
name: Release Build
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-and-release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
NEMESIS_VERSION_NAME: "${{ github.ref_name }}"
|
|
||||||
NEMESIS_BUILD_CHANNEL: "production"
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v6.0.1
|
|
||||||
|
|
||||||
- name: Set up Java
|
|
||||||
uses: actions/setup-java@v5.1.0
|
|
||||||
with:
|
|
||||||
distribution: temurin
|
|
||||||
java-version: 21
|
|
||||||
|
|
||||||
- name: Set up Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v5
|
|
||||||
|
|
||||||
- name: Download CB1060
|
|
||||||
run: |
|
|
||||||
mkdir -p libs
|
|
||||||
curl -L -o libs/craftbukkit-1060.jar \
|
|
||||||
https://archive.org/download/craftbukkit1060/craftbukkit1-7-3%281060%29.jar
|
|
||||||
|
|
||||||
- name: Build with Gradle
|
|
||||||
run: ./gradlew buildAll
|
|
||||||
|
|
||||||
- name: Upload artifacts to release
|
|
||||||
run: |
|
|
||||||
curl -X POST \
|
|
||||||
-H "Authorization: token ${{ secrets.FORGEJO_TOKEN }}" \
|
|
||||||
-H "Content-Type: application/octet-stream" \
|
|
||||||
https://inspiran.beetal-castor.ts.net/git/api/v1/repos/${{ github.repository }}/releases/tags/${{ github.ref_name }}/assets \
|
|
||||||
--data-binary @build/libs/your-artifact.jar
|
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -1,6 +1,4 @@
|
||||||
.gradle/
|
.gradle/
|
||||||
build/
|
build/
|
||||||
out/
|
out/
|
||||||
.idea/
|
.idea/
|
||||||
libs/
|
|
||||||
run/
|
|
||||||
24
README.md
24
README.md
|
|
@ -1,24 +1,4 @@
|
||||||
<img alt="eye_of_nemesis_social_cover" src="https://github.com/user-attachments/assets/a24bc92f-4dc2-4594-93c9-d056130f9695" />
|
|
||||||
|
|
||||||
[](https://modrinth.com/plugin/eye-of-nemesis)
|
|
||||||
[](https://github.com/adrianvic/NemesisEye/wiki)
|
|
||||||
[](https://mgr.rf.gd/w/Eye_of_Nemesis)
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> This project is in an early stage, please report any bug you find.
|
|
||||||
|
|
||||||
# Eye of Nemesis
|
# Eye of Nemesis
|
||||||
Eye of Nemesis is a plugin that allows server admins to write policies that will deny or allow (black/whitelist) players to do specific things based on the value of nodes.
|
Eye of Nemesis is a Minecraft Paper plugin that allows server admins to write *policies* that will deny or allow (black/whitelist) players to do specific things.
|
||||||
|
|
||||||
## Motivations
|
You can create policies based on player location, ~but other types of policies are available, like permission and player-name policy.~ (WIP)
|
||||||
I made this plugin as an effort to preserve a village from my private server. Originally from beta 1.7.3 Betalands server, then transferred to RetroMC, and then finally we downloaded the chunks to merge into our server, I was afraid it would not have the same feeling after all the updates, so I had the idea to make a plugin that can block the newer features.
|
|
||||||
|
|
||||||
## Game version and loaders
|
|
||||||
Since version 1.0.3-SNAPSHOT, Eye of Nemesis has _reflection_, a technique that allows me to target multiple versions of the game while sharing the codebase across versions.
|
|
||||||
|
|
||||||
Currently, we support the following Minecraft versions/loaders:
|
|
||||||
- **PaperMC** `1.21, 1.21.1, 1.21.2, 1.21.3, 1.21.4, 1.21.5, 1.21.6, 1.21.7, 1.21.8, 1.21.9, 1.21.10`
|
|
||||||
- **Bukkit** `b1.7.3 (CB1060)`
|
|
||||||
|
|
||||||
## Performance
|
|
||||||
This plugin is not scalable as it is and will end up running unoptimized checks when your players do things with policies in effect, I made it for a server with a few friends. I'll look forward into writing more performant code after all my other priorities are implemented.
|
|
||||||
|
|
|
||||||
55
build.gradle
Normal file
55
build.gradle
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id("xyz.jpenilla.run-paper") version "2.3.1"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'io.github.adrianvic'
|
||||||
|
version = '1.0.1-SNAPSHOT'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven {
|
||||||
|
name = "papermc-repo"
|
||||||
|
url = "https://repo.papermc.io/repository/maven-public/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
runServer {
|
||||||
|
// Configure the Minecraft version for our task.
|
||||||
|
// This is the only required configuration besides applying the plugin.
|
||||||
|
// Your plugin's jar (or shadowJar if present) will be used automatically.
|
||||||
|
minecraftVersion("1.21")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def targetJavaVersion = 21
|
||||||
|
java {
|
||||||
|
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||||
|
sourceCompatibility = javaVersion
|
||||||
|
targetCompatibility = javaVersion
|
||||||
|
if (JavaVersion.current() < javaVersion) {
|
||||||
|
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
|
||||||
|
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
||||||
|
options.release.set(targetJavaVersion)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
def props = [version: version]
|
||||||
|
inputs.properties props
|
||||||
|
filteringCharset 'UTF-8'
|
||||||
|
filesMatching('plugin.yml') {
|
||||||
|
expand props
|
||||||
|
}
|
||||||
|
}
|
||||||
154
build.gradle.kts
154
build.gradle.kts
|
|
@ -1,154 +0,0 @@
|
||||||
plugins {
|
|
||||||
java
|
|
||||||
id("xyz.jpenilla.run-paper") version "2.3.1"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = "io.github.adrianvic"
|
|
||||||
version = System.getenv("NEMESIS_VERSION_NAME") ?: "unknown"
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven("https://repo.papermc.io/repository/maven-public/")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
/* SUPPORTED VERSIONS */
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
|
|
||||||
val mcVersions = listOf(
|
|
||||||
"b1_7_3",
|
|
||||||
"r1_21"
|
|
||||||
)
|
|
||||||
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
/* CREATE SOURCE SET PER VERSION */
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
|
|
||||||
tasks.withType<ProcessResources> {
|
|
||||||
inputs.property("version", project.version)
|
|
||||||
|
|
||||||
filesMatching("plugin.yml") {
|
|
||||||
expand("version" to project.version)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mcVersions.forEach { ver ->
|
|
||||||
val ss = sourceSets.create(ver) {
|
|
||||||
java.srcDir("src/$ver/java")
|
|
||||||
|
|
||||||
resources.setSrcDirs(listOf("src/$ver/resources", "src/main/resources"))
|
|
||||||
|
|
||||||
compileClasspath += sourceSets["main"].output
|
|
||||||
runtimeClasspath += output + compileClasspath
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<ProcessResources> {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations[ss.implementationConfigurationName]
|
|
||||||
.extendsFrom(configurations["implementation"])
|
|
||||||
|
|
||||||
configurations[ss.compileOnlyConfigurationName]
|
|
||||||
.extendsFrom(configurations["compileOnly"])
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
/* DEPENDENCIES */
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
add("compileOnly", "io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
|
|
||||||
add("r1_21CompileOnly", "io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
|
|
||||||
add("b1_7_3CompileOnly", files("libs/craftbukkit-1060.jar"))
|
|
||||||
|
|
||||||
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
|
|
||||||
testImplementation("org.mockito:mockito-core:5.5.0")
|
|
||||||
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
|
||||||
testImplementation("io.papermc.paper:paper-api:1.21-R0.1-SNAPSHOT")
|
|
||||||
testImplementation("com.github.seeseemelk:MockBukkit-v1.21:3.102.0")
|
|
||||||
|
|
||||||
// Allow tests to see the versioned implementations
|
|
||||||
mcVersions.forEach { ver ->
|
|
||||||
testImplementation(sourceSets[ver].output)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
/* BUILD TASKS */
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
|
|
||||||
mcVersions.forEach { ver ->
|
|
||||||
tasks.register<Jar>("jar${ver.replace(".", "_").replace("-", "_").replace("/", "_").capitalize()}") {
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
from(sourceSets["main"].output)
|
|
||||||
from(sourceSets[ver].output)
|
|
||||||
archiveClassifier.set(ver)
|
|
||||||
|
|
||||||
manifest {
|
|
||||||
attributes(
|
|
||||||
"Nemesis-Impl-Version" to ver,
|
|
||||||
"Nemesis-Environment" to (System.getenv("NEMESIS_BUILD_CHANNEL") ?: "dev")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register("buildAll") {
|
|
||||||
dependsOn(tasks.withType<Jar>())
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register<Jar>("shadowJar") {
|
|
||||||
from(sourceSets["main"].output)
|
|
||||||
mcVersions.forEach { ver ->
|
|
||||||
from(sourceSets[ver].output)
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is kinda gross and, essentially, we shouldn't have it here...
|
|
||||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
|
||||||
|
|
||||||
archiveClassifier.set("all-implementations")
|
|
||||||
archiveVersion.set(project.version.toString())
|
|
||||||
|
|
||||||
manifest {
|
|
||||||
attributes(
|
|
||||||
"Implemented-Versions" to mcVersions.joinToString(",")
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
/* JAVA SETTINGS */
|
|
||||||
/* ----------------------------------------- */
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType<JavaCompile> {
|
|
||||||
options.encoding = "UTF-8"
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.runServer {
|
|
||||||
minecraftVersion("1.21")
|
|
||||||
downloadPlugins {
|
|
||||||
modrinth("viaversion", "5.7.0")
|
|
||||||
modrinth("luckperms", "v5.5.17-bukkit")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register("runServerClean") {
|
|
||||||
doFirst {
|
|
||||||
exec {
|
|
||||||
commandLine("rm", "run/plugins/Eye-of-Nemesis/settings.yml")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependsOn("runServer")
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
# Nodes
|
|
||||||
Nodes narrow down even further if an action can be done or not. A node needs _properties_ to know what it should check against, for example, a HIT node needs a _list_ of blocks that it will check if the player is holding; while a USE_ENCHANTMENT node needs a mapping of enchantment to level. Some nodes like glyde don't need a value and will ignore if you provide one.
|
|
||||||
```yaml
|
|
||||||
nodes:
|
|
||||||
- [HIT]:
|
|
||||||
values:
|
|
||||||
- 'GOLD_SWORD'
|
|
||||||
- [USE_ENCHANTMENT]:
|
|
||||||
values:
|
|
||||||
- "UNBREAKING": "1"
|
|
||||||
- [GLYDE]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Available nodes
|
|
||||||
### INTERACT
|
|
||||||
Triggered on `InteractionEvent`, returns true when the provided `list` contains the material used to interact.
|
|
||||||
|
|
||||||
### HIT
|
|
||||||
Triggered on `EntityDamageByEntityEvent`, returns true when the provided `list` contains the material used to hit.
|
|
||||||
|
|
||||||
### PLACE
|
|
||||||
Triggered on `BlockPlaceEvent`, returns true when the provided `list` contains the material being placed.
|
|
||||||
|
|
||||||
### BREAK
|
|
||||||
Triggered on `BlockBreakEvent`, returns true when the provided `list` contains the material used to break.
|
|
||||||
|
|
||||||
### EQUIP
|
|
||||||
Triggered on `InventoryClickEvent` and `PlayerInteractEvent` (only if item is an armor), returns true when the provided `list` contains the material being equipped.
|
|
||||||
|
|
||||||
### GLYDE
|
|
||||||
Triggered on `PlayerMoveEvent`, returns true if player is gliding.
|
|
||||||
|
|
||||||
### USE_ENCHANTMENT
|
|
||||||
Triggered on `BlockBreakEvent` and `onEntityDamageByEntityEvent`, returns true the used item has an enchantment matching the provided mapping of enchantment-level.
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
# Policies
|
|
||||||
Policies are a list of nodes with a specific condition to be met, they also determine what effect a node is going to have. Below is an example policy:
|
|
||||||
```yaml
|
|
||||||
- name: "Allow example"
|
|
||||||
type: "location"
|
|
||||||
effect: ALLOW
|
|
||||||
weight: 1
|
|
||||||
worlds: [world]
|
|
||||||
locations:
|
|
||||||
coordinates:
|
|
||||||
- corner1: { x: 2100, y: 256, z: 1400 }
|
|
||||||
corner2: { x: 1000, y: -64, z: 2200 }
|
|
||||||
nodes:
|
|
||||||
- [INTERACT, BREAK, HIT, PLACE]:
|
|
||||||
values:
|
|
||||||
- AIR
|
|
||||||
```
|
|
||||||
|
|
||||||
## Properties
|
|
||||||
### `name`
|
|
||||||
Name of the policy, must not contain spaces or else commands that require you to type the policy name will not work.
|
|
||||||
|
|
||||||
Example: `name: "disable-axe-damage"`
|
|
||||||
|
|
||||||
### `type`
|
|
||||||
One of the policy [types](#Types).
|
|
||||||
|
|
||||||
Example: `type: location`
|
|
||||||
|
|
||||||
### `effect`
|
|
||||||
Can be `deny` to block the action if a node check returns true, `ALLOW` to revert `DENY` effects if the node check is true or `ALLOWONLY` to allow the action **only** if the node check returns true.
|
|
||||||
|
|
||||||
Example: `effect: DENY`
|
|
||||||
|
|
||||||
### `weight`
|
|
||||||
A policy with greater weight will override a conflicting policy of lower weight.
|
|
||||||
|
|
||||||
Example: `weight: 0`
|
|
||||||
|
|
||||||
### `nodes`
|
|
||||||
Must contain a list of node mappings to evaluate if the policy applies to a player.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
```yaml
|
|
||||||
nodes:
|
|
||||||
- [HIT]:
|
|
||||||
values:
|
|
||||||
- '.*_AXE$'
|
|
||||||
```
|
|
||||||
|
|
||||||
### `locations`
|
|
||||||
Only used for `type: "location"`, is a list of mappings where corner1 and corner2 should map x, y and z to two corners of a rectangular area where the policy will take effect; `worlds` may be defined here.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
locations:
|
|
||||||
worlds: [world]
|
|
||||||
coordinates:
|
|
||||||
- corner1: { x: 2100, y: 256, z: 1400 }
|
|
||||||
corner2: { x: 1000, y: -64, z: 2200 }
|
|
||||||
```
|
|
||||||
|
|
||||||
### `permissions`
|
|
||||||
Only used for `type: "permission"`, is a list of permissions.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
permissions:
|
|
||||||
- "server.axehit"
|
|
||||||
```
|
|
||||||
|
|
||||||
### `names`
|
|
||||||
Only used for `type: "playerName"`, is a list of player names.
|
|
||||||
|
|
||||||
## Types
|
|
||||||
|
|
||||||
### `global`
|
|
||||||
Always matches.
|
|
||||||
|
|
||||||
### `location`
|
|
||||||
Matches if the player location is inside any rectangle defined in the `locations` property.
|
|
||||||
|
|
||||||
### `playerName`
|
|
||||||
Matches if the player name is in the `names` property.
|
|
||||||
|
|
||||||
### `permission`
|
|
||||||
Matches if the player has a permission in the `permissions` property.
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
rootProject.name = 'eyeofnemesis'
|
rootProject.name = 'regions'
|
||||||
|
|
|
||||||
|
|
@ -1,89 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
import org.bukkit.util.config.Configuration;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
|
|
||||||
public class ConfigurationEx extends Configuration {
|
|
||||||
private final File configFile;
|
|
||||||
private final Log logger;
|
|
||||||
JavaPlugin plugin;
|
|
||||||
|
|
||||||
public ConfigurationEx(String fileName, Log _logger) {
|
|
||||||
super(new File(Nemesis.getInstance().getDataFolder(), fileName));
|
|
||||||
this.plugin = Nemesis.getInstance();
|
|
||||||
logger = _logger;
|
|
||||||
this.configFile = new File(plugin.getDataFolder(), fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void load() {
|
|
||||||
createParentDirectories();
|
|
||||||
|
|
||||||
if (!configFile.exists()) {
|
|
||||||
copyDefaultConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
super.load();
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createParentDirectories() {
|
|
||||||
try {
|
|
||||||
Files.createDirectories(configFile.getParentFile().toPath());
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.severe(String.format("Failed to generate default config directory: %s", e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void copyDefaultConfig() {
|
|
||||||
// Load the config from the JAR directly (it is located at the root level)
|
|
||||||
String resourcePath = "/" + configFile.getName(); // Root path of JAR
|
|
||||||
|
|
||||||
try (InputStream input = plugin.getClass().getResourceAsStream(resourcePath)) {
|
|
||||||
if (input == null) {
|
|
||||||
logger.severe(String.format("Default config '%s' wasn't found in the JAR.", configFile.getName()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Files.copy(input, configFile.toPath());
|
|
||||||
if (Files.exists(configFile.toPath())) {
|
|
||||||
logger.info(String.format("Default config '%s' generated successfully.", configFile.getName()));
|
|
||||||
} else {
|
|
||||||
logger.warning("We tried to generate the default config file, but it was not found even after the creation. Maybe your permissions are broken?");
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
logger.severe(String.format("Failed to generate default config '%s': %s", configFile.getName(), e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadConfig() {
|
|
||||||
try {
|
|
||||||
this.load();
|
|
||||||
logger.info(String.format("Config '%s' loaded successfully.", configFile.getName()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.severe(String.format("Failed to load config '%s': %s", configFile.getName(), e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void saveConfig() {
|
|
||||||
try {
|
|
||||||
this.save();
|
|
||||||
logger.info(String.format("Config '%s' saved successfully.", configFile.getName()));
|
|
||||||
} catch (Exception e) {
|
|
||||||
logger.severe(String.format("Failed to save config '%s': %s", configFile.getName(), e.getMessage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public File getConfig() {
|
|
||||||
return configFile;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,41 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import static org.bukkit.Bukkit.getServer;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
public class Log {
|
|
||||||
JavaPlugin plugin;
|
|
||||||
PluginDescriptionFile pdf;
|
|
||||||
|
|
||||||
public Log() {
|
|
||||||
plugin = Nemesis.getInstance();
|
|
||||||
pdf = plugin.getDescription();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void info(String message) {
|
|
||||||
getServer().getLogger().info("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void infoc(String message) {
|
|
||||||
getServer().getLogger().info("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void warning(String message) {
|
|
||||||
getServer().getLogger().warning("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void warningc(String message) {
|
|
||||||
getServer().getLogger().warning("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void severe(String message) {
|
|
||||||
getServer().getLogger().severe("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void severec(String message) {
|
|
||||||
getServer().getLogger().severe("[" + pdf.getName() + "] " + message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,152 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.impl.commands.Eye;
|
|
||||||
import io.github.adrianvic.nemesiseye.impl.events.BlockEventListener;
|
|
||||||
import io.github.adrianvic.nemesiseye.impl.events.EntityEventListener;
|
|
||||||
import io.github.adrianvic.nemesiseye.impl.events.PlayerEventListener;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyParsers;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class b1_7_3 implements Glimmer {
|
|
||||||
JavaPlugin plugin;
|
|
||||||
PluginManager pm;
|
|
||||||
ConfigurationEx config;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public File loadConfigFile() {
|
|
||||||
config = new ConfigurationEx("settings.yml", new Log());
|
|
||||||
config.load();
|
|
||||||
return config.getConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> loadPoliciesFromFile(File file) {
|
|
||||||
List<?> rawPolicies = config.getList("Policies");
|
|
||||||
|
|
||||||
if (rawPolicies == null) {
|
|
||||||
return new ArrayList<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<?, ?>> result = new ArrayList<>(rawPolicies.size());
|
|
||||||
|
|
||||||
for (Object entry : rawPolicies) {
|
|
||||||
if (entry instanceof Map<?,?> m) {
|
|
||||||
result.add(m);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Policy> allPolicies = new ArrayList<>();
|
|
||||||
for (Map<?, ?> policyMap : result) {
|
|
||||||
if (policyMap.get("type") != null && policyMap.get("type") instanceof String type) {
|
|
||||||
allPolicies.add(PolicyParsers.get(type).parse(policyMap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allPolicies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoad() {
|
|
||||||
plugin = Nemesis.getInstance();
|
|
||||||
pm = Nemesis.getInstance().getPluginManager();
|
|
||||||
pm.registerEvent(Event.Type.ENTITY_DAMAGE, new EntityEventListener(), Event.Priority.Normal, plugin);
|
|
||||||
pm.registerEvent(Event.Type.BLOCK_BREAK, new BlockEventListener(), Event.Priority.Normal, plugin);
|
|
||||||
pm.registerEvent(Event.Type.PLAYER_INTERACT, new PlayerEventListener(), Event.Priority.Normal, plugin);
|
|
||||||
plugin.getCommand("eye").setExecutor(new Eye());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemInMainHandHumanEntity(HumanEntity entity) {
|
|
||||||
return entity.getItemInHand();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAir(ItemStack item) {
|
|
||||||
return item == null || item.getType() == Material.AIR;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGliding(org.bukkit.entity.Player player) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setGliding(org.bukkit.entity.Player player, boolean gliding) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(org.bukkit.command.CommandSender sender, String permission) {
|
|
||||||
if (sender instanceof org.bukkit.entity.Player p) {
|
|
||||||
return p.isOp();
|
|
||||||
}
|
|
||||||
return true; // Console always has permission
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isArmorEquipAttempt(org.bukkit.event.Event event) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getEquippedItem(org.bukkit.event.Event event) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(CommandSender commandSender, String text) {
|
|
||||||
String[] lines = text.split("\\r?\\n");
|
|
||||||
for (String line : lines) {
|
|
||||||
commandSender.sendMessage(line);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasItemMeta(ItemStack item) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<World> getWorlds() {
|
|
||||||
return plugin.getServer().getWorlds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasEnchantment(ItemStack item, Map<String, String> valuesmap) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasAnyEnchantment(ItemStack itemStack) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isArmor(ItemStack item) {
|
|
||||||
if (item == null || item.getType() == Material.AIR) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = item.getType().name();
|
|
||||||
|
|
||||||
return name.endsWith("_HELMET")
|
|
||||||
|| name.endsWith("_CHESTPLATE")
|
|
||||||
|| name.endsWith("_LEGGINGS")
|
|
||||||
|| name.endsWith("_BOOTS");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl.commands;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.commands.EyeCore;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
public class Eye implements CommandExecutor {
|
|
||||||
private final EyeCore core;
|
|
||||||
|
|
||||||
public Eye() {
|
|
||||||
core = new EyeCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(CommandSender commandSender, Command command, String s, String [] strings) {
|
|
||||||
return core.onCommand(commandSender, command, s, strings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,18 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl.events;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Events;
|
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
|
||||||
import org.bukkit.event.block.BlockListener;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
|
|
||||||
public class BlockEventListener extends BlockListener {
|
|
||||||
@Override
|
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
|
||||||
Events.onBlockBreak(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onBlockPlace(BlockPlaceEvent event) {
|
|
||||||
Events.onBlockPlaceEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl.events;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Events;
|
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageEvent;
|
|
||||||
import org.bukkit.event.entity.EntityListener;
|
|
||||||
|
|
||||||
public class EntityEventListener extends EntityListener {
|
|
||||||
@Override
|
|
||||||
public void onEntityDamage(EntityDamageEvent event) {
|
|
||||||
if (event instanceof EntityDamageByEntityEvent e) Events.onEntityDamageByEntityEvent(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl.events;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Events;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
|
||||||
import org.bukkit.event.player.PlayerListener;
|
|
||||||
|
|
||||||
public class PlayerEventListener extends PlayerListener {
|
|
||||||
@Override
|
|
||||||
public void onPlayerInteract(PlayerInteractEvent event) {
|
|
||||||
Events.onInteractionEvent(event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,45 +1,56 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
package io.github.adrianvic.nemesiseye;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
import io.github.adrianvic.nemesiseye.policy.LocationPolicy;
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.GlobalPolicy;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Config {
|
public class Config {
|
||||||
private static Config instance = new Config();
|
private final static Config instance = new Config();
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
private File file;
|
private File file;
|
||||||
private List<Policy> policies = new ArrayList<>();
|
private YamlConfiguration config;
|
||||||
|
|
||||||
private Config() {}
|
private List<LocationPolicy> locationPolicies;
|
||||||
|
// private List<PermissionPolicy> permissionPolicies;
|
||||||
|
// private List<PlayerNamePolicy> playerNamePolicies;
|
||||||
|
|
||||||
public void load() {
|
private Config() {
|
||||||
policies = glim.loadPoliciesFromFile(glim.loadConfigFile());
|
|
||||||
policies.sort(Comparator.comparingInt(Policy::weight).reversed());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Implement config saving
|
public void load() {
|
||||||
//
|
file = new File(Nemesis.getInstance().getDataFolder(), "settings.yml");
|
||||||
// public void save() {
|
|
||||||
// try {
|
|
||||||
// config.save(file);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// public void set(String path, Object value) {
|
|
||||||
// config.set(path, value);
|
|
||||||
// save();
|
|
||||||
// }
|
|
||||||
|
|
||||||
public List<Policy> getPolicies() {
|
if (!file.exists())
|
||||||
return policies;
|
Nemesis.getInstance().saveResource("settings.yml", false);
|
||||||
|
|
||||||
|
config = new YamlConfiguration();
|
||||||
|
config.options().parseComments(true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
config.load(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
locationPolicies = LocationPolicy.parseLocationPolicy(config.getMapList("Policies.Location"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save() {
|
||||||
|
try {
|
||||||
|
config.save(file);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(String path, Object value) {
|
||||||
|
config.set(path, value);
|
||||||
|
save();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<LocationPolicy> getLocationPolicies() {
|
||||||
|
return locationPolicies;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Config getInstance() {
|
public static Config getInstance() {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,5 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
package io.github.adrianvic.nemesiseye;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
public class DataShifter {
|
public class DataShifter {
|
||||||
|
|
@ -12,52 +8,4 @@ public class DataShifter {
|
||||||
Pattern pattern = Pattern.compile(cleanPattern, Pattern.CASE_INSENSITIVE);
|
Pattern pattern = Pattern.compile(cleanPattern, Pattern.CASE_INSENSITIVE);
|
||||||
return pattern.matcher(against).matches();
|
return pattern.matcher(against).matches();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean safeMatches(List<String> expressions, String against) {
|
|
||||||
for (String s : expressions) {
|
|
||||||
if (DataShifter.safeMatches(s, against)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<String> parseValueToStringList(List<Object> values) {
|
|
||||||
List<String> result = new ArrayList<>();
|
|
||||||
for (Object o : values) {
|
|
||||||
if (o instanceof String) result.add((String) o);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<String,String> parseValueToStringMap(List<Object> raw) {
|
|
||||||
Map<String,String> out = new HashMap<>();
|
|
||||||
|
|
||||||
for (Object o : raw) {
|
|
||||||
if (o instanceof Map<?,?> map) {
|
|
||||||
for (Map.Entry<?,?> e : map.entrySet()) {
|
|
||||||
out.put(String.valueOf(e.getKey()), String.valueOf(e.getValue()));
|
|
||||||
}
|
|
||||||
} else if (o instanceof String s) {
|
|
||||||
|
|
||||||
String[] parts = s.split(":", 2);
|
|
||||||
if (parts.length == 2) {
|
|
||||||
out.put(parts[0].trim(), parts[1].trim());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T extends Enum<T>> T enumOrDefault(Class<T> type, String string, T def) {
|
|
||||||
try {
|
|
||||||
return Enum.valueOf(type, string);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
return def;
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package io.github.adrianvic.nemesiseye;
|
||||||
|
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.EventHandler;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.event.block.BlockBreakEvent;
|
||||||
|
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
||||||
|
import org.bukkit.event.player.PlayerInteractEvent;
|
||||||
|
|
||||||
|
public class EventListener implements Listener {
|
||||||
|
@EventHandler
|
||||||
|
public void onBlockBreak(BlockBreakEvent event) {
|
||||||
|
event.setCancelled(!Validator.canBreak(event.getPlayer()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onInteractionEvent(PlayerInteractEvent event) {
|
||||||
|
if (event.getItem() != null) {
|
||||||
|
event.setCancelled(!Validator.canInteract(event.getPlayer()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@EventHandler
|
||||||
|
public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
|
||||||
|
if (event.getDamager() instanceof Player) {
|
||||||
|
event.setCancelled(!Validator.canHit((HumanEntity) event.getDamager()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Events {
|
|
||||||
|
|
||||||
private static Glimmer g() {
|
|
||||||
return Nemesis.getInstance().getGlimmer();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onBlockBreak(BlockBreakEvent event) {
|
|
||||||
event.setCancelled(
|
|
||||||
!Validator.can(
|
|
||||||
event.getPlayer(),
|
|
||||||
List.of(Action.BREAK, Action.USE_ENCHANTMENT),
|
|
||||||
event
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onInteractionEvent(PlayerInteractEvent event) {
|
|
||||||
ItemStack item = event.getItem();
|
|
||||||
|
|
||||||
if (g().isAir(item)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Right-click armor equipping
|
|
||||||
if (g().isArmor(item)
|
|
||||||
&& !Validator.can(event.getPlayer(), Action.EQUIP, event)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Normal item interaction
|
|
||||||
event.setCancelled(
|
|
||||||
!Validator.can(event.getPlayer(), Action.INTERACT, event)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onBlockPlaceEvent(BlockPlaceEvent event) {
|
|
||||||
event.setCancelled(
|
|
||||||
!Validator.can(event.getPlayer(), Action.PLACE, event)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
|
|
||||||
if (event.getDamager() instanceof Player player) {
|
|
||||||
event.setCancelled(
|
|
||||||
!Validator.can(
|
|
||||||
player,
|
|
||||||
List.of(Action.HIT, Action.USE_ENCHANTMENT),
|
|
||||||
event
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onPlayerMoveEvent(PlayerMoveEvent event) {
|
|
||||||
if (g().isGliding(event.getPlayer())
|
|
||||||
&& !Validator.can(
|
|
||||||
event.getPlayer(),
|
|
||||||
List.of(Action.GLYDE),
|
|
||||||
event
|
|
||||||
)) {
|
|
||||||
g().setGliding(event.getPlayer(), false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onInventoryClickEvent(InventoryClickEvent event) {
|
|
||||||
if (!g().isArmorEquipAttempt(event)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HumanEntity entity = event.getWhoClicked();
|
|
||||||
|
|
||||||
if (!Validator.can(entity, Action.EQUIP, event)) {
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void onCreatureSpawnEvent(CreatureSpawnEvent event) {
|
|
||||||
event.setCancelled(!Validator.can(event.getEntity(), Action.SPAWN, event));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +1,23 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
package io.github.adrianvic.nemesiseye;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
import io.github.adrianvic.nemesiseye.commands.Eye;
|
||||||
import io.github.adrianvic.nemesiseye.reflection.VersionMatcher;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
|
||||||
import org.bukkit.plugin.java.JavaPlugin;
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
public final class Nemesis extends JavaPlugin {
|
public final class Nemesis extends JavaPlugin {
|
||||||
private Glimmer glim;
|
|
||||||
private static final String VERSION_PROP = "impl.version";
|
|
||||||
private static Nemesis instance;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
instance = this;
|
getServer().getPluginManager().registerEvents(new EventListener(), this);
|
||||||
glim = new VersionMatcher().loadGlim();
|
|
||||||
glim.onLoad();
|
|
||||||
Config.getInstance().load();
|
Config.getInstance().load();
|
||||||
|
getCommand("eye").setExecutor(new Eye());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisable() {
|
public void onDisable() {
|
||||||
|
// Plugin shutdown logic
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Nemesis getInstance() { return instance; }
|
public static Nemesis getInstance() {
|
||||||
public Glimmer getGlimmer() { return glim; }
|
return getPlugin(Nemesis.class);
|
||||||
public PluginManager getPluginManager() { return this.getServer().getPluginManager(); }
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,55 +1,63 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
package io.github.adrianvic.nemesiseye;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
import io.github.adrianvic.nemesiseye.policy.Action;
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
import io.github.adrianvic.nemesiseye.policy.LocationPolicy;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
import org.bukkit.util.BoundingBox;
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Validator {
|
public class Validator {
|
||||||
public static boolean can(HumanEntity entity, List<Action> actions, Event event) {
|
public static boolean canInteract(HumanEntity entity) {
|
||||||
for (Action action : actions) {
|
return checkAgainstEntity(entity, Action.INTERACT);
|
||||||
if (!can(entity, action, event)) {
|
}
|
||||||
return false;
|
public static boolean canBreak(HumanEntity entity) {
|
||||||
}
|
return checkAgainstEntity(entity, Action.BREAK);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean canHit(HumanEntity entity) {
|
||||||
|
return checkAgainstEntity(entity, Action.HIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkAgainstEntity(HumanEntity entity, Action action) {
|
||||||
|
return checkAgainstNodes(entity, getNodesForPolicies(getPoliciesForEntity(entity)), action);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean checkAgainstNodes(HumanEntity entity, List<PolicyNode> nodes, Action action) {
|
||||||
|
for (PolicyNode n : nodes) {
|
||||||
|
if (!checkAgainstNode(entity, n, action)) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean can(LivingEntity entity, Action action, Event event) {
|
public static boolean checkAgainstNode(HumanEntity entity, PolicyNode node, Action action) {
|
||||||
boolean restricted = false;
|
boolean allowed = node.getHandler().allows(entity, node, action);
|
||||||
boolean allowed = false;
|
return node.isWhitelist() != allowed;
|
||||||
|
|
||||||
for (Policy policy : getPoliciesForEntity(entity)) {
|
|
||||||
boolean matches = policy.matches(entity, action, event);
|
|
||||||
|
|
||||||
switch (policy.effect()) {
|
|
||||||
case ALLOW:
|
|
||||||
if (matches) return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case DENY:
|
|
||||||
if (matches) return false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<PolicyNode> getNodesForPolicies(List<LocationPolicy> policies) {
|
||||||
public static List<Policy> getPoliciesForEntity(LivingEntity entity) {
|
List<PolicyNode> nodes = new ArrayList<>();
|
||||||
List<Policy> ps = Config.getInstance().getPolicies();
|
for (LocationPolicy p : policies) {
|
||||||
List<Policy> result = new ArrayList<>();
|
nodes.addAll(p.nodes());
|
||||||
|
|
||||||
for (Policy policy : ps) {
|
|
||||||
if (policy.applies(entity)) result.add(policy);
|
|
||||||
}
|
}
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
public static List<LocationPolicy> getPoliciesForEntity(HumanEntity entity) {
|
||||||
|
List<LocationPolicy> lps = Config.getInstance().getLocationPolicies();
|
||||||
|
List<LocationPolicy> applyingLPS = new ArrayList<>();
|
||||||
|
for (LocationPolicy lp : lps) {
|
||||||
|
for (ArrayList<BoundingBox> boxes : lp.locations()) {
|
||||||
|
for (BoundingBox box : boxes) {
|
||||||
|
if (box.contains(entity.getLocation().toVector())) {
|
||||||
|
applyingLPS.add(lp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return applyingLPS;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.commands.sub.*;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Commands {
|
|
||||||
private static final Map<String, Subcommand> commands = new HashMap<>();
|
|
||||||
private static final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
static {
|
|
||||||
commands.put("help", new Help());
|
|
||||||
commands.put("listpolicies", new ListPolicies());
|
|
||||||
commands.put("currentpolicies", new CurrentPolicies());
|
|
||||||
commands.put("policyinfo", new PolicyInfo());
|
|
||||||
commands.put("reload", new Reload());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<String, Subcommand> getAll() {
|
|
||||||
return commands;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Subcommand get(String type) {
|
|
||||||
return commands.get(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void sendNoPermissionError(CommandSender sender) {
|
|
||||||
glim.sendMessage(sender, "You do not have the necessary permission to use this command.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.commands;
|
||||||
|
|
||||||
|
import io.github.adrianvic.nemesiseye.Nemesis;
|
||||||
|
import io.github.adrianvic.nemesiseye.commands.sub.*;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.Command;
|
||||||
|
import org.bukkit.command.CommandExecutor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class Eye implements CommandExecutor, TabCompleter {
|
||||||
|
private final Map<String, Subcommand> subs = new HashMap<>();
|
||||||
|
|
||||||
|
public Eye() {
|
||||||
|
register(new Reload());
|
||||||
|
register(new ListPolicies());
|
||||||
|
register(new PolicyInfo());
|
||||||
|
register(new CurrentPolicies());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void register(Subcommand sub) {
|
||||||
|
subs.put(sub.name(), sub);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
|
||||||
|
if (strings.length == 0) {
|
||||||
|
commandSender.sendMessage("""
|
||||||
|
%sEye of Nemesis%s version %s
|
||||||
|
Usage: '/eye <command>'
|
||||||
|
Use '/eye help' for a list of available commands
|
||||||
|
""".formatted(ChatColor.RED, ChatColor.RESET, Nemesis.getInstance().getDescription().getVersion()));
|
||||||
|
} else {
|
||||||
|
Subcommand sub = subs.get(strings[0].toLowerCase());
|
||||||
|
if (sub == null) {
|
||||||
|
commandSender.sendMessage("Unknown command, try '/eye help' to list available commands.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return sub.execute(commandSender, Arrays.copyOfRange(strings, 1, strings.length));
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
|
||||||
|
if (strings.length == 1) {
|
||||||
|
return new ArrayList<>(subs.keySet());
|
||||||
|
}
|
||||||
|
Subcommand sub = subs.get(strings[0].toLowerCase());
|
||||||
|
if (sub != null) {
|
||||||
|
return sub.onTabComplete(commandSender, Arrays.copyOfRange(strings, 1, strings.length));
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.commands.sub.*;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.ChatColor;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class EyeCore {
|
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
public EyeCore() {}
|
|
||||||
|
|
||||||
public boolean onCommand(CommandSender commandSender, Command command, String s, String [] strings) {
|
|
||||||
if (strings.length == 0) {
|
|
||||||
glim.sendMessage(commandSender, """
|
|
||||||
%sEye of Nemesis%s version %s%s%s
|
|
||||||
Usage: '/eye <command>'
|
|
||||||
Use '/eye help' for a list of available commands
|
|
||||||
""".formatted(ChatColor.AQUA, ChatColor.WHITE, ChatColor.GRAY, Nemesis.getInstance().getDescription().getVersion(), ChatColor.WHITE));
|
|
||||||
} else {
|
|
||||||
Subcommand sub = Commands.get(strings[0].toLowerCase());
|
|
||||||
if (sub == null) {
|
|
||||||
commandSender.sendMessage("Unknown command, try '/eye help' to list available commands.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (glim.hasPermission(commandSender, sub.permission())) {
|
|
||||||
return sub.execute(commandSender, Arrays.copyOfRange(strings, 1, strings.length));
|
|
||||||
} else {
|
|
||||||
// Nemesis.getInstance().getLogger().info("does not have %s".formatted(sub.permission()));
|
|
||||||
Commands.sendNoPermissionError(commandSender);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<String> onTabComplete(CommandSender commandSender, Command command, String s, String [] strings) {
|
|
||||||
if (strings.length == 1) {
|
|
||||||
Map<String, Subcommand> cmds = new HashMap<>();
|
|
||||||
for (Map.Entry<String, Subcommand> e : Commands.getAll().entrySet()) {
|
|
||||||
if (glim.hasPermission(commandSender, e.getValue().permission())) {
|
|
||||||
cmds.put(e.getKey(), e.getValue());
|
|
||||||
cmds.put(e.getKey(), e.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new ArrayList<>(cmds.keySet());
|
|
||||||
}
|
|
||||||
Subcommand sub = Commands.get(strings[0].toLowerCase());
|
|
||||||
if (sub != null && glim.hasPermission(commandSender, sub.permission())) {
|
|
||||||
return sub.onTabComplete(commandSender, Arrays.copyOfRange(strings, 1, strings.length));
|
|
||||||
}
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
package io.github.adrianvic.nemesiseye.commands.sub;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Validator;
|
import io.github.adrianvic.nemesiseye.Validator;
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
import io.github.adrianvic.nemesiseye.policy.LocationPolicy;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
|
||||||
|
|
@ -9,11 +9,16 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CurrentPolicies implements Subcommand {
|
public class CurrentPolicies implements Subcommand {
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "currentpolicies";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender commandSender, String[] args) {
|
public boolean execute(CommandSender commandSender, String[] args) {
|
||||||
List<Policy> policies = Validator.getPoliciesForEntity((HumanEntity) commandSender);
|
List<LocationPolicy> policies = Validator.getPoliciesForEntity((HumanEntity) commandSender);
|
||||||
List<String> pstrings = new ArrayList<>();
|
List<String> pstrings = new ArrayList<>();
|
||||||
for (Policy p : policies) {
|
for (LocationPolicy p : policies) {
|
||||||
pstrings.add(" %s (%s nodes)".formatted(p.name(), p.nodes().size()));
|
pstrings.add(" %s (%s nodes)".formatted(p.name(), p.nodes().size()));
|
||||||
}
|
}
|
||||||
if (pstrings.isEmpty()) {
|
if (pstrings.isEmpty()) {
|
||||||
|
|
@ -29,19 +34,4 @@ public class CurrentPolicies implements Subcommand {
|
||||||
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String description() {
|
|
||||||
return "Lists policies appliying to you.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String usage() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String permission() {
|
|
||||||
return "nemsiseye.policies.list.self";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,54 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.commands.Commands;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class Help implements Subcommand {
|
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean execute(CommandSender commandSender, String[] strings) {
|
|
||||||
List<String> rstr = new ArrayList<>();
|
|
||||||
Map<String, Subcommand> allSubcommands = Commands.getAll();
|
|
||||||
if (allSubcommands.isEmpty()) {
|
|
||||||
rstr.add("No commands found.");
|
|
||||||
}
|
|
||||||
for (Map.Entry<String, Subcommand> e : allSubcommands.entrySet()) {
|
|
||||||
if (e.getValue().hasPermission(commandSender)) {
|
|
||||||
rstr.add("""
|
|
||||||
%s - %s
|
|
||||||
Usage: /eye %s %s
|
|
||||||
""".formatted(e.getKey(), e.getValue().description(), e.getKey(), e.getValue().usage()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
glim.sendMessage(commandSender, String.join("\n", rstr));
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> onTabComplete(CommandSender sender, String[] strings) {
|
|
||||||
return List.of();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String description() {
|
|
||||||
return "Lists all commands.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String usage() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String permission() {
|
|
||||||
return "nemsiseye.help";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,17 +1,23 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
package io.github.adrianvic.nemesiseye.commands.sub;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Config;
|
import io.github.adrianvic.nemesiseye.Config;
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
import io.github.adrianvic.nemesiseye.policy.LocationPolicy;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class ListPolicies implements Subcommand {
|
public class ListPolicies implements Subcommand {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "listpolicies";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender commandSender, String[] args) {
|
public boolean execute(CommandSender commandSender, String[] args) {
|
||||||
List<String> rstr = new ArrayList<>();
|
List<String> rstr = new ArrayList<>();
|
||||||
for (Policy p : Config.getInstance().getPolicies()) {
|
for (LocationPolicy p : Config.getInstance().getLocationPolicies()) {
|
||||||
rstr.add(p.name());
|
rstr.add(p.name());
|
||||||
}
|
}
|
||||||
commandSender.sendMessage(String.join(", ", rstr) + ".");
|
commandSender.sendMessage(String.join(", ", rstr) + ".");
|
||||||
|
|
@ -22,19 +28,4 @@ public class ListPolicies implements Subcommand {
|
||||||
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
||||||
return List.of();
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String description() {
|
|
||||||
return "Lists all loaded policies.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String usage() {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String permission() {
|
|
||||||
return "nemsiseye.policy.list.all";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
package io.github.adrianvic.nemesiseye.commands.sub;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Config;
|
import io.github.adrianvic.nemesiseye.Config;
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
import io.github.adrianvic.nemesiseye.policy.LocationPolicy;
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
|
|
@ -11,18 +9,25 @@ import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class PolicyInfo implements Subcommand {
|
public class PolicyInfo implements Subcommand {
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
@Override
|
||||||
|
public String name() {
|
||||||
|
return "policyinfo";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender commandSender, String[] strings) {
|
public boolean execute(CommandSender commandSender, String[] strings) {
|
||||||
List<Policy> policies = Config.getInstance().getPolicies();
|
List<LocationPolicy> policies = Config.getInstance().getLocationPolicies();
|
||||||
for (Policy policy : policies) {
|
for (LocationPolicy lp : policies) {
|
||||||
if (policy.name().equals(strings[0])) {
|
if (lp.name().equals(strings[0])) {
|
||||||
glim.sendMessage(commandSender, String.format("""
|
String locations = lp.locations().toString();
|
||||||
Showing info for policy %s%s%s:
|
|
||||||
|
commandSender.sendMessage(String.format("""
|
||||||
|
Showing info for policy "%s%s%s":
|
||||||
Type: %s
|
Type: %s
|
||||||
|
Locations: %s
|
||||||
Nodes: %s
|
Nodes: %s
|
||||||
""", ChatColor.GREEN, policy.name(), ChatColor.WHITE, policy.getClass().getTypeName(), policy.nodes().size()));
|
%s
|
||||||
|
""", ChatColor.UNDERLINE, lp.name(), ChatColor.RESET, "location", locations, lp.nodes().size(), lp.allowlist() ? "Is allowlist" : "Is blacklist"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -31,24 +36,9 @@ public class PolicyInfo implements Subcommand {
|
||||||
@Override
|
@Override
|
||||||
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
public List<String> onTabComplete(CommandSender sender, String[] args) {
|
||||||
List<String> rstr = new ArrayList<>();
|
List<String> rstr = new ArrayList<>();
|
||||||
for (Policy p : Config.getInstance().getPolicies()) {
|
for (LocationPolicy p : Config.getInstance().getLocationPolicies()) {
|
||||||
rstr.add(p.name());
|
rstr.add(p.name());
|
||||||
}
|
}
|
||||||
return rstr;
|
return rstr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String description() {
|
|
||||||
return "Shows info for a specified policy.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String usage() {
|
|
||||||
return "<policy>";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String permission() {
|
|
||||||
return "nemsiseye.policy.info";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
package io.github.adrianvic.nemesiseye.commands.sub;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Config;
|
import io.github.adrianvic.nemesiseye.Config;
|
||||||
import io.github.adrianvic.nemesiseye.commands.Commands;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class Reload implements Subcommand {
|
public class Reload implements Subcommand {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean execute(CommandSender commandSender, String [] strings) {
|
public boolean execute(CommandSender commandSender, String [] strings) {
|
||||||
Config.getInstance().load();
|
Config.getInstance().load();
|
||||||
commandSender.sendMessage("Reloading...");
|
commandSender.sendMessage("Reloading...");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -20,17 +20,7 @@ public class Reload implements Subcommand {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String permission() {
|
public String name() {
|
||||||
return "nemsiseye.reload";
|
return "reload";
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String description() {
|
|
||||||
return "Reloads the plugin configuration file.";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String usage() {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,12 @@
|
||||||
package io.github.adrianvic.nemesiseye.commands.sub;
|
package io.github.adrianvic.nemesiseye.commands.sub;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.bukkit.permissions.Permission;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public interface Subcommand {
|
public interface Subcommand {
|
||||||
String description();
|
String name();
|
||||||
String usage();
|
|
||||||
@SuppressWarnings("SameReturnValue")
|
@SuppressWarnings("SameReturnValue")
|
||||||
boolean execute(CommandSender commandSender, String[] strings);
|
boolean execute(CommandSender commandSender, String[] strings);
|
||||||
List<String> onTabComplete(CommandSender sender, String[] strings);
|
List<String> onTabComplete(CommandSender sender, String[] strings);
|
||||||
String permission();
|
|
||||||
default boolean hasPermission(CommandSender sender) {
|
|
||||||
return Nemesis.getInstance().getGlimmer().hasPermission(sender, permission());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,10 +4,6 @@ public enum Action {
|
||||||
INTERACT,
|
INTERACT,
|
||||||
BREAK,
|
BREAK,
|
||||||
HIT,
|
HIT,
|
||||||
// TODO CRAFT,
|
CRAFT,
|
||||||
EQUIP,
|
EQUIP
|
||||||
PLACE,
|
|
||||||
USE_ENCHANTMENT,
|
|
||||||
GLYDE,
|
|
||||||
SPAWN
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
|
||||||
|
|
||||||
public enum Effect {
|
|
||||||
DENY,
|
|
||||||
ALLOW,
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.util.BoundingBox;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public record LocationPolicy(String name, List<ArrayList<BoundingBox>> locations, List<PolicyNode> nodes, boolean allowlist) {
|
||||||
|
public static List<LocationPolicy> parseLocationPolicy(List<Map<?,?>> raw) {
|
||||||
|
List<LocationPolicy> out = new ArrayList<>(raw.size());
|
||||||
|
for (Map<?,?> m : raw) {
|
||||||
|
String name = (String) m.get("name");
|
||||||
|
boolean allowlist = Boolean.TRUE.equals(m.get("allowList"));
|
||||||
|
|
||||||
|
// Nodes
|
||||||
|
Object rawNodes = m.get("nodes");
|
||||||
|
List<Map<String, Object>> nodeList = new ArrayList<>();
|
||||||
|
if (rawNodes instanceof List<?> list) {
|
||||||
|
for (Object o : list) {
|
||||||
|
if (o instanceof Map<?, ?> map)
|
||||||
|
nodeList.add((Map<String, Object>) map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<PolicyNode> nodes = PolicyNode.parseNodes(nodeList, allowlist);
|
||||||
|
|
||||||
|
// Parsing locations
|
||||||
|
List<ArrayList<BoundingBox>> locations = new ArrayList<>();
|
||||||
|
Object rawGroups = m.get("locations");
|
||||||
|
List<?> groups = rawGroups instanceof List ? (List<?>) rawGroups : List.of();
|
||||||
|
|
||||||
|
// Getting groups
|
||||||
|
for (Object gObj : groups) {
|
||||||
|
List<?> group = (List<?>) gObj;
|
||||||
|
ArrayList<BoundingBox> boxes = new ArrayList<>(group.size());
|
||||||
|
|
||||||
|
// Now iterate over regions inside the group
|
||||||
|
for (Object rObj : group) {
|
||||||
|
Map<?,?> region = (Map<?, ?>) rObj;
|
||||||
|
Map<?,?> c1 = (Map<?, ?>) region.get("corner1");
|
||||||
|
Map<?,?> c2 = (Map<?, ?>) region.get("corner2");
|
||||||
|
|
||||||
|
double x1 = ((Number) c1.get("x")).doubleValue();
|
||||||
|
double y1 = ((Number) c1.get("y")).doubleValue();
|
||||||
|
double z1 = ((Number) c1.get("z")).doubleValue();
|
||||||
|
|
||||||
|
double x2 = ((Number) c2.get("x")).doubleValue();
|
||||||
|
double y2 = ((Number) c2.get("y")).doubleValue();
|
||||||
|
double z2 = ((Number) c2.get("z")).doubleValue();
|
||||||
|
|
||||||
|
Location loc1 = new Location(Bukkit.getWorlds().getFirst(), x1, y1, z1);
|
||||||
|
Location loc2 = new Location(Bukkit.getWorlds().getFirst(), x2, y2, z2);
|
||||||
|
|
||||||
|
boxes.add(BoundingBox.of(loc1, loc2));
|
||||||
|
}
|
||||||
|
locations.add(boxes);
|
||||||
|
}
|
||||||
|
out.add(new LocationPolicy(name, locations, nodes, allowlist));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,7 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
import org.bukkit.entity.HumanEntity;
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
public interface NodeHandler {
|
public interface NodeHandler {
|
||||||
boolean check(LivingEntity entity, PolicyNode node, Action action, Event event);
|
boolean allows(HumanEntity entity, PolicyNode node, Action action);
|
||||||
}
|
}
|
||||||
|
|
@ -1,25 +1,22 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.handlers.*;
|
import io.github.adrianvic.nemesiseye.policy.handlers.attackWith;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.handlers.useEnchantment;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.handlers.useItem;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class NodeHandlers {
|
public class NodeHandlers {
|
||||||
private static final Map<Action, NodeHandler> handlers = new HashMap<>();
|
private static final Map<String, NodeHandler> handlers = new HashMap<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
handlers.put(Action.HIT, new UseItem());
|
handlers.put("attackWithItemInHand", new attackWith());
|
||||||
handlers.put(Action.PLACE, new BePlaced());
|
handlers.put("useItem", new useItem());
|
||||||
handlers.put(Action.INTERACT, new UseItem());
|
handlers.put("useEnchantment", new useEnchantment());
|
||||||
handlers.put(Action.USE_ENCHANTMENT, new UseEnchantment());
|
|
||||||
handlers.put(Action.GLYDE, new Glyde());
|
|
||||||
handlers.put(Action.EQUIP, new Equip());
|
|
||||||
handlers.put(Action.SPAWN, new Spawn());
|
|
||||||
handlers.put(Action.BREAK, new UseItem()); // TODO: implement place handler
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NodeHandler get(Action type) {
|
public static NodeHandler get(String type) {
|
||||||
return handlers.get(type);
|
return handlers.get(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
public class NodeValueParser {
|
||||||
|
public static List<String> parseValueToStringList(List<Object> values) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
for (Object o : values) {
|
||||||
|
if (o instanceof String) result.add((String) o);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> parseValueToStringMap(List<Object> values) {
|
||||||
|
Map<String, String> result = new HashMap<>();
|
||||||
|
|
||||||
|
for (Object o : values) {
|
||||||
|
if (o instanceof Map<?, ?> raw) {
|
||||||
|
for (Map.Entry<?, ?> e : raw.entrySet()) {
|
||||||
|
if (e.getKey() instanceof String k && e.getValue() instanceof String v) {
|
||||||
|
result.put(k, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
|
import org.bukkit.permissions.Permission;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public record PermissionPolicy(String name, ArrayList<Permission> permissions, PolicyNode nodes, boolean allowlist) {}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public record PlayerNamePolicy(String name, ArrayList<String> playerName, PolicyNode nodes, boolean allowlist) {}
|
||||||
|
|
@ -1,35 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
|
||||||
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface Policy {
|
|
||||||
String name();
|
|
||||||
List<PolicyNode> nodes();
|
|
||||||
boolean policyAllowList();
|
|
||||||
boolean applies(LivingEntity entity);
|
|
||||||
Effect effect();
|
|
||||||
int weight();
|
|
||||||
List<String> worlds();
|
|
||||||
|
|
||||||
default void addNode(PolicyNode node) {
|
|
||||||
nodes().add(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean matches(LivingEntity entity, Action action, Event event) {
|
|
||||||
if (!worlds().contains(entity.getWorld().getName())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (PolicyNode node : nodes()) {
|
|
||||||
if (node.matches(entity, action, event)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,73 +1,34 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
package io.github.adrianvic.nemesiseye.policy;
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public record PolicyNode(List<Action> actions, List<Object> values) {
|
public record PolicyNode(String type, List<Object> values, boolean isWhitelist) {
|
||||||
public static List<PolicyNode> parseNodes(List<Map<Object,Object>> raw, Effect effect) {
|
public static List<PolicyNode> parseNodes(List<Map<String,Object>> raw, boolean isWhitelist) {
|
||||||
List<PolicyNode> nodes = new ArrayList<>();
|
List<PolicyNode> nodes = new ArrayList<>();
|
||||||
|
|
||||||
for (Map<Object, Object> m : raw) {
|
for (Map<String, Object> m : raw) {
|
||||||
for (Map.Entry<Object, Object> rawNode : m.entrySet()) {
|
for (Map.Entry<String, Object> entry : m.entrySet()) {
|
||||||
List<Action> nodeActions = new ArrayList<>();
|
String type = entry.getKey();
|
||||||
List<Object> nodeValues = new ArrayList<>();
|
List<Object> values = new ArrayList<>();
|
||||||
|
Object val = entry.getValue();
|
||||||
|
|
||||||
if (rawNode.getKey() instanceof List<?> rawTypes && rawNode.getValue() instanceof Map<?,?> rawNodeValues) {
|
if (val instanceof String s) {
|
||||||
for (Object rawType : rawTypes) {
|
values.add(s);
|
||||||
if (rawType instanceof String rts && !rts.isEmpty() && !(rts == null) && DataShifter.enumOrDefault(Action.class, rts, null) != null) {
|
} else if (val instanceof List<?> l) {
|
||||||
nodeActions.add(DataShifter.enumOrDefault(Action.class, rts, null));
|
values.addAll(l);
|
||||||
}
|
} else if (val instanceof Map<?,?> map) {
|
||||||
}
|
values.add(map);
|
||||||
Map<String, Object> semiParsedNodeValue = new HashMap<>();
|
|
||||||
for (Map.Entry<?,?> rawNodeValueEntries : rawNodeValues.entrySet()) {
|
|
||||||
if (rawNodeValueEntries.getKey() instanceof String stringKey) {
|
|
||||||
semiParsedNodeValue.put(stringKey, rawNodeValueEntries.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semiParsedNodeValue.get("values") instanceof List<?> l) {
|
|
||||||
for (Object v : l) {
|
|
||||||
nodeValues.add(v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!nodeActions.isEmpty() && !nodeValues.isEmpty()) {
|
nodes.add(new PolicyNode(type, values, isWhitelist));
|
||||||
PolicyNode newNode = new PolicyNode(nodeActions, nodeValues);
|
|
||||||
nodes.add(newNode);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<NodeHandler> getHandler() {
|
public NodeHandler getHandler() {
|
||||||
List<NodeHandler> handlers = new ArrayList<>();
|
return NodeHandlers.get(type);
|
||||||
for (Action a : actions) {
|
|
||||||
handlers.add(NodeHandlers.get(a));
|
|
||||||
}
|
|
||||||
return handlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean matches(LivingEntity entity, Action action, Event event) {
|
|
||||||
if (!actions.contains(action)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
NodeHandler handler = NodeHandlers.get(action);
|
|
||||||
|
|
||||||
if (handler == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean result = handler.check(entity, this, action, event);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,47 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.Core;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface PolicyParser {
|
|
||||||
default Policy parse(Map<?, ?> raw) {
|
|
||||||
boolean policyAllowList = Boolean.TRUE.equals(raw.get("policyAllowList"));
|
|
||||||
boolean nodesAllowList = Boolean.TRUE.equals(raw.get("nodesAllowList"));
|
|
||||||
Effect effect = DataShifter.enumOrDefault(Effect.class, (String) raw.get("effect"), Effect.DENY);
|
|
||||||
String name = (String) raw.get("name");
|
|
||||||
Integer weightObj = (Integer) raw.get("weight");
|
|
||||||
int weight = weightObj != null ? weightObj : 0;
|
|
||||||
|
|
||||||
// Worlds
|
|
||||||
List<String> worlds = new ArrayList<>();
|
|
||||||
if (raw.get("worlds") instanceof List<?> list) {
|
|
||||||
for (Object object : list) {
|
|
||||||
if (object instanceof String result) {
|
|
||||||
worlds.add(result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
worlds.add("world");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nodes
|
|
||||||
Object rawNodes = raw.get("nodes");
|
|
||||||
List<Map<Object, Object>> nodeList = new ArrayList<>();
|
|
||||||
|
|
||||||
if (rawNodes instanceof List<?> list) {
|
|
||||||
for (Object o : list) {
|
|
||||||
if (o instanceof Map<?, ?> map)
|
|
||||||
nodeList.add((Map<Object, Object>) map);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<PolicyNode> nodes = PolicyNode.parseNodes(nodeList, effect);
|
|
||||||
return parse(new Core(name, worlds, nodes, nodesAllowList, policyAllowList, effect, weight), raw);
|
|
||||||
}
|
|
||||||
|
|
||||||
Policy parse(Core corePolicy, Map<?, ?> raw);
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.parser.GlobalPolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.parser.LocationPolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.parser.PermissionPolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.parser.PlayerNamePolicyParser;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class PolicyParsers {
|
|
||||||
private static final Map<String, PolicyParser> handlers = new HashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
handlers.put("location", new LocationPolicyParser());
|
|
||||||
handlers.put("global", new GlobalPolicyParser());
|
|
||||||
handlers.put("playerName", new PlayerNamePolicyParser());
|
|
||||||
handlers.put("permission", new PermissionPolicyParser());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PolicyParser get(String type) {
|
|
||||||
return handlers.get(type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class BePlaced implements NodeHandler {
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
if (event instanceof BlockPlaceEvent bpe) {
|
|
||||||
String type = bpe.getBlock().getType().toString();
|
|
||||||
List<String> parsedValue = DataShifter.parseValueToStringList(node.values());
|
|
||||||
|
|
||||||
return DataShifter.safeMatches(parsedValue, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Equip implements NodeHandler {
|
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
ItemStack item = glim.getEquippedItem(event);
|
|
||||||
|
|
||||||
if (!glim.isArmor(item)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String type = item.getType().name();
|
|
||||||
List<String> parsedValue = DataShifter.parseValueToStringList(node.values());
|
|
||||||
|
|
||||||
return DataShifter.safeMatches(parsedValue, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
public class Glyde implements NodeHandler {
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class Spawn implements NodeHandler {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
String type = entity.getType().name();
|
|
||||||
List<String> parsedValue = DataShifter.parseValueToStringList(node.values());
|
|
||||||
|
|
||||||
return DataShifter.safeMatches(parsedValue, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
|
|
||||||
public class UseEnchantment implements NodeHandler {
|
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
if (entity instanceof HumanEntity e) {
|
|
||||||
ItemStack item = glim.getItemInMainHandHumanEntity(e);
|
|
||||||
|
|
||||||
if (glim.isAir(item)) return false;
|
|
||||||
if (!glim.hasItemMeta(item)) return false;
|
|
||||||
if (!glim.hasAnyEnchantment(item)) return false;
|
|
||||||
|
|
||||||
boolean matches = glim.hasEnchantment(item,
|
|
||||||
DataShifter.parseValueToStringMap(node.values()));
|
|
||||||
|
|
||||||
return matches;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,33 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.handlers;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class UseItem implements NodeHandler {
|
|
||||||
|
|
||||||
private final Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean check(LivingEntity entity, PolicyNode node, Action action, Event event) {
|
|
||||||
if (entity instanceof HumanEntity e) {
|
|
||||||
org.bukkit.inventory.ItemStack item = glim.getItemInMainHandHumanEntity(e);
|
|
||||||
if (glim.isAir(item)) return false;
|
|
||||||
|
|
||||||
String type = item.getType().toString();
|
|
||||||
List<String> parsedValue = DataShifter.parseValueToStringList(node.values());
|
|
||||||
|
|
||||||
return DataShifter.safeMatches(parsedValue, type);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy.handlers;
|
||||||
|
|
||||||
|
import io.github.adrianvic.nemesiseye.DataShifter;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.Action;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeValueParser;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
|
||||||
|
public class attackWith implements NodeHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allows(HumanEntity entity, PolicyNode node, Action action) {
|
||||||
|
if (action == Action.HIT) {
|
||||||
|
for (String s : NodeValueParser.parseValueToStringList(node.values())) {
|
||||||
|
if (DataShifter.safeMatches(s, entity.getInventory().getItemInMainHand().getType().toString())) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy.handlers;
|
||||||
|
|
||||||
|
import io.github.adrianvic.nemesiseye.DataShifter;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.Action;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeValueParser;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
||||||
|
import org.bukkit.enchantments.Enchantment;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class useEnchantment implements NodeHandler {
|
||||||
|
@Override
|
||||||
|
public boolean allows(HumanEntity entity, PolicyNode node, Action action) {
|
||||||
|
ItemStack item = entity.getInventory().getItemInMainHand();
|
||||||
|
if (item.getItemMeta() == null) {
|
||||||
|
return !node.isWhitelist();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Enchantment, Integer> enchants = item.getItemMeta().getEnchants();
|
||||||
|
|
||||||
|
if (enchants.isEmpty()) {
|
||||||
|
return !node.isWhitelist();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> valuesmap = NodeValueParser.parseValueToStringMap(node.values());
|
||||||
|
|
||||||
|
for (Map.Entry<Enchantment, Integer> e : enchants.entrySet()) {
|
||||||
|
String enchantment = e.getKey().getKey().getKey();
|
||||||
|
String level = e.getValue().toString();
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> entry : valuesmap.entrySet()) {
|
||||||
|
if (DataShifter.safeMatches(entry.getKey().trim(), enchantment) && DataShifter.safeMatches(entry.getValue().trim(), level)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package io.github.adrianvic.nemesiseye.policy.handlers;
|
||||||
|
|
||||||
|
import io.github.adrianvic.nemesiseye.DataShifter;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.Action;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeHandler;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.NodeValueParser;
|
||||||
|
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
||||||
|
import org.bukkit.entity.HumanEntity;
|
||||||
|
|
||||||
|
public class useItem implements NodeHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean allows(HumanEntity entity, PolicyNode node, Action action) {
|
||||||
|
String type = entity.getInventory().getItemInMainHand().getType().toString();
|
||||||
|
|
||||||
|
for (String s : NodeValueParser.parseValueToStringList(node.values())) {
|
||||||
|
if (DataShifter.safeMatches(s, type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.parser;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.Core;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.GlobalPolicy;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class GlobalPolicyParser implements PolicyParser {
|
|
||||||
@Override
|
|
||||||
public Policy parse(Core corePolicy, Map<?, ?> raw) {
|
|
||||||
return new GlobalPolicy(corePolicy.name(), corePolicy.worlds(), corePolicy.nodes(), corePolicy.policyAllowList(), corePolicy.effect(), corePolicy.weight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.parser;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.*;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.Core;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.LocationPolicy;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class LocationPolicyParser implements PolicyParser {
|
|
||||||
private Glimmer glim = Nemesis.getInstance().getGlimmer();
|
|
||||||
|
|
||||||
public Policy parse(Core corePolicy, Map<?, ?> raw) {
|
|
||||||
Object rawLocations = raw.get("locations");
|
|
||||||
Object rawCoordinates = null;
|
|
||||||
List<String> worlds = new ArrayList<>();
|
|
||||||
if (rawLocations instanceof Map<?,?> rawLocationMap) {
|
|
||||||
rawCoordinates = rawLocationMap.get("coordinates");
|
|
||||||
|
|
||||||
if (rawLocationMap.get("worlds") instanceof List<?> rawWorldsList) {
|
|
||||||
for (Object worldObject : rawWorldsList) {
|
|
||||||
if (worldObject instanceof String worldString) {
|
|
||||||
worlds.add(worldString);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
worlds.add("world");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Glimmer.Box> locations = new ArrayList<>();
|
|
||||||
|
|
||||||
// Parsing locations
|
|
||||||
List<?> groups = rawCoordinates instanceof List ? (List<?>) rawCoordinates : List.of();
|
|
||||||
|
|
||||||
// Now iterate over regions
|
|
||||||
for (Object rObj : groups) {
|
|
||||||
Map<?, ?> region = (Map<?, ?>) rObj;
|
|
||||||
Map<?, ?> c1 = (Map<?, ?>) region.get("corner1");
|
|
||||||
Map<?, ?> c2 = (Map<?, ?>) region.get("corner2");
|
|
||||||
|
|
||||||
double x1 = ((Number) c1.get("x")).doubleValue();
|
|
||||||
double y1 = ((Number) c1.get("y")).doubleValue();
|
|
||||||
double z1 = ((Number) c1.get("z")).doubleValue();
|
|
||||||
|
|
||||||
double x2 = ((Number) c2.get("x")).doubleValue();
|
|
||||||
double y2 = ((Number) c2.get("y")).doubleValue();
|
|
||||||
double z2 = ((Number) c2.get("z")).doubleValue();
|
|
||||||
|
|
||||||
Location loc1 = new Location(glim.getWorlds().getFirst(), x1, y1, z1);
|
|
||||||
Location loc2 = new Location(glim.getWorlds().getFirst(), x2, y2, z2);
|
|
||||||
|
|
||||||
locations.add(Glimmer.Box.of(loc1, loc2));
|
|
||||||
}
|
|
||||||
|
|
||||||
return new LocationPolicy(corePolicy.name(), corePolicy.worlds(), locations, corePolicy.nodes(), corePolicy.nodeAllowlist(), corePolicy.policyAllowList(), corePolicy.effect(), corePolicy.weight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.parser;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.Core;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.PermissionPolicy;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class PermissionPolicyParser implements PolicyParser {
|
|
||||||
@Override
|
|
||||||
public Policy parse(Core corePolicy, Map<?, ?> raw) {
|
|
||||||
Object rawPerms = raw.get("permissions");
|
|
||||||
List<String> permissions = new ArrayList<>();
|
|
||||||
|
|
||||||
if (rawPerms instanceof List<?> list) {
|
|
||||||
for (Object o : list) {
|
|
||||||
if (o instanceof String s) {
|
|
||||||
permissions.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PermissionPolicy(corePolicy.name(), corePolicy.worlds(), permissions, corePolicy.nodes(), corePolicy.policyAllowList(), corePolicy.effect(), corePolicy.weight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.parser;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyParser;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.Core;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.policies.PlayerNamePolicy;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class PlayerNamePolicyParser implements PolicyParser {
|
|
||||||
@Override
|
|
||||||
public Policy parse(Core corePolicy, Map<?, ?> raw) {
|
|
||||||
Object rawNames = raw.get("names");
|
|
||||||
List<String> names = new ArrayList<>();
|
|
||||||
|
|
||||||
if (rawNames instanceof List<?> list) {
|
|
||||||
for (Object o : list) {
|
|
||||||
if (o instanceof String s) {
|
|
||||||
names.add(s);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new PlayerNamePolicy(corePolicy.name(), corePolicy.worlds(), names, corePolicy.nodes(), corePolicy.effect(), corePolicy.policyAllowList(), corePolicy.weight());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.policies;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record Core(String name, List<String> worlds, List<PolicyNode> nodes, boolean nodeAllowlist, boolean policyAllowList, Effect effect, int weight) implements Policy {
|
|
||||||
@Override
|
|
||||||
public boolean applies(LivingEntity entity) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,15 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.policies;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record GlobalPolicy(String name, List<String> worlds, List<PolicyNode> nodes, boolean policyAllowList, Effect effect, int weight) implements Policy {
|
|
||||||
public boolean applies(LivingEntity entity) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.policies;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record LocationPolicy(String name, List<String> worlds, List<Glimmer.Box> locations, List<PolicyNode> nodes, boolean nodeAllowlist, boolean policyAllowList, Effect effect, int weight) implements Policy {
|
|
||||||
@Override
|
|
||||||
public boolean applies(LivingEntity entity) {
|
|
||||||
for (Glimmer.Box box : locations) {
|
|
||||||
if (box.contains(entity.getLocation().toVector(), entity.getWorld())) {
|
|
||||||
return !policyAllowList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return policyAllowList;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.policies;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record PermissionPolicy(String name, List<String> worlds, List<String> permissions, List<PolicyNode> nodes, boolean policyAllowList, Effect effect, int weight) implements Policy {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(LivingEntity entity) {
|
|
||||||
for (String perm : permissions) {
|
|
||||||
if (Nemesis.getInstance().getGlimmer().hasPermission(entity, perm)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.policy.policies;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyNode;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.entity.LivingEntity;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public record PlayerNamePolicy(String name, List<String> worlds, List<String> playerName, List<PolicyNode> nodes, Effect effect, boolean policyAllowList, int weight) implements Policy {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean applies(LivingEntity entity) {
|
|
||||||
if (playerName.contains(entity.getName())) {
|
|
||||||
return !policyAllowList();
|
|
||||||
} else {
|
|
||||||
return policyAllowList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,82 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.reflection;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import org.bukkit.Location;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.util.Vector;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
|
|
||||||
public interface Glimmer {
|
|
||||||
void onLoad();
|
|
||||||
|
|
||||||
List<World> getWorlds();
|
|
||||||
|
|
||||||
// Configuration
|
|
||||||
File loadConfigFile();
|
|
||||||
List<Policy> loadPoliciesFromFile(File file);
|
|
||||||
|
|
||||||
// Items
|
|
||||||
boolean hasItemMeta(ItemStack item);
|
|
||||||
boolean hasEnchantment(ItemStack item, Map<String, String> valuesmap);
|
|
||||||
boolean hasAnyEnchantment(ItemStack itemStack);
|
|
||||||
boolean isArmor(ItemStack item);
|
|
||||||
boolean isAir(ItemStack item);
|
|
||||||
ItemStack getItemInMainHandHumanEntity(HumanEntity entity);
|
|
||||||
|
|
||||||
// Players
|
|
||||||
boolean isGliding(org.bukkit.entity.Player player);
|
|
||||||
void setGliding(org.bukkit.entity.Player player, boolean gliding);
|
|
||||||
boolean hasPermission(org.bukkit.command.CommandSender sender, String permission);
|
|
||||||
|
|
||||||
// Events
|
|
||||||
boolean isArmorEquipAttempt(org.bukkit.event.Event event);
|
|
||||||
ItemStack getEquippedItem(org.bukkit.event.Event event);
|
|
||||||
|
|
||||||
// Commands
|
|
||||||
void sendMessage(CommandSender commandSender, String text);
|
|
||||||
|
|
||||||
class Box {
|
|
||||||
public final double x1, y1, z1, x2, y2, z2;
|
|
||||||
public final String world;
|
|
||||||
|
|
||||||
public Box(String world, double x1, double y1, double z1, double x2, double y2, double z2) {
|
|
||||||
this.x1 = Math.min(x1, x2);
|
|
||||||
this.y1 = Math.min(y1, y2);
|
|
||||||
this.z1 = Math.min(z1, z2);
|
|
||||||
this.x2 = Math.max(x1, x2);
|
|
||||||
this.y2 = Math.max(y1, y2);
|
|
||||||
this.z2 = Math.max(z1, z2);
|
|
||||||
this.world = world;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(double x, double y, double z) {
|
|
||||||
return x >= x1 && x <= x2
|
|
||||||
&& y >= y1 && y <= y2
|
|
||||||
&& z >= z1 && z <= z2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Vector v) {
|
|
||||||
return v.getX() >= x1 && v.getX() <= x2
|
|
||||||
&& v.getY() >= y1 && v.getY() <= y2
|
|
||||||
&& v.getZ() >= z1 && v.getZ() <= z2;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Vector v, String w) {
|
|
||||||
return (Objects.equals(w, world)) && contains(v);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean contains(Vector v, World w) {
|
|
||||||
return contains(v, w.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Box of(Location loc1, Location loc2) { return new Box(loc1.getWorld().getName(), loc1.getX(), loc1.getY(), loc1.getZ(), loc2.getX(), loc2.getY(), loc2.getZ()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,171 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.reflection;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class VersionMatcher {
|
|
||||||
|
|
||||||
public VersionMatcher() {}
|
|
||||||
|
|
||||||
private record Entry(String pattern, String classSuffix) {}
|
|
||||||
|
|
||||||
public String getVersion(String type, String serverVersion) {
|
|
||||||
if (type == null || serverVersion == null) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, List<Entry>> map = populateMap();
|
|
||||||
List<Entry> entries = map.get(type.toLowerCase());
|
|
||||||
if (entries == null || entries.isEmpty()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Entry e : entries) {
|
|
||||||
if (DataShifter.safeMatches(e.pattern, serverVersion)) {
|
|
||||||
return e.pattern + "|" + e.classSuffix;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Entry> sorted = new ArrayList<>(entries);
|
|
||||||
Collections.sort(sorted, (a, b) -> compareVersions(a.pattern, b.pattern));
|
|
||||||
|
|
||||||
Entry oldest = sorted.get(0);
|
|
||||||
Entry newest = sorted.get(sorted.size() - 1);
|
|
||||||
|
|
||||||
int cmpOldest = compareVersions(serverVersion, oldest.pattern);
|
|
||||||
int cmpNewest = compareVersions(serverVersion, newest.pattern);
|
|
||||||
|
|
||||||
if (cmpOldest < 0) {
|
|
||||||
return oldest.pattern + "|" + oldest.classSuffix;
|
|
||||||
} else if (cmpNewest > 0) {
|
|
||||||
return newest.pattern + "|" + newest.classSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
// should not happen because we already tried all patterns
|
|
||||||
return newest.pattern + "|" + newest.classSuffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Map<String, List<Entry>> populateMap() {
|
|
||||||
Map<String, List<Entry>> map = new HashMap<>();
|
|
||||||
|
|
||||||
// RELEASE patterns, newest first (order does not matter for matching)
|
|
||||||
map.put("release", List.of(
|
|
||||||
new Entry("^1\\.21\\..*$", "r1_21")
|
|
||||||
));
|
|
||||||
|
|
||||||
// BETA patterns
|
|
||||||
map.put("beta", List.of(
|
|
||||||
new Entry("^1\\.7\\.3$", "b1_7_3")
|
|
||||||
));
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int compareVersions(String v1, String v2) {
|
|
||||||
String clean1 = v1.replaceAll("[^0-9.]", "");
|
|
||||||
String clean2 = v2.replaceAll("[^0-9.]", "");
|
|
||||||
|
|
||||||
String[] a1 = clean1.split("\\.");
|
|
||||||
String[] a2 = clean2.split("\\.");
|
|
||||||
|
|
||||||
int len = Math.max(a1.length, a2.length);
|
|
||||||
for (int i = 0; i < len; i++) {
|
|
||||||
int n1 = i < a1.length ? parseInt(a1[i]) : 0;
|
|
||||||
int n2 = i < a2.length ? parseInt(a2[i]) : 0;
|
|
||||||
if (n1 != n2) {
|
|
||||||
return n1 - n2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int parseInt(String s) {
|
|
||||||
try {
|
|
||||||
return Integer.parseInt(s);
|
|
||||||
} catch (NumberFormatException e) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Glimmer loadGlim() {
|
|
||||||
String rawVersion = null;
|
|
||||||
try {
|
|
||||||
rawVersion = Bukkit.getMinecraftVersion();
|
|
||||||
} catch (NoSuchMethodError ignored) {}
|
|
||||||
|
|
||||||
if (rawVersion == null || rawVersion.isEmpty()) {
|
|
||||||
String v = Bukkit.getVersion(); // e.g. "git-Bukkit-0.0.0-1060-... (MC: 1.7.3)"
|
|
||||||
int start = v.lastIndexOf("MC: ");
|
|
||||||
if (start != -1) {
|
|
||||||
rawVersion = v.substring(start + 4, v.length() - 1);
|
|
||||||
} else {
|
|
||||||
rawVersion = "unknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String matchInfo = getVersion("release", rawVersion);
|
|
||||||
if (matchInfo.isEmpty()) {
|
|
||||||
matchInfo = getVersion("beta", rawVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matchInfo.isEmpty()) {
|
|
||||||
// Fallback to b1.7.3 if everything fails, or throw error?
|
|
||||||
// User said it supports b1.7.3 and 1.21.x.
|
|
||||||
Glimmer fallback = tryInstantiate("io.github.adrianvic.nemesiseye.impl.b1_7_3");
|
|
||||||
if (fallback != null) return fallback;
|
|
||||||
throw new IllegalStateException("No suitable implementation found for version " + rawVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
String[] partsInfo = matchInfo.split("\\|");
|
|
||||||
String classSuffix = partsInfo[1];
|
|
||||||
|
|
||||||
Glimmer glimmer = tryInstantiate("io.github.adrianvic.nemesiseye.impl." + classSuffix);
|
|
||||||
if (glimmer != null) return glimmer;
|
|
||||||
|
|
||||||
// Backward search for older implementations
|
|
||||||
String[] versionParts = rawVersion.split("\\.");
|
|
||||||
int major = parseInt(versionParts[0]);
|
|
||||||
int minor = versionParts.length > 1 ? parseInt(versionParts[1]) : 0;
|
|
||||||
int patch = versionParts.length > 2 ? parseInt(versionParts[2]) : 0;
|
|
||||||
|
|
||||||
while (major >= 0) {
|
|
||||||
while (minor >= 0) {
|
|
||||||
while (patch >= 0) {
|
|
||||||
String className = String.format("io.github.adrianvic.nemesiseye.impl.r%d_%d_%d", major, minor, patch);
|
|
||||||
glimmer = tryInstantiate(className);
|
|
||||||
if (glimmer != null) return glimmer;
|
|
||||||
|
|
||||||
className = String.format("io.github.adrianvic.nemesiseye.impl.r%d_%d", major, minor);
|
|
||||||
glimmer = tryInstantiate(className);
|
|
||||||
if (glimmer != null) return glimmer;
|
|
||||||
|
|
||||||
patch--;
|
|
||||||
}
|
|
||||||
minor--;
|
|
||||||
patch = 20; // Search up to .20 patch of previous minor
|
|
||||||
}
|
|
||||||
major--;
|
|
||||||
minor = 30; // Search up to .30 minor of previous major
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new IllegalStateException("No suitable implementation found for version " + rawVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Glimmer tryInstantiate(String className) {
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(className, true, getClass().getClassLoader());
|
|
||||||
if (!Glimmer.class.isAssignableFrom(clazz)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return (Glimmer) clazz.getDeclaredConstructor().newInstance();
|
|
||||||
} catch (ReflectiveOperationException ignored) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,19 +1,10 @@
|
||||||
name: "Eye-of-Nemesis"
|
name: "Eye-of-Nemesis"
|
||||||
version: ${version}
|
version: '1.0.1-SNAPSHOT'
|
||||||
main: io.github.adrianvic.nemesiseye.Nemesis
|
main: io.github.adrianvic.nemesiseye.Nemesis
|
||||||
api-version: '1.13'
|
api-version: '1.21'
|
||||||
author: 'Adrian Victor'
|
author: 'Adrian Victor'
|
||||||
website: "https://github.io/adrianvic/NemesisEye"
|
website: "https://github.io/adrianvic/NemesisEye"
|
||||||
description: "Change what players can do based in custom criteria."
|
description: "Change what players can do based in custom criteria."
|
||||||
commands:
|
commands:
|
||||||
eye:
|
eye:
|
||||||
usage: "/eye <option> (help for all available options)"
|
usage: "/eye <option> (help for all available options)"
|
||||||
permissions:
|
|
||||||
nemesiseye.reload:
|
|
||||||
default: op
|
|
||||||
nemesiseye.policy.list.all:
|
|
||||||
default: op
|
|
||||||
nemesiseye.policy.list.self:
|
|
||||||
default: true
|
|
||||||
nemesiseye.help:
|
|
||||||
default: true
|
|
||||||
|
|
@ -1,66 +1,11 @@
|
||||||
# __ _______ __ ___________________ _______
|
|
||||||
# / / \ _ \ \ \ \_ _____/\_____ \ \ \
|
|
||||||
# / / / /_\ \ \ \ | __)_ / | \ / | \
|
|
||||||
# \ \ \ \_/ \ / / | \/ | \/ | \
|
|
||||||
# \_\ \_____ / /_/ /_______ /\_______ /\____|__ /
|
|
||||||
# \/ \/ \/ \/
|
|
||||||
# EYE OF NEMESIS - Example config file.
|
|
||||||
# Documentation in our wiki: https://github.com/adrianvic/NemesisEye
|
|
||||||
|
|
||||||
Policies:
|
Policies:
|
||||||
- name: "Bedrock-allow-admins"
|
Location:
|
||||||
type: "permission"
|
# NO SPACES
|
||||||
worlds: [world]
|
- name: "Beta-1.7.3-items-only"
|
||||||
effect: ALLOW
|
# Will deny anything that's not allowed by the nodes if set to true
|
||||||
weight: 3
|
allowList: true
|
||||||
permissions:
|
nodes:
|
||||||
- "server.usebedrock"
|
- useItem:
|
||||||
nodes:
|
|
||||||
- [BREAK, PLACE, HIT, INTERACT]:
|
|
||||||
values:
|
|
||||||
- BEDROCK
|
|
||||||
|
|
||||||
- name: "Bedrock-deny"
|
|
||||||
type: "global"
|
|
||||||
worlds: [world]
|
|
||||||
effect: DENY
|
|
||||||
weight: 2
|
|
||||||
nodes:
|
|
||||||
- [BREAK, PLACE, HIT, INTERACT]:
|
|
||||||
values:
|
|
||||||
- BEDROCK
|
|
||||||
|
|
||||||
- name: "Block-non-beta-items" # No spaces here or else commands which need the name as argument will not work
|
|
||||||
type: "location" # global | location | permission | playerName
|
|
||||||
effect: DENY # DENY | ALLOW (overrides deny) | ALLOWONLY (allow only if met)
|
|
||||||
worlds: [world]
|
|
||||||
weight: 0 # Greater weight overrides lower
|
|
||||||
policyAllowList: false # Inverts the policy validation logic, for example a location policy will affect all players NOT inside it's location
|
|
||||||
locations:
|
|
||||||
worlds: [world]
|
|
||||||
coordinates:
|
|
||||||
- corner1: { x: 2100, y: 256, z: 1400 }
|
|
||||||
corner2: { x: 1000, y: -64, z: 2200 }
|
|
||||||
nodes:
|
|
||||||
- [INTERACT, BREAK, HIT, PLACE]:
|
|
||||||
values:
|
|
||||||
- '.*'
|
|
||||||
- [USE_ENCHANTMENT]:
|
|
||||||
values:
|
|
||||||
- ".*": ".*"
|
|
||||||
|
|
||||||
- name: "Allow-beta-items"
|
|
||||||
type: "location"
|
|
||||||
effect: ALLOW
|
|
||||||
weight: 1
|
|
||||||
worlds: [world]
|
|
||||||
locations:
|
|
||||||
coordinates:
|
|
||||||
- corner1: { x: 2100, y: 256, z: 1400 }
|
|
||||||
corner2: { x: 1000, y: -64, z: 2200 }
|
|
||||||
nodes:
|
|
||||||
- [INTERACT, BREAK, HIT, PLACE]:
|
|
||||||
values:
|
|
||||||
- AIR
|
- AIR
|
||||||
- STONE
|
- STONE
|
||||||
- COBBLESTONE
|
- COBBLESTONE
|
||||||
|
|
@ -77,7 +22,7 @@ Policies:
|
||||||
- COBWEB
|
- COBWEB
|
||||||
- PISTON
|
- PISTON
|
||||||
- STICKY_PISTON
|
- STICKY_PISTON
|
||||||
- GRASS_BLOCK
|
- GRASS
|
||||||
- DISPENSER
|
- DISPENSER
|
||||||
- NOTE_BLOCK
|
- NOTE_BLOCK
|
||||||
- SANDSTONE
|
- SANDSTONE
|
||||||
|
|
@ -89,7 +34,7 @@ Policies:
|
||||||
- POPPY
|
- POPPY
|
||||||
- DANDELION
|
- DANDELION
|
||||||
- "^(RED|BROWN)_MUSHROOM$"
|
- "^(RED|BROWN)_MUSHROOM$"
|
||||||
- "^(OAK|COBBLESTONE|SMOOTH_STONE)_SLAB$"
|
- "^(OAK|COBBLESTONE)_SLAB$"
|
||||||
- BRICK_BLOCK
|
- BRICK_BLOCK
|
||||||
- TNT
|
- TNT
|
||||||
- BOOKSHELF
|
- BOOKSHELF
|
||||||
|
|
@ -168,4 +113,10 @@ Policies:
|
||||||
- MUSIC_DISK_CAT
|
- MUSIC_DISK_CAT
|
||||||
- MUSIC_DISK_13
|
- MUSIC_DISK_13
|
||||||
- DIRT
|
- DIRT
|
||||||
- BREAD
|
- BREAD
|
||||||
|
- useEnchantment:
|
||||||
|
"gibberish": 999999
|
||||||
|
locations:
|
||||||
|
-
|
||||||
|
- corner1: { x: 2100, y: 256, z: 1400 }
|
||||||
|
corner2: { x: 1000, y: -64, z: 2200 }
|
||||||
|
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.Events;
|
|
||||||
import org.bukkit.event.EventHandler;
|
|
||||||
import org.bukkit.event.EventPriority;
|
|
||||||
import org.bukkit.event.Listener;
|
|
||||||
import org.bukkit.event.block.BlockBreakEvent;
|
|
||||||
import org.bukkit.event.block.BlockPlaceEvent;
|
|
||||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
|
||||||
import org.bukkit.event.entity.EntityDamageByEntityEvent;
|
|
||||||
import org.bukkit.event.entity.EntitySpawnEvent;
|
|
||||||
import org.bukkit.event.inventory.InventoryClickEvent;
|
|
||||||
import org.bukkit.event.player.PlayerInteractEvent;
|
|
||||||
import org.bukkit.event.player.PlayerMoveEvent;
|
|
||||||
|
|
||||||
public class EventListener implements Listener {
|
|
||||||
@EventHandler
|
|
||||||
public void onBlockBreak(BlockBreakEvent event) {
|
|
||||||
Events.onBlockBreak(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onInteractionEvent(PlayerInteractEvent event) {
|
|
||||||
Events.onInteractionEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onEntityDamageByEntityEvent(EntityDamageByEntityEvent event) {
|
|
||||||
Events.onEntityDamageByEntityEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onBlockPlaceEvent(BlockPlaceEvent event) {
|
|
||||||
Events.onBlockPlaceEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onPlayerMoveEvent(PlayerMoveEvent event) { Events.onPlayerMoveEvent(event); }
|
|
||||||
|
|
||||||
@EventHandler(priority = EventPriority.HIGH, ignoreCancelled = true)
|
|
||||||
public void onInventoryClickEvent(InventoryClickEvent event) { Events.onInventoryClickEvent(event); }
|
|
||||||
|
|
||||||
@EventHandler
|
|
||||||
public void onCreatureSpawnEvent(CreatureSpawnEvent event) { Events.onCreatureSpawnEvent(event); }
|
|
||||||
}
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl.commands;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.commands.EyeCore;
|
|
||||||
import org.bukkit.command.Command;
|
|
||||||
import org.bukkit.command.CommandExecutor;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.command.TabCompleter;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
public class Eye implements CommandExecutor, TabCompleter {
|
|
||||||
private final EyeCore core;
|
|
||||||
|
|
||||||
public Eye() {
|
|
||||||
core = new EyeCore();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onCommand(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
|
|
||||||
return core.onCommand(commandSender, command, s, strings);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @Nullable List<String> onTabComplete(@NotNull CommandSender commandSender, @NotNull Command command, @NotNull String s, @NotNull String @NotNull [] strings) {
|
|
||||||
return core.onTabComplete(commandSender, command, s, strings);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,201 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.DataShifter;
|
|
||||||
import io.github.adrianvic.nemesiseye.Nemesis;
|
|
||||||
import io.github.adrianvic.nemesiseye.impl.commands.Eye;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.PolicyParsers;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.command.CommandSender;
|
|
||||||
import org.bukkit.configuration.file.YamlConfiguration;
|
|
||||||
import org.bukkit.enchantments.Enchantment;
|
|
||||||
import org.bukkit.entity.HumanEntity;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.bukkit.plugin.PluginManager;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class r1_21 implements Glimmer {
|
|
||||||
@Override
|
|
||||||
public File loadConfigFile() {
|
|
||||||
File file = new File(Nemesis.getInstance().getDataFolder(), "settings.yml");
|
|
||||||
|
|
||||||
if (!file.exists())
|
|
||||||
Nemesis.getInstance().saveResource("settings.yml", false);
|
|
||||||
|
|
||||||
return file;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<Policy> loadPoliciesFromFile(File file) {
|
|
||||||
YamlConfiguration config = new YamlConfiguration();
|
|
||||||
config.options().parseComments(true);
|
|
||||||
|
|
||||||
try {
|
|
||||||
config.load(file);
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Map<?, ?>> rawPolicies = config.getMapList("Policies");
|
|
||||||
List<Policy> allPolicies = new ArrayList<>();
|
|
||||||
|
|
||||||
for (Map<?, ?> policyMap : rawPolicies) {
|
|
||||||
if (policyMap.get("type") != null && policyMap.get("type") instanceof String type) {
|
|
||||||
allPolicies.add(PolicyParsers.get(type).parse(policyMap));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return allPolicies;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onLoad() {
|
|
||||||
PluginManager pm = Nemesis.getInstance().getPluginManager();
|
|
||||||
Nemesis.getInstance().getCommand("eye").setExecutor(new Eye());
|
|
||||||
pm.registerEvents(new EventListener(), Nemesis.getInstance());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getItemInMainHandHumanEntity(HumanEntity entity) {
|
|
||||||
return entity.getInventory().getItemInMainHand();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isAir(ItemStack item) {
|
|
||||||
return item == null || item.getType().isAir();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isGliding(org.bukkit.entity.Player player) {
|
|
||||||
return player.isGliding();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setGliding(org.bukkit.entity.Player player, boolean gliding) {
|
|
||||||
player.setGliding(gliding);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPermission(org.bukkit.command.CommandSender sender, String permission) {
|
|
||||||
return sender.hasPermission(permission);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isArmorEquipAttempt(org.bukkit.event.Event event) {
|
|
||||||
if (!(event instanceof org.bukkit.event.inventory.InventoryClickEvent e)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.getSlotType() == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.isShiftClick()) {
|
|
||||||
return isArmor(e.getCurrentItem());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY
|
|
||||||
&& e.getSlotType() == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR
|
|
||||||
&& e.getWhoClicked() instanceof org.bukkit.entity.Player player) {
|
|
||||||
return isArmor(
|
|
||||||
player.getInventory().getItem(e.getHotbarButton())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ItemStack getEquippedItem(org.bukkit.event.Event event) {
|
|
||||||
if (event instanceof org.bukkit.event.inventory.InventoryClickEvent e) {
|
|
||||||
org.bukkit.event.inventory.InventoryType.SlotType slotType = e.getSlotType();
|
|
||||||
|
|
||||||
if (e.getClick() == org.bukkit.event.inventory.ClickType.NUMBER_KEY // hotbar key swap
|
|
||||||
&& slotType == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR
|
|
||||||
&& e.getWhoClicked() instanceof org.bukkit.entity.Player player) {
|
|
||||||
return player.getInventory().getItem(e.getHotbarButton());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (e.isShiftClick()) {
|
|
||||||
ItemStack current = e.getCurrentItem();
|
|
||||||
if (isArmor(current)) return current;
|
|
||||||
}
|
|
||||||
|
|
||||||
// regular click
|
|
||||||
if (slotType == org.bukkit.event.inventory.InventoryType.SlotType.ARMOR) {
|
|
||||||
ItemStack cursor = e.getCursor();
|
|
||||||
if (isArmor(cursor)) return cursor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try Paper's PlayerArmorChangeEvent via reflection or just check if class exists
|
|
||||||
try {
|
|
||||||
if (event instanceof com.destroystokyo.paper.event.player.PlayerArmorChangeEvent e) {
|
|
||||||
return e.getNewItem();
|
|
||||||
}
|
|
||||||
} catch (NoClassDefFoundError | Exception ignored) {}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void sendMessage(CommandSender commandSender, String text) {
|
|
||||||
commandSender.sendMessage(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasItemMeta(ItemStack item) {
|
|
||||||
return item.getItemMeta() != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<World> getWorlds() {
|
|
||||||
return Bukkit.getWorlds();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasEnchantment(ItemStack item, Map<String, String> valuesmap) {
|
|
||||||
Map<Enchantment, Integer> enchantments = item.getEnchantments();
|
|
||||||
|
|
||||||
for (Map.Entry<Enchantment, Integer> ench : enchantments.entrySet()) {
|
|
||||||
String enchKey = ench.getKey().getKey().getKey();
|
|
||||||
String enchLevel = ench.getValue().toString();
|
|
||||||
|
|
||||||
for (Map.Entry<String, String> rule : valuesmap.entrySet()) {
|
|
||||||
if (
|
|
||||||
DataShifter.safeMatches(rule.getKey(), enchKey) &&
|
|
||||||
DataShifter.safeMatches(rule.getValue(), enchLevel)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasAnyEnchantment(ItemStack item) {
|
|
||||||
return !(item.getItemMeta().getEnchants().isEmpty());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isArmor(ItemStack item) {
|
|
||||||
if (item == null || item.getType().isAir()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
String name = item.getType().name();
|
|
||||||
|
|
||||||
return name.endsWith("_HELMET")
|
|
||||||
|| name.endsWith("_CHESTPLATE")
|
|
||||||
|| name.endsWith("_LEGGINGS")
|
|
||||||
|| name.endsWith("_BOOTS")
|
|
||||||
|| item.getType() == org.bukkit.Material.ELYTRA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye;
|
|
||||||
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Action;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Effect;
|
|
||||||
import io.github.adrianvic.nemesiseye.policy.Policy;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
import org.bukkit.event.Event;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
import org.mockito.MockedStatic;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
import static org.mockito.Mockito.*;
|
|
||||||
|
|
||||||
public class ValidatorTest {
|
|
||||||
|
|
||||||
private Glimmer mockGlim;
|
|
||||||
private Config mockConfig;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
mockGlim = mock(Glimmer.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testValidatorCanDeny() {
|
|
||||||
Player player = mock(Player.class);
|
|
||||||
Event event = mock(Event.class);
|
|
||||||
Policy policy = mock(Policy.class);
|
|
||||||
|
|
||||||
when(policy.applies(player)).thenReturn(true);
|
|
||||||
when(policy.matches(player, Action.BREAK, event)).thenReturn(true);
|
|
||||||
when(policy.effect()).thenReturn(Effect.DENY);
|
|
||||||
|
|
||||||
// We need to handle the static Config.getInstance()
|
|
||||||
// This is tricky without refactoring or Mockito-inline
|
|
||||||
// For now, let's just demonstrate the concept if Validator was more testable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,64 +0,0 @@
|
||||||
package io.github.adrianvic.nemesiseye.impl;
|
|
||||||
|
|
||||||
import be.seeseemelk.mockbukkit.MockBukkit;
|
|
||||||
import be.seeseemelk.mockbukkit.ServerMock;
|
|
||||||
import io.github.adrianvic.nemesiseye.reflection.Glimmer;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.inventory.ItemStack;
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
|
||||||
import org.junit.jupiter.params.ParameterizedTest;
|
|
||||||
import org.junit.jupiter.params.provider.MethodSource;
|
|
||||||
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
|
||||||
|
|
||||||
public class ImplementationContractTest {
|
|
||||||
|
|
||||||
private ServerMock server;
|
|
||||||
|
|
||||||
@BeforeEach
|
|
||||||
void setUp() {
|
|
||||||
server = MockBukkit.mock();
|
|
||||||
}
|
|
||||||
|
|
||||||
@AfterEach
|
|
||||||
void tearDown() {
|
|
||||||
MockBukkit.unmock();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Stream<Glimmer> implementations() {
|
|
||||||
return Stream.of(
|
|
||||||
new b1_7_3(),
|
|
||||||
new r1_21()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@MethodSource("implementations")
|
|
||||||
void testIsArmor(Glimmer glim) {
|
|
||||||
// Helmets
|
|
||||||
assertTrue(glim.isArmor(new ItemStack(Material.IRON_HELMET)));
|
|
||||||
assertTrue(glim.isArmor(new ItemStack(Material.DIAMOND_HELMET)));
|
|
||||||
|
|
||||||
// Chestplates
|
|
||||||
assertTrue(glim.isArmor(new ItemStack(Material.GOLDEN_CHESTPLATE)));
|
|
||||||
|
|
||||||
// Non-armor
|
|
||||||
assertFalse(glim.isArmor(new ItemStack(Material.STICK)));
|
|
||||||
assertFalse(glim.isArmor(new ItemStack(Material.DIRT)));
|
|
||||||
|
|
||||||
// Null/Air
|
|
||||||
assertFalse(glim.isArmor(null));
|
|
||||||
assertFalse(glim.isArmor(new ItemStack(Material.AIR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
@ParameterizedTest
|
|
||||||
@MethodSource("implementations")
|
|
||||||
void testIsAir(Glimmer glim) {
|
|
||||||
assertTrue(glim.isAir(null));
|
|
||||||
assertTrue(glim.isAir(new ItemStack(Material.AIR)));
|
|
||||||
assertFalse(glim.isAir(new ItemStack(Material.STONE)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue