added files.
This commit is contained in:
commit
db0d8ce913
2186 files changed
+238581
No files matched your search
@@ -0,0 +1,4 @@
|
|||||||
|
.gradle/
|
||||||
|
build/
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<p align="center">
|
||||||
|
<img src="assets/ss.png" alt="Skid Solutions Banner" width="350" />
|
||||||
|
<br>
|
||||||
|
<font size="6"><b>OpenLPX</b></font>
|
||||||
|
<br>
|
||||||
|
<font size="3">by Skid Solutions</font>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://discord.gg/AEwatvnvSf">https://discord.gg/AEwatvnvSf</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<img src="assets/jak.jpg" alt="jak" height="150" />
|
||||||
|
<img src="assets/hack.jpg" alt="hack" height="150" />
|
||||||
|
<img src="assets/deobf2.png" alt="deobf2" height="150" />
|
||||||
|
<img src="assets/deobf.jpg" alt="deobf" height="150" />
|
||||||
|
</p>
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How to build
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
- **Java Development Kit**: JDK 17 (the Gradle wrapper 8.14.3 does not run on newer JDKs)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Building LPX
|
||||||
|
|
||||||
|
Run from this folder:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
$env:JAVA_HOME = "C:\Program Files\Java\jdk-17"
|
||||||
|
|
||||||
|
.\gradlew.bat clean build
|
||||||
|
```
|
||||||
|
|
||||||
|
Generated `build/libs/`:
|
||||||
|
- `LPX-3.9.1.jar`
|
||||||
|
- `LPX-3.9.1-sources.jar`
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 135 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 323 KiB |
@@ -0,0 +1,83 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'idea'
|
||||||
|
id 'eclipse'
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'it.ytnoos.lpx'
|
||||||
|
version = '3.9.1'
|
||||||
|
|
||||||
|
def javaVersion = 17
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
maven { url = uri('https://hub.spigotmc.org/nexus/content/repositories/snapshots/') }
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
apiGenerator
|
||||||
|
}
|
||||||
|
|
||||||
|
def generatorClasses = layout.buildDirectory.dir('api-generator/classes')
|
||||||
|
tasks.register('compileApiGenerator', JavaCompile) {
|
||||||
|
source = files('gradle/GenerateCompileApis.java')
|
||||||
|
classpath = configurations.apiGenerator
|
||||||
|
destinationDirectory = generatorClasses
|
||||||
|
javaCompiler = javaToolchains.compilerFor { languageVersion = JavaLanguageVersion.of(javaVersion) }
|
||||||
|
options.release = javaVersion
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
}
|
||||||
|
tasks.register('generateCompileApis', JavaExec) {
|
||||||
|
group = 'build setup'
|
||||||
|
description = 'Generates compile-only API headers from text declarations.'
|
||||||
|
dependsOn tasks.named('compileApiGenerator')
|
||||||
|
inputs.dir('gradle/api-signatures')
|
||||||
|
outputs.dir(layout.buildDirectory.dir('compile-apis'))
|
||||||
|
classpath = files(generatorClasses) + configurations.apiGenerator
|
||||||
|
javaLauncher = javaToolchains.launcherFor { languageVersion = JavaLanguageVersion.of(javaVersion) }
|
||||||
|
mainClass = 'GenerateCompileApis'
|
||||||
|
maxHeapSize = '2g'
|
||||||
|
args file('gradle/api-signatures').absolutePath, layout.buildDirectory.dir('compile-apis').get().asFile.absolutePath
|
||||||
|
}
|
||||||
|
def compileApi = { String name ->
|
||||||
|
files(layout.buildDirectory.file("compile-apis/${name}.jar")).builtBy(tasks.named('generateCompileApis'))
|
||||||
|
}
|
||||||
|
tasks.register('prepareIde') {
|
||||||
|
group = 'ide'
|
||||||
|
description = 'Generates the compile-only API headers used by the IDE import.'
|
||||||
|
dependsOn tasks.named('generateCompileApis')
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain.languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
apiGenerator 'org.ow2.asm:asm:9.8'
|
||||||
|
apiGenerator 'com.google.code.gson:gson:2.10.1'
|
||||||
|
|
||||||
|
compileOnly compileApi('lpx')
|
||||||
|
compileOnly 'org.jetbrains:annotations:26.0.2-1'
|
||||||
|
compileOnly 'org.jspecify:jspecify:1.0.0'
|
||||||
|
compileOnly 'org.checkerframework:checker-qual:3.49.3'
|
||||||
|
compileOnly 'com.google.code.gson:gson:2.10.1'
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
if (name != 'compileApiGenerator') {
|
||||||
|
dependsOn tasks.named('generateCompileApis')
|
||||||
|
}
|
||||||
|
options.release = javaVersion
|
||||||
|
options.encoding = 'UTF-8'
|
||||||
|
options.compilerArgs += ['-parameters', '-Xmaxerrs', '1500']
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(AbstractArchiveTask).configureEach {
|
||||||
|
preserveFileTimestamps = false
|
||||||
|
reproducibleFileOrder = true
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest.attributes('Implementation-Title': 'LPX', 'Implementation-Version': project.version)
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
org.gradle.jvmargs=-Xmx3g -Dfile.encoding=UTF-8
|
||||||
|
org.gradle.workers.max=2
|
||||||
|
org.gradle.parallel=false
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
import com.google.gson.*;
|
||||||
|
import org.objectweb.asm.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.jar.*;
|
||||||
|
|
||||||
|
public final class GenerateCompileApis implements Opcodes {
|
||||||
|
static String text(JsonObject o,String k){return o.has(k)&&!o.get(k).isJsonNull()?o.get(k).getAsString():null;}
|
||||||
|
static int number(JsonObject o,String k){return o.get(k).getAsInt();}
|
||||||
|
static JsonArray array(JsonObject o,String k){return o.has(k)?o.getAsJsonArray(k):new JsonArray();}
|
||||||
|
static String[] strings(JsonObject o,String k){List<String> r=new ArrayList<>();for(JsonElement e:array(o,k))r.add(e.getAsString());return r.toArray(new String[0]);}
|
||||||
|
static Object scalar(JsonObject o){String v=text(o,"value");return switch(text(o,"type")){
|
||||||
|
case "Long"->Long.valueOf(v);case "Integer"->Integer.valueOf(v);case "Float"->Float.valueOf(v);case "Double"->Double.valueOf(v);case "Byte"->Byte.valueOf(v);case "Short"->Short.valueOf(v);case "Character"->v.charAt(0);default->throw new IllegalArgumentException(o.toString());};}
|
||||||
|
static Object constant(JsonElement e){if(e==null||e.isJsonNull())return null;if(e.isJsonObject())return scalar(e.getAsJsonObject());return e.getAsString();}
|
||||||
|
static void annotationValue(AnnotationVisitor visitor,String name,JsonElement value){
|
||||||
|
if(value.isJsonArray()){AnnotationVisitor nested=visitor.visitArray(name);for(JsonElement e:value.getAsJsonArray())annotationValue(nested,null,e);nested.visitEnd();}
|
||||||
|
else if(value.isJsonObject()){JsonObject o=value.getAsJsonObject();switch(text(o,"kind")){
|
||||||
|
case "scalar"->visitor.visit(name,scalar(o));case "type"->visitor.visit(name,Type.getType(text(o,"descriptor")));
|
||||||
|
case "enum"->visitor.visitEnum(name,text(o,"descriptor"),text(o,"name"));
|
||||||
|
case "annotation"->{JsonObject a=o.getAsJsonObject("annotation");writeAnnotation(visitor.visitAnnotation(name,text(a,"descriptor")),a);}
|
||||||
|
default->throw new IllegalArgumentException(o.toString());}}
|
||||||
|
else if(value.getAsJsonPrimitive().isBoolean())visitor.visit(name,value.getAsBoolean());
|
||||||
|
else visitor.visit(name,value.getAsString());
|
||||||
|
}
|
||||||
|
static void writeAnnotation(AnnotationVisitor visitor,JsonObject annotation){if(visitor==null)return;for(var e:annotation.getAsJsonObject("values").entrySet())annotationValue(visitor,e.getKey(),e.getValue());visitor.visitEnd();}
|
||||||
|
interface Factory {AnnotationVisitor create(JsonObject annotation);}
|
||||||
|
static void annotations(JsonObject o,String key,Factory factory){for(JsonElement a:array(o,key)){JsonObject obj=a.getAsJsonObject();writeAnnotation(factory.create(obj),obj);}}
|
||||||
|
static TypePath path(JsonObject o){return TypePath.fromString(text(o,"typePath"));}
|
||||||
|
static byte[] compile(JsonObject c){
|
||||||
|
ClassWriter cw=new ClassWriter(0);cw.visit(number(c,"version"),number(c,"access"),text(c,"name"),text(c,"signature"),text(c,"superName"),strings(c,"interfaces"));
|
||||||
|
if(c.has("outerClass"))cw.visitOuterClass(text(c,"outerClass"),text(c,"outerMethod"),text(c,"outerMethodDescriptor"));
|
||||||
|
if(c.has("nestHostClass"))cw.visitNestHost(text(c,"nestHostClass"));
|
||||||
|
for(String n:strings(c,"nestMembers"))cw.visitNestMember(n);for(String n:strings(c,"permittedSubclasses"))cw.visitPermittedSubclass(n);
|
||||||
|
annotations(c,"annotations",a->cw.visitAnnotation(text(a,"descriptor"),a.get("visible").getAsBoolean()));
|
||||||
|
annotations(c,"typeAnnotations",a->cw.visitTypeAnnotation(number(a,"typeRef"),path(a),text(a,"descriptor"),a.get("visible").getAsBoolean()));
|
||||||
|
for(JsonElement el:array(c,"innerClasses")){var n=el.getAsJsonObject();cw.visitInnerClass(text(n,"name"),text(n,"outerName"),text(n,"innerName"),number(n,"access"));}
|
||||||
|
for(JsonElement el:array(c,"recordComponents")){var r=el.getAsJsonObject();var rv=cw.visitRecordComponent(text(r,"name"),text(r,"descriptor"),text(r,"signature"));annotations(r,"annotations",a->rv.visitAnnotation(text(a,"descriptor"),a.get("visible").getAsBoolean()));annotations(r,"typeAnnotations",a->rv.visitTypeAnnotation(number(a,"typeRef"),path(a),text(a,"descriptor"),a.get("visible").getAsBoolean()));rv.visitEnd();}
|
||||||
|
for(JsonElement el:array(c,"fields")){var f=el.getAsJsonObject();var fv=cw.visitField(number(f,"access"),text(f,"name"),text(f,"descriptor"),text(f,"signature"),constant(f.get("constant")));annotations(f,"annotations",a->fv.visitAnnotation(text(a,"descriptor"),a.get("visible").getAsBoolean()));annotations(f,"typeAnnotations",a->fv.visitTypeAnnotation(number(a,"typeRef"),path(a),text(a,"descriptor"),a.get("visible").getAsBoolean()));fv.visitEnd();}
|
||||||
|
for(JsonElement el:array(c,"methods")){var m=el.getAsJsonObject();int access=number(m,"access");String descriptor=text(m,"descriptor");var mv=cw.visitMethod(access,text(m,"name"),descriptor,text(m,"signature"),strings(m,"exceptions"));
|
||||||
|
for(JsonElement pe:array(m,"parameters")){var p=pe.getAsJsonObject();mv.visitParameter(text(p,"name"),number(p,"access"));}
|
||||||
|
annotations(m,"annotations",a->mv.visitAnnotation(text(a,"descriptor"),a.get("visible").getAsBoolean()));annotations(m,"typeAnnotations",a->mv.visitTypeAnnotation(number(a,"typeRef"),path(a),text(a,"descriptor"),a.get("visible").getAsBoolean()));
|
||||||
|
annotations(m,"parameterAnnotations",a->mv.visitParameterAnnotation(number(a,"parameter"),text(a,"descriptor"),a.get("visible").getAsBoolean()));
|
||||||
|
if(m.has("annotationDefault")){var av=mv.visitAnnotationDefault();annotationValue(av,null,m.get("annotationDefault"));av.visitEnd();}
|
||||||
|
if((access&(ACC_ABSTRACT|ACC_NATIVE))==0){mv.visitCode();mv.visitTypeInsn(NEW,"java/lang/UnsupportedOperationException");mv.visitInsn(DUP);mv.visitLdcInsn("Compile-only API header; use the real server or library at runtime");mv.visitMethodInsn(INVOKESPECIAL,"java/lang/UnsupportedOperationException","<init>","(Ljava/lang/String;)V",false);mv.visitInsn(ATHROW);int locals=(access&ACC_STATIC)==0?1:0;for(Type t:Type.getArgumentTypes(descriptor))locals+=t.getSize();mv.visitMaxs(3,locals);}
|
||||||
|
mv.visitEnd();}
|
||||||
|
cw.visitEnd();return cw.toByteArray();
|
||||||
|
}
|
||||||
|
static SortedMap<String,JsonObject> declarations(Path input,Path schema,Set<Path> active)throws Exception {
|
||||||
|
if(!active.add(schema))throw new IllegalArgumentException("Cyclic API declaration inheritance: "+schema);
|
||||||
|
JsonObject data;try(Reader r=Files.newBufferedReader(schema)){data=JsonParser.parseReader(r).getAsJsonObject();}
|
||||||
|
SortedMap<String,JsonObject> classes=new TreeMap<>();
|
||||||
|
if(data.has("base"))classes.putAll(declarations(input,input.resolve(text(data,"base")+".json"),active));
|
||||||
|
for(JsonElement entry:array(data,"classes")){JsonObject c=entry.getAsJsonObject();classes.put(text(c,"name"),c);}
|
||||||
|
active.remove(schema);return classes;
|
||||||
|
}
|
||||||
|
public static void main(String[] args)throws Exception{
|
||||||
|
Path input=Path.of(args[0]),output=Path.of(args[1]);Files.createDirectories(output);
|
||||||
|
for(Path schema:Files.list(input).filter(p->p.toString().endsWith(".json")).sorted().toList()){
|
||||||
|
SortedMap<String,JsonObject> classes=declarations(input,schema,new HashSet<>());
|
||||||
|
String name=schema.getFileName().toString().replace(".json",".jar");Path jar=output.resolve(name);
|
||||||
|
try(var out=new JarOutputStream(Files.newOutputStream(jar))){for(JsonObject c:classes.values()){var entry=new JarEntry(text(c,"name")+".class");entry.setTime(0);out.putNextEntry(entry);out.write(compile(c));out.closeEntry();}}
|
||||||
|
System.out.println("Generated compile API "+name+" ("+classes.size()+" declarations)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{"formatVersion":1,"purpose":"Compile-only API declarations; not runtime implementations","classes":[{"name":"com/destroystokyo/paper/event/server/ServerTickStartEvent","version":61,"access":33,"superName":"java/lang/Object"},{"name":"com/google/auto/service/AutoService","version":61,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"],"methods":[{"name":"value","access":1025,"descriptor":"()[Ljava/lang/Class;"}]},{"name":"com/google/common/annotations/Beta","version":52,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"]},{"name":"com/google/common/annotations/GwtCompatible","version":52,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"],"methods":[{"name":"serializable","access":1025,"descriptor":"()Z","annotationDefault":false},{"name":"emulated","access":1025,"descriptor":"()Z","annotationDefault":false}]},{"name":"com/google/common/annotations/GwtIncompatible","version":52,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"],"methods":[{"name":"value","access":1025,"descriptor":"()Ljava/lang/String;","annotationDefault":""}]},{"name":"com/google/common/annotations/J2ktIncompatible","version":52,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"]},{"name":"com/google/common/annotations/VisibleForTesting","version":52,"access":9729,"superName":"java/lang/Object","interfaces":["java/lang/annotation/Annotation"]},{"name":"com/google/common/annotations/package-info","version":52,"access":5632,"superName":"java/lang/Object"},{"name":"com/google/common/base/Absent","version":52,"access":48,"signature":"<T:Ljava/lang/Object;>Lcom/google/common/base/Optional<TT;>;","superName":"com/google/common/base/Optional","fields":[{"name":"INSTANCE","access":24,"descriptor":"Lcom/google/common/base/Absent;","signature":"Lcom/google/common/base/Absent<Ljava/lang/Object;>;"},{"name":"serialVersionUID","access":26,"descriptor":"J","constant":{"kind":"scalar","type":"Long","value":"0"}}],"methods":[{"name":"withType","access":8,"descriptor":"()Lcom/google/common/base/Optional;","signature":"<T:Ljava/lang/Object;>()Lcom/google/common/base/Optional<TT;>;"},{"name":"<init>","access":2,"descriptor":"()V"},{"name":"isPresent","access":1,"descriptor":"()Z"},{"name":"get","access":1,"descriptor":"()Ljava/lang/Object;","signature":"()TT;"},{"name":"or","access":1,"descriptor":"(Ljava/lang/Object;)Ljava/lang/Object;","signature":"(TT;)TT;"},{"name":"or","access":1,"descriptor":"(Lcom/google/common/base/Optional;)Lcom/google/common/base/Optional;","signature":"(Lcom/google/common/base/Optional<+TT;>;)Lcom/google/common/base/Optional<TT;>;"},{"name":"or","access":1,"descriptor":"(Lcom/google/common/base/Supplier;)Ljava/lang/Object;","signature":"(Lcom/google/common/base/Supplier<+TT;>;)TT;"},{"name":"orNull","access":1,"descriptor":"()Ljava/lang/Object;","signature":"()TT;"},{"name":"asSet","access":1,"descriptor":"()Ljava/util/Set;","signature":"()Ljava/util/Set<TT;>;"},{"name":"transform","access":1,"descriptor":"(Lcom/google/common/base/Function;)Lcom/google/common/base/Optional;","signature":"<V:Ljava/lang/Object;>(Lcom/google/common/base/Function<-TT;TV;>;)Lcom/google/common/base/Optional<TV;>;"},{"name":"equals","access":1,"descriptor":"(Ljava/lang/Object;)Z"},{"name":"hashCode","access":1,"descriptor":"()I"},{"name":"toString","access":1,"descriptor":"()Ljava/lang/String;"},{"name":"readResolve","access":2,"descriptor":"()Ljava/lang/Object;"}]},{"name":"com/google/common/base/AbstractIterator","version":52,"access":1056,"signature":"<T:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/Iterator<TT;>;","superName":"java/lang/Object","interfaces":["java/util/Iterator"],"innerClasses":[{"name":"com/google/common/base/AbstractIterator$State","outerName":"com/google/common/base/AbstractIterator","innerName":"State","access":16410}],"fields":[{"name":"state","access":2,"descriptor":"Lcom/google/common/base/AbstractIterator$State;"},{"name":"next","access":2,"descriptor":"Ljava/lang/Object;","signature":"TT;"}],"methods":[{"name":"<init>","access":4,"descriptor":"()V"},{"name":"computeNext","access":1028,"descriptor":"()Ljava/lang/Object;","signature":"()TT;"},{"name":"endOfData","access":20,"descriptor":"()Ljava/lang/Object;","signature":"()TT;"},{"name":"hasNext","access":17,"descriptor":"()Z"},{"name":"tryToComputeNext","access":2,"descriptor":"()Z"},{"name":"next","access":17,"descriptor":"()Ljava/lang/Object;","signature":"()TT;"},{"name":"remove","access":17,"descriptor":"()V"}]},{"name":"com/google/common/base/AbstractIterator$State","version":52,"access":16432,"signature":"Ljava/lang/Enum<Lcom/google/common/base/AbstractIterator$State;>;","superName":"java/lang/Enum","innerClasses":[{"name":"com/google/common/base/AbstractIterator$State","outerName":"com/google/common/base/AbstractIterator","innerName":"State","access":16410}Line truncated
|
||||||
Vendored
BIN
Binary file not shown.
+8
@@ -0,0 +1,8 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
|
||||||
|
networkTimeout=10000
|
||||||
|
validateDistributionUrl=true
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
||||||
|
distributionSha256Sum=bd71102213493060956ec229d946beee57158dbd89d0e62b91bca0fa2c5f3531
|
||||||
@@ -0,0 +1,251 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
#
|
||||||
|
# Copyright © 2015-2021 the original authors.
|
||||||
|
#
|
||||||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
# you may not use this file except in compliance with the License.
|
||||||
|
# You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing, software
|
||||||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
# See the License for the specific language governing permissions and
|
||||||
|
# limitations under the License.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
##############################################################################
|
||||||
|
#
|
||||||
|
# Gradle start up script for POSIX generated by Gradle.
|
||||||
|
#
|
||||||
|
# Important for running:
|
||||||
|
#
|
||||||
|
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||||
|
# noncompliant, but you have some other compliant shell such as ksh or
|
||||||
|
# bash, then to run this script, type that shell name before the whole
|
||||||
|
# command line, like:
|
||||||
|
#
|
||||||
|
# ksh Gradle
|
||||||
|
#
|
||||||
|
# Busybox and similar reduced shells will NOT work, because this script
|
||||||
|
# requires all of these POSIX shell features:
|
||||||
|
# * functions;
|
||||||
|
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||||
|
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||||
|
# * compound commands having a testable exit status, especially «case»;
|
||||||
|
# * various built-in commands including «command», «set», and «ulimit».
|
||||||
|
#
|
||||||
|
# Important for patching:
|
||||||
|
#
|
||||||
|
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||||
|
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||||
|
#
|
||||||
|
# The "traditional" practice of packing multiple parameters into a
|
||||||
|
# space-separated string is a well documented source of bugs and security
|
||||||
|
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||||
|
# options in "$@", and eventually passing that to Java.
|
||||||
|
#
|
||||||
|
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||||
|
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||||
|
# see the in-line comments for details.
|
||||||
|
#
|
||||||
|
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||||
|
# Darwin, MinGW, and NonStop.
|
||||||
|
#
|
||||||
|
# (3) This script is generated from the Groovy template
|
||||||
|
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||||
|
# within the Gradle project.
|
||||||
|
#
|
||||||
|
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||||
|
#
|
||||||
|
##############################################################################
|
||||||
|
|
||||||
|
# Attempt to set APP_HOME
|
||||||
|
|
||||||
|
# Resolve links: $0 may be a link
|
||||||
|
app_path=$0
|
||||||
|
|
||||||
|
# Need this for daisy-chained symlinks.
|
||||||
|
while
|
||||||
|
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||||
|
[ -h "$app_path" ]
|
||||||
|
do
|
||||||
|
ls=$( ls -ld "$app_path" )
|
||||||
|
link=${ls#*' -> '}
|
||||||
|
case $link in #(
|
||||||
|
/*) app_path=$link ;; #(
|
||||||
|
*) app_path=$APP_HOME$link ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# This is normally unused
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
APP_BASE_NAME=${0##*/}
|
||||||
|
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||||
|
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||||
|
|
||||||
|
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||||
|
MAX_FD=maximum
|
||||||
|
|
||||||
|
warn () {
|
||||||
|
echo "$*"
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "$( uname )" in #(
|
||||||
|
CYGWIN* ) cygwin=true ;; #(
|
||||||
|
Darwin* ) darwin=true ;; #(
|
||||||
|
MSYS* | MINGW* ) msys=true ;; #(
|
||||||
|
NONSTOP* ) nonstop=true ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
|
# Determine the Java command to use to start the JVM.
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||||
|
else
|
||||||
|
JAVACMD=$JAVA_HOME/bin/java
|
||||||
|
fi
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD=java
|
||||||
|
if ! command -v java >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
|
|
||||||
|
Please set the JAVA_HOME variable in your environment to match the
|
||||||
|
location of your Java installation."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Increase the maximum file descriptors if we can.
|
||||||
|
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||||
|
case $MAX_FD in #(
|
||||||
|
max*)
|
||||||
|
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
MAX_FD=$( ulimit -H -n ) ||
|
||||||
|
warn "Could not query maximum file descriptor limit"
|
||||||
|
esac
|
||||||
|
case $MAX_FD in #(
|
||||||
|
'' | soft) :;; #(
|
||||||
|
*)
|
||||||
|
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||||
|
# shellcheck disable=SC2039,SC3045
|
||||||
|
ulimit -n "$MAX_FD" ||
|
||||||
|
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||||
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Collect all arguments for the java command, stacking in reverse order:
|
||||||
|
# * args from the command line
|
||||||
|
# * the main class name
|
||||||
|
# * -classpath
|
||||||
|
# * -D...appname settings
|
||||||
|
# * --module-path (only if needed)
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||||
|
|
||||||
|
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||||
|
if "$cygwin" || "$msys" ; then
|
||||||
|
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||||
|
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||||
|
|
||||||
|
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||||
|
|
||||||
|
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||||
|
for arg do
|
||||||
|
if
|
||||||
|
case $arg in #(
|
||||||
|
-*) false ;; # don't mess with options #(
|
||||||
|
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||||
|
[ -e "$t" ] ;; #(
|
||||||
|
*) false ;;
|
||||||
|
esac
|
||||||
|
then
|
||||||
|
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||||
|
fi
|
||||||
|
# Roll the args list around exactly as many times as the number of
|
||||||
|
# args, so each arg winds up back in the position where it started, but
|
||||||
|
# possibly modified.
|
||||||
|
#
|
||||||
|
# NB: a `for` loop captures its iteration list before it begins, so
|
||||||
|
# changing the positional parameters here affects neither the number of
|
||||||
|
# iterations, nor the values presented in `arg`.
|
||||||
|
shift # remove old arg
|
||||||
|
set -- "$@" "$arg" # push replacement arg
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||||
|
|
||||||
|
# Collect all arguments for the java command:
|
||||||
|
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
|
||||||
|
# and any embedded shellness will be escaped.
|
||||||
|
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
|
||||||
|
# treated as '${Hostname}' itself on the command line.
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
|
-classpath "$CLASSPATH" \
|
||||||
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
|
"$@"
|
||||||
|
|
||||||
|
# Stop when "xargs" is not available.
|
||||||
|
if ! command -v xargs >/dev/null 2>&1
|
||||||
|
then
|
||||||
|
die "xargs is not available"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Use "xargs" to parse quoted args.
|
||||||
|
#
|
||||||
|
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||||
|
#
|
||||||
|
# In Bash we could simply go:
|
||||||
|
#
|
||||||
|
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||||
|
# set -- "${ARGS[@]}" "$@"
|
||||||
|
#
|
||||||
|
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||||
|
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||||
|
# character that might be a shell metacharacter, then use eval to reverse
|
||||||
|
# that process (while maintaining the separation between arguments), and wrap
|
||||||
|
# the whole thing up as a single "set" statement.
|
||||||
|
#
|
||||||
|
# This will of course break if any of these variables contains a newline or
|
||||||
|
# an unmatched quote.
|
||||||
|
#
|
||||||
|
|
||||||
|
eval "set -- $(
|
||||||
|
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||||
|
xargs -n1 |
|
||||||
|
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||||
|
tr '\n' ' '
|
||||||
|
)" '"$@"'
|
||||||
|
|
||||||
|
exec "$JAVACMD" "$@"
|
||||||
Vendored
+94
@@ -0,0 +1,94 @@
|
|||||||
|
@rem
|
||||||
|
@rem Copyright 2015 the original author or authors.
|
||||||
|
@rem
|
||||||
|
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@rem you may not use this file except in compliance with the License.
|
||||||
|
@rem You may obtain a copy of the License at
|
||||||
|
@rem
|
||||||
|
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@rem
|
||||||
|
@rem Unless required by applicable law or agreed to in writing, software
|
||||||
|
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@rem See the License for the specific language governing permissions and
|
||||||
|
@rem limitations under the License.
|
||||||
|
@rem
|
||||||
|
@rem SPDX-License-Identifier: Apache-2.0
|
||||||
|
@rem
|
||||||
|
|
||||||
|
@if "%DEBUG%"=="" @echo off
|
||||||
|
@rem ##########################################################################
|
||||||
|
@rem
|
||||||
|
@rem Gradle startup script for Windows
|
||||||
|
@rem
|
||||||
|
@rem ##########################################################################
|
||||||
|
|
||||||
|
@rem Set local scope for the variables with windows NT shell
|
||||||
|
if "%OS%"=="Windows_NT" setlocal
|
||||||
|
|
||||||
|
set DIRNAME=%~dp0
|
||||||
|
if "%DIRNAME%"=="" set DIRNAME=.
|
||||||
|
@rem This is normally unused
|
||||||
|
set APP_BASE_NAME=%~n0
|
||||||
|
set APP_HOME=%DIRNAME%
|
||||||
|
|
||||||
|
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||||
|
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||||
|
|
||||||
|
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||||
|
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||||
|
|
||||||
|
@rem Find java.exe
|
||||||
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
set JAVA_EXE=java.exe
|
||||||
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:findJavaFromJavaHome
|
||||||
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
|
echo. 1>&2
|
||||||
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
|
echo. 1>&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
|
goto fail
|
||||||
|
|
||||||
|
:execute
|
||||||
|
@rem Setup the command line
|
||||||
|
|
||||||
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
|
@rem Execute Gradle
|
||||||
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
|
:end
|
||||||
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||||
|
|
||||||
|
:fail
|
||||||
|
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||||
|
rem the _cmd.exe /c_ return code!
|
||||||
|
set EXIT_CODE=%ERRORLEVEL%
|
||||||
|
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||||
|
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||||
|
exit /b %EXIT_CODE%
|
||||||
|
|
||||||
|
:mainEnd
|
||||||
|
if "%OS%"=="Windows_NT" endlocal
|
||||||
|
|
||||||
|
:omega
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rootProject.name = 'LPX'
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package it.ytnoos.lpx;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.LPX;
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.config.ConfigFile;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.settings.PacketEventsSettings;
|
||||||
|
import it.ytnoos.lpx.utils.PacketExceptionHandler;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.plugin.java.JavaPlugin;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class LPXBootstrap extends JavaPlugin implements LPXPlugin {
|
||||||
|
|
||||||
|
private LPX lpx;
|
||||||
|
|
||||||
|
private FileConfiguration config;
|
||||||
|
|
||||||
|
private File file;
|
||||||
|
|
||||||
|
public void onLoad() {
|
||||||
|
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||||
|
PacketEvents.getAPI()
|
||||||
|
.getSettings()
|
||||||
|
.reEncodeByDefault(false)
|
||||||
|
.checkForUpdates(false)
|
||||||
|
.fullStackTrace(false)
|
||||||
|
.kickOnPacketException(true);
|
||||||
|
PacketEvents.getAPI().load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onEnable() {
|
||||||
|
FileConfiguration config2 = super.getConfig();
|
||||||
|
if (config2.getBoolean("options.external-config", false)) {
|
||||||
|
LPXBootstrap lPXBootstrap = this;
|
||||||
|
ConfigFile configFile = new ConfigFile(lPXBootstrap, (String) "config.yml");
|
||||||
|
this.config = configFile.getConfiguration();
|
||||||
|
this.file = configFile.getFile();
|
||||||
|
} else {
|
||||||
|
this.config = config2;
|
||||||
|
this.file = null;
|
||||||
|
}
|
||||||
|
LPXBootstrap lPXBootstrap2 = this;
|
||||||
|
LPXBukkit lPXBukkit = new LPXBukkit(lPXBootstrap2);
|
||||||
|
this.lpx = lPXBukkit;
|
||||||
|
PacketEventsSettings settings = PacketEvents.getAPI().getSettings();
|
||||||
|
PacketExceptionHandler packetExceptionHandler2 =
|
||||||
|
new PacketExceptionHandler((LPXBukkit) this.lpx);
|
||||||
|
settings.packetExceptionHandler(packetExceptionHandler2);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onDisable() {
|
||||||
|
PacketEvents.getAPI().getSettings().packetExceptionHandler(null);
|
||||||
|
if (this.lpx != null) {
|
||||||
|
this.lpx.disable(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public File getConfigFile() {
|
||||||
|
return this.file != null ? this.file : new File(this.getDataFolder(), "config.yml");
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileConfiguration getConfig() {
|
||||||
|
return this.config;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveConfig() {
|
||||||
|
if (this.file != null) {
|
||||||
|
try {
|
||||||
|
this.config.save(this.file);
|
||||||
|
} catch (IOException oException) {
|
||||||
|
oException.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
super.saveConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
if (super.getConfig().getBoolean("options.external-config", false)) {
|
||||||
|
LPXBootstrap lPXBootstrap = this;
|
||||||
|
ConfigFile configFile = new ConfigFile(lPXBootstrap, (String) "config.yml");
|
||||||
|
this.config = configFile.getConfiguration();
|
||||||
|
} else {
|
||||||
|
super.reloadConfig();
|
||||||
|
this.config = super.getConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,290 @@
|
|||||||
|
package it.ytnoos.lpx;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.activation.ActivationState;
|
||||||
|
import it.ytnoos.lpx.adapter.LegacyInventoryViewAdapter;
|
||||||
|
import it.ytnoos.lpx.adapter.ModernInventoryViewAdapter;
|
||||||
|
import it.ytnoos.lpx.alerts.AlertManager;
|
||||||
|
import it.ytnoos.lpx.alerts.ViolationRecord;
|
||||||
|
import it.ytnoos.lpx.api.LPX;
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.api.adapter.InventoryViewAdapter;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.CheckManager;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.api.protocol.PlayerRegistry;
|
||||||
|
import it.ytnoos.lpx.check.BukkitCheckManager;
|
||||||
|
import it.ytnoos.lpx.commands.LPXCommand;
|
||||||
|
import it.ytnoos.lpx.config.ConfigManager;
|
||||||
|
import it.ytnoos.lpx.config.GeneralOptions;
|
||||||
|
import it.ytnoos.lpx.inventories.MenuFactory;
|
||||||
|
import it.ytnoos.lpx.inventories.smartinvs.InventoryManager;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.EntityScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.player.PlayerManager;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.server.WrapperPlayServerDisconnect;
|
||||||
|
import it.ytnoos.lpx.logging.PacketLogger;
|
||||||
|
import it.ytnoos.lpx.netty.NettyHealthMonitor;
|
||||||
|
import it.ytnoos.lpx.netty.NettyWatchdog;
|
||||||
|
import it.ytnoos.lpx.player.PlayerRegistryImpl;
|
||||||
|
import it.ytnoos.lpx.utils.ColorUtils;
|
||||||
|
import it.ytnoos.lpx.utils.PacketUtils;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class LPXBukkit implements LPX {
|
||||||
|
|
||||||
|
private final LPXBootstrap plugin;
|
||||||
|
|
||||||
|
private final PlayerRegistry registry;
|
||||||
|
|
||||||
|
private final CheckManager checkManager;
|
||||||
|
|
||||||
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
|
private final InventoryManager inventoryManager;
|
||||||
|
|
||||||
|
private final MenuFactory menuFactory;
|
||||||
|
|
||||||
|
private final PacketLogger packetLogger;
|
||||||
|
|
||||||
|
private final AlertManager alertManager;
|
||||||
|
|
||||||
|
private final ArrayDeque<ViolationRecord> values;
|
||||||
|
|
||||||
|
private final NettyHealthMonitor nettyHealthMonitor;
|
||||||
|
|
||||||
|
private final NettyWatchdog nettyWatchdog;
|
||||||
|
|
||||||
|
private boolean updated = true;
|
||||||
|
|
||||||
|
private boolean disabled = false;
|
||||||
|
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
@Nullable private LPXCommand command;
|
||||||
|
|
||||||
|
public LPXBukkit(LPXBootstrap lPXBootstrap) {
|
||||||
|
this.plugin = lPXBootstrap;
|
||||||
|
ArrayDeque values2 = new ArrayDeque();
|
||||||
|
this.values = values2;
|
||||||
|
ConfigManager configManager2 = new ConfigManager(lPXBootstrap);
|
||||||
|
this.configManager = configManager2;
|
||||||
|
LPXBukkit lPXBukkit = this;
|
||||||
|
AlertManager alertManager2 = new AlertManager(lPXBukkit);
|
||||||
|
this.alertManager = alertManager2;
|
||||||
|
LPXBukkit lPXBukkit2 = this;
|
||||||
|
PlayerRegistryImpl playerRegistryImpl = new PlayerRegistryImpl(lPXBukkit2);
|
||||||
|
this.registry = playerRegistryImpl;
|
||||||
|
InventoryManager inventoryManager2 = new InventoryManager(this);
|
||||||
|
this.inventoryManager = inventoryManager2;
|
||||||
|
MenuFactory menuFactory2 = new MenuFactory(this);
|
||||||
|
this.menuFactory = menuFactory2;
|
||||||
|
LPXBukkit lPXBukkit3 = this;
|
||||||
|
PacketLogger packetLogger2 = new PacketLogger(lPXBukkit3);
|
||||||
|
this.packetLogger = packetLogger2;
|
||||||
|
BukkitCheckManager bukkitCheckManager = new BukkitCheckManager(this);
|
||||||
|
this.checkManager = bukkitCheckManager;
|
||||||
|
LPXBukkit lPXBukkit4 = this;
|
||||||
|
NettyHealthMonitor nettyHealthMonitor2 = new NettyHealthMonitor(lPXBukkit4);
|
||||||
|
this.nettyHealthMonitor = nettyHealthMonitor2;
|
||||||
|
LPXBukkit lPXBukkit5 = this;
|
||||||
|
NettyWatchdog nettyWatchdog2 = new NettyWatchdog(lPXBukkit5);
|
||||||
|
this.nettyWatchdog = nettyWatchdog2;
|
||||||
|
PacketEvents.getAPI().init();
|
||||||
|
ActivationState.enable(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable(boolean matches) {
|
||||||
|
if (!this.disabled) {
|
||||||
|
this.disabled = true;
|
||||||
|
if (!matches) {
|
||||||
|
this.plugin.getServer().getPluginManager().disablePlugin(this.plugin);
|
||||||
|
}
|
||||||
|
if (this.registry != null) {
|
||||||
|
this.registry.uninjectAll();
|
||||||
|
}
|
||||||
|
if (this.packetLogger != null) {
|
||||||
|
this.packetLogger.shutdown();
|
||||||
|
}
|
||||||
|
if (this.nettyWatchdog != null) {
|
||||||
|
this.nettyWatchdog.shutdown();
|
||||||
|
}
|
||||||
|
this.nettyHealthMonitor.stop();
|
||||||
|
PacketEvents.getAPI().terminate();
|
||||||
|
this.alertManager.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reloadConfig() {
|
||||||
|
LPXBukkit lPXBukkit = this;
|
||||||
|
this.configManager.reload(lPXBukkit);
|
||||||
|
if (this.command != null) {
|
||||||
|
this.command.update();
|
||||||
|
if (PacketEvents.getAPI()
|
||||||
|
.getServerManager()
|
||||||
|
.getVersion()
|
||||||
|
.isNewerThanOrEquals(ServerVersion.V_1_13)) {
|
||||||
|
for (Player player : this.plugin.getServer().getOnlinePlayers()) {
|
||||||
|
EntityScheduler entityScheduler = FoliaScheduler.getEntityScheduler();
|
||||||
|
entityScheduler.run(
|
||||||
|
player, this.plugin, result -> player.updateCommands(), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LPXCommand getCommand() {
|
||||||
|
return this.command;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCommand(LPXCommand lPXCommand) {
|
||||||
|
this.command = lPXCommand;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryViewAdapter getInventoryViewAdapter(Player player) {
|
||||||
|
if (PacketEvents.getAPI()
|
||||||
|
.getServerManager()
|
||||||
|
.getVersion()
|
||||||
|
.isNewerThanOrEquals(ServerVersion.V_1_21)) {
|
||||||
|
return new LegacyInventoryViewAdapter(player);
|
||||||
|
} else {
|
||||||
|
return new ModernInventoryViewAdapter(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerListener(Listener listener) {
|
||||||
|
this.plugin.getServer().getPluginManager().registerEvents(listener, this.plugin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerListeners(Listener[] listeners) {
|
||||||
|
int value = listeners.length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
Listener listener = listeners[index];
|
||||||
|
this.registerListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServer() {
|
||||||
|
ConfigManager configManager2 = this.configManager;
|
||||||
|
GeneralOptions options = configManager2.getOptions();
|
||||||
|
return options.getServer();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LPXPlugin getPlugin() {
|
||||||
|
return this.plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlayerRegistry getRegistry() {
|
||||||
|
return this.registry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckManager getCheckManager() {
|
||||||
|
return this.checkManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConfigManager getConfigManager() {
|
||||||
|
return this.configManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AlertManager getAlertManager() {
|
||||||
|
return this.alertManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketLogger getPacketLogger() {
|
||||||
|
return this.packetLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isUpdated() {
|
||||||
|
return this.updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdated(boolean updated) {
|
||||||
|
this.updated = updated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public InventoryManager getInventoryManager() {
|
||||||
|
return this.inventoryManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MenuFactory getMenuFactory() {
|
||||||
|
return this.menuFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deque getValues() {
|
||||||
|
return this.values;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NettyHealthMonitor getNettyHealthMonitor() {
|
||||||
|
return this.nettyHealthMonitor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NettyWatchdog getNettyWatchdog() {
|
||||||
|
return this.nettyWatchdog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getFirstJoinTime() {
|
||||||
|
return this.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstJoinTime(long time) {
|
||||||
|
this.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean canPacketLogHeavy() {
|
||||||
|
return this.time != 0L && System.currentTimeMillis() - this.time > 5000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void kick(Player player2, String text) {
|
||||||
|
Optional<ProtocolPlayer> player3 = this.registry.getPlayer(player2);
|
||||||
|
player3.ifPresent(result -> result.kick(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void forceKick(ProtocolPlayer protocolPlayer, String text) {
|
||||||
|
User user = protocolPlayer.getUser();
|
||||||
|
Optional<Player> player = protocolPlayer.getPlayer();
|
||||||
|
player.ifPresent(
|
||||||
|
result -> {
|
||||||
|
PlayerManager name = PacketEvents.getAPI().getPlayerManager();
|
||||||
|
WrapperPlayServerDisconnect wrapperPlayServerDisconnect =
|
||||||
|
new WrapperPlayServerDisconnect(ColorUtils.deserialize(text));
|
||||||
|
name.sendPacket(result, wrapperPlayServerDisconnect);
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
if (user != null) {
|
||||||
|
Channel channel = (Channel) user.getChannel();
|
||||||
|
PacketUtils.handleChannel(channel);
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Logger logger = this.getLogger();
|
||||||
|
logger.log(
|
||||||
|
Level.SEVERE,
|
||||||
|
exception,
|
||||||
|
() -> {
|
||||||
|
String name = user.getName();
|
||||||
|
String text2 = name;
|
||||||
|
return (String) "Unable to force kick player " + text2;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void debug(Supplier supplier) {
|
||||||
|
ConfigManager configManager2 = this.configManager;
|
||||||
|
GeneralOptions options = configManager2.getOptions();
|
||||||
|
if (options.isDebug()) {
|
||||||
|
this.getLogger().info(supplier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,106 @@
|
|||||||
|
package it.ytnoos.lpx.activation;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.LPXBukkit;
|
||||||
|
import it.ytnoos.lpx.api.LPX;
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.api.metrics.MetricsLite;
|
||||||
|
import it.ytnoos.lpx.commands.LPXCommand;
|
||||||
|
import it.ytnoos.lpx.config.ConfigManager;
|
||||||
|
import it.ytnoos.lpx.config.GeneralOptions;
|
||||||
|
import it.ytnoos.lpx.inventories.smartinvs.InventoryManager;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.AsyncScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.EventManager;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.VersionComparison;
|
||||||
|
import it.ytnoos.lpx.listeners.CommandVisibilityListener;
|
||||||
|
import it.ytnoos.lpx.listeners.InventoryListener;
|
||||||
|
import it.ytnoos.lpx.listeners.PlayerLoginListener;
|
||||||
|
import it.ytnoos.lpx.listeners.PlayerStateListener;
|
||||||
|
import it.ytnoos.lpx.listeners.RedstoneListener;
|
||||||
|
import it.ytnoos.lpx.netty.PacketCheckListener;
|
||||||
|
import it.ytnoos.lpx.netty.PacketCheckProcessor;
|
||||||
|
import it.ytnoos.lpx.netty.PreViaPacketListener;
|
||||||
|
import it.ytnoos.lpx.scheduler.PlayerTickTask;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.event.Listener;
|
||||||
|
import org.bukkit.plugin.ServicePriority;
|
||||||
|
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
public class ActivationState {
|
||||||
|
|
||||||
|
private static boolean enabled;
|
||||||
|
|
||||||
|
private static final String TEXT = "LPX enabled!";
|
||||||
|
|
||||||
|
public static void enable(LPXBukkit lPXBukkit) {
|
||||||
|
if (!enabled) {
|
||||||
|
enabled = true;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
LPXPlugin plugin = lPXBukkit.getPlugin();
|
||||||
|
configManager.load(plugin);
|
||||||
|
lPXBukkit.getAlertManager().load();
|
||||||
|
lPXBukkit.getCheckManager().registerChecks();
|
||||||
|
InventoryManager inventoryManager = lPXBukkit.getInventoryManager();
|
||||||
|
inventoryManager.init();
|
||||||
|
Listener[] listeners = new Listener[2];
|
||||||
|
PlayerStateListener playerStateListener = new PlayerStateListener(lPXBukkit);
|
||||||
|
listeners[0] = playerStateListener;
|
||||||
|
InventoryListener inventoryListener = new InventoryListener(lPXBukkit);
|
||||||
|
listeners[1] = inventoryListener;
|
||||||
|
lPXBukkit.registerListeners(listeners);
|
||||||
|
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||||
|
if (version.is(VersionComparison.NEWER_THAN_OR_EQUALS, ServerVersion.V_1_13)
|
||||||
|
&& version.is(VersionComparison.OLDER_THAN, ServerVersion.V_1_19_4)) {
|
||||||
|
RedstoneListener redstoneListener = new RedstoneListener(lPXBukkit);
|
||||||
|
lPXBukkit.registerListener(redstoneListener);
|
||||||
|
}
|
||||||
|
if (version.is(VersionComparison.NEWER_THAN_OR_EQUALS, ServerVersion.V_1_13)) {
|
||||||
|
CommandVisibilityListener commandVisibilityListener =
|
||||||
|
new CommandVisibilityListener(lPXBukkit);
|
||||||
|
lPXBukkit.registerListener(commandVisibilityListener);
|
||||||
|
}
|
||||||
|
if (version.is(VersionComparison.OLDER_THAN_OR_EQUALS, ServerVersion.V_1_8_8)) {
|
||||||
|
PlayerLoginListener playerLoginListener = new PlayerLoginListener(lPXBukkit);
|
||||||
|
lPXBukkit.registerListener(playerLoginListener);
|
||||||
|
}
|
||||||
|
LPXCommand lPXCommand = new LPXCommand(lPXBukkit);
|
||||||
|
lPXBukkit.setCommand(lPXCommand);
|
||||||
|
configManager = lPXBukkit.getConfigManager();
|
||||||
|
GeneralOptions options = configManager.getOptions();
|
||||||
|
if (options.isEnabled8()) {
|
||||||
|
AsyncScheduler asyncScheduler = FoliaScheduler.getAsyncScheduler();
|
||||||
|
LPXPlugin plugin2 = lPXBukkit.getPlugin();
|
||||||
|
Consumer consumer =
|
||||||
|
result -> {
|
||||||
|
PlayerTickTask playerTickTask = new PlayerTickTask(lPXBukkit);
|
||||||
|
playerTickTask.run();
|
||||||
|
};
|
||||||
|
ConfigManager configManager2 = lPXBukkit.getConfigManager();
|
||||||
|
GeneralOptions options2 = configManager2.getOptions();
|
||||||
|
asyncScheduler.runAtFixedRate(plugin2, consumer, 1L, options2.getLimit() * 20L);
|
||||||
|
}
|
||||||
|
configManager = lPXBukkit.getConfigManager();
|
||||||
|
GeneralOptions options3 = configManager.getOptions();
|
||||||
|
if (options3.isBStats()) {
|
||||||
|
MetricsLite metricsLite = new MetricsLite(lPXBukkit.getPlugin());
|
||||||
|
}
|
||||||
|
lPXBukkit.getLogger().log(Level.INFO, TEXT);
|
||||||
|
PacketCheckProcessor packetCheckProcessor = new PacketCheckProcessor(lPXBukkit);
|
||||||
|
EventManager eventManager = PacketEvents.getAPI().getEventManager();
|
||||||
|
PreViaPacketListener preViaPacketListener =
|
||||||
|
new PreViaPacketListener(packetCheckProcessor);
|
||||||
|
eventManager.registerListener(preViaPacketListener);
|
||||||
|
EventManager eventManager2 = PacketEvents.getAPI().getEventManager();
|
||||||
|
PacketCheckListener packetCheckListener =
|
||||||
|
new PacketCheckListener(lPXBukkit, packetCheckProcessor);
|
||||||
|
eventManager2.registerListener(packetCheckListener);
|
||||||
|
Bukkit.getServicesManager()
|
||||||
|
.register(LPX.class, lPXBukkit, lPXBukkit.getPlugin(), ServicePriority.Normal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package it.ytnoos.lpx.adapter;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.adapter.InventoryViewAdapter;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
|
||||||
|
public class LegacyInventoryViewAdapter implements InventoryViewAdapter {
|
||||||
|
|
||||||
|
private final InventoryView inventoryView;
|
||||||
|
|
||||||
|
public LegacyInventoryViewAdapter(Player player) {
|
||||||
|
this.inventoryView = player.getOpenInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNull() {
|
||||||
|
return this.inventoryView == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return this.inventoryView.getType().name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getTopInventory() {
|
||||||
|
return this.inventoryView.getTopInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getBottomInventory() {
|
||||||
|
return this.inventoryView.getBottomInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countSlots() {
|
||||||
|
return this.inventoryView.countSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int convertSlot(int value) {
|
||||||
|
return this.inventoryView.convertSlot(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package it.ytnoos.lpx.adapter;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.adapter.InventoryViewAdapter;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
import org.bukkit.inventory.InventoryView;
|
||||||
|
|
||||||
|
public class ModernInventoryViewAdapter implements InventoryViewAdapter {
|
||||||
|
|
||||||
|
private final InventoryView inventoryView;
|
||||||
|
|
||||||
|
public ModernInventoryViewAdapter(Player player) {
|
||||||
|
this.inventoryView = player.getOpenInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isNull() {
|
||||||
|
return this.inventoryView == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return this.inventoryView.getType().name();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getTopInventory() {
|
||||||
|
return this.inventoryView.getTopInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Inventory getBottomInventory() {
|
||||||
|
return this.inventoryView.getBottomInventory();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int countSlots() {
|
||||||
|
return this.inventoryView.countSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int convertSlot(int value) {
|
||||||
|
return this.inventoryView.convertSlot(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,318 @@
|
|||||||
|
package it.ytnoos.lpx.alerts;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.LPXBukkit;
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.check.options.PersonalCheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.event.LPXAlertEvent;
|
||||||
|
import it.ytnoos.lpx.api.event.LPXPunishEvent;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.commands.KickCommand;
|
||||||
|
import it.ytnoos.lpx.config.AlertsOptions;
|
||||||
|
import it.ytnoos.lpx.config.ConfigManager;
|
||||||
|
import it.ytnoos.lpx.config.GeneralOptions;
|
||||||
|
import it.ytnoos.lpx.config.Messages;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.AsyncScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.GlobalRegionScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.VersionComparison;
|
||||||
|
import it.ytnoos.lpx.logging.FileLogger;
|
||||||
|
import it.ytnoos.lpx.utils.ColorUtils;
|
||||||
|
import it.ytnoos.lpx.utils.TimeUtils;
|
||||||
|
|
||||||
|
import net.md_5.bungee.api.chat.BaseComponent;
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent;
|
||||||
|
import net.md_5.bungee.api.chat.HoverEvent.Action;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.command.CommandSender;
|
||||||
|
import org.bukkit.command.ConsoleCommandSender;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.PluginManager;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Deque;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class AlertManager {
|
||||||
|
|
||||||
|
private final LPXBukkit lpx;
|
||||||
|
|
||||||
|
private final FileLogger fileLogger;
|
||||||
|
|
||||||
|
private final DiscordAlertHandler discord;
|
||||||
|
|
||||||
|
private final Set<UUID> values;
|
||||||
|
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
public AlertManager(LPXBukkit lPXBukkit) {
|
||||||
|
HashSet values2 = new HashSet();
|
||||||
|
this.values = values2;
|
||||||
|
this.time = 0L;
|
||||||
|
this.lpx = lPXBukkit;
|
||||||
|
FileLogger fileLogger2 = new FileLogger(lPXBukkit);
|
||||||
|
this.fileLogger = fileLogger2;
|
||||||
|
DiscordAlertHandler discordAlertHandler = new DiscordAlertHandler(lPXBukkit);
|
||||||
|
this.discord = discordAlertHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
this.fileLogger.load();
|
||||||
|
this.discord.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void disable() {
|
||||||
|
this.fileLogger.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void flag(ProtocolPlayer protocolPlayer, Check check, FlagInfo[] flagInfos) {
|
||||||
|
if (!protocolPlayer.isKicked()) {
|
||||||
|
this.fileLogger.writeFlag(protocolPlayer, check, flagInfos);
|
||||||
|
LPXBukkit lPXBukkit = this.lpx;
|
||||||
|
if (lPXBukkit.getValues().size() >= 360) {
|
||||||
|
lPXBukkit = this.lpx;
|
||||||
|
lPXBukkit.getValues().removeLast();
|
||||||
|
}
|
||||||
|
lPXBukkit = this.lpx;
|
||||||
|
Deque values2 = lPXBukkit.getValues();
|
||||||
|
String username = protocolPlayer.getUsername();
|
||||||
|
PersonalCheckOptions options = check.getOptions();
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
ViolationRecord violationRecord =
|
||||||
|
new ViolationRecord(username, options, now, flagInfos);
|
||||||
|
values2.addFirst(violationRecord);
|
||||||
|
Runnable runnable =
|
||||||
|
() -> {
|
||||||
|
PluginManager pluginManager = Bukkit.getPluginManager();
|
||||||
|
LPXAlertEvent result = new LPXAlertEvent(protocolPlayer, check, flagInfos);
|
||||||
|
pluginManager.callEvent(result);
|
||||||
|
};
|
||||||
|
this.callEvent(runnable);
|
||||||
|
int minVl = check.getOptions().getCheckOptions().getMinVl();
|
||||||
|
if (minVl != -1 && check.getOptions().getVl() >= minVl) {
|
||||||
|
lPXBukkit = this.lpx;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
Messages messages = configManager.getMessages();
|
||||||
|
AlertsOptions alertsOptions = messages.getAlertsOptions();
|
||||||
|
String format = alertsOptions.getFormat();
|
||||||
|
String text = this.replace(format, protocolPlayer, check, flagInfos);
|
||||||
|
Logger logger = this.lpx.getLogger();
|
||||||
|
logger.log(Level.INFO, ColorUtils.createText(text));
|
||||||
|
long lastPunish = protocolPlayer.getLastPunish();
|
||||||
|
Long value = ((Long) lastPunish);
|
||||||
|
long value2 = TimeUtils.calculateTime(value);
|
||||||
|
LPXBukkit lPXBukkit2 = this.lpx;
|
||||||
|
ConfigManager configManager2 = lPXBukkit2.getConfigManager();
|
||||||
|
GeneralOptions options2 = configManager2.getOptions();
|
||||||
|
if (value2 >= options2.getLimit6()) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
int value3 = 0;
|
||||||
|
while (true) {
|
||||||
|
if (value3 >= alertsOptions.getHover().size()) {
|
||||||
|
Action action = Action.SHOW_TEXT;
|
||||||
|
String text2 = stringBuilder.toString();
|
||||||
|
HoverEvent hoverEvent =
|
||||||
|
new HoverEvent(action, ColorUtils.createBaseComponents(text2));
|
||||||
|
BaseComponent[] baseComponents = ColorUtils.createBaseComponents(text);
|
||||||
|
int value4 = baseComponents.length;
|
||||||
|
for (int index = 0; index < value4; index++) {
|
||||||
|
baseComponents[index].setHoverEvent(hoverEvent);
|
||||||
|
}
|
||||||
|
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||||
|
onlinePlayers.forEach(
|
||||||
|
result -> {
|
||||||
|
Object[] result3 = new Object[0];
|
||||||
|
if (result.hasPermission(alertsOptions.getPermission())
|
||||||
|
&& !this.values.contains(result.getUniqueId())) {
|
||||||
|
result.getPlayer().spigot().sendMessage(baseComponents);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AsyncScheduler asyncScheduler = FoliaScheduler.getAsyncScheduler();
|
||||||
|
LPXPlugin plugin = this.lpx.getPlugin();
|
||||||
|
asyncScheduler.runNow(
|
||||||
|
plugin,
|
||||||
|
result2 -> {
|
||||||
|
Check result3 = check;
|
||||||
|
Check check2 = result3;
|
||||||
|
this.discord.handleFlagInfos(
|
||||||
|
protocolPlayer, check2, flagInfos);
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
String text3 = (String) alertsOptions.getHover().get(value3);
|
||||||
|
stringBuilder.append(this.replace(text3, protocolPlayer, check, flagInfos));
|
||||||
|
if (value3 != alertsOptions.getHover().size() - 1) {
|
||||||
|
stringBuilder.append('\n');
|
||||||
|
}
|
||||||
|
value3++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void punish(ProtocolPlayer protocolPlayer, Check check) {
|
||||||
|
long lastPunish = protocolPlayer.getLastPunish();
|
||||||
|
Long value = ((Long) lastPunish);
|
||||||
|
long value2 = TimeUtils.calculateTime(value);
|
||||||
|
LPXBukkit lPXBukkit = this.lpx;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
GeneralOptions options = configManager.getOptions();
|
||||||
|
if (value2 >= options.getLimit6()) {
|
||||||
|
Runnable runnable =
|
||||||
|
() -> {
|
||||||
|
PluginManager player = Bukkit.getPluginManager();
|
||||||
|
LPXPunishEvent lPXPunishEvent = new LPXPunishEvent(protocolPlayer, check);
|
||||||
|
player.callEvent(lPXPunishEvent);
|
||||||
|
};
|
||||||
|
this.callEvent(runnable);
|
||||||
|
protocolPlayer.updateLastPunish();
|
||||||
|
for (String text : check.getOptions().getCheckOptions().getPunishCommands()) {
|
||||||
|
String text2 = text;
|
||||||
|
String text3 = this.createText(text2, protocolPlayer);
|
||||||
|
text = text3;
|
||||||
|
if (text3.startsWith("lpx kick")) {
|
||||||
|
LPXBukkit lPXBukkit2 = this.lpx;
|
||||||
|
ConsoleCommandSender consoleSender = Bukkit.getConsoleSender();
|
||||||
|
String[] texts = text.substring(4).split(" ");
|
||||||
|
CommandSender sender = (CommandSender) consoleSender;
|
||||||
|
KickCommand.runCommand(lPXBukkit2, sender, texts);
|
||||||
|
} else {
|
||||||
|
String text4 = text;
|
||||||
|
GlobalRegionScheduler globalRegionScheduler =
|
||||||
|
FoliaScheduler.getGlobalRegionScheduler();
|
||||||
|
LPXPlugin plugin = this.lpx.getPlugin();
|
||||||
|
globalRegionScheduler.execute(
|
||||||
|
plugin, () -> Bukkit.dispatchCommand(Bukkit.getConsoleSender(), text4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||||
|
onlinePlayers.forEach(
|
||||||
|
result -> {
|
||||||
|
LPXBukkit lPXBukkit3 = this.lpx;
|
||||||
|
ConfigManager configManager2 = lPXBukkit3.getConfigManager();
|
||||||
|
Messages messages = configManager2.getMessages();
|
||||||
|
AlertsOptions alertsOptions = messages.getAlertsOptions();
|
||||||
|
if (result.hasPermission(alertsOptions.getPermission())
|
||||||
|
&& !this.values.contains(result.getUniqueId())) {
|
||||||
|
Player player = result.getPlayer();
|
||||||
|
LPXBukkit lPXBukkit4 = this.lpx;
|
||||||
|
ConfigManager configManager3 = lPXBukkit4.getConfigManager();
|
||||||
|
Messages messages2 = configManager3.getMessages();
|
||||||
|
String text5 = messages2.getText();
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[0];
|
||||||
|
String text6 = this.replace(text5, protocolPlayer, check, flagInfos);
|
||||||
|
Player player2 = player;
|
||||||
|
player = player2;
|
||||||
|
Player player3 = player;
|
||||||
|
ColorUtils.handleText(player3, text6);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String replace(
|
||||||
|
String text, ProtocolPlayer protocolPlayer, Check check, FlagInfo[] flagInfos) {
|
||||||
|
String text2 = this.createText(text);
|
||||||
|
String text3 = this.createText(text2, protocolPlayer);
|
||||||
|
String text4 = text3;
|
||||||
|
text3 = text4;
|
||||||
|
String text5 = text3;
|
||||||
|
return this.createText(text5, check, flagInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String createText(String text, ProtocolPlayer protocolPlayer) {
|
||||||
|
return text.replace("%player%", protocolPlayer.getUsername())
|
||||||
|
.replace("%uuid%", protocolPlayer.getUniqueId().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createText(String text, Check check, FlagInfo[] flagInfos) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder(flagInfos.length == 0 ? ":(" : "\n");
|
||||||
|
int value = flagInfos.length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
FlagInfo flagInfo = flagInfos[index];
|
||||||
|
LPXBukkit lPXBukkit = this.lpx;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
Messages messages = configManager.getMessages();
|
||||||
|
StringBuilder stringBuilder2 =
|
||||||
|
stringBuilder
|
||||||
|
.append(messages.getSecondColor())
|
||||||
|
.append(flagInfo.getName())
|
||||||
|
.append(": ")
|
||||||
|
.append(ChatColor.GRAY);
|
||||||
|
String text2 = String.valueOf(flagInfo.getValue());
|
||||||
|
stringBuilder2.append(ColorUtils.escapeTags(text2)).append('\n');
|
||||||
|
}
|
||||||
|
return text.replace("%check%", check.getType().getCategory().getFormattedName())
|
||||||
|
.replace("%type%", check.getType().getId().name())
|
||||||
|
.replace("%vl%", check.getOptions().getVl() + "")
|
||||||
|
.replace("%infos%", stringBuilder.toString())
|
||||||
|
.replace("%description%", check.getType().getDescription())
|
||||||
|
.replace("%max-vl%", check.getOptions().getCheckOptions().getMaxVL() + "");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void callEvent(Runnable runnable) {
|
||||||
|
if (PacketEvents.getAPI()
|
||||||
|
.getServerManager()
|
||||||
|
.getVersion()
|
||||||
|
.is(VersionComparison.NEWER_THAN_OR_EQUALS, ServerVersion.V_1_13)) {
|
||||||
|
FoliaScheduler.getGlobalRegionScheduler().execute(this.lpx.getPlugin(), runnable);
|
||||||
|
} else {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createText(String text) {
|
||||||
|
return text.replace("%server%", this.lpx.getServer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPermissionAlert(String text, String text2) {
|
||||||
|
Collection<? extends Player> onlinePlayers = Bukkit.getOnlinePlayers();
|
||||||
|
onlinePlayers.forEach(
|
||||||
|
result -> {
|
||||||
|
if (result.hasPermission(text2)
|
||||||
|
&& !this.values.contains(result.getUniqueId())) {
|
||||||
|
Player player = ((Player) result);
|
||||||
|
ColorUtils.handleText(player, text);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Logger logger = this.lpx.getLogger();
|
||||||
|
logger.log(Level.INFO, ColorUtils.createText(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean testPlayer(Player player) {
|
||||||
|
UUID uniqueId = player.getUniqueId();
|
||||||
|
if (this.values.contains(uniqueId)) {
|
||||||
|
this.values.remove(uniqueId);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
this.values.add(uniqueId);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleValue(Object result) {
|
||||||
|
this.values.remove(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
this.discord.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileLogger getFileLogger() {
|
||||||
|
return this.fileLogger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UUID> getValues() {
|
||||||
|
return this.values;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
package it.ytnoos.lpx.alerts;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.LPXBukkit;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.config.ConfigManager;
|
||||||
|
import it.ytnoos.lpx.config.DiscordOptions;
|
||||||
|
import it.ytnoos.lpx.utils.DiscordWebhook;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class DiscordAlertHandler {
|
||||||
|
|
||||||
|
private static final Logger log = LogManager.getLogger(DiscordAlertHandler.class);
|
||||||
|
|
||||||
|
private static final Pattern PATTERN =
|
||||||
|
Pattern.compile(
|
||||||
|
"(?:https?://)?(?:\\w+\\.)?\\w+\\.\\w+/api(?:/v\\d+)?/webhooks/(\\d+)/([\\w-]+)(?:/(?:\\w+)?)?");
|
||||||
|
|
||||||
|
private final LPXBukkit lpx;
|
||||||
|
|
||||||
|
private Color color;
|
||||||
|
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
public DiscordAlertHandler(LPXBukkit lPXBukkit) {
|
||||||
|
this.lpx = lPXBukkit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void load() {
|
||||||
|
LPXBukkit lPXBukkit = this.lpx;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
DiscordOptions discord = configManager.getDiscord();
|
||||||
|
if (discord.isEnabled()) {
|
||||||
|
String url2 = discord.getUrl();
|
||||||
|
if (url2 != null && !url2.isEmpty()) {
|
||||||
|
if (!PATTERN.matcher(url2).matches()) {
|
||||||
|
IllegalArgumentException illegalArgumentException =
|
||||||
|
new IllegalArgumentException(
|
||||||
|
(String) "Webhook URL is not valid! " + url2);
|
||||||
|
throw illegalArgumentException;
|
||||||
|
}
|
||||||
|
this.color = Color.decode(discord.getColor());
|
||||||
|
this.url = url2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleFlagInfos(ProtocolPlayer protocolPlayer, Check check, FlagInfo[] flagInfos) {
|
||||||
|
if (this.url != null) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
LPXBukkit lPXBukkit = this.lpx;
|
||||||
|
ConfigManager configManager = lPXBukkit.getConfigManager();
|
||||||
|
DiscordOptions discord = configManager.getDiscord();
|
||||||
|
for (String text : (Iterable<String>) ((Iterable) discord.getContent())) {
|
||||||
|
stringBuilder.append(text).append("\n");
|
||||||
|
}
|
||||||
|
lPXBukkit = this.lpx;
|
||||||
|
AlertManager alertManager = lPXBukkit.getAlertManager();
|
||||||
|
String text2 = stringBuilder.toString();
|
||||||
|
String text3 =
|
||||||
|
alertManager
|
||||||
|
.replace(text2, protocolPlayer, check, flagInfos)
|
||||||
|
.replaceAll("§[a-zA-Z0-9]", "")
|
||||||
|
.replace("_", "\\_");
|
||||||
|
DiscordWebhook discordWebhook = new DiscordWebhook(this.url);
|
||||||
|
DiscordWebhook.EmbedObject embedObject = new DiscordWebhook.EmbedObject();
|
||||||
|
DiscordWebhook.EmbedObject embedObject2 =
|
||||||
|
embedObject.setImage((String) "https://i.stack.imgur.com/Fzh0w.png");
|
||||||
|
String username = protocolPlayer.getUsername();
|
||||||
|
String text4 = (String) "https://crafthead.net/helm/" + username;
|
||||||
|
DiscordWebhook.EmbedObject embedObject3 = embedObject2.setThumbnail(text4);
|
||||||
|
Color color2 = this.color;
|
||||||
|
DiscordWebhook.EmbedObject embedObject4 = embedObject3.setColor(color2);
|
||||||
|
DiscordWebhook.EmbedObject embedObject5 = embedObject4.setTitle((String) "**LPX**");
|
||||||
|
DiscordWebhook.EmbedObject embedObject6 = embedObject5.setDescription(text3);
|
||||||
|
Instant instant = Instant.now();
|
||||||
|
DiscordWebhook.EmbedObject embedObject7 = embedObject6.setTimestamp(instant);
|
||||||
|
discordWebhook.addEmbed(embedObject7);
|
||||||
|
try {
|
||||||
|
discordWebhook.execute();
|
||||||
|
} catch (IOException oException) {
|
||||||
|
if (oException.getMessage() == null || !oException.getMessage().contains("429")) {
|
||||||
|
java.util.logging.Logger logger = this.lpx.getLogger();
|
||||||
|
Level level = Level.WARNING;
|
||||||
|
String message = oException.getMessage();
|
||||||
|
String json = discordWebhook.getJson();
|
||||||
|
logger.log(
|
||||||
|
level,
|
||||||
|
(String) "Unable to send alert to Discord due to IOException: "
|
||||||
|
+ message
|
||||||
|
+ (String) ", Payload: "
|
||||||
|
+ json,
|
||||||
|
oException);
|
||||||
|
}
|
||||||
|
} catch (IllegalArgumentException illegalArgumentException) {
|
||||||
|
java.util.logging.Logger logger2 = this.lpx.getLogger();
|
||||||
|
Level level2 = Level.WARNING;
|
||||||
|
String message2 = illegalArgumentException.getMessage();
|
||||||
|
String json2 = discordWebhook.getJson();
|
||||||
|
logger2.log(
|
||||||
|
level2,
|
||||||
|
(String) "Unable to send alert to Discord: "
|
||||||
|
+ message2
|
||||||
|
+ (String) ", Payload: "
|
||||||
|
+ json2,
|
||||||
|
illegalArgumentException);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
java.util.logging.Logger logger3 = this.lpx.getLogger();
|
||||||
|
Level level3 = Level.WARNING;
|
||||||
|
String json3 = discordWebhook.getJson();
|
||||||
|
logger3.log(
|
||||||
|
level3,
|
||||||
|
(String) "An unexpected error occurred while trying to send Discord alert: "
|
||||||
|
+ json3,
|
||||||
|
exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package it.ytnoos.lpx.alerts;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.PersonalCheckOptions;
|
||||||
|
|
||||||
|
public class ViolationRecord {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final PersonalCheckOptions checkOptions;
|
||||||
|
|
||||||
|
private final long timestamp;
|
||||||
|
|
||||||
|
private final FlagInfo[] info;
|
||||||
|
|
||||||
|
public ViolationRecord(
|
||||||
|
String name,
|
||||||
|
PersonalCheckOptions personalCheckOptions,
|
||||||
|
long timestamp,
|
||||||
|
FlagInfo[] flagInfos) {
|
||||||
|
this.name = name;
|
||||||
|
this.checkOptions = personalCheckOptions;
|
||||||
|
this.timestamp = timestamp;
|
||||||
|
this.info = flagInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonalCheckOptions getCheckOptions() {
|
||||||
|
return this.checkOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getTimestamp() {
|
||||||
|
return this.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlagInfo[] getInfo() {
|
||||||
|
return this.info;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package it.ytnoos.lpx.api;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.adapter.InventoryViewAdapter;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.CheckManager;
|
||||||
|
import it.ytnoos.lpx.api.protocol.PlayerRegistry;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public interface LPX {
|
||||||
|
|
||||||
|
String getServer();
|
||||||
|
|
||||||
|
LPXPlugin getPlugin();
|
||||||
|
|
||||||
|
PlayerRegistry getRegistry();
|
||||||
|
|
||||||
|
CheckManager getCheckManager();
|
||||||
|
|
||||||
|
void disable(boolean matches);
|
||||||
|
|
||||||
|
void reloadConfig();
|
||||||
|
|
||||||
|
default Logger getLogger() {
|
||||||
|
return this.getPlugin().getLogger();
|
||||||
|
}
|
||||||
|
|
||||||
|
InventoryViewAdapter getInventoryViewAdapter(Player player);
|
||||||
|
|
||||||
|
boolean isUpdated();
|
||||||
|
|
||||||
|
void setUpdated(boolean matches);
|
||||||
|
|
||||||
|
long getFirstJoinTime();
|
||||||
|
|
||||||
|
void setFirstJoinTime(long value);
|
||||||
|
|
||||||
|
boolean canPacketLogHeavy();
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package it.ytnoos.lpx.api;
|
||||||
|
|
||||||
|
import org.bukkit.Server;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public interface LPXPlugin extends Plugin {
|
||||||
|
|
||||||
|
Logger getLogger();
|
||||||
|
|
||||||
|
File getDataFolder();
|
||||||
|
|
||||||
|
File getConfigFile();
|
||||||
|
|
||||||
|
InputStream getResource(String text);
|
||||||
|
|
||||||
|
PluginDescriptionFile getDescription();
|
||||||
|
|
||||||
|
Server getServer();
|
||||||
|
|
||||||
|
FileConfiguration getConfig();
|
||||||
|
|
||||||
|
void reload();
|
||||||
|
|
||||||
|
void saveDefaultConfig();
|
||||||
|
|
||||||
|
void saveConfig();
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package it.ytnoos.lpx.api.adapter;
|
||||||
|
|
||||||
|
import org.bukkit.inventory.Inventory;
|
||||||
|
|
||||||
|
public interface InventoryViewAdapter {
|
||||||
|
|
||||||
|
boolean isNull();
|
||||||
|
|
||||||
|
String getType();
|
||||||
|
|
||||||
|
Inventory getTopInventory();
|
||||||
|
|
||||||
|
Inventory getBottomInventory();
|
||||||
|
|
||||||
|
int countSlots();
|
||||||
|
|
||||||
|
int convertSlot(int value);
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
public enum CheckResult {
|
||||||
|
ALLOW,
|
||||||
|
CHANGE,
|
||||||
|
DENY;
|
||||||
|
|
||||||
|
public static CheckResult merge(CheckResult checkResult, CheckResult checkResult2) {
|
||||||
|
if (checkResult == DENY || checkResult2 == DENY) {
|
||||||
|
return DENY;
|
||||||
|
} else {
|
||||||
|
return checkResult != CHANGE && checkResult2 != CHANGE ? ALLOW : CHANGE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult merge(CheckResult checkResult) {
|
||||||
|
return merge(this, checkResult);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
|
||||||
|
import org.jspecify.annotations.Nullable;
|
||||||
|
|
||||||
|
public class CheckResultInfo {
|
||||||
|
|
||||||
|
private final CheckResult result;
|
||||||
|
|
||||||
|
@Nullable private final Check<?> lastCheck;
|
||||||
|
|
||||||
|
public CheckResultInfo(CheckResult checkResult, @Nullable Check<?> check) {
|
||||||
|
this.result = checkResult;
|
||||||
|
this.lastCheck = check;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResultInfo(CheckResult checkResult) {
|
||||||
|
this(checkResult, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult result() {
|
||||||
|
return this.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResultInfo result(CheckResult checkResult) {
|
||||||
|
return new CheckResultInfo(checkResult, this.lastCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Check<?> lastCheck() {
|
||||||
|
return this.lastCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResultInfo lastCheck(@Nullable Check<?> check) {
|
||||||
|
return new CheckResultInfo(this.result, check);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
public class FlagInfo {
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private final Object value;
|
||||||
|
|
||||||
|
public FlagInfo(String name, Object value) {
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static FlagInfo of(String text, Object result) {
|
||||||
|
return new FlagInfo(text, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.name + "=" + this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
public class IntervalCounter {
|
||||||
|
|
||||||
|
protected final long maxCounter;
|
||||||
|
|
||||||
|
protected final long interval;
|
||||||
|
|
||||||
|
protected double counter;
|
||||||
|
|
||||||
|
protected long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
|
protected long lastFlag = 0L;
|
||||||
|
|
||||||
|
public IntervalCounter(long maxCounter) {
|
||||||
|
this.maxCounter = maxCounter;
|
||||||
|
this.interval = 1000L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IntervalCounter(long maxCounter, long interval) {
|
||||||
|
this.maxCounter = maxCounter;
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean increment() {
|
||||||
|
return this.increment(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean increment(double counter) {
|
||||||
|
if (this.maxCounter < 0L) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (System.currentTimeMillis() - this.startTime >= this.interval) {
|
||||||
|
this.reset();
|
||||||
|
}
|
||||||
|
this.counter += counter;
|
||||||
|
if (this.counter > this.maxCounter) {
|
||||||
|
this.lastFlag = System.currentTimeMillis();
|
||||||
|
this.reset();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void reset() {
|
||||||
|
this.counter = 0.0;
|
||||||
|
this.startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInterval() {
|
||||||
|
return this.interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getMaxCounter() {
|
||||||
|
return this.maxCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getStartTime() {
|
||||||
|
return this.startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFlaggedRecently() {
|
||||||
|
return this.hasFlaggedRecently(this.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFlaggedRecently(long value) {
|
||||||
|
return System.currentTimeMillis() - this.lastFlag < value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.CheckFunction;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
|
||||||
|
public class RegisteredCheck<T> {
|
||||||
|
|
||||||
|
private final CheckType type;
|
||||||
|
|
||||||
|
private final CheckOptions options;
|
||||||
|
|
||||||
|
private final CheckFunction function;
|
||||||
|
|
||||||
|
public RegisteredCheck(
|
||||||
|
CheckType checkType, CheckOptions checkOptions, CheckFunction checkFunction) {
|
||||||
|
this.type = checkType;
|
||||||
|
this.options = checkOptions;
|
||||||
|
this.function = checkFunction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckType getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckOptions getOptions() {
|
||||||
|
return this.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckFunction getFunction() {
|
||||||
|
return this.function;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
public class RepeatedIntervalCounter extends IntervalCounter {
|
||||||
|
|
||||||
|
private final int maxWarnings;
|
||||||
|
|
||||||
|
private final boolean[] periodWarnings;
|
||||||
|
|
||||||
|
private int period;
|
||||||
|
|
||||||
|
public RepeatedIntervalCounter(int value, int value2, int value3, int maxWarnings) {
|
||||||
|
super(value, value2);
|
||||||
|
this.maxWarnings = maxWarnings;
|
||||||
|
this.periodWarnings = new boolean[value3];
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepeatedIntervalCounter(int value, int value2, int value3) {
|
||||||
|
this(value, 616907311, value2, value3);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean increment(double counter) {
|
||||||
|
if (this.maxCounter < 0L) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean matches = this.advancePeriodsIfNeeded(System.currentTimeMillis());
|
||||||
|
this.counter += counter;
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOverLimit() {
|
||||||
|
if (this.maxCounter < 0L) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.advancePeriodsIfNeeded(System.currentTimeMillis());
|
||||||
|
return this.counter > this.maxCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getValue() {
|
||||||
|
this.advancePeriodsIfNeeded(System.currentTimeMillis());
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean advancePeriods(int value) {
|
||||||
|
if (value >= this.periodWarnings.length) {
|
||||||
|
this.resetWarnings();
|
||||||
|
this.period = 0;
|
||||||
|
this.counter = 0.0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
if (this.counter > this.maxCounter) {
|
||||||
|
this.periodWarnings[this.period] = true;
|
||||||
|
}
|
||||||
|
this.period++;
|
||||||
|
if (this.period > this.periodWarnings.length - 1) {
|
||||||
|
this.period = 0;
|
||||||
|
}
|
||||||
|
this.periodWarnings[this.period] = false;
|
||||||
|
this.counter = 0.0;
|
||||||
|
}
|
||||||
|
if (this.countWarnings() >= this.maxWarnings) {
|
||||||
|
this.resetWarnings();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPeriod() {
|
||||||
|
return this.period;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWarnings() {
|
||||||
|
this.advancePeriodsIfNeeded(System.currentTimeMillis());
|
||||||
|
return this.countWarnings();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxPeriods() {
|
||||||
|
return this.periodWarnings.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxWarnings() {
|
||||||
|
return this.maxWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetWarnings() {
|
||||||
|
Arrays.fill(this.periodWarnings, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean advancePeriodsIfNeeded(long value) {
|
||||||
|
long value2;
|
||||||
|
if ((value2 = value - this.startTime) < this.interval) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
int value3 = (int) (value2 / this.interval);
|
||||||
|
boolean matches = this.advancePeriods(value3);
|
||||||
|
this.startTime = this.startTime + value3 * this.interval;
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int countWarnings() {
|
||||||
|
int value = 0;
|
||||||
|
boolean[] matchess = this.periodWarnings;
|
||||||
|
int value2 = this.periodWarnings.length;
|
||||||
|
for (int index = 0; index < value2; index++) {
|
||||||
|
if (matchess[index]) {
|
||||||
|
value++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package it.ytnoos.lpx.api.check;
|
||||||
|
|
||||||
|
public final class RollingIntervalCounter {
|
||||||
|
|
||||||
|
private final double maxCounter;
|
||||||
|
|
||||||
|
private final long interval;
|
||||||
|
|
||||||
|
private final long intervalNanos;
|
||||||
|
|
||||||
|
private long[] sampleTimes;
|
||||||
|
|
||||||
|
private double[] sampleValues;
|
||||||
|
|
||||||
|
private int headIndex;
|
||||||
|
|
||||||
|
private int tailIndex;
|
||||||
|
|
||||||
|
private double counter;
|
||||||
|
|
||||||
|
private long lastFlag;
|
||||||
|
|
||||||
|
private boolean overLimit;
|
||||||
|
|
||||||
|
public RollingIntervalCounter(long value) {
|
||||||
|
this(value, 1000L);
|
||||||
|
}
|
||||||
|
|
||||||
|
public RollingIntervalCounter(long maxCounter, long interval) {
|
||||||
|
if (interval <= 0L) {
|
||||||
|
throw new IllegalArgumentException("interval must be positive");
|
||||||
|
}
|
||||||
|
this.maxCounter = maxCounter;
|
||||||
|
this.interval = interval;
|
||||||
|
this.intervalNanos = interval * 1000000L;
|
||||||
|
this.sampleTimes = new long[8];
|
||||||
|
this.sampleValues = new double[8];
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean increment() {
|
||||||
|
return this.increment(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean increment(double value) {
|
||||||
|
if (this.maxCounter < 0.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
long value2 = System.nanoTime();
|
||||||
|
this.evictExpired(value2);
|
||||||
|
this.addSample(value2, value);
|
||||||
|
boolean matches;
|
||||||
|
boolean matches2 = (matches = this.counter > this.maxCounter) && !this.overLimit;
|
||||||
|
this.overLimit = matches;
|
||||||
|
if (matches2) {
|
||||||
|
this.lastFlag = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
return matches2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOverLimit() {
|
||||||
|
if (this.maxCounter < 0.0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.evictExpired(System.nanoTime());
|
||||||
|
this.overLimit = this.counter > this.maxCounter;
|
||||||
|
return this.overLimit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getInterval() {
|
||||||
|
return this.interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getValue() {
|
||||||
|
this.evictExpired(System.nanoTime());
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getMaxCounter() {
|
||||||
|
return this.maxCounter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFlaggedRecently() {
|
||||||
|
return this.hasFlaggedRecently(this.interval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasFlaggedRecently(long value) {
|
||||||
|
return System.currentTimeMillis() - this.lastFlag < value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void evictExpired(long value) {
|
||||||
|
long value2 = value - this.intervalNanos;
|
||||||
|
while (this.headIndex != this.tailIndex && this.sampleTimes[this.headIndex] < value2) {
|
||||||
|
this.counter = this.counter - this.sampleValues[this.headIndex];
|
||||||
|
this.sampleValues[this.headIndex] = 0.0;
|
||||||
|
this.headIndex++;
|
||||||
|
if (this.headIndex >= this.sampleTimes.length) {
|
||||||
|
this.headIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.counter <= 0.0) {
|
||||||
|
this.counter = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addSample(long value, double counter) {
|
||||||
|
if (!(counter <= 0.0)) {
|
||||||
|
int value3;
|
||||||
|
if ((value3 = incrementIndex(this.tailIndex, this.sampleTimes.length))
|
||||||
|
== this.headIndex) {
|
||||||
|
this.resize();
|
||||||
|
value3 = incrementIndex(this.tailIndex, this.sampleTimes.length);
|
||||||
|
}
|
||||||
|
this.sampleTimes[this.tailIndex] = value;
|
||||||
|
this.sampleValues[this.tailIndex] = counter;
|
||||||
|
this.tailIndex = value3;
|
||||||
|
this.counter += counter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resize() {
|
||||||
|
int size2 = this.size();
|
||||||
|
int value;
|
||||||
|
long[] values = new long[value = this.sampleTimes.length * 2];
|
||||||
|
double[] values2 = new double[value];
|
||||||
|
for (int index = 0; index < size2; index++) {
|
||||||
|
int value2 = (this.headIndex + index) % this.sampleTimes.length;
|
||||||
|
values[index] = this.sampleTimes[value2];
|
||||||
|
values2[index] = this.sampleValues[value2];
|
||||||
|
}
|
||||||
|
this.sampleTimes = values;
|
||||||
|
this.sampleValues = values2;
|
||||||
|
this.headIndex = 0;
|
||||||
|
this.tailIndex = size2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int size() {
|
||||||
|
return this.tailIndex >= this.headIndex
|
||||||
|
? this.tailIndex - this.headIndex
|
||||||
|
: this.tailIndex + (this.sampleTimes.length - this.headIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int incrementIndex(int value, int value2) {
|
||||||
|
return value + 1 >= value2 ? 0 : value + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.abstraction;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.check.options.PersonalCheckOptions;
|
||||||
|
|
||||||
|
public interface Check<T> {
|
||||||
|
|
||||||
|
CheckType getType();
|
||||||
|
|
||||||
|
CheckResult handle(T t);
|
||||||
|
|
||||||
|
PersonalCheckOptions getOptions();
|
||||||
|
|
||||||
|
default void reload() {
|
||||||
|
this.reset();
|
||||||
|
this.loadOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isPreVia() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
void loadOptions();
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.abstraction;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
|
public interface CheckFunction extends BiFunction<ProtocolPlayer, CheckOptions, Check<?>> {}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.abstraction;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.api.check.RegisteredCheck;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.api.protocol.CheckContainer;
|
||||||
|
|
||||||
|
import java.util.Comparator;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public abstract class CheckManager {
|
||||||
|
|
||||||
|
public static final CheckContainer<?> EMPTY_CONTAINER = new CheckContainer();
|
||||||
|
|
||||||
|
private final LPXPlugin plugin;
|
||||||
|
|
||||||
|
private final Map<Object, List<RegisteredCheck<?>>> checks = Maps.newHashMap();
|
||||||
|
|
||||||
|
public CheckManager(LPXPlugin lPXPlugin) {
|
||||||
|
this.plugin = lPXPlugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void register(Object result, CheckFunction checkFunction, CheckType checkType) {
|
||||||
|
this.checks
|
||||||
|
.computeIfAbsent(result, result2 -> Lists.newArrayList())
|
||||||
|
.add(
|
||||||
|
new RegisteredCheck(
|
||||||
|
checkType,
|
||||||
|
new CheckOptions(this.plugin, checkType),
|
||||||
|
checkFunction));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sortByPriority() {
|
||||||
|
Iterator<List<RegisteredCheck<?>>> iterator2 = this.checks.values().iterator();
|
||||||
|
while (iterator2.hasNext()) {
|
||||||
|
((List) iterator2.next())
|
||||||
|
.sort(
|
||||||
|
Comparator.comparingInt(
|
||||||
|
(RegisteredCheck<?> registeredCheck) ->
|
||||||
|
registeredCheck.getType().getPriority()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Object, CheckContainer<?>> createPlayerChecks(ProtocolPlayer protocolPlayer) {
|
||||||
|
HashMap<Object, CheckContainer<?>> entries = Maps.newHashMap();
|
||||||
|
this.checks.forEach(
|
||||||
|
(result, result2) -> {
|
||||||
|
CheckContainer checkContainer = new CheckContainer();
|
||||||
|
for (RegisteredCheck registeredCheck :
|
||||||
|
(Iterable<RegisteredCheck>) ((Iterable) result2)) {
|
||||||
|
checkContainer.add(
|
||||||
|
registeredCheck
|
||||||
|
.getFunction()
|
||||||
|
.apply(protocolPlayer, registeredCheck.getOptions()));
|
||||||
|
}
|
||||||
|
entries.put(result, checkContainer);
|
||||||
|
});
|
||||||
|
return entries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<Object, List<RegisteredCheck<?>>> getChecks() {
|
||||||
|
return this.checks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void registerChecks();
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.enums;
|
||||||
|
|
||||||
|
public enum CheckCategory {
|
||||||
|
NETTY("netty"),
|
||||||
|
WINDOW("window"),
|
||||||
|
ITEM("item"),
|
||||||
|
CREATIVE("creative"),
|
||||||
|
PLACE("place"),
|
||||||
|
FLOOD("flood"),
|
||||||
|
POSITION("position"),
|
||||||
|
PAYLOAD("payload"),
|
||||||
|
BOOK("book"),
|
||||||
|
TAB("tab"),
|
||||||
|
COMMAND("command"),
|
||||||
|
RECIPE("recipe");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
CheckCategory(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormattedName() {
|
||||||
|
return capitalise(this.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String capitalise(String text) {
|
||||||
|
if (text == null) {
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return text.isEmpty() ? "" : Character.toTitleCase(text.charAt(0)) + text.substring(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.enums;
|
||||||
|
|
||||||
|
public enum CheckID {
|
||||||
|
ZERO,
|
||||||
|
ONE,
|
||||||
|
TWO,
|
||||||
|
THREE,
|
||||||
|
A,
|
||||||
|
B,
|
||||||
|
C,
|
||||||
|
D,
|
||||||
|
E,
|
||||||
|
F,
|
||||||
|
G,
|
||||||
|
H,
|
||||||
|
I,
|
||||||
|
J,
|
||||||
|
K,
|
||||||
|
L
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.enums;
|
||||||
|
|
||||||
|
public enum CheckType {
|
||||||
|
NETTY_A(
|
||||||
|
CheckCategory.NETTY,
|
||||||
|
CheckID.A,
|
||||||
|
"Packet size pre via. (May false with big items on 1.13+, if so disable automatic mode and increase the max size)",
|
||||||
|
1),
|
||||||
|
NETTY_B(CheckCategory.NETTY, CheckID.B, "Packet exceeded decoding limits", 1),
|
||||||
|
NETTY_C(
|
||||||
|
CheckCategory.NETTY,
|
||||||
|
CheckID.A,
|
||||||
|
"Packet size post via. (May false with big items on 1.13+, if so disable automatic mode and increase the max size)",
|
||||||
|
1),
|
||||||
|
WINDOW_A(CheckCategory.WINDOW, CheckID.A, "Legacy max slot", 2),
|
||||||
|
WINDOW_B(CheckCategory.WINDOW, CheckID.B, "Modern max slot", 2),
|
||||||
|
WINDOW_C(CheckCategory.WINDOW, CheckID.C, "Inventory not open", 1),
|
||||||
|
WINDOW_D(CheckCategory.WINDOW, CheckID.D, "Lectern crash exploit", 3),
|
||||||
|
WINDOW_E(CheckCategory.WINDOW, CheckID.E, "Hashed click stack overload", 4),
|
||||||
|
ITEM_0(CheckCategory.ITEM, CheckID.ZERO, "HIDDEN", 1),
|
||||||
|
ITEM_1(CheckCategory.ITEM, CheckID.ONE, "HIDDEN", 1),
|
||||||
|
ITEM_2(CheckCategory.ITEM, CheckID.TWO, "HIDDEN", 1),
|
||||||
|
ITEM_3(CheckCategory.ITEM, CheckID.THREE, "HIDDEN", 1),
|
||||||
|
ITEM_A(CheckCategory.ITEM, CheckID.A, "HIDDEN", 2),
|
||||||
|
ITEM_B(CheckCategory.ITEM, CheckID.B, "HIDDEN", 3),
|
||||||
|
ITEM_C(CheckCategory.ITEM, CheckID.C, "HIDDEN", 4),
|
||||||
|
ITEM_D(CheckCategory.ITEM, CheckID.D, "HIDDEN", 5),
|
||||||
|
ITEM_E(CheckCategory.ITEM, CheckID.E, "HIDDEN", 6),
|
||||||
|
ITEM_F(CheckCategory.ITEM, CheckID.F, "HIDDEN", 7),
|
||||||
|
ITEM_G(CheckCategory.ITEM, CheckID.G, "HIDDEN", 8),
|
||||||
|
ITEM_H(CheckCategory.ITEM, CheckID.G, "HIDDEN", 9),
|
||||||
|
ITEM_J(CheckCategory.ITEM, CheckID.J, "HIDDEN", 11),
|
||||||
|
ITEM_K(CheckCategory.ITEM, CheckID.K, "HIDDEN", 12),
|
||||||
|
CREATIVE_A(CheckCategory.CREATIVE, CheckID.A, "Packet while not in creative", 1),
|
||||||
|
CREATIVE_B(CheckCategory.CREATIVE, CheckID.B, "Illegal enchanted item"),
|
||||||
|
CREATIVE_C(CheckCategory.CREATIVE, CheckID.C, "Long item name"),
|
||||||
|
CREATIVE_D(CheckCategory.CREATIVE, CheckID.D, "Long lore name"),
|
||||||
|
CREATIVE_E(CheckCategory.CREATIVE, CheckID.E, "Book with blacklisted words"),
|
||||||
|
CREATIVE_F(CheckCategory.CREATIVE, CheckID.F, "Illegal amount item"),
|
||||||
|
CREATIVE_G(CheckCategory.CREATIVE, CheckID.G, "Illegal BlockEntityTag key"),
|
||||||
|
CREATIVE_H(
|
||||||
|
CheckCategory.CREATIVE,
|
||||||
|
CheckID.H,
|
||||||
|
"Test instance block action while not in creative",
|
||||||
|
1),
|
||||||
|
CREATIVE_I(CheckCategory.CREATIVE, CheckID.I, "Set test block while not in creative", 1),
|
||||||
|
PLACE_A(CheckCategory.PLACE, CheckID.A, "Placed a block too far away"),
|
||||||
|
PLACE_B(CheckCategory.PLACE, CheckID.B, "Placed a sign with too long rows"),
|
||||||
|
PLACE_C(CheckCategory.PLACE, CheckID.C, "Digging too far away"),
|
||||||
|
FLOOD_A(
|
||||||
|
CheckCategory.FLOOD,
|
||||||
|
CheckID.A,
|
||||||
|
"Too many packets per second. (CAN FALSE DURING PLAYER/SERVER LAG)"),
|
||||||
|
FLOOD_B(
|
||||||
|
CheckCategory.FLOOD,
|
||||||
|
CheckID.B,
|
||||||
|
"Specific packet flood. (CAN FALSE DURING PLAYER/SERVER LAG)"),
|
||||||
|
FLOOD_C(CheckCategory.FLOOD, CheckID.C, "Item flood", 1),
|
||||||
|
FLOOD_D(CheckCategory.FLOOD, CheckID.D, "Book flood", 2),
|
||||||
|
FLOOD_F(CheckCategory.FLOOD, CheckID.F, "Command flood"),
|
||||||
|
FLOOD_G(CheckCategory.FLOOD, CheckID.G, "Map slots flood"),
|
||||||
|
POSITION_A(CheckCategory.POSITION, CheckID.A, "AntiCheat crasher", 1),
|
||||||
|
POSITION_B(CheckCategory.POSITION, CheckID.B, "Unloaded chunk move", 4),
|
||||||
|
POSITION_C(CheckCategory.POSITION, CheckID.C, "High Y", 2),
|
||||||
|
POSITION_D(CheckCategory.POSITION, CheckID.D, "High Yaw", 3),
|
||||||
|
POSITION_E(CheckCategory.POSITION, CheckID.E, "Constant large deltaXZ", true),
|
||||||
|
PAYLOAD_A(CheckCategory.PAYLOAD, CheckID.A, "Empty payload", 1),
|
||||||
|
PAYLOAD_B(CheckCategory.PAYLOAD, CheckID.B, "Legacy book payload flood", 2),
|
||||||
|
PAYLOAD_C(CheckCategory.PAYLOAD, CheckID.C, "Legacy empty hand", 3),
|
||||||
|
PAYLOAD_D(CheckCategory.PAYLOAD, CheckID.D, "Invalid book NBT preVia", 4),
|
||||||
|
PAYLOAD_G(CheckCategory.PAYLOAD, CheckID.D, "Invalid book NBT postVia", 4),
|
||||||
|
PAYLOAD_E(CheckCategory.PAYLOAD, CheckID.E, "Too many registered channels", 5),
|
||||||
|
PAYLOAD_F(CheckCategory.PAYLOAD, CheckID.F, "Purpur beehive location crasher", 6),
|
||||||
|
BOOK_A(CheckCategory.BOOK, CheckID.A, "Max title length", 1),
|
||||||
|
BOOK_B(CheckCategory.PAYLOAD, CheckID.B, "Modern book payload flood", 2),
|
||||||
|
BOOK_C(CheckCategory.PAYLOAD, CheckID.C, "Modern empty hand", 3),
|
||||||
|
BOOK_0(CheckCategory.BOOK, CheckID.ZERO, "HIDDEN", Integer.MAX_VALUE),
|
||||||
|
TAB_A(CheckCategory.TAB, CheckID.A, "Tab complete exploit", 2),
|
||||||
|
TAB_B(CheckCategory.TAB, CheckID.B, "Tab complete length", 1),
|
||||||
|
COMMAND_A(CheckCategory.COMMAND, CheckID.A, "Not allowed command", 1),
|
||||||
|
RECIPE_A(CheckCategory.RECIPE, CheckID.A, "Invalid recipe ID", 1),
|
||||||
|
RECIPE_B(CheckCategory.RECIPE, CheckID.B, "Invalid recipe ID", 1);
|
||||||
|
|
||||||
|
private final CheckCategory category;
|
||||||
|
|
||||||
|
private final CheckID id;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
private final int priority;
|
||||||
|
|
||||||
|
private final boolean beta;
|
||||||
|
|
||||||
|
CheckType(CheckCategory checkCategory, CheckID checkID, String text) {
|
||||||
|
this(checkCategory, checkID, text, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckType(CheckCategory checkCategory, CheckID checkID, String text, int value) {
|
||||||
|
this(checkCategory, checkID, text, value, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckType(CheckCategory checkCategory, CheckID checkID, String text, boolean matches) {
|
||||||
|
this(checkCategory, checkID, text, 0, matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckType(
|
||||||
|
CheckCategory checkCategory,
|
||||||
|
CheckID checkID,
|
||||||
|
String description,
|
||||||
|
int priority,
|
||||||
|
boolean beta) {
|
||||||
|
this.category = checkCategory;
|
||||||
|
this.id = checkID;
|
||||||
|
this.description = description;
|
||||||
|
this.priority = priority;
|
||||||
|
this.beta = beta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckCategory getCategory() {
|
||||||
|
return this.category;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckID getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return this.description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getPriority() {
|
||||||
|
return this.priority;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,111 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.options;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.LPXPlugin;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
|
||||||
|
import org.bukkit.ChatColor;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CheckOptions {
|
||||||
|
|
||||||
|
private final LPXPlugin plugin;
|
||||||
|
|
||||||
|
private final String path;
|
||||||
|
|
||||||
|
private final CheckType type;
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
private boolean punish;
|
||||||
|
|
||||||
|
private int maxVL;
|
||||||
|
|
||||||
|
private int minVl;
|
||||||
|
|
||||||
|
private List<String> punishCommands;
|
||||||
|
|
||||||
|
private int maxBuffer;
|
||||||
|
|
||||||
|
private int bufferMultiplier;
|
||||||
|
|
||||||
|
private int bufferDecay;
|
||||||
|
|
||||||
|
public CheckOptions(LPXPlugin lPXPlugin, CheckType checkType) {
|
||||||
|
this.plugin = lPXPlugin;
|
||||||
|
this.type = checkType;
|
||||||
|
this.path =
|
||||||
|
"checks."
|
||||||
|
+ checkType.getCategory().name().toLowerCase()
|
||||||
|
+ "."
|
||||||
|
+ checkType.getId().name().toLowerCase()
|
||||||
|
+ ".";
|
||||||
|
this.reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reload() {
|
||||||
|
this.enabled = this.getConfig().getBoolean(this.path + "enabled", true);
|
||||||
|
this.punish = this.getConfig().getBoolean(this.path + "punish");
|
||||||
|
this.maxVL = this.getConfig().getInt(this.path + "max-vl");
|
||||||
|
this.minVl = this.getConfig().getInt(this.path + "min-vl");
|
||||||
|
this.punishCommands = this.getConfig().getStringList(this.path + "punish-commands");
|
||||||
|
for (int index = 0; index < this.punishCommands.size(); index++) {
|
||||||
|
this.punishCommands.set(
|
||||||
|
index,
|
||||||
|
ChatColor.translateAlternateColorCodes(
|
||||||
|
(char) (38), this.punishCommands.get(index)));
|
||||||
|
}
|
||||||
|
this.maxBuffer = this.getConfig().getInt(this.path + "buffer.max", 1);
|
||||||
|
this.bufferMultiplier = this.getConfig().getInt(this.path + "buffer.multiply", 0);
|
||||||
|
this.bufferDecay = this.getConfig().getInt(this.path + "buffer.decay", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LPXPlugin getPlugin() {
|
||||||
|
return this.plugin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileConfiguration getConfig() {
|
||||||
|
return this.plugin.getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return this.path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckType getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPunish() {
|
||||||
|
return this.punish;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxVL() {
|
||||||
|
return this.maxVL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMinVl() {
|
||||||
|
return this.minVl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<String> getPunishCommands() {
|
||||||
|
return this.punishCommands;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getMaxBuffer() {
|
||||||
|
return this.maxBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferMultiplier() {
|
||||||
|
return this.bufferMultiplier;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getBufferDecay() {
|
||||||
|
return this.bufferDecay;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package it.ytnoos.lpx.api.check.options;
|
||||||
|
|
||||||
|
public class PersonalCheckOptions {
|
||||||
|
|
||||||
|
private final CheckOptions checkOptions;
|
||||||
|
|
||||||
|
private int vl;
|
||||||
|
|
||||||
|
private double buffer;
|
||||||
|
|
||||||
|
public PersonalCheckOptions(CheckOptions checkOptions2) {
|
||||||
|
this.checkOptions = checkOptions2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckOptions getCheckOptions() {
|
||||||
|
return this.checkOptions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVl() {
|
||||||
|
return this.vl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVl(int vl) {
|
||||||
|
this.vl = vl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void increaseVl() {
|
||||||
|
this.vl++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getBuffer() {
|
||||||
|
return this.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBuffer(double buffer) {
|
||||||
|
this.buffer = buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
this.vl = 0;
|
||||||
|
this.buffer = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package it.ytnoos.lpx.api.event;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class LPXAlertEvent extends Event {
|
||||||
|
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
||||||
|
private final ProtocolPlayer protocolPlayer;
|
||||||
|
|
||||||
|
private final Check<?> check;
|
||||||
|
|
||||||
|
private final FlagInfo[] infos;
|
||||||
|
|
||||||
|
public LPXAlertEvent(ProtocolPlayer protocolPlayer2, Check<?> check2, FlagInfo[] flagInfos) {
|
||||||
|
this.protocolPlayer = protocolPlayer2;
|
||||||
|
this.check = check2;
|
||||||
|
this.infos = flagInfos;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProtocolPlayer getProtocolPlayer() {
|
||||||
|
return this.protocolPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Check<?> getCheck() {
|
||||||
|
return this.check;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FlagInfo[] getInfos() {
|
||||||
|
return this.infos;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package it.ytnoos.lpx.api.event;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
|
||||||
|
import org.bukkit.event.Event;
|
||||||
|
import org.bukkit.event.HandlerList;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class LPXPunishEvent extends Event {
|
||||||
|
|
||||||
|
private static final HandlerList HANDLERS = new HandlerList();
|
||||||
|
|
||||||
|
private final ProtocolPlayer protocolPlayer;
|
||||||
|
|
||||||
|
private final Check<?> check;
|
||||||
|
|
||||||
|
public LPXPunishEvent(ProtocolPlayer protocolPlayer2, Check<?> check2) {
|
||||||
|
this.protocolPlayer = protocolPlayer2;
|
||||||
|
this.check = check2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static HandlerList getHandlerList() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HandlerList getHandlers() {
|
||||||
|
return HANDLERS;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProtocolPlayer getProtocolPlayer() {
|
||||||
|
return this.protocolPlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Check<?> getCheck() {
|
||||||
|
return this.check;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,717 @@
|
|||||||
|
package it.ytnoos.lpx.api.metrics;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.FoliaScheduler;
|
||||||
|
import it.ytnoos.lpx.lib.com.github.retrooper.packetevents.util.folia.GlobalRegionScheduler;
|
||||||
|
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.DataOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import java.util.zip.GZIPOutputStream;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
public class MetricsLite {
|
||||||
|
|
||||||
|
private final Plugin plugin;
|
||||||
|
|
||||||
|
private final MetricsLite.MetricsBase metricsBase;
|
||||||
|
|
||||||
|
public MetricsLite(Plugin plugin2) {
|
||||||
|
this.plugin = plugin2;
|
||||||
|
File file = new File(plugin2.getDataFolder().getParentFile(), "bStats");
|
||||||
|
File file2;
|
||||||
|
YamlConfiguration yamlConfiguration;
|
||||||
|
if (!(yamlConfiguration =
|
||||||
|
YamlConfiguration.loadConfiguration(file2 = new File(file, "config.yml")))
|
||||||
|
.isSet("serverUuid")) {
|
||||||
|
yamlConfiguration.addDefault("enabled", true);
|
||||||
|
yamlConfiguration.addDefault("serverUuid", UUID.randomUUID().toString());
|
||||||
|
yamlConfiguration.addDefault("logFailedRequests", false);
|
||||||
|
yamlConfiguration.addDefault("logSentData", false);
|
||||||
|
yamlConfiguration.addDefault("logResponseStatusText", false);
|
||||||
|
yamlConfiguration
|
||||||
|
.options()
|
||||||
|
.header(
|
||||||
|
"bStats (https://bStats.org) collects some basic information for plugin authors, like how\nmany people use their plugin and their total player count. It's recommended to keep bStats\nenabled, but if you're not comfortable with this, you can turn this setting off. There is no\nperformance penalty associated with having metrics enabled, and data sent to bStats is fully\nanonymous.")
|
||||||
|
.copyDefaults(true);
|
||||||
|
try {
|
||||||
|
yamlConfiguration.save(file2);
|
||||||
|
} catch (IOException oException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean booleanValue = yamlConfiguration.getBoolean("enabled", true);
|
||||||
|
String string = yamlConfiguration.getString("serverUuid");
|
||||||
|
boolean booleanValue2 = yamlConfiguration.getBoolean("logFailedRequests", false);
|
||||||
|
boolean booleanValue3 = yamlConfiguration.getBoolean("logSentData", false);
|
||||||
|
boolean booleanValue4 = yamlConfiguration.getBoolean("logResponseStatusText", false);
|
||||||
|
this.metricsBase =
|
||||||
|
new MetricsLite.MetricsBase(
|
||||||
|
"bukkit",
|
||||||
|
string,
|
||||||
|
9156,
|
||||||
|
booleanValue,
|
||||||
|
this::appendPlatformData,
|
||||||
|
this::appendServiceData,
|
||||||
|
result -> {
|
||||||
|
GlobalRegionScheduler globalRegionScheduler =
|
||||||
|
FoliaScheduler.getGlobalRegionScheduler();
|
||||||
|
globalRegionScheduler.run(plugin2, result2 -> result.run());
|
||||||
|
},
|
||||||
|
plugin2::isEnabled,
|
||||||
|
(result, result3) ->
|
||||||
|
this.plugin.getLogger().log(Level.WARNING, result, result3),
|
||||||
|
result -> this.plugin.getLogger().log(Level.INFO, result),
|
||||||
|
booleanValue2,
|
||||||
|
booleanValue3,
|
||||||
|
booleanValue4);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
this.metricsBase.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCustomChart(MetricsLite.CustomChart customChart) {
|
||||||
|
this.metricsBase.addCustomChart(customChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendPlatformData(MetricsLite.JsonObjectBuilder jsonObjectBuilder) {
|
||||||
|
jsonObjectBuilder.appendField("playerAmount", this.getPlayerAmount());
|
||||||
|
jsonObjectBuilder.appendField("onlineMode", Bukkit.getOnlineMode() ? 1 : 0);
|
||||||
|
jsonObjectBuilder.appendField("bukkitVersion", Bukkit.getVersion());
|
||||||
|
jsonObjectBuilder.appendField("bukkitName", Bukkit.getName());
|
||||||
|
jsonObjectBuilder.appendField("javaVersion", System.getProperty("java.version"));
|
||||||
|
jsonObjectBuilder.appendField("osName", System.getProperty("os.name"));
|
||||||
|
jsonObjectBuilder.appendField("osArch", System.getProperty("os.arch"));
|
||||||
|
jsonObjectBuilder.appendField("osVersion", System.getProperty("os.version"));
|
||||||
|
jsonObjectBuilder.appendField("coreCount", Runtime.getRuntime().availableProcessors());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendServiceData(MetricsLite.JsonObjectBuilder jsonObjectBuilder) {
|
||||||
|
jsonObjectBuilder.appendField("pluginVersion", this.plugin.getDescription().getVersion());
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getPlayerAmount() {
|
||||||
|
try {
|
||||||
|
Method method;
|
||||||
|
return (method = Class.forName("org.bukkit.Server").getMethod("getOnlinePlayers"))
|
||||||
|
.getReturnType()
|
||||||
|
.equals(Collection.class)
|
||||||
|
? ((Collection) method.invoke(Bukkit.getServer())).size()
|
||||||
|
: ((Player[]) method.invoke(Bukkit.getServer())).length;
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return Bukkit.getOnlinePlayers().size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AdvancedBarChart extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Map<String, int[]>> callable;
|
||||||
|
|
||||||
|
public AdvancedBarChart(String text, Callable<Map<String, int[]>> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
Map<String, int[]> entries;
|
||||||
|
if ((entries = this.callable.call()) != null && !entries.isEmpty()) {
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<String, int[]> entry : entries.entrySet()) {
|
||||||
|
if (((int[]) entry.getValue()).length != 0) {
|
||||||
|
matches = false;
|
||||||
|
jsonObjectBuilder.appendField(
|
||||||
|
(String) entry.getKey(), (int[]) entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
? null
|
||||||
|
: new MetricsLite.JsonObjectBuilder()
|
||||||
|
.appendField("values", jsonObjectBuilder.build())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AdvancedPie extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Map<String, Integer>> callable;
|
||||||
|
|
||||||
|
public AdvancedPie(String text, Callable<Map<String, Integer>> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
Map<String, Integer> entries;
|
||||||
|
if ((entries = this.callable.call()) != null && !entries.isEmpty()) {
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<String, Integer> entry : entries.entrySet()) {
|
||||||
|
if ((Integer) entry.getValue() != 0) {
|
||||||
|
matches = false;
|
||||||
|
jsonObjectBuilder.appendField(
|
||||||
|
(String) entry.getKey(), (Integer) entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
? null
|
||||||
|
: new MetricsLite.JsonObjectBuilder()
|
||||||
|
.appendField("values", jsonObjectBuilder.build())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract static class CustomChart {
|
||||||
|
|
||||||
|
private final String chartId;
|
||||||
|
|
||||||
|
protected CustomChart(String chartId) {
|
||||||
|
if (chartId == null) {
|
||||||
|
throw new IllegalArgumentException("chartId must not be null");
|
||||||
|
}
|
||||||
|
this.chartId = chartId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder.JsonObject getRequestJsonObject(
|
||||||
|
BiConsumer<String, Throwable> biConsumer, boolean matches) {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder;
|
||||||
|
(jsonObjectBuilder = new MetricsLite.JsonObjectBuilder())
|
||||||
|
.appendField("chartId", this.chartId);
|
||||||
|
try {
|
||||||
|
MetricsLite.JsonObjectBuilder.JsonObject jsonObject;
|
||||||
|
if ((jsonObject = this.getChartData()) == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
jsonObjectBuilder.appendField("data", jsonObject);
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
if (matches) {
|
||||||
|
biConsumer.accept(
|
||||||
|
"Failed to get data for custom chart with id " + this.chartId,
|
||||||
|
throwable);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return jsonObjectBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DrilldownPie extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Map<String, Map<String, Integer>>> callable;
|
||||||
|
|
||||||
|
public DrilldownPie(String text, Callable<Map<String, Map<String, Integer>>> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
Map<String, Map<String, Integer>> entries;
|
||||||
|
if ((entries = this.callable.call()) != null && !entries.isEmpty()) {
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<String, Map<String, Integer>> entry : entries.entrySet()) {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder2 =
|
||||||
|
new MetricsLite.JsonObjectBuilder();
|
||||||
|
boolean matches2 = true;
|
||||||
|
for (Entry<Object, Object> entry2 :
|
||||||
|
((Iterable<Entry<Object, Object>>)
|
||||||
|
((Iterable<?>)
|
||||||
|
((Map) entries.get(entry.getKey())).entrySet()))) {
|
||||||
|
jsonObjectBuilder2.appendField(
|
||||||
|
(String) entry2.getKey(), (Integer) entry2.getValue());
|
||||||
|
matches2 = false;
|
||||||
|
}
|
||||||
|
if (!matches2) {
|
||||||
|
matches = false;
|
||||||
|
jsonObjectBuilder.appendField(
|
||||||
|
(String) entry.getKey(), jsonObjectBuilder2.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
? null
|
||||||
|
: new MetricsLite.JsonObjectBuilder()
|
||||||
|
.appendField("values", jsonObjectBuilder.build())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JsonObjectBuilder {
|
||||||
|
|
||||||
|
private StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
private boolean hasAtLeastOneField = false;
|
||||||
|
|
||||||
|
public JsonObjectBuilder() {
|
||||||
|
this.builder.append("{");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String escape(String text) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (int index = 0; index < text.length(); index++) {
|
||||||
|
char value;
|
||||||
|
if ((value = text.charAt(index)) == '"') {
|
||||||
|
stringBuilder.append("\\\"");
|
||||||
|
} else if (value == '\\') {
|
||||||
|
stringBuilder.append("\\\\");
|
||||||
|
} else if (value <= 15) {
|
||||||
|
stringBuilder.append("\\u000").append(Integer.toHexString(value));
|
||||||
|
} else if (value <= 31) {
|
||||||
|
stringBuilder.append("\\u00").append(Integer.toHexString(value));
|
||||||
|
} else {
|
||||||
|
stringBuilder.append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendNull(String text) {
|
||||||
|
this.appendFieldUnescaped(text, "null");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(String text, String text2) {
|
||||||
|
if (text2 == null) {
|
||||||
|
throw new IllegalArgumentException("JSON value must not be null");
|
||||||
|
}
|
||||||
|
this.appendFieldUnescaped(text, "\"" + escape(text2) + "\"");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(String text, int value) {
|
||||||
|
this.appendFieldUnescaped(text, String.valueOf(value));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(
|
||||||
|
String text, MetricsLite.JsonObjectBuilder.JsonObject jsonObject) {
|
||||||
|
if (jsonObject == null) {
|
||||||
|
throw new IllegalArgumentException("JSON object must not be null");
|
||||||
|
}
|
||||||
|
this.appendFieldUnescaped(text, jsonObject.toString());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(String text, String[] texts) {
|
||||||
|
if (texts == null) {
|
||||||
|
throw new IllegalArgumentException("JSON values must not be null");
|
||||||
|
}
|
||||||
|
String text2 =
|
||||||
|
Arrays.stream(texts)
|
||||||
|
.map(result -> "\"" + escape(result) + "\"")
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
this.appendFieldUnescaped(text, "[" + text2 + "]");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(String text, int[] values) {
|
||||||
|
if (values == null) {
|
||||||
|
throw new IllegalArgumentException("JSON values must not be null");
|
||||||
|
}
|
||||||
|
String text2 =
|
||||||
|
Arrays.stream(values)
|
||||||
|
.mapToObj(String::valueOf)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
this.appendFieldUnescaped(text, "[" + text2 + "]");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder appendField(
|
||||||
|
String text, MetricsLite.JsonObjectBuilder.JsonObject[] jsonObjects) {
|
||||||
|
if (jsonObjects == null) {
|
||||||
|
throw new IllegalArgumentException("JSON values must not be null");
|
||||||
|
}
|
||||||
|
String text2 =
|
||||||
|
Arrays.stream(jsonObjects)
|
||||||
|
.map(MetricsLite.JsonObjectBuilder.JsonObject::toString)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
this.appendFieldUnescaped(text, "[" + text2 + "]");
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendFieldUnescaped(String text, String text2) {
|
||||||
|
if (this.builder == null) {
|
||||||
|
throw new IllegalStateException("JSON has already been built");
|
||||||
|
}
|
||||||
|
if (text == null) {
|
||||||
|
throw new IllegalArgumentException("JSON key must not be null");
|
||||||
|
}
|
||||||
|
if (this.hasAtLeastOneField) {
|
||||||
|
this.builder.append(",");
|
||||||
|
}
|
||||||
|
this.builder.append("\"").append(escape(text)).append("\":").append(text2);
|
||||||
|
this.hasAtLeastOneField = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MetricsLite.JsonObjectBuilder.JsonObject build() {
|
||||||
|
if (this.builder == null) {
|
||||||
|
throw new IllegalStateException("JSON has already been built");
|
||||||
|
}
|
||||||
|
MetricsLite.JsonObjectBuilder.JsonObject jsonObject =
|
||||||
|
new MetricsLite.JsonObjectBuilder.JsonObject(
|
||||||
|
this.builder.append("}").toString());
|
||||||
|
this.builder = null;
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class JsonObject {
|
||||||
|
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
private JsonObject(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MetricsBase {
|
||||||
|
|
||||||
|
public static final String METRICS_VERSION = "3.0.2";
|
||||||
|
|
||||||
|
private final ScheduledExecutorService scheduler;
|
||||||
|
|
||||||
|
private final String platform;
|
||||||
|
|
||||||
|
private final String serverUuid;
|
||||||
|
|
||||||
|
private final int serviceId;
|
||||||
|
|
||||||
|
private final Consumer<MetricsLite.JsonObjectBuilder> appendPlatformDataConsumer;
|
||||||
|
|
||||||
|
private final Consumer<MetricsLite.JsonObjectBuilder> appendServiceDataConsumer;
|
||||||
|
|
||||||
|
private final Consumer<Runnable> submitTaskConsumer;
|
||||||
|
|
||||||
|
private final Supplier<Boolean> checkServiceEnabledSupplier;
|
||||||
|
|
||||||
|
private final BiConsumer<String, Throwable> errorLogger;
|
||||||
|
|
||||||
|
private final Consumer<String> infoLogger;
|
||||||
|
|
||||||
|
private final boolean logErrors;
|
||||||
|
|
||||||
|
private final boolean logSentData;
|
||||||
|
|
||||||
|
private final boolean logResponseStatusText;
|
||||||
|
|
||||||
|
private final Set<MetricsLite.CustomChart> customCharts = new HashSet<>();
|
||||||
|
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
public MetricsBase(
|
||||||
|
String text,
|
||||||
|
String text2,
|
||||||
|
int value,
|
||||||
|
boolean matches,
|
||||||
|
Consumer<MetricsLite.JsonObjectBuilder> consumer,
|
||||||
|
Consumer<MetricsLite.JsonObjectBuilder> consumer2,
|
||||||
|
Consumer<Runnable> consumer3,
|
||||||
|
Supplier<Boolean> supplier,
|
||||||
|
BiConsumer<String, Throwable> biConsumer,
|
||||||
|
Consumer<String> consumer4,
|
||||||
|
boolean matches2,
|
||||||
|
boolean matches3,
|
||||||
|
boolean matches4) {
|
||||||
|
ScheduledThreadPoolExecutor scheduledThreadPoolExecutor;
|
||||||
|
(scheduledThreadPoolExecutor =
|
||||||
|
new ScheduledThreadPoolExecutor(
|
||||||
|
1, result -> new Thread(result, "bStats-Metrics")))
|
||||||
|
.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
|
||||||
|
this.scheduler = scheduledThreadPoolExecutor;
|
||||||
|
this.platform = text;
|
||||||
|
this.serverUuid = text2;
|
||||||
|
this.serviceId = value;
|
||||||
|
this.enabled = matches;
|
||||||
|
this.appendPlatformDataConsumer = consumer;
|
||||||
|
this.appendServiceDataConsumer = consumer2;
|
||||||
|
this.submitTaskConsumer = consumer3;
|
||||||
|
this.checkServiceEnabledSupplier = supplier;
|
||||||
|
this.errorLogger = biConsumer;
|
||||||
|
this.infoLogger = consumer4;
|
||||||
|
this.logErrors = matches2;
|
||||||
|
this.logSentData = matches3;
|
||||||
|
this.logResponseStatusText = matches4;
|
||||||
|
this.checkRelocation();
|
||||||
|
if (matches) {
|
||||||
|
this.startSubmitting();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static byte[] compress(String text) throws IOException {
|
||||||
|
if (text == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
|
try (GZIPOutputStream gZIPOutputStream = new GZIPOutputStream(byteArrayOutputStream)) {
|
||||||
|
gZIPOutputStream.write(text.getBytes(StandardCharsets.UTF_8));
|
||||||
|
}
|
||||||
|
return byteArrayOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addCustomChart(MetricsLite.CustomChart customChart) {
|
||||||
|
this.customCharts.add(customChart);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
this.scheduler.shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void startSubmitting() {
|
||||||
|
Runnable runnable =
|
||||||
|
() -> {
|
||||||
|
if (this.enabled && this.checkServiceEnabledSupplier.get()) {
|
||||||
|
if (this.submitTaskConsumer != null) {
|
||||||
|
this.submitTaskConsumer.accept(this::submitData);
|
||||||
|
} else {
|
||||||
|
this.submitData();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.scheduler.shutdown();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
long value = (long) (60000.0 * (3.0 + Math.random() * 3.0));
|
||||||
|
long value2 = (long) (60000.0 * (Math.random() * 30.0));
|
||||||
|
this.scheduler.schedule(runnable, value, TimeUnit.MILLISECONDS);
|
||||||
|
this.scheduler.scheduleAtFixedRate(
|
||||||
|
runnable, value + value2, 1800000L, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void submitData() {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
this.appendPlatformDataConsumer.accept(jsonObjectBuilder);
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder2 = new MetricsLite.JsonObjectBuilder();
|
||||||
|
this.appendServiceDataConsumer.accept(jsonObjectBuilder2);
|
||||||
|
Stream<it.ytnoos.lpx.api.metrics.MetricsLite.CustomChart> stream2 =
|
||||||
|
this.customCharts.stream();
|
||||||
|
MetricsLite.JsonObjectBuilder.JsonObject[] jsonObjects =
|
||||||
|
stream2.<MetricsLite.JsonObjectBuilder.JsonObject>map(
|
||||||
|
result ->
|
||||||
|
result.getRequestJsonObject(
|
||||||
|
this.errorLogger, this.logErrors))
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toArray(MetricsLite.JsonObjectBuilder.JsonObject[]::new);
|
||||||
|
jsonObjectBuilder2.appendField("id", this.serviceId);
|
||||||
|
jsonObjectBuilder2.appendField("customCharts", jsonObjects);
|
||||||
|
jsonObjectBuilder.appendField("service", jsonObjectBuilder2.build());
|
||||||
|
jsonObjectBuilder.appendField("serverUUID", this.serverUuid);
|
||||||
|
jsonObjectBuilder.appendField("metricsVersion", "3.0.2");
|
||||||
|
MetricsLite.JsonObjectBuilder.JsonObject jsonObject = jsonObjectBuilder.build();
|
||||||
|
this.scheduler.execute(
|
||||||
|
() -> {
|
||||||
|
try {
|
||||||
|
this.sendData(jsonObject);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
if (this.logErrors) {
|
||||||
|
this.errorLogger.accept(
|
||||||
|
"Could not submit bStats metrics data", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendData(MetricsLite.JsonObjectBuilder.JsonObject jsonObject)
|
||||||
|
throws Exception {
|
||||||
|
if (this.logSentData) {
|
||||||
|
this.infoLogger.accept("Sent bStats metrics data: " + jsonObject.toString());
|
||||||
|
}
|
||||||
|
String text = String.format("https://bStats.org/api/v2/data/%s", this.platform);
|
||||||
|
HttpsURLConnection httpsURLConnection =
|
||||||
|
(HttpsURLConnection) new URL(text).openConnection();
|
||||||
|
byte[] values = compress(jsonObject.toString());
|
||||||
|
httpsURLConnection.setRequestMethod("POST");
|
||||||
|
httpsURLConnection.addRequestProperty("Accept", "application/json");
|
||||||
|
httpsURLConnection.addRequestProperty("Connection", "close");
|
||||||
|
httpsURLConnection.addRequestProperty("Content-Encoding", "gzip");
|
||||||
|
httpsURLConnection.addRequestProperty("Content-Length", String.valueOf(values.length));
|
||||||
|
httpsURLConnection.setRequestProperty("Content-Type", "application/json");
|
||||||
|
httpsURLConnection.setRequestProperty("User-Agent", "Metrics-Service/1");
|
||||||
|
httpsURLConnection.setDoOutput(true);
|
||||||
|
try (DataOutputStream dataOutputStream =
|
||||||
|
new DataOutputStream(httpsURLConnection.getOutputStream())) {
|
||||||
|
dataOutputStream.write(values);
|
||||||
|
}
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
BufferedReader bufferedReader =
|
||||||
|
new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
|
||||||
|
String text2;
|
||||||
|
try {
|
||||||
|
while ((text2 = bufferedReader.readLine()) != null) {
|
||||||
|
stringBuilder.append(text2);
|
||||||
|
}
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
try {
|
||||||
|
bufferedReader.close();
|
||||||
|
} catch (Throwable throwable2) {
|
||||||
|
throwable.addSuppressed(throwable2);
|
||||||
|
}
|
||||||
|
throw throwable;
|
||||||
|
}
|
||||||
|
bufferedReader.close();
|
||||||
|
if (this.logResponseStatusText) {
|
||||||
|
this.infoLogger.accept(
|
||||||
|
"Sent data to bStats and received response: " + stringBuilder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkRelocation() {
|
||||||
|
if (System.getProperty("bstats.relocatecheck") == null
|
||||||
|
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
|
||||||
|
String text =
|
||||||
|
new String(new byte[] {111, 114, 103, 46, 98, 115, 116, 97, 116, 115});
|
||||||
|
String text2 =
|
||||||
|
new String(
|
||||||
|
new byte[] {
|
||||||
|
121, 111, 117, 114, 46, 112, 97, 99, 107, 97, 103, 101
|
||||||
|
});
|
||||||
|
if (MetricsLite.MetricsBase.class.getPackage().getName().startsWith(text)
|
||||||
|
|| MetricsLite.MetricsBase.class.getPackage().getName().startsWith(text2)) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"bStats Metrics class has not been relocated correctly!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MultiLineChart extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Map<String, Integer>> callable;
|
||||||
|
|
||||||
|
public MultiLineChart(String text, Callable<Map<String, Integer>> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
Map<String, Integer> entries;
|
||||||
|
if ((entries = this.callable.call()) != null && !entries.isEmpty()) {
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<String, Integer> entry : entries.entrySet()) {
|
||||||
|
if ((Integer) entry.getValue() != 0) {
|
||||||
|
matches = false;
|
||||||
|
jsonObjectBuilder.appendField(
|
||||||
|
(String) entry.getKey(), (Integer) entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches
|
||||||
|
? null
|
||||||
|
: new MetricsLite.JsonObjectBuilder()
|
||||||
|
.appendField("values", jsonObjectBuilder.build())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SimpleBarChart extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Map<String, Integer>> callable;
|
||||||
|
|
||||||
|
public SimpleBarChart(String text, Callable<Map<String, Integer>> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
MetricsLite.JsonObjectBuilder jsonObjectBuilder = new MetricsLite.JsonObjectBuilder();
|
||||||
|
Map<String, Integer> entries;
|
||||||
|
if ((entries = this.callable.call()) != null && !entries.isEmpty()) {
|
||||||
|
for (Entry<String, Integer> entry : entries.entrySet()) {
|
||||||
|
jsonObjectBuilder.appendField(
|
||||||
|
(String) entry.getKey(), new int[] {(Integer) entry.getValue()});
|
||||||
|
}
|
||||||
|
return new MetricsLite.JsonObjectBuilder()
|
||||||
|
.appendField("values", jsonObjectBuilder.build())
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SimplePie extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<String> callable;
|
||||||
|
|
||||||
|
public SimplePie(String text, Callable<String> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
String text;
|
||||||
|
return (text = this.callable.call()) != null && !text.isEmpty()
|
||||||
|
? new MetricsLite.JsonObjectBuilder().appendField("value", text).build()
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class SingleLineChart extends MetricsLite.CustomChart {
|
||||||
|
|
||||||
|
private final Callable<Integer> callable;
|
||||||
|
|
||||||
|
public SingleLineChart(String text, Callable<Integer> callable2) {
|
||||||
|
super(text);
|
||||||
|
this.callable = callable2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected MetricsLite.JsonObjectBuilder.JsonObject getChartData() throws Exception {
|
||||||
|
int value;
|
||||||
|
return (value = this.callable.call()) == 0
|
||||||
|
? null
|
||||||
|
: new MetricsLite.JsonObjectBuilder().appendField("value", value).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
package it.ytnoos.lpx.api.player;
|
||||||
|
|
||||||
|
public interface PrinterData {
|
||||||
|
|
||||||
|
PrinterStatus getPrinterStatus();
|
||||||
|
|
||||||
|
boolean isUsingPrinter();
|
||||||
|
|
||||||
|
void setPrinterMode(boolean matches);
|
||||||
|
|
||||||
|
void setPrinterMode(PrinterStatus printerStatus);
|
||||||
|
|
||||||
|
void updateLastPlace();
|
||||||
|
|
||||||
|
long getLastPlace();
|
||||||
|
|
||||||
|
int increaseBlocksPlaced();
|
||||||
|
|
||||||
|
int getBlocksPlaced();
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package it.ytnoos.lpx.api.player;
|
||||||
|
|
||||||
|
public enum PrinterStatus {
|
||||||
|
NONE,
|
||||||
|
AUTOMATIC,
|
||||||
|
API
|
||||||
|
}
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
package it.ytnoos.lpx.api.player;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.LPX;
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResultInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.protocol.CheckContainer;
|
||||||
|
import it.ytnoos.lpx.api.protocol.ReceivedPacket;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface ProtocolPlayer {
|
||||||
|
|
||||||
|
Optional<Player> getPlayer();
|
||||||
|
|
||||||
|
User getUser();
|
||||||
|
|
||||||
|
String getUsername();
|
||||||
|
|
||||||
|
UUID getUniqueId();
|
||||||
|
|
||||||
|
PrinterData getPrinterData();
|
||||||
|
|
||||||
|
boolean isBedrock();
|
||||||
|
|
||||||
|
void setBedrock(boolean matches);
|
||||||
|
|
||||||
|
boolean isProcessingPayload();
|
||||||
|
|
||||||
|
void setProcessingPayload(boolean matches);
|
||||||
|
|
||||||
|
Map<Object, CheckContainer<?>> getChecks();
|
||||||
|
|
||||||
|
CheckContainer<?> getChecks(Object result);
|
||||||
|
|
||||||
|
boolean hasAnyCheck(Object result, boolean matches);
|
||||||
|
|
||||||
|
CheckResultInfo handleChecks(Object result, Object result2);
|
||||||
|
|
||||||
|
CheckResultInfo handleChecks(Object result, Object result2, boolean matches);
|
||||||
|
|
||||||
|
<T> Check<T> getCheck(Object result, CheckType checkType, LPX lPX);
|
||||||
|
|
||||||
|
ReceivedPacket getLastReceivedPacket();
|
||||||
|
|
||||||
|
long getLastAlert();
|
||||||
|
|
||||||
|
long getLastPunish();
|
||||||
|
|
||||||
|
long getLastTeleport();
|
||||||
|
|
||||||
|
void updateLastAlert();
|
||||||
|
|
||||||
|
long getLastPortalTeleport();
|
||||||
|
|
||||||
|
long getLastShears();
|
||||||
|
|
||||||
|
long getLastContainerInteract();
|
||||||
|
|
||||||
|
void setLastReceivedPacket(ReceivedPacket receivedPacket);
|
||||||
|
|
||||||
|
void updateLastPunish();
|
||||||
|
|
||||||
|
void updateLastTeleport();
|
||||||
|
|
||||||
|
void updateLastPortalTeleport();
|
||||||
|
|
||||||
|
void updateLastShears();
|
||||||
|
|
||||||
|
void updateLastContainerInteract();
|
||||||
|
|
||||||
|
long incrementPacketCount();
|
||||||
|
|
||||||
|
long getPacketCount();
|
||||||
|
|
||||||
|
long getLastKeepAliveSent();
|
||||||
|
|
||||||
|
void setLastKeepAliveSent(long value);
|
||||||
|
|
||||||
|
double getPlayerPing();
|
||||||
|
|
||||||
|
void setPlayerPing(double value);
|
||||||
|
|
||||||
|
void flag(Check<?> check, Object result, FlagInfo... flagInfo);
|
||||||
|
|
||||||
|
void punish(Check<?> check);
|
||||||
|
|
||||||
|
void kick(String text);
|
||||||
|
|
||||||
|
boolean isKicked();
|
||||||
|
|
||||||
|
boolean ignoreChecks();
|
||||||
|
|
||||||
|
boolean hasExemptPermission();
|
||||||
|
|
||||||
|
default boolean usesComponents() {
|
||||||
|
return this.getUser().getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_20_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean usesHashedStacks() {
|
||||||
|
return this.getUser().getClientVersion().isNewerThanOrEquals(ClientVersion.V_1_21_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean serverUsesHashedStacks() {
|
||||||
|
return PacketEvents.getAPI()
|
||||||
|
.getServerManager()
|
||||||
|
.getVersion()
|
||||||
|
.isNewerThanOrEquals(ServerVersion.V_1_21_5);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isLegacyClientOnLegacyServer() {
|
||||||
|
return !this.usesHashedStacks() && !this.serverUsesHashedStacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isLegacyClientOnHashedServer() {
|
||||||
|
return !this.usesHashedStacks() && this.serverUsesHashedStacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isHashedClientOnLegacyServer() {
|
||||||
|
return this.usesHashedStacks() && !this.serverUsesHashedStacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isHashedClientOnHashedServer() {
|
||||||
|
return this.usesHashedStacks() && this.serverUsesHashedStacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
default double itemFloodMultiplier() {
|
||||||
|
if (this.isLegacyClientOnHashedServer()) {
|
||||||
|
return 1.5;
|
||||||
|
} else {
|
||||||
|
return this.isHashedClientOnHashedServer() ? 0.5 : 1.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LPX lpx();
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
package it.ytnoos.lpx.api.protocol;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class CheckContainer<T> extends ArrayList<Check<T>> {}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package it.ytnoos.lpx.api.protocol;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.User;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public interface PlayerRegistry {
|
||||||
|
|
||||||
|
Optional<ProtocolPlayer> getPlayer(User user);
|
||||||
|
|
||||||
|
Map<User, ProtocolPlayer> getPlayers();
|
||||||
|
|
||||||
|
void uninjectAll();
|
||||||
|
|
||||||
|
void uninject(User user);
|
||||||
|
|
||||||
|
Optional<ProtocolPlayer> getPlayer(Player player);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
ProtocolPlayer addPlayer(User user, ProtocolPlayer protocolPlayer);
|
||||||
|
}
|
||||||
@@ -0,0 +1,298 @@
|
|||||||
|
package it.ytnoos.lpx.api.protocol;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.ComponentType;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTByteArray;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTIntArray;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTLongArray;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
|
import java.text.NumberFormat;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class ReceivedPacket {
|
||||||
|
|
||||||
|
private static final ThreadLocal<NumberFormat> FORMAT =
|
||||||
|
ThreadLocal.withInitial(() -> new DecimalFormat("0.000"));
|
||||||
|
|
||||||
|
private final String playerName;
|
||||||
|
|
||||||
|
private final ClientVersion clientVersion;
|
||||||
|
|
||||||
|
private final long createdAtNanos;
|
||||||
|
|
||||||
|
private final long receivedAtTick;
|
||||||
|
|
||||||
|
private final PacketTypeCommon packetType;
|
||||||
|
|
||||||
|
private final long size;
|
||||||
|
|
||||||
|
private Object packet;
|
||||||
|
|
||||||
|
private long elapsedTime;
|
||||||
|
|
||||||
|
private String packetString;
|
||||||
|
|
||||||
|
private List<NBT> originalNbtData;
|
||||||
|
|
||||||
|
public ReceivedPacket(
|
||||||
|
String playerName,
|
||||||
|
ClientVersion clientVersion2,
|
||||||
|
long receivedAtTick,
|
||||||
|
PacketTypeCommon packetTypeCommon,
|
||||||
|
long size,
|
||||||
|
Object packet) {
|
||||||
|
this.playerName = playerName;
|
||||||
|
this.clientVersion = clientVersion2;
|
||||||
|
this.receivedAtTick = receivedAtTick;
|
||||||
|
this.packetType = packetTypeCommon;
|
||||||
|
this.createdAtNanos = System.nanoTime();
|
||||||
|
this.size = size;
|
||||||
|
this.packet = packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlayerName() {
|
||||||
|
return this.playerName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getReceivedAtTick() {
|
||||||
|
return this.receivedAtTick;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientVersion getClientVersion() {
|
||||||
|
return this.clientVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getClientVersionName() {
|
||||||
|
return this.clientVersion.getReleaseName();
|
||||||
|
}
|
||||||
|
|
||||||
|
public PacketTypeCommon getPacketType() {
|
||||||
|
return this.packetType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getPacket() {
|
||||||
|
return this.packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPacket(Object packet) {
|
||||||
|
this.packet = packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize() {
|
||||||
|
return this.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOriginalNbt(NBT nBT) {
|
||||||
|
if (this.originalNbtData == null) {
|
||||||
|
this.originalNbtData = new ArrayList<>();
|
||||||
|
}
|
||||||
|
if (this.originalNbtData.size() < 1000) {
|
||||||
|
this.originalNbtData.add(nBT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getElapsedTime() {
|
||||||
|
if (this.elapsedTime == 0L) {
|
||||||
|
this.elapsedTime = System.nanoTime() - this.createdAtNanos;
|
||||||
|
}
|
||||||
|
return this.elapsedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormattedElapsedTime() {
|
||||||
|
return FORMAT.get().format(this.getElapsedTime() / 1000000.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (this.packetString == null) {
|
||||||
|
this.packetString = this.buildPacketString().replace('\n', ' ');
|
||||||
|
this.originalNbtData = null;
|
||||||
|
}
|
||||||
|
return this.packetString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String buildPacketString() {
|
||||||
|
if (this.packet == null) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
Field[] fields;
|
||||||
|
int value = (fields = this.packet.getClass().getDeclaredFields()).length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
Field field = fields[index];
|
||||||
|
if (field.getDeclaringClass().equals(this.packet.getClass())) {
|
||||||
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
|
Object result = field.get(this.packet);
|
||||||
|
stringBuilder.append(field.getName()).append("=");
|
||||||
|
appendValue(result, stringBuilder);
|
||||||
|
stringBuilder.append(" ");
|
||||||
|
} catch (IllegalAccessException illegalAccessException) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.originalNbtData != null && !this.originalNbtData.isEmpty()) {
|
||||||
|
stringBuilder.append("originalNbt=[");
|
||||||
|
boolean matches = true;
|
||||||
|
for (NBT nBT : this.originalNbtData) {
|
||||||
|
if (!matches) {
|
||||||
|
stringBuilder.append(", ");
|
||||||
|
}
|
||||||
|
matches = false;
|
||||||
|
appendNbt(nBT, stringBuilder);
|
||||||
|
}
|
||||||
|
stringBuilder.append("] ");
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendValue(Object result, StringBuilder stringBuilder) {
|
||||||
|
if (result instanceof ItemStack) {
|
||||||
|
appendItemStack((ItemStack) result, stringBuilder);
|
||||||
|
} else if (result instanceof Map) {
|
||||||
|
appendMap((Map<?, ?>) result, stringBuilder);
|
||||||
|
} else if (result instanceof Optional) {
|
||||||
|
Optional optional;
|
||||||
|
if ((optional = (Optional) result).isPresent()) {
|
||||||
|
appendValue(optional.get(), stringBuilder);
|
||||||
|
} else {
|
||||||
|
stringBuilder.append("empty");
|
||||||
|
}
|
||||||
|
} else if (result instanceof Object[]) {
|
||||||
|
appendArray((Object[]) result, stringBuilder);
|
||||||
|
} else if (result instanceof NBT) {
|
||||||
|
appendNbt((NBT) result, stringBuilder);
|
||||||
|
} else if (result instanceof byte[] values) {
|
||||||
|
stringBuilder.append(Arrays.toString(values));
|
||||||
|
} else {
|
||||||
|
stringBuilder.append(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendItemStack(ItemStack itemStack, StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("[type=").append(itemStack.getType().getName());
|
||||||
|
NBTCompound nBTCompound;
|
||||||
|
if ((nBTCompound = itemStack.getNBT()) != null && !nBTCompound.isEmpty()) {
|
||||||
|
stringBuilder.append(", nbt=");
|
||||||
|
appendNbt(nBTCompound, stringBuilder);
|
||||||
|
}
|
||||||
|
if (itemStack.hasComponentPatches()) {
|
||||||
|
appendComponentPatches(itemStack, stringBuilder);
|
||||||
|
}
|
||||||
|
stringBuilder.append("]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendComponentPatches(ItemStack itemStack, StringBuilder stringBuilder) {
|
||||||
|
ClientVersion version = itemStack.getVersion();
|
||||||
|
for (Entry<ComponentType<?>, Optional<?>> entry :
|
||||||
|
itemStack.getComponents().getPatches().entrySet()) {
|
||||||
|
stringBuilder
|
||||||
|
.append(", ")
|
||||||
|
.append(((ComponentType) entry.getKey()).getName())
|
||||||
|
.append("=");
|
||||||
|
if (((Optional) entry.getValue()).isPresent()) {
|
||||||
|
try {
|
||||||
|
appendNbt(
|
||||||
|
((ComponentType) entry.getKey())
|
||||||
|
.encode(((Optional) entry.getValue()).get(), version),
|
||||||
|
stringBuilder);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
stringBuilder.append(((Optional) entry.getValue()).get());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stringBuilder.append("REMOVED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendMap(Map<?, ?> entries, StringBuilder stringBuilder) {
|
||||||
|
stringBuilder.append("{");
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<?, ?> entry : entries.entrySet()) {
|
||||||
|
if (!matches) {
|
||||||
|
stringBuilder.append(", ");
|
||||||
|
}
|
||||||
|
matches = false;
|
||||||
|
stringBuilder.append(entry.getKey()).append("=");
|
||||||
|
appendValue(entry.getValue(), stringBuilder);
|
||||||
|
}
|
||||||
|
stringBuilder.append("}");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendArray(Object[] results, StringBuilder stringBuilder) {
|
||||||
|
if (results.length != 0) {
|
||||||
|
stringBuilder.append("[");
|
||||||
|
boolean matches = true;
|
||||||
|
int value = results.length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
Object result = results[index];
|
||||||
|
if (!matches) {
|
||||||
|
stringBuilder.append(", ");
|
||||||
|
}
|
||||||
|
matches = false;
|
||||||
|
appendValue(result, stringBuilder);
|
||||||
|
}
|
||||||
|
stringBuilder.append("]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void appendNbt(NBT nBT, StringBuilder stringBuilder) {
|
||||||
|
if (nBT instanceof NBTCompound) {
|
||||||
|
NBTCompound nBTCompound;
|
||||||
|
if ((nBTCompound = (NBTCompound) nBT).isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
stringBuilder.append("[");
|
||||||
|
boolean matches = true;
|
||||||
|
for (Entry<String, NBT> entry : nBTCompound.getTags().entrySet()) {
|
||||||
|
if (!matches) {
|
||||||
|
stringBuilder.append(", ");
|
||||||
|
}
|
||||||
|
matches = false;
|
||||||
|
stringBuilder.append((String) entry.getKey()).append("=");
|
||||||
|
appendNbt((NBT) entry.getValue(), stringBuilder);
|
||||||
|
}
|
||||||
|
stringBuilder.append("]");
|
||||||
|
} else if (nBT instanceof NBTList) {
|
||||||
|
NBTList nBTList;
|
||||||
|
if ((nBTList = (NBTList) nBT).isEmpty()) {
|
||||||
|
stringBuilder.append("[]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
boolean matches2 = true;
|
||||||
|
for (NBT nBT2 : ((Iterable<NBT>) ((Iterable<?>) nBTList.getTags()))) {
|
||||||
|
if (!matches2) {
|
||||||
|
stringBuilder.append(", ");
|
||||||
|
}
|
||||||
|
matches2 = false;
|
||||||
|
appendNbt(nBT2, stringBuilder);
|
||||||
|
}
|
||||||
|
} else if (nBT instanceof NBTNumber nBTNumber) {
|
||||||
|
stringBuilder.append(nBTNumber.getAsNumber());
|
||||||
|
} else if (nBT instanceof NBTString nBTString) {
|
||||||
|
stringBuilder.append(nBTString.getValue());
|
||||||
|
} else if (nBT instanceof NBTByteArray nBTByteArray) {
|
||||||
|
stringBuilder.append(Arrays.toString(nBTByteArray.getValue()));
|
||||||
|
} else if (nBT instanceof NBTIntArray nBTIntArray) {
|
||||||
|
stringBuilder.append(Arrays.toString(nBTIntArray.getValue()));
|
||||||
|
} else if (nBT instanceof NBTLongArray nBTLongArray) {
|
||||||
|
stringBuilder.append(Arrays.toString(nBTLongArray.getValue()));
|
||||||
|
} else {
|
||||||
|
stringBuilder.append(nBT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
package it.ytnoos.lpx.check;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.Check;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.check.options.PersonalCheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.ComponentTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemBees.BeeEntry;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
public abstract class AbstractCheck<T> implements Check<T> {
|
||||||
|
|
||||||
|
protected final ProtocolPlayer player;
|
||||||
|
|
||||||
|
protected final PersonalCheckOptions options;
|
||||||
|
|
||||||
|
private static final String TEXT = "options.";
|
||||||
|
|
||||||
|
public AbstractCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
this.player = protocolPlayer;
|
||||||
|
PersonalCheckOptions personalCheckOptions = new PersonalCheckOptions(checkOptions);
|
||||||
|
this.options = personalCheckOptions;
|
||||||
|
this.loadOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void flag(Object result, FlagInfo[] flagInfos) {
|
||||||
|
this.player.flag(this, result, flagInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean flagViolation(Object result, FlagInfo[] flagInfos) {
|
||||||
|
this.options.increaseVl();
|
||||||
|
this.options.setBuffer(
|
||||||
|
this.options.getBuffer() * this.options.getCheckOptions().getBufferMultiplier());
|
||||||
|
this.flag(result, flagInfos);
|
||||||
|
if (this.options.getVl() >= this.options.getCheckOptions().getMaxVL()) {
|
||||||
|
if (this.options.getCheckOptions().isPunish()) {
|
||||||
|
this.player.punish(this);
|
||||||
|
}
|
||||||
|
this.options.setVl(0);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void reset() {
|
||||||
|
this.options.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean increaseBuffer(Object result, FlagInfo[] flagInfos) {
|
||||||
|
Double value = ((Double) (double) 1.0);
|
||||||
|
double value2 = ((double) value);
|
||||||
|
return this.increaseBuffer(result, value2, flagInfos);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean increaseBuffer(Object result, double value, FlagInfo[] flagInfos) {
|
||||||
|
this.options.setBuffer(
|
||||||
|
Math.min(
|
||||||
|
this.options.getCheckOptions().getMaxBuffer(),
|
||||||
|
this.options.getBuffer() + value));
|
||||||
|
if (this.options.getBuffer() >= this.options.getCheckOptions().getMaxBuffer()) {
|
||||||
|
this.flagViolation(result, flagInfos);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void decayBuffer() {
|
||||||
|
if (!(this.options.getBuffer() <= 0.0)) {
|
||||||
|
this.options.setBuffer(
|
||||||
|
Math.max(
|
||||||
|
0.0,
|
||||||
|
this.options.getBuffer()
|
||||||
|
- this.options.getCheckOptions().getBufferDecay()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract CheckResult check(ProtocolPlayer protocolPlayer, T t);
|
||||||
|
|
||||||
|
public void loadOptions() {}
|
||||||
|
|
||||||
|
public CheckResult handle(T t) {
|
||||||
|
if (this.options.getCheckOptions().isEnabled() && !this.player.ignoreChecks()) {
|
||||||
|
ProtocolPlayer protocolPlayer = this.player;
|
||||||
|
Object result = ((Object) t);
|
||||||
|
return this.check(protocolPlayer, ((T) result));
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public PersonalCheckOptions getOptions() {
|
||||||
|
return this.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckType getType() {
|
||||||
|
return this.options.getCheckOptions().getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String createText(String text) {
|
||||||
|
String path = this.options.getCheckOptions().getPath();
|
||||||
|
String text2 = TEXT;
|
||||||
|
return path + text2 + text;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected FileConfiguration getCheckConfiguration() {
|
||||||
|
return this.options.getCheckOptions().getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean testEnabled(String text, boolean matches) {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
return checkConfiguration.getBoolean(this.createText(text), matches);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int calculateLimit(String text, int value) {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
return checkConfiguration.getInt(this.createText(text), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected long calculateTime(String text, long value) {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
return checkConfiguration.getLong(this.createText(text), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected double calculateValue(String text, double value) {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
return checkConfiguration.getDouble(this.createText(text), value);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected List<String> createValues(String text, String[] texts) {
|
||||||
|
String text2 = this.createText(text);
|
||||||
|
if (this.getCheckConfiguration().isSet(text2)) {
|
||||||
|
return this.getCheckConfiguration().getStringList(text2);
|
||||||
|
} else {
|
||||||
|
return new ArrayList<>(Arrays.asList(texts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleNBT(ItemStack itemStack, Consumer consumer) {
|
||||||
|
if (itemStack != null) {
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
if (nBT != null) {
|
||||||
|
consumer.accept(nBT);
|
||||||
|
}
|
||||||
|
itemStack.getComponent(ComponentTypes.CUSTOM_DATA).ifPresent(consumer);
|
||||||
|
itemStack.getComponent(ComponentTypes.ENTITY_DATA).ifPresent(consumer);
|
||||||
|
itemStack.getComponent(ComponentTypes.BUCKET_ENTITY_DATA).ifPresent(consumer);
|
||||||
|
itemStack.getComponent(ComponentTypes.BLOCK_ENTITY_DATA).ifPresent(consumer);
|
||||||
|
Optional<
|
||||||
|
it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component
|
||||||
|
.builtin.item.ItemBees>
|
||||||
|
component2 = itemStack.getComponent(ComponentTypes.BEES);
|
||||||
|
component2.ifPresent(
|
||||||
|
result -> {
|
||||||
|
for (BeeEntry beeEntry : result.getBees()) {
|
||||||
|
consumer.accept(beeEntry.getEntityData());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
itemStack.getComponent(ComponentTypes.DEBUG_STICK_STATE).ifPresent(result2 -> {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
package it.ytnoos.lpx.check;
|
||||||
|
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.LPXBukkit;
|
||||||
|
import it.ytnoos.lpx.api.check.abstraction.CheckManager;
|
||||||
|
import it.ytnoos.lpx.api.check.enums.CheckType;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.impl.book.Book0Check;
|
||||||
|
import it.ytnoos.lpx.check.impl.book.BookACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.book.BookBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.book.BookCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.command.CommandACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeDCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeECheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeFCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeGCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeHCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.creative.CreativeICheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodDCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodFCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.flood.FloodGCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.Item0Check;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.Item1Check;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.Item2Check;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.Item3Check;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemDCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemECheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemFCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemGCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemHCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemJCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.item.ItemKCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.netty.PacketLimitCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.netty.PacketSizeCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadDirectionCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadECheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.payload.PayloadFCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.place.PlaceACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.place.PlaceBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.place.PlaceCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.position.PositionACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.position.PositionBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.position.PositionCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.position.PositionDCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.tab.TabACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.tab.TabBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.window.WindowACheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.window.WindowBCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.window.WindowCCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.window.WindowDCheck;
|
||||||
|
import it.ytnoos.lpx.check.impl.window.WindowECheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.PacketPlayReceiveEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ReadSlotsEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.exception.PacketLimitException;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.VersionComparison;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCraftRecipeRequest;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientSetDisplayedRecipe;
|
||||||
|
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class BukkitCheckManager extends CheckManager {
|
||||||
|
|
||||||
|
public static final List<String> VALUES;
|
||||||
|
|
||||||
|
public BukkitCheckManager(LPXBukkit lPXBukkit) {
|
||||||
|
super(lPXBukkit.getPlugin());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void registerChecks() {
|
||||||
|
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||||
|
boolean matches = version.is(VersionComparison.OLDER_THAN_OR_EQUALS, ServerVersion.V_1_8_8);
|
||||||
|
this.register(
|
||||||
|
ByteBuf.class,
|
||||||
|
(result, result2) -> new PacketSizeCheck(result, result2, true),
|
||||||
|
CheckType.NETTY_A);
|
||||||
|
this.register(
|
||||||
|
ByteBuf.class,
|
||||||
|
(result, result2) -> new PacketSizeCheck(result, result2, false),
|
||||||
|
CheckType.NETTY_C);
|
||||||
|
this.register(
|
||||||
|
PacketLimitException.class,
|
||||||
|
(result, result2) -> new PacketLimitCheck(result, result2, true),
|
||||||
|
CheckType.NETTY_B);
|
||||||
|
this.register(
|
||||||
|
PacketLimitException.class,
|
||||||
|
(result, result2) -> new PacketLimitCheck(result, result2, false),
|
||||||
|
CheckType.NETTY_B);
|
||||||
|
if (matches) {
|
||||||
|
this.register(Client.CLICK_WINDOW, WindowACheck::new, CheckType.WINDOW_A);
|
||||||
|
}
|
||||||
|
if (version.is(VersionComparison.NEWER_THAN_OR_EQUALS, ServerVersion.V_1_12)) {
|
||||||
|
this.register(Client.CLICK_WINDOW, WindowBCheck::new, CheckType.WINDOW_B);
|
||||||
|
}
|
||||||
|
this.register(Client.CLICK_WINDOW, WindowCCheck::new, CheckType.WINDOW_C);
|
||||||
|
this.register(Client.CLICK_WINDOW, WindowDCheck::new, CheckType.WINDOW_D);
|
||||||
|
this.register(Client.CLICK_WINDOW, WindowECheck::new, CheckType.WINDOW_E);
|
||||||
|
this.register(NBTDecodeEvent.class, Item0Check::new, CheckType.ITEM_0);
|
||||||
|
this.register(ItemStackDecodeEvent.class, Item1Check::new, CheckType.ITEM_1);
|
||||||
|
this.register(Client.PICK_ITEM_FROM_BLOCK, Item2Check::new, CheckType.ITEM_2);
|
||||||
|
this.register(Client.PICK_ITEM_FROM_ENTITY, Item3Check::new, CheckType.ITEM_3);
|
||||||
|
this.register(ItemStackDecodeEvent.class, ItemACheck::new, CheckType.ITEM_A);
|
||||||
|
this.register(NBTDecodeEvent.class, ItemBCheck::new, CheckType.ITEM_B);
|
||||||
|
this.register(NBTDecodeEvent.class, ItemCCheck::new, CheckType.ITEM_C);
|
||||||
|
this.register(ItemStackDecodeEvent.class, ItemDCheck::new, CheckType.ITEM_D);
|
||||||
|
this.register(NBTDecodeEvent.class, ItemECheck::new, CheckType.ITEM_E);
|
||||||
|
this.register(NBTDecodeEvent.class, ItemFCheck::new, CheckType.ITEM_F);
|
||||||
|
this.register(NBTDecodeEvent.class, ItemGCheck::new, CheckType.ITEM_G);
|
||||||
|
this.register(ItemStackDecodeEvent.class, ItemHCheck::new, CheckType.ITEM_H);
|
||||||
|
this.register(ItemStackDecodeEvent.class, ItemJCheck::new, CheckType.ITEM_J);
|
||||||
|
this.register(ItemStackDecodeEvent.class, ItemKCheck::new, CheckType.ITEM_K);
|
||||||
|
this.register(PacketPlayReceiveEvent.class, CreativeACheck::new, CheckType.CREATIVE_A);
|
||||||
|
this.register(Client.CREATIVE_INVENTORY_ACTION, CreativeBCheck::new, CheckType.CREATIVE_B);
|
||||||
|
this.register(Client.CREATIVE_INVENTORY_ACTION, CreativeCCheck::new, CheckType.CREATIVE_C);
|
||||||
|
this.register(Client.CREATIVE_INVENTORY_ACTION, CreativeDCheck::new, CheckType.CREATIVE_D);
|
||||||
|
this.register(ItemStackDecodeEvent.class, CreativeECheck::new, CheckType.CREATIVE_E);
|
||||||
|
this.register(Client.CREATIVE_INVENTORY_ACTION, CreativeFCheck::new, CheckType.CREATIVE_F);
|
||||||
|
this.register(Client.CREATIVE_INVENTORY_ACTION, CreativeGCheck::new, CheckType.CREATIVE_G);
|
||||||
|
this.register(PacketPlayReceiveEvent.class, CreativeHCheck::new, CheckType.CREATIVE_H);
|
||||||
|
this.register(PacketPlayReceiveEvent.class, CreativeICheck::new, CheckType.CREATIVE_I);
|
||||||
|
this.register(Client.PLAYER_BLOCK_PLACEMENT, PlaceACheck::new, CheckType.PLACE_A);
|
||||||
|
this.register(Client.UPDATE_SIGN, PlaceBCheck::new, CheckType.PLACE_B);
|
||||||
|
if (version == ServerVersion.V_1_16
|
||||||
|
|| version == ServerVersion.V_1_16_1
|
||||||
|
|| version == ServerVersion.V_1_16_2
|
||||||
|
|| version == ServerVersion.V_1_16_3
|
||||||
|
|| version == ServerVersion.V_1_16_4
|
||||||
|
|| version == ServerVersion.V_1_16_5) {
|
||||||
|
this.register(Client.PLAYER_DIGGING, PlaceCCheck::new, CheckType.PLACE_C);
|
||||||
|
}
|
||||||
|
this.register(PacketPlayReceiveEvent.class, FloodACheck::new, CheckType.FLOOD_A);
|
||||||
|
this.register(PacketPlayReceiveEvent.class, FloodBCheck::new, CheckType.FLOOD_B);
|
||||||
|
this.register(ItemStackDecodeEvent.class, FloodCCheck::new, CheckType.FLOOD_C);
|
||||||
|
this.register(ItemStackDecodeEvent.class, FloodDCheck::new, CheckType.FLOOD_D);
|
||||||
|
this.register(PlayerCommandPreprocessEvent.class, FloodFCheck::new, CheckType.FLOOD_F);
|
||||||
|
this.register(ReadSlotsEvent.class, FloodGCheck::new, CheckType.FLOOD_G);
|
||||||
|
this.register(Client.PLAYER_FLYING, PositionACheck::new, CheckType.POSITION_A);
|
||||||
|
this.register(Client.PLAYER_FLYING, PositionBCheck::new, CheckType.POSITION_B);
|
||||||
|
this.register(Client.PLAYER_FLYING, PositionCCheck::new, CheckType.POSITION_C);
|
||||||
|
this.register(Client.PLAYER_FLYING, PositionDCheck::new, CheckType.POSITION_D);
|
||||||
|
this.register(Client.PLUGIN_MESSAGE, PayloadACheck::new, CheckType.PAYLOAD_A);
|
||||||
|
this.register(Client.PLUGIN_MESSAGE, PayloadBCheck::new, CheckType.PAYLOAD_B);
|
||||||
|
this.register(Client.PLUGIN_MESSAGE, PayloadCCheck::new, CheckType.PAYLOAD_C);
|
||||||
|
this.register(
|
||||||
|
Client.PLUGIN_MESSAGE,
|
||||||
|
(result, result2) -> new PayloadDirectionCheck(result, result2, true),
|
||||||
|
CheckType.PAYLOAD_D);
|
||||||
|
this.register(
|
||||||
|
Client.PLUGIN_MESSAGE,
|
||||||
|
(result, result2) -> new PayloadDirectionCheck(result, result2, false),
|
||||||
|
CheckType.PAYLOAD_G);
|
||||||
|
if (matches) {
|
||||||
|
this.register(Client.PLUGIN_MESSAGE, PayloadECheck::new, CheckType.PAYLOAD_E);
|
||||||
|
}
|
||||||
|
this.register(Client.PLUGIN_MESSAGE, PayloadFCheck::new, CheckType.PAYLOAD_F);
|
||||||
|
this.register(Client.EDIT_BOOK, BookACheck::new, CheckType.BOOK_A);
|
||||||
|
this.register(Client.EDIT_BOOK, BookBCheck::new, CheckType.BOOK_B);
|
||||||
|
this.register(Client.EDIT_BOOK, BookCCheck::new, CheckType.BOOK_C);
|
||||||
|
this.register(Client.EDIT_BOOK, Book0Check::new, CheckType.BOOK_0);
|
||||||
|
this.register(Client.TAB_COMPLETE, TabACheck::new, CheckType.TAB_A);
|
||||||
|
this.register(Client.TAB_COMPLETE, TabBCheck::new, CheckType.TAB_B);
|
||||||
|
this.register(PlayerCommandPreprocessEvent.class, CommandACheck::new, CheckType.COMMAND_A);
|
||||||
|
if (version == ServerVersion.V_1_21_2 || version == ServerVersion.V_1_21_3) {
|
||||||
|
this.register(
|
||||||
|
Client.CRAFT_RECIPE_REQUEST,
|
||||||
|
(result2, result3) -> new BukkitCheckManager.RecipeACheck(result2, result3),
|
||||||
|
CheckType.RECIPE_A);
|
||||||
|
this.register(
|
||||||
|
Client.SET_DISPLAYED_RECIPE,
|
||||||
|
(result2, result3) -> new BukkitCheckManager.RecipeBCheck(result2, result3),
|
||||||
|
CheckType.RECIPE_B);
|
||||||
|
}
|
||||||
|
this.sortByPriority();
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] texts = new String[] {"MC|BEdit", null};
|
||||||
|
texts[1] = "MC|BSign";
|
||||||
|
VALUES = Lists.newArrayList(texts);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecipeACheck extends RecipeCheck<WrapperPlayClientCraftRecipeRequest> {
|
||||||
|
|
||||||
|
RecipeACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRecipeId(
|
||||||
|
WrapperPlayClientCraftRecipeRequest wrapperPlayClientCraftRecipeRequest) {
|
||||||
|
return wrapperPlayClientCraftRecipeRequest.getRecipeId().getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecipeBCheck extends RecipeCheck<WrapperPlayClientSetDisplayedRecipe> {
|
||||||
|
|
||||||
|
RecipeBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRecipeId(
|
||||||
|
WrapperPlayClientSetDisplayedRecipe wrapperPlayClientSetDisplayedRecipe) {
|
||||||
|
return wrapperPlayClientSetDisplayedRecipe.getRecipeId().getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package it.ytnoos.lpx.check;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public abstract class CreativeCheck extends AbstractCheck<PacketReceiveEvent> {
|
||||||
|
|
||||||
|
private final PacketTypeCommon packetType;
|
||||||
|
|
||||||
|
public CreativeCheck(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
CheckOptions checkOptions,
|
||||||
|
PacketTypeCommon packetTypeCommon) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
this.packetType = packetTypeCommon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, PacketReceiveEvent packetReceiveEvent) {
|
||||||
|
if (packetReceiveEvent.getPacketType() != this.packetType) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player != null && player.getGameMode() != GameMode.CREATIVE) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[0];
|
||||||
|
this.flagViolation(packetReceiveEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
package it.ytnoos.lpx.check;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.compat.ReflectionNames;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public abstract class RecipeCheck<T> extends AbstractCheck<T> {
|
||||||
|
|
||||||
|
private static List<?> values;
|
||||||
|
|
||||||
|
public RecipeCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, T t) {
|
||||||
|
if (values == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int recipeId = this.getRecipeId(t);
|
||||||
|
int size2 = values.size();
|
||||||
|
if (recipeId >= 0 && recipeId < size2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("recipeId", recipeId), null};
|
||||||
|
flagInfos[1] = FlagInfo.of("displaysSize", size2);
|
||||||
|
this.flagViolation(t, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract int getRecipeId(T t);
|
||||||
|
|
||||||
|
static {
|
||||||
|
try {
|
||||||
|
Object result =
|
||||||
|
Class.forName("net.minecraft.server.MinecraftServer")
|
||||||
|
.getMethod("getServer")
|
||||||
|
.invoke(null);
|
||||||
|
Class<?> classValue = result.getClass();
|
||||||
|
Class[] classs = new Class[0];
|
||||||
|
Class classValue2 = classValue;
|
||||||
|
String text =
|
||||||
|
ReflectionNames.methodName((String) "getRecipeManager", classValue2, classs);
|
||||||
|
Object result2 = classValue2.getMethod(text, classs).invoke(result);
|
||||||
|
classValue = result2.getClass();
|
||||||
|
Class classValue3 = classValue;
|
||||||
|
String text2 = ReflectionNames.fieldName(classValue3, (String) "allDisplays");
|
||||||
|
Field declaredField = classValue3.getDeclaredField(text2);
|
||||||
|
declaredField.setAccessible(true);
|
||||||
|
values = (List<?>) declaredField.get(result2);
|
||||||
|
} catch (Exception exception) {
|
||||||
|
exception.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.book;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTType;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Book0Check extends AbstractCheck<WrapperPlayClientEditBook> {
|
||||||
|
|
||||||
|
public Book0Check(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, WrapperPlayClientEditBook wrapperPlayClientEditBook) {
|
||||||
|
ItemStack itemStack = wrapperPlayClientEditBook.getItemStack();
|
||||||
|
NBTList nBTList = new NBTList(NBTType.STRING);
|
||||||
|
NBTList nBTList2 = nBTList;
|
||||||
|
NBTCompound nBTCompound;
|
||||||
|
if (itemStack == null) {
|
||||||
|
NBTCompound nBTCompound2 = new NBTCompound();
|
||||||
|
nBTCompound = nBTCompound2;
|
||||||
|
for (String text : wrapperPlayClientEditBook.getPages()) {
|
||||||
|
NBTString nBTString = new NBTString(text);
|
||||||
|
nBTList2.addTag(nBTString);
|
||||||
|
}
|
||||||
|
nBTCompound.setTag("pages", nBTList2);
|
||||||
|
itemStack =
|
||||||
|
ItemStack.builder()
|
||||||
|
.type(ItemTypes.WRITABLE_BOOK)
|
||||||
|
.nbt(nBTCompound)
|
||||||
|
.amount(1)
|
||||||
|
.build();
|
||||||
|
} else {
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
nBTCompound = nBT;
|
||||||
|
if (nBT != null) {
|
||||||
|
NBTList stringListTagOrNull = nBTCompound.getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull != null) {
|
||||||
|
nBTList2 = stringListTagOrNull;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NBTCompound nBTCompound3 = new NBTCompound();
|
||||||
|
nBTCompound = nBTCompound3;
|
||||||
|
itemStack.setNBT(nBTCompound);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
protocolPlayer.setProcessingPayload(true);
|
||||||
|
try {
|
||||||
|
NBTDecodeEvent nBTDecodeEvent =
|
||||||
|
new NBTDecodeEvent(wrapperPlayClientEditBook, null, nBTCompound);
|
||||||
|
CheckResult checkResult =
|
||||||
|
protocolPlayer
|
||||||
|
.handleChecks(NBTDecodeEvent.class, nBTDecodeEvent, this.isPreVia())
|
||||||
|
.result();
|
||||||
|
CheckResult checkResult2 = checkResult;
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent =
|
||||||
|
new ItemStackDecodeEvent(wrapperPlayClientEditBook, null, itemStack);
|
||||||
|
CheckResult checkResult3 =
|
||||||
|
checkResult2.merge(
|
||||||
|
protocolPlayer
|
||||||
|
.handleChecks(
|
||||||
|
ItemStackDecodeEvent.class,
|
||||||
|
itemStackDecodeEvent,
|
||||||
|
this.isPreVia())
|
||||||
|
.result());
|
||||||
|
checkResult2 = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
if (checkResult2 == CheckResult.CHANGE) {
|
||||||
|
ArrayList<String> values = new ArrayList<>();
|
||||||
|
for (NBTString nBTString2 :
|
||||||
|
((Iterable<NBTString>) ((Iterable<?>) nBTList2.getTags()))) {
|
||||||
|
values.add(nBTString2.getValue());
|
||||||
|
}
|
||||||
|
wrapperPlayClientEditBook.setPages(values);
|
||||||
|
}
|
||||||
|
return checkResult2;
|
||||||
|
} finally {
|
||||||
|
protocolPlayer.setProcessingPayload(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.book;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||||
|
|
||||||
|
public class BookACheck extends AbstractCheck<WrapperPlayClientEditBook> {
|
||||||
|
|
||||||
|
private int maxSize;
|
||||||
|
|
||||||
|
public BookACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 15);
|
||||||
|
this.maxSize = this.calculateLimit((String) "max", ((int) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, WrapperPlayClientEditBook wrapperPlayClientEditBook) {
|
||||||
|
String title = wrapperPlayClientEditBook.getTitle();
|
||||||
|
if (title != null) {
|
||||||
|
int size = title.length();
|
||||||
|
if (size > this.maxSize) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("title", title), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("length", size);
|
||||||
|
flagInfos[2] = FlagInfo.of("max", this.maxSize);
|
||||||
|
this.flagViolation(wrapperPlayClientEditBook, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.book;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||||
|
import it.ytnoos.lpx.utils.TimeUtils;
|
||||||
|
|
||||||
|
public class BookBCheck extends AbstractCheck<WrapperPlayClientEditBook> {
|
||||||
|
|
||||||
|
private long last;
|
||||||
|
|
||||||
|
private int delay;
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
public BookBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = Integer.valueOf((short) 1000);
|
||||||
|
this.delay = this.calculateLimit((String) "delay", ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((byte) 15);
|
||||||
|
RollingIntervalCounter rollingIntervalCounter2 =
|
||||||
|
new RollingIntervalCounter(this.calculateLimit((String) "max", ((int) value2)));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, WrapperPlayClientEditBook wrapperPlayClientEditBook) {
|
||||||
|
if (this.rollingIntervalCounter.increment()) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("pps", this.rollingIntervalCounter.getMaxCounter())
|
||||||
|
};
|
||||||
|
this.flagViolation(wrapperPlayClientEditBook, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else if (this.rollingIntervalCounter.isOverLimit()) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
long value = this.last;
|
||||||
|
Long value2 = ((Long) value);
|
||||||
|
long value3 = TimeUtils.calculateTime(value2);
|
||||||
|
this.last = TimeUtils.current();
|
||||||
|
if (value3 < this.delay) {
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[] {FlagInfo.of("delay", value3)};
|
||||||
|
this.flagViolation(wrapperPlayClientEditBook, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.book;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientEditBook;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public class BookCCheck extends AbstractCheck<WrapperPlayClientEditBook> {
|
||||||
|
|
||||||
|
public BookCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, WrapperPlayClientEditBook wrapperPlayClientEditBook) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
ItemStack itemInHand = player.getInventory().getItemInHand();
|
||||||
|
if (itemInHand == null
|
||||||
|
|| !itemInHand.getType().name().contains("QUILL")
|
||||||
|
&& !itemInHand.getType().name().contains("WRITABLE")) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of(
|
||||||
|
"hand",
|
||||||
|
itemInHand == null ? "null" : itemInHand.getType().name())
|
||||||
|
};
|
||||||
|
this.flagViolation(wrapperPlayClientEditBook, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.command;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.utils.string.StringUtils;
|
||||||
|
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CommandACheck extends AbstractCheck<PlayerCommandPreprocessEvent> {
|
||||||
|
|
||||||
|
private static final String[] TEXTS;
|
||||||
|
|
||||||
|
private List<String> values;
|
||||||
|
|
||||||
|
public CommandACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String[] texts = TEXTS;
|
||||||
|
this.values = this.createValues((String) "commands", texts);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
PlayerCommandPreprocessEvent playerCommandPreprocessEvent) {
|
||||||
|
String message = playerCommandPreprocessEvent.getMessage();
|
||||||
|
if (message != null && this.values != null) {
|
||||||
|
for (String text : this.values) {
|
||||||
|
CharSequence charSequence = ((CharSequence) message);
|
||||||
|
if (StringUtils.testCharSequence(charSequence, ((CharSequence) text))) {
|
||||||
|
playerCommandPreprocessEvent.setCancelled(true);
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("command", message)};
|
||||||
|
this.flagViolation(playerCommandPreprocessEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] texts = new String[22];
|
||||||
|
texts[0] = "//calc";
|
||||||
|
texts[1] = "//calculate";
|
||||||
|
texts[2] = "//eval";
|
||||||
|
texts[3] = "//evaluate";
|
||||||
|
texts[4] = "//solve";
|
||||||
|
texts[5] = "/hd readtext";
|
||||||
|
texts[6] = "/holo readtext";
|
||||||
|
texts[7] = "/hologram readtext";
|
||||||
|
texts[8] = "/holograms readtext";
|
||||||
|
texts[9] = "/holographicdisplays readtext";
|
||||||
|
texts[10] = "/pex promote";
|
||||||
|
texts[11] = "/pex demote";
|
||||||
|
texts[12] = "/promote";
|
||||||
|
texts[13] = "/demote";
|
||||||
|
texts[14] = "/execute";
|
||||||
|
texts[15] = "/mv ^";
|
||||||
|
texts[16] = "/mv help ^";
|
||||||
|
texts[17] = "/mvhelp ^";
|
||||||
|
texts[18] = "/mv <";
|
||||||
|
texts[19] = "/mv help <";
|
||||||
|
texts[20] = "/mvhelp <";
|
||||||
|
texts[21] = "/$";
|
||||||
|
TEXTS = texts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class CreativeACheck extends AbstractCheck<PacketReceiveEvent> {
|
||||||
|
|
||||||
|
public CreativeACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, PacketReceiveEvent packetReceiveEvent) {
|
||||||
|
if (packetReceiveEvent.getPacketType() != Client.CREATIVE_INVENTORY_ACTION) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (!protocolPlayer.getPrinterData().isUsingPrinter()
|
||||||
|
&& player.getGameMode() != GameMode.CREATIVE) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[0];
|
||||||
|
this.flagViolation(packetReceiveEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.enchantment.Enchantment;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction;
|
||||||
|
|
||||||
|
public class CreativeBCheck extends AbstractCheck<WrapperPlayClientCreativeInventoryAction> {
|
||||||
|
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
private int min;
|
||||||
|
|
||||||
|
public CreativeBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 127);
|
||||||
|
String text = (String) "max";
|
||||||
|
String text2 = text;
|
||||||
|
this.max = this.calculateLimit(text2, ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((byte) 0);
|
||||||
|
String text3 = "min";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.min = this.calculateLimit(text4, ((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientCreativeInventoryAction wrapperPlayClientCreativeInventoryAction) {
|
||||||
|
try {
|
||||||
|
for (Enchantment enchantment :
|
||||||
|
wrapperPlayClientCreativeInventoryAction
|
||||||
|
.getItemStack()
|
||||||
|
.getEnchantments(protocolPlayer.getUser().getClientVersion())) {
|
||||||
|
int level = enchantment.getLevel();
|
||||||
|
if (level > this.max || level < this.min) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("enchantment", enchantment.getType().getName()), null
|
||||||
|
};
|
||||||
|
flagInfos[1] = FlagInfo.of("enchantment-level", level);
|
||||||
|
this.flagViolation(wrapperPlayClientCreativeInventoryAction, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction;
|
||||||
|
import it.ytnoos.lpx.utils.ItemUtils;
|
||||||
|
|
||||||
|
public class CreativeCCheck extends AbstractCheck<WrapperPlayClientCreativeInventoryAction> {
|
||||||
|
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public CreativeCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 3000);
|
||||||
|
this.max = this.calculateLimit((String) "max", ((int) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientCreativeInventoryAction wrapperPlayClientCreativeInventoryAction) {
|
||||||
|
ItemStack itemStack = wrapperPlayClientCreativeInventoryAction.getItemStack();
|
||||||
|
String text = (String) ItemUtils.getDisplayName(itemStack).orElse(null);
|
||||||
|
if (text == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int size = text.length();
|
||||||
|
if (size <= this.max) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("length", size), null};
|
||||||
|
flagInfos[1] = FlagInfo.of("display-name", text);
|
||||||
|
this.flagViolation(wrapperPlayClientCreativeInventoryAction, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction;
|
||||||
|
import it.ytnoos.lpx.utils.ItemUtils;
|
||||||
|
|
||||||
|
public class CreativeDCheck extends AbstractCheck<WrapperPlayClientCreativeInventoryAction> {
|
||||||
|
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public CreativeDCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 16384);
|
||||||
|
this.max = this.calculateLimit((String) "max", ((int) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientCreativeInventoryAction wrapperPlayClientCreativeInventoryAction) {
|
||||||
|
ItemStack itemStack = wrapperPlayClientCreativeInventoryAction.getItemStack();
|
||||||
|
NBTList nBTList = (NBTList) ItemUtils.createOptional(itemStack).orElse(null);
|
||||||
|
if (nBTList != null && !nBTList.isEmpty()) {
|
||||||
|
int value = 0;
|
||||||
|
for (NBTString nBTString : ((Iterable<NBTString>) ((Iterable<?>) nBTList.getTags()))) {
|
||||||
|
value += nBTString.getValue().length();
|
||||||
|
}
|
||||||
|
if (value <= this.max) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("lore-length", value)};
|
||||||
|
this.flagViolation(wrapperPlayClientCreativeInventoryAction, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.utils.PacketUtils;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class CreativeECheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private static final String[] TEXTS;
|
||||||
|
|
||||||
|
private List<String> blacklist;
|
||||||
|
|
||||||
|
public CreativeECheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String[] texts = TEXTS;
|
||||||
|
this.blacklist = this.createValues((String) "blacklist", texts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
ItemType type = itemStack.getType();
|
||||||
|
if (type != ItemTypes.BOOK
|
||||||
|
&& type != ItemTypes.WRITABLE_BOOK
|
||||||
|
&& type != ItemTypes.WRITTEN_BOOK) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
if (nBT == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
for (String text : this.blacklist) {
|
||||||
|
NBT nBT2 = (NBT) nBT;
|
||||||
|
if (PacketUtils.testText(nBT2, text)) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("blacklisted", text)};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] texts = new String[] {"run_command", null};
|
||||||
|
texts[1] = "translation.test.invalid";
|
||||||
|
TEXTS = texts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction;
|
||||||
|
|
||||||
|
public class CreativeFCheck extends AbstractCheck<WrapperPlayClientCreativeInventoryAction> {
|
||||||
|
|
||||||
|
private int max;
|
||||||
|
|
||||||
|
public CreativeFCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 64);
|
||||||
|
this.max = this.calculateLimit((String) "max", ((int) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientCreativeInventoryAction wrapperPlayClientCreativeInventoryAction) {
|
||||||
|
int amount = wrapperPlayClientCreativeInventoryAction.getItemStack().getAmount();
|
||||||
|
if (amount <= this.max) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("amount", amount)};
|
||||||
|
this.flagViolation(wrapperPlayClientCreativeInventoryAction, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTNumber;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction;
|
||||||
|
|
||||||
|
import org.bukkit.World;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class CreativeGCheck extends AbstractCheck<WrapperPlayClientCreativeInventoryAction> {
|
||||||
|
|
||||||
|
public CreativeGCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientCreativeInventoryAction wrapperPlayClientCreativeInventoryAction) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTCompound nBT = wrapperPlayClientCreativeInventoryAction.getItemStack().getNBT();
|
||||||
|
if (nBT == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTCompound compoundTagOrNull = nBT.getCompoundTagOrNull("BlockEntityTag");
|
||||||
|
if (compoundTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTNumber numberTagOrNull = compoundTagOrNull.getNumberTagOrNull("x");
|
||||||
|
if (numberTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTNumber numberTagOrNull2 = compoundTagOrNull.getNumberTagOrNull("z");
|
||||||
|
if (numberTagOrNull2 == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int value;
|
||||||
|
int value2;
|
||||||
|
try {
|
||||||
|
value = numberTagOrNull.getAsInt();
|
||||||
|
value2 = numberTagOrNull2.getAsInt();
|
||||||
|
} catch (Exception exception) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int value3 = value / 16;
|
||||||
|
int value4 = value2 / 16;
|
||||||
|
World world = player.getWorld();
|
||||||
|
if (!world.isChunkLoaded(value3, value4)) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[5];
|
||||||
|
flagInfos[0] = FlagInfo.of("world", world.getName());
|
||||||
|
flagInfos[1] = FlagInfo.of("x", value);
|
||||||
|
flagInfos[2] = FlagInfo.of("z", value2);
|
||||||
|
flagInfos[3] = FlagInfo.of("chunk-x", value3);
|
||||||
|
flagInfos[4] = FlagInfo.of("chunk-z", value4);
|
||||||
|
this.flagViolation(wrapperPlayClientCreativeInventoryAction, flagInfos);
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.CreativeCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
|
||||||
|
public class CreativeHCheck extends CreativeCheck {
|
||||||
|
|
||||||
|
public CreativeHCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions, Client.TEST_INSTANCE_BLOCK_ACTION);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.creative;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.CreativeCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
|
||||||
|
public class CreativeICheck extends CreativeCheck {
|
||||||
|
|
||||||
|
public CreativeICheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions, Client.SET_TEST_BLOCK);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||||
|
|
||||||
|
public class FloodACheck extends AbstractCheck<PacketReceiveEvent> {
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
public FloodACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 1100);
|
||||||
|
RollingIntervalCounter rollingIntervalCounter2 =
|
||||||
|
new RollingIntervalCounter(this.calculateLimit((String) "max", ((int) value)));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, PacketReceiveEvent packetReceiveEvent) {
|
||||||
|
if (protocolPlayer.getPrinterData().isUsingPrinter()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter.increment()) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("pps", this.rollingIntervalCounter.getMaxCounter())
|
||||||
|
};
|
||||||
|
this.flagViolation(packetReceiveEvent, flagInfos);
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,375 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RepeatedIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.PacketReceiveEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||||
|
import it.ytnoos.lpx.player.ProtocolPlayerImpl;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class FloodBCheck extends AbstractCheck<PacketReceiveEvent> {
|
||||||
|
|
||||||
|
private Map<PacketTypeCommon, List<FloodBCheck.WindowSample>> entries;
|
||||||
|
|
||||||
|
public FloodBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
HashMap entries2 = new HashMap();
|
||||||
|
this.entries = entries2;
|
||||||
|
FileConfiguration fileConfiguration =
|
||||||
|
((FileConfiguration) ((FileConfiguration) this.getCheckConfiguration()));
|
||||||
|
ConfigurationSection configurationSection =
|
||||||
|
fileConfiguration.getConfigurationSection(this.createText((String) "limits"));
|
||||||
|
if (configurationSection != null) {
|
||||||
|
for (String text : configurationSection.getKeys(false)) {
|
||||||
|
ArrayList<it.ytnoos.lpx.check.impl.flood.FloodBCheck.WindowSample> values =
|
||||||
|
new ArrayList<>();
|
||||||
|
if (configurationSection.isList(text)) {
|
||||||
|
for (Map<?, ?> entries3 : configurationSection.getMapList(text)) {
|
||||||
|
values.add(this.createWindowSample(entries3));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ConfigurationSection configurationSection2 =
|
||||||
|
configurationSection.getConfigurationSection(text);
|
||||||
|
if (configurationSection2 != null) {
|
||||||
|
values.add(this.createWindowSample(configurationSection2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!values.isEmpty()) {
|
||||||
|
this.handleValue(text, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileConfiguration =
|
||||||
|
((FileConfiguration) ((FileConfiguration) this.getCheckConfiguration()));
|
||||||
|
for (String text2 :
|
||||||
|
fileConfiguration.getStringList(this.createText((String) "limits"))) {
|
||||||
|
String[] texts = text2.split(",");
|
||||||
|
int value = texts.length;
|
||||||
|
if (value < 2) {
|
||||||
|
ProtocolPlayerImpl protocolPlayerImpl = (ProtocolPlayerImpl) this.player;
|
||||||
|
Logger logger = protocolPlayerImpl.getLpx().getLogger();
|
||||||
|
logger.warning(() -> text2 + " is not a valid FloodB parameter!");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
int value2 = Integer.parseInt(texts[1]);
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter;
|
||||||
|
if (value == 2) {
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter2 =
|
||||||
|
new RepeatedIntervalCounter(value2, 6, 3);
|
||||||
|
repeatedIntervalCounter = repeatedIntervalCounter2;
|
||||||
|
} else if (value == 3) {
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter3 =
|
||||||
|
new RepeatedIntervalCounter(
|
||||||
|
value2, Integer.parseInt(texts[2]), 3, 1);
|
||||||
|
repeatedIntervalCounter = repeatedIntervalCounter3;
|
||||||
|
} else {
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter4 =
|
||||||
|
new RepeatedIntervalCounter(
|
||||||
|
value2,
|
||||||
|
Integer.parseInt(texts[2]),
|
||||||
|
Integer.parseInt(texts[3]),
|
||||||
|
Integer.parseInt(texts[4]));
|
||||||
|
repeatedIntervalCounter = repeatedIntervalCounter4;
|
||||||
|
}
|
||||||
|
String text3 = texts[0];
|
||||||
|
long value3 = -1L;
|
||||||
|
long value4 = -1L;
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter5 = repeatedIntervalCounter;
|
||||||
|
FloodBCheck.WindowSample windowSample =
|
||||||
|
new FloodBCheck.WindowSample(
|
||||||
|
repeatedIntervalCounter5,
|
||||||
|
(boolean) false,
|
||||||
|
value4,
|
||||||
|
value3,
|
||||||
|
(boolean) false);
|
||||||
|
this.registerFallbackLimit(text3, windowSample);
|
||||||
|
} catch (NumberFormatException numberFormatException) {
|
||||||
|
ProtocolPlayerImpl protocolPlayerImpl2 = (ProtocolPlayerImpl) this.player;
|
||||||
|
protocolPlayerImpl2
|
||||||
|
.getLpx()
|
||||||
|
.getLogger()
|
||||||
|
.severe("Second and third parameter must be numbers for FloodB!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private FloodBCheck.WindowSample createWindowSample(ConfigurationSection section) {
|
||||||
|
int intValue = section.getInt("max", 20);
|
||||||
|
int intValue2 = section.getInt("interval", 500);
|
||||||
|
int intValue3 = section.getInt("periods", 5);
|
||||||
|
int intValue4 = section.getInt("warnings", 2);
|
||||||
|
boolean matches = "drop".equalsIgnoreCase(section.getString("action", "flag"));
|
||||||
|
long longValue = section.getLong("min-bytes", -1L);
|
||||||
|
long longValue2 = section.getLong("max-bytes", -1L);
|
||||||
|
boolean booleanValue = section.getBoolean("allow-duplicates", false);
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter =
|
||||||
|
new RepeatedIntervalCounter(intValue, intValue2, intValue3, intValue4);
|
||||||
|
return new FloodBCheck.WindowSample(
|
||||||
|
repeatedIntervalCounter, matches, longValue, longValue2, booleanValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private FloodBCheck.WindowSample createWindowSample(Map entries) {
|
||||||
|
Integer value = Integer.valueOf((byte) 20);
|
||||||
|
Map entries2 = entries;
|
||||||
|
Map entries3 = entries2;
|
||||||
|
int intValue = getInt(entries3, (String) "max", ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((short) 500);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries4 = entries2;
|
||||||
|
int intValue2 = getInt(entries4, (String) "interval", ((int) value2));
|
||||||
|
Integer value3 = Integer.valueOf((byte) 5);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries5 = entries2;
|
||||||
|
int intValue3 = getInt(entries5, (String) "periods", ((int) value3));
|
||||||
|
Integer value4 = Integer.valueOf((byte) 2);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries6 = entries2;
|
||||||
|
int intValue4 = getInt(entries6, (String) "warnings", ((int) value4));
|
||||||
|
Object result = entries.get("action");
|
||||||
|
boolean matches = "drop".equalsIgnoreCase(result != null ? String.valueOf(result) : "flag");
|
||||||
|
long value5 = -1L;
|
||||||
|
Long value6 = ((Long) value5);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries7 = entries2;
|
||||||
|
long longValue = getLong(entries7, (String) "min-bytes", ((long) value6));
|
||||||
|
long value7 = -1L;
|
||||||
|
Long value8 = ((Long) value7);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries8 = entries2;
|
||||||
|
long longValue2 = getLong(entries8, (String) "max-bytes", ((long) value8));
|
||||||
|
Boolean matches2 = ((Boolean) (boolean) false);
|
||||||
|
entries2 = entries;
|
||||||
|
Map entries9 = entries2;
|
||||||
|
boolean booleanValue =
|
||||||
|
getBoolean(entries9, (String) "allow-duplicates", ((boolean) matches2));
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter =
|
||||||
|
new RepeatedIntervalCounter(intValue, intValue2, intValue3, intValue4);
|
||||||
|
return new FloodBCheck.WindowSample(
|
||||||
|
repeatedIntervalCounter, matches, longValue, longValue2, booleanValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int getInt(Map entries, Object result, int value) {
|
||||||
|
Object result2 = entries.get(result);
|
||||||
|
return result2 instanceof Number ? ((Number) result2).intValue() : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static long getLong(Map entries, Object result, long value) {
|
||||||
|
Object result2 = entries.get(result);
|
||||||
|
return result2 instanceof Number ? ((Number) result2).longValue() : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean getBoolean(Map entries, Object result, boolean matches) {
|
||||||
|
Object result2 = entries.get(result);
|
||||||
|
if (result2 instanceof Boolean) {
|
||||||
|
return (Boolean) result2;
|
||||||
|
} else {
|
||||||
|
return result2 instanceof String ? Boolean.parseBoolean((String) result2) : matches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, PacketReceiveEvent packetReceiveEvent) {
|
||||||
|
if (protocolPlayer.getPrinterData().isUsingPrinter()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FloodBCheck.PacketSample packetSample =
|
||||||
|
this.createPacketSample(protocolPlayer, packetReceiveEvent);
|
||||||
|
List<FloodBCheck.WindowSample> values = this.createValues(packetSample);
|
||||||
|
if (values == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
PacketTypeCommon packetType2 = packetReceiveEvent.getPacketType();
|
||||||
|
double weight = this.getWeight(packetType2, protocolPlayer);
|
||||||
|
boolean matches = false;
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
for (FloodBCheck.WindowSample windowSample : values) {
|
||||||
|
long time = packetSample.getTime();
|
||||||
|
Long value = ((Long) time);
|
||||||
|
if (windowSample.testTime(((long) value))) {
|
||||||
|
long time2 = packetSample.getTime();
|
||||||
|
Long value2 = ((Long) now);
|
||||||
|
Long value3 = ((Long) time2);
|
||||||
|
long value4 = ((long) value3);
|
||||||
|
if (!windowSample.testTime(value4, ((long) value2))) {
|
||||||
|
boolean matches2 = windowSample.counter.increment(weight);
|
||||||
|
if (matches2) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[5];
|
||||||
|
flagInfos[0] = FlagInfo.of("packet", packetSample.packetType().getName());
|
||||||
|
flagInfos[1] =
|
||||||
|
FlagInfo.of("max-counter", windowSample.counter.getMaxCounter());
|
||||||
|
flagInfos[2] =
|
||||||
|
FlagInfo.of("interval", windowSample.counter.getInterval() + "ms");
|
||||||
|
flagInfos[3] =
|
||||||
|
FlagInfo.of("max-periods", windowSample.counter.getMaxPeriods());
|
||||||
|
flagInfos[4] =
|
||||||
|
FlagInfo.of("max-warnings", windowSample.counter.getMaxWarnings());
|
||||||
|
this.flagViolation(packetReceiveEvent, flagInfos);
|
||||||
|
}
|
||||||
|
if (windowSample.enabled && (matches2 || windowSample.counter.isOverLimit())) {
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches ? CheckResult.DENY : CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<it.ytnoos.lpx.check.impl.flood.FloodBCheck.WindowSample> createValues(
|
||||||
|
FloodBCheck.PacketSample packetSample) {
|
||||||
|
return this.entries.get(packetSample.packetType());
|
||||||
|
}
|
||||||
|
|
||||||
|
private FloodBCheck.PacketSample createPacketSample(
|
||||||
|
ProtocolPlayer protocolPlayer, PacketReceiveEvent packetReceiveEvent) {
|
||||||
|
PacketTypeCommon packetType = packetReceiveEvent.getPacketType();
|
||||||
|
return new FloodBCheck.PacketSample(packetType, this.calculateTime(protocolPlayer));
|
||||||
|
}
|
||||||
|
|
||||||
|
private long calculateTime(ProtocolPlayer protocolPlayer) {
|
||||||
|
return protocolPlayer.getLastReceivedPacket() != null
|
||||||
|
? protocolPlayer.getLastReceivedPacket().getSize()
|
||||||
|
: -1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleValue(String text, Object result) {
|
||||||
|
String text2 = normalizePacketName(text);
|
||||||
|
Client client = this.createClient(text2);
|
||||||
|
if (client == null) {
|
||||||
|
this.warnInvalidPacketKey(text);
|
||||||
|
} else {
|
||||||
|
this.entries.put(client, (List<FloodBCheck.WindowSample>) result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerFallbackLimit(String text, Object result) {
|
||||||
|
String text2 = normalizePacketName(text);
|
||||||
|
Client client = this.createClient(text2);
|
||||||
|
if (client == null) {
|
||||||
|
this.warnInvalidPacketKey(text);
|
||||||
|
} else {
|
||||||
|
this.entries
|
||||||
|
.computeIfAbsent(client, result2 -> new ArrayList<>())
|
||||||
|
.add((FloodBCheck.WindowSample) result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Client createClient(String text) {
|
||||||
|
try {
|
||||||
|
return Client.valueOf(text);
|
||||||
|
} catch (IllegalArgumentException illegalArgumentException) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void warnInvalidPacketKey(String text) {
|
||||||
|
ProtocolPlayerImpl protocolPlayerImpl = (ProtocolPlayerImpl) this.player;
|
||||||
|
Logger logger = protocolPlayerImpl.getLpx().getLogger();
|
||||||
|
logger.warning(
|
||||||
|
() -> {
|
||||||
|
return (String) "Invalid FloodB packet key '"
|
||||||
|
+ text
|
||||||
|
+ "' in config, skipping it.";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizePacketName(String text) {
|
||||||
|
return text.trim().toUpperCase(Locale.ROOT);
|
||||||
|
}
|
||||||
|
|
||||||
|
private double getWeight(PacketTypeCommon packetTypeCommon, ProtocolPlayer protocolPlayer) {
|
||||||
|
return packetTypeCommon != Client.CLICK_WINDOW
|
||||||
|
&& packetTypeCommon != Client.CREATIVE_INVENTORY_ACTION
|
||||||
|
? 1.0
|
||||||
|
: protocolPlayer.itemFloodMultiplier();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
record PacketSample(PacketTypeCommon packetType, long time) {
|
||||||
|
|
||||||
|
public long getTime() {
|
||||||
|
return this.time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class WindowSample {
|
||||||
|
|
||||||
|
private final RepeatedIntervalCounter counter;
|
||||||
|
|
||||||
|
private final boolean enabled;
|
||||||
|
|
||||||
|
private final long time;
|
||||||
|
|
||||||
|
private final long maxBytes;
|
||||||
|
|
||||||
|
private final boolean enabled2;
|
||||||
|
|
||||||
|
private long time2 = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
private long time3 = Long.MIN_VALUE;
|
||||||
|
|
||||||
|
private WindowSample(
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter,
|
||||||
|
boolean enabled,
|
||||||
|
long time,
|
||||||
|
long maxBytes,
|
||||||
|
boolean enabled2) {
|
||||||
|
this.counter = repeatedIntervalCounter;
|
||||||
|
this.enabled = enabled;
|
||||||
|
this.time = time;
|
||||||
|
this.maxBytes = maxBytes;
|
||||||
|
this.enabled2 = enabled2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RepeatedIntervalCounter counter() {
|
||||||
|
return this.counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return this.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean testTime(long value) {
|
||||||
|
if (value < 0L) {
|
||||||
|
return this.time < 0L && this.maxBytes < 0L;
|
||||||
|
} else {
|
||||||
|
return this.time >= 0L && value < this.time
|
||||||
|
? false
|
||||||
|
: this.maxBytes < 0L || value <= this.maxBytes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean testTime(long time2, long time3) {
|
||||||
|
if (this.enabled2 && time2 >= 0L) {
|
||||||
|
boolean matches =
|
||||||
|
this.time2 == time2 && time3 - this.time3 <= this.counter.getInterval();
|
||||||
|
this.time2 = time2;
|
||||||
|
this.time3 = time3;
|
||||||
|
return matches;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RepeatedIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.utils.ItemUtils;
|
||||||
|
|
||||||
|
public class FloodCCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private RepeatedIntervalCounter repeatedIntervalCounter;
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
private long time2;
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
public FloodCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value2 = Integer.valueOf((byte) 100);
|
||||||
|
String text = (String) "reset-interval";
|
||||||
|
String text2 = text;
|
||||||
|
int value3 = this.calculateLimit(text2, ((int) value2));
|
||||||
|
Integer value4 = Integer.valueOf((byte) 6);
|
||||||
|
String text3 = "max-periods";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
int value5 = this.calculateLimit(text4, ((int) value4));
|
||||||
|
Integer value6 = Integer.valueOf((byte) 3);
|
||||||
|
String text5 = "max-warnings";
|
||||||
|
text = text5;
|
||||||
|
String text6 = text;
|
||||||
|
int value7 = this.calculateLimit(text6, ((int) value6));
|
||||||
|
Integer value8 = Integer.valueOf((byte) 32);
|
||||||
|
String text7 = "sustained-max";
|
||||||
|
text = text7;
|
||||||
|
String text8 = text;
|
||||||
|
int value9 = this.calculateLimit(text8, ((int) value8));
|
||||||
|
Integer value10 = Integer.valueOf((short) 1000);
|
||||||
|
String text9 = "sustained-interval";
|
||||||
|
text = text9;
|
||||||
|
String text10 = text;
|
||||||
|
int value11 = this.calculateLimit(text10, ((int) value10));
|
||||||
|
Long value12 = ((Long) 6000L);
|
||||||
|
String text11 = (String) "big-threshold";
|
||||||
|
String text12 = text11;
|
||||||
|
this.time = this.calculateTime(text12, ((long) value12));
|
||||||
|
Long value13 = ((Long) 512L);
|
||||||
|
String text13 = "harmless-threshold";
|
||||||
|
text11 = text13;
|
||||||
|
String text14 = text11;
|
||||||
|
this.time2 = this.calculateTime(text14, ((long) value13));
|
||||||
|
Double value14 = ((Double) (double) 0.05);
|
||||||
|
this.value =
|
||||||
|
Math.max(
|
||||||
|
0.01,
|
||||||
|
this.calculateValue((String) "harmless-multiplier", ((double) value14)));
|
||||||
|
Integer value15 = Integer.valueOf((byte) 20);
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter2 =
|
||||||
|
new RepeatedIntervalCounter(
|
||||||
|
this.calculateLimit((String) "max", ((int) value15)),
|
||||||
|
value3,
|
||||||
|
value5,
|
||||||
|
value7);
|
||||||
|
this.repeatedIntervalCounter = repeatedIntervalCounter2;
|
||||||
|
this.rollingIntervalCounter =
|
||||||
|
value9 >= 0 ? new RollingIntervalCounter(value9, value11) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (protocolPlayer.getPrinterData().isUsingPrinter()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int decodedSizeBytes = itemStackDecodeEvent.getItemStack().getDecodedSizeBytes();
|
||||||
|
if (decodedSizeBytes <= 0) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
double value2 = (int) (decodedSizeBytes / this.time / 4L);
|
||||||
|
double value3 = value2;
|
||||||
|
if (value2 == 0.0) {
|
||||||
|
value3 = 1.0;
|
||||||
|
}
|
||||||
|
if (decodedSizeBytes < this.time) {
|
||||||
|
value3 = 0.25;
|
||||||
|
}
|
||||||
|
if (decodedSizeBytes <= this.time2) {
|
||||||
|
value3 *= this.value;
|
||||||
|
}
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
if (ItemUtils.testItemStack(itemStack)) {
|
||||||
|
value3 *= 0.15;
|
||||||
|
} else {
|
||||||
|
value3 *= protocolPlayer.itemFloodMultiplier();
|
||||||
|
}
|
||||||
|
if (this.repeatedIntervalCounter.increment(value3)) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("max-counter", this.repeatedIntervalCounter.getMaxCounter()),
|
||||||
|
null
|
||||||
|
};
|
||||||
|
flagInfos[1] = FlagInfo.of("size", decodedSizeBytes);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter != null) {
|
||||||
|
if (this.rollingIntervalCounter.increment(value3)) {
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[4];
|
||||||
|
flagInfos2[0] = FlagInfo.of("mode", "rolling");
|
||||||
|
flagInfos2[1] =
|
||||||
|
FlagInfo.of("max-counter", this.rollingIntervalCounter.getMaxCounter());
|
||||||
|
flagInfos2[2] =
|
||||||
|
FlagInfo.of("interval", this.rollingIntervalCounter.getInterval() + "ms");
|
||||||
|
flagInfos2[3] = FlagInfo.of("size", decodedSizeBytes);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter.isOverLimit()) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,93 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
public class FloodDCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter2;
|
||||||
|
|
||||||
|
public FloodDCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
FileConfiguration fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
RollingIntervalCounter rollingIntervalCounter3 =
|
||||||
|
new RollingIntervalCounter(
|
||||||
|
fileConfiguration.getInt(this.createText((String) "max"), 13));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter3;
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit = checkConfiguration.getInt(this.createText((String) "big-threshold"), 4000);
|
||||||
|
fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
RollingIntervalCounter rollingIntervalCounter4 =
|
||||||
|
new RollingIntervalCounter(
|
||||||
|
fileConfiguration.getInt(this.createText((String) "max-big"), 6));
|
||||||
|
this.rollingIntervalCounter2 = rollingIntervalCounter4;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
if (itemStack.getType() != ItemTypes.WRITABLE_BOOK) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter.increment()) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("books-ps", this.rollingIntervalCounter.getMaxCounter())
|
||||||
|
};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter.isOverLimit()) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
if (nBT != null && nBT.getTags().containsKey("pages")) {
|
||||||
|
int decodedSizeBytes = itemStack.getDecodedSizeBytes();
|
||||||
|
if (decodedSizeBytes <= 0) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (decodedSizeBytes > this.limit) {
|
||||||
|
if (this.rollingIntervalCounter2.increment()) {
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of(
|
||||||
|
"big-books-ps",
|
||||||
|
this.rollingIntervalCounter2.getMaxCounter()),
|
||||||
|
null
|
||||||
|
};
|
||||||
|
flagInfos2[1] = FlagInfo.of("size", decodedSizeBytes);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.rollingIntervalCounter2.isOverLimit()) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
|
||||||
|
import org.bukkit.event.player.PlayerCommandPreprocessEvent;
|
||||||
|
|
||||||
|
public class FloodFCheck extends AbstractCheck<PlayerCommandPreprocessEvent> {
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
public FloodFCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 8);
|
||||||
|
RollingIntervalCounter rollingIntervalCounter2 =
|
||||||
|
new RollingIntervalCounter(this.calculateLimit((String) "max", ((int) value)));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
PlayerCommandPreprocessEvent playerCommandPreprocessEvent) {
|
||||||
|
if (this.rollingIntervalCounter.increment()) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("command", playerCommandPreprocessEvent.getMessage())
|
||||||
|
};
|
||||||
|
this.flagViolation(playerCommandPreprocessEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return this.rollingIntervalCounter.isOverLimit() ? CheckResult.DENY : CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.flood;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RepeatedIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ReadSlotsEvent;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
public class FloodGCheck extends AbstractCheck<ReadSlotsEvent> {
|
||||||
|
|
||||||
|
private RepeatedIntervalCounter counter;
|
||||||
|
|
||||||
|
private boolean cancel;
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
public FloodGCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
FileConfiguration fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
int intValue = fileConfiguration.getInt(this.createText((String) "max"), 70);
|
||||||
|
fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
int intValue2 = fileConfiguration.getInt(this.createText((String) "interval"), 250);
|
||||||
|
fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
int intValue3 = fileConfiguration.getInt(this.createText((String) "periods"), 5);
|
||||||
|
fileConfiguration = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
int intValue4 = fileConfiguration.getInt(this.createText((String) "warnings"), 2);
|
||||||
|
RepeatedIntervalCounter repeatedIntervalCounter =
|
||||||
|
new RepeatedIntervalCounter(intValue, intValue2, intValue3, intValue4);
|
||||||
|
this.counter = repeatedIntervalCounter;
|
||||||
|
FileConfiguration fileConfiguration2 = ((FileConfiguration) this.getCheckConfiguration());
|
||||||
|
this.cancel = fileConfiguration2.getBoolean(this.createText((String) "cancel"), true);
|
||||||
|
Integer value2 = Integer.valueOf((byte) 3);
|
||||||
|
String text = (String) "low-slots-threshold";
|
||||||
|
String text2 = text;
|
||||||
|
this.limit = Math.max(0, this.calculateLimit(text2, ((int) value2)));
|
||||||
|
Double value3 = ((Double) (double) 0.7);
|
||||||
|
String text3 = "low-slots-multiplier";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.value = Math.max(0.1, this.calculateValue(text4, ((double) value3)));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(ProtocolPlayer protocolPlayer, ReadSlotsEvent readSlotsEvent) {
|
||||||
|
double value2 = readSlotsEvent.getSlotsCount() * protocolPlayer.itemFloodMultiplier();
|
||||||
|
if (readSlotsEvent.getSlotsCount() <= this.limit) {
|
||||||
|
value2 *= this.value;
|
||||||
|
}
|
||||||
|
if (this.counter.increment(value2)) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[4];
|
||||||
|
flagInfos[0] = FlagInfo.of("max-counter", this.counter.getMaxCounter());
|
||||||
|
flagInfos[1] = FlagInfo.of("interval", this.counter.getInterval() + "ms");
|
||||||
|
flagInfos[2] = FlagInfo.of("slots-count", readSlotsEvent.getSlotsCount());
|
||||||
|
flagInfos[3] = FlagInfo.of("amount", value2);
|
||||||
|
this.flagViolation(readSlotsEvent, flagInfos);
|
||||||
|
return this.cancel ? CheckResult.DENY : CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
return this.cancel && this.counter.isOverLimit() ? CheckResult.DENY : CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.api.protocol.ReceivedPacket;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.config.CreativeExemption;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketType.Play.Client;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype.PacketTypeCommon;
|
||||||
|
import it.ytnoos.lpx.utils.ItemDecodeLimits;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class Item0Check extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private CreativeExemption creativeExemption;
|
||||||
|
|
||||||
|
private ItemDecodeLimits itemDecodeLimits;
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
public Item0Check(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String string =
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getString(
|
||||||
|
"options.disable-item-decoding", CreativeExemption.DEFAULT.name());
|
||||||
|
this.creativeExemption = CreativeExemption.fromString(string);
|
||||||
|
this.itemDecodeLimits = ItemDecodeLimits.defaults();
|
||||||
|
this.limit =
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getInt("options.dialog-payload-max-bytes", 32768);
|
||||||
|
RollingIntervalCounter rollingIntervalCounter2 =
|
||||||
|
new RollingIntervalCounter(
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getInt("options.dialog-payload-bytes-per-second", 262144));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
if (protocolPlayer.isProcessingPayload()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
int decodedSizeBytes = nBTDecodeEvent.getNbt().getDecodedSizeBytes();
|
||||||
|
if (this.creativeExemption != CreativeExemption.NONE) {
|
||||||
|
if (this.testPlayer(protocolPlayer)) {
|
||||||
|
if (decodedSizeBytes < this.limit) {
|
||||||
|
this.rollingIntervalCounter.increment(decodedSizeBytes);
|
||||||
|
if (!this.rollingIntervalCounter.isOverLimit()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
return this.check(nBTDecodeEvent, ((boolean) matches));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
boolean matches2 = player != null && player.getGameMode() == GameMode.CREATIVE;
|
||||||
|
boolean matches3 = decodedSizeBytes >= this.itemDecodeLimits.calculateLimit(protocolPlayer);
|
||||||
|
switch (this.creativeExemption) {
|
||||||
|
case NONE:
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
case SMART:
|
||||||
|
if (!matches3 || matches2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
if (matches2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
case CREATIVE:
|
||||||
|
}
|
||||||
|
boolean matches4 = !matches2 || this.creativeExemption != CreativeExemption.CREATIVE;
|
||||||
|
Boolean matches5 = ((Boolean) matches4);
|
||||||
|
return this.check(nBTDecodeEvent, ((boolean) matches5));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean testPlayer(ProtocolPlayer protocolPlayer) {
|
||||||
|
ReceivedPacket lastReceivedPacket = protocolPlayer.getLastReceivedPacket();
|
||||||
|
if (lastReceivedPacket == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
PacketTypeCommon packetType = lastReceivedPacket.getPacketType();
|
||||||
|
return packetType == Client.CUSTOM_CLICK_ACTION
|
||||||
|
|| packetType
|
||||||
|
== it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.packettype
|
||||||
|
.PacketType.Configuration.Client.CUSTOM_CLICK_ACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(NBTDecodeEvent nBTDecodeEvent, boolean matches) {
|
||||||
|
NBT nbt = nBTDecodeEvent.getNbt();
|
||||||
|
ReceivedPacket lastReceivedPacket = this.player.getLastReceivedPacket();
|
||||||
|
if (lastReceivedPacket != null && this.player.isLegacyClientOnHashedServer()) {
|
||||||
|
lastReceivedPacket.addOriginalNbt(nbt instanceof NBTList ? nbt.copy() : nbt);
|
||||||
|
}
|
||||||
|
if (nbt instanceof NBTCompound) {
|
||||||
|
NBTCompound nBTCompound = new NBTCompound();
|
||||||
|
nBTDecodeEvent.setNbt(nBTCompound);
|
||||||
|
} else if (nbt instanceof NBTString) {
|
||||||
|
if (matches || ((NBTString) nbt).getValue().length() >= 256) {
|
||||||
|
NBTString nBTString = new NBTString("");
|
||||||
|
nBTDecodeEvent.setNbt(nBTString);
|
||||||
|
}
|
||||||
|
} else if (nbt instanceof NBTList nBTList2) {
|
||||||
|
if (matches) {
|
||||||
|
NBTList nBTList = new NBTList(nBTList2.getType(), 0);
|
||||||
|
nBTDecodeEvent.setNbt(nBTList);
|
||||||
|
} else {
|
||||||
|
for (int value = nBTList2.size() - 1; value >= 0; value--) {
|
||||||
|
NBT tag = nBTList2.getTag(value);
|
||||||
|
if (tag instanceof NBTString) {
|
||||||
|
if (((NBTString) tag).getValue().length() >= 256) {
|
||||||
|
nBTList2.removeTag(value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nBTList2.removeTag(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nBTDecodeEvent.setNbt(nBTList2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.config.CreativeExemption;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.utils.ItemDecodeLimits;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class Item1Check extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private static final String[] TEXTS;
|
||||||
|
|
||||||
|
private CreativeExemption creativeExemption;
|
||||||
|
|
||||||
|
private ItemDecodeLimits itemDecodeLimits;
|
||||||
|
|
||||||
|
private Set<String> values;
|
||||||
|
|
||||||
|
public Item1Check(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String string =
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getString(
|
||||||
|
"options.disable-item-decoding", CreativeExemption.DEFAULT.name());
|
||||||
|
this.creativeExemption = CreativeExemption.fromString(string);
|
||||||
|
this.itemDecodeLimits = ItemDecodeLimits.defaults();
|
||||||
|
HashSet values2 = new HashSet();
|
||||||
|
this.values = values2;
|
||||||
|
this.values.addAll(
|
||||||
|
this.getOptions().getCheckOptions().getConfig().isSet("options.creative-exempts")
|
||||||
|
? this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getStringList("options.creative-exempts")
|
||||||
|
: Arrays.asList(TEXTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player != null && !protocolPlayer.isProcessingPayload()) {
|
||||||
|
boolean matches = player.getGameMode() == GameMode.CREATIVE;
|
||||||
|
int decodedSizeBytes = itemStackDecodeEvent.getItemStack().getDecodedSizeBytes();
|
||||||
|
boolean matches2 =
|
||||||
|
decodedSizeBytes >= this.itemDecodeLimits.calculateLimit(protocolPlayer);
|
||||||
|
switch (this.creativeExemption) {
|
||||||
|
case NONE:
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
case SMART:
|
||||||
|
if (!matches2 || matches) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ALL:
|
||||||
|
if (matches) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
case CREATIVE:
|
||||||
|
}
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
itemStack.setNBT(null);
|
||||||
|
if (matches && this.creativeExemption == CreativeExemption.CREATIVE) {
|
||||||
|
Set<
|
||||||
|
it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol
|
||||||
|
.component.ComponentType<
|
||||||
|
?>>
|
||||||
|
values2 = itemStack.getComponents().getPatches().keySet();
|
||||||
|
values2.removeIf(result -> !this.values.contains(result.getName().getKey()));
|
||||||
|
} else {
|
||||||
|
itemStack.setComponents(null);
|
||||||
|
}
|
||||||
|
itemStackDecodeEvent.setItemStack(itemStack);
|
||||||
|
return CheckResult.CHANGE;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] texts = new String[] {"custom_name", null, null};
|
||||||
|
texts[1] = "lore";
|
||||||
|
texts[2] = "enchantments";
|
||||||
|
TEXTS = texts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.config.CreativeExemption;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPickItemFromBlock;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class Item2Check extends AbstractCheck<WrapperPlayClientPickItemFromBlock> {
|
||||||
|
|
||||||
|
private CreativeExemption creativeExemption;
|
||||||
|
|
||||||
|
private static final String TEXT = "options.disable-item-decoding";
|
||||||
|
|
||||||
|
public Item2Check(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String string =
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getString(TEXT, CreativeExemption.DEFAULT.name());
|
||||||
|
this.creativeExemption = CreativeExemption.fromString(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPickItemFromBlock wrapperPlayClientPickItemFromBlock) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (this.creativeExemption == CreativeExemption.CREATIVE
|
||||||
|
&& player.getGameMode() == GameMode.CREATIVE) {
|
||||||
|
wrapperPlayClientPickItemFromBlock.setIncludeData(false);
|
||||||
|
return CheckResult.CHANGE;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.config.CreativeExemption;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPickItemFromEntity;
|
||||||
|
|
||||||
|
import org.bukkit.GameMode;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class Item3Check extends AbstractCheck<WrapperPlayClientPickItemFromEntity> {
|
||||||
|
|
||||||
|
private CreativeExemption creativeExemption;
|
||||||
|
|
||||||
|
private static final String TEXT = "options.disable-item-decoding";
|
||||||
|
|
||||||
|
public Item3Check(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
String string =
|
||||||
|
this.getOptions()
|
||||||
|
.getCheckOptions()
|
||||||
|
.getConfig()
|
||||||
|
.getString(TEXT, CreativeExemption.DEFAULT.name());
|
||||||
|
this.creativeExemption = CreativeExemption.fromString(string);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPickItemFromEntity wrapperPlayClientPickItemFromEntity) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (this.creativeExemption == CreativeExemption.CREATIVE
|
||||||
|
&& player.getGameMode() == GameMode.CREATIVE) {
|
||||||
|
wrapperPlayClientPickItemFromEntity.setIncludeData(false);
|
||||||
|
return CheckResult.CHANGE;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemType;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.type.ItemTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
|
||||||
|
public class ItemACheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
public ItemACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isResolved(ItemStack itemStack) {
|
||||||
|
boolean matches = itemStack.getType() == ItemTypes.WRITTEN_BOOK;
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
if (nBT != null && nBT.getTags().containsKey("resolved")) {
|
||||||
|
matches = nBT.getBoolean("resolved");
|
||||||
|
}
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
ItemType type = itemStack.getType();
|
||||||
|
if (isResolved(itemStack) && type != ItemTypes.WRITTEN_BOOK) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("resolved", true), null};
|
||||||
|
flagInfos[1] = FlagInfo.of("item", type.getName());
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||||
|
|
||||||
|
public class ItemBCheck extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private int limit2;
|
||||||
|
|
||||||
|
public ItemBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = Integer.valueOf((byte) 50);
|
||||||
|
String text = (String) "max";
|
||||||
|
String text2 = text;
|
||||||
|
this.limit = this.calculateLimit(text2, ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((byte) 100);
|
||||||
|
String text3 = "max-modern";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.limit2 = this.calculateLimit(text4, ((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
NBT nbt = nBTDecodeEvent.getNbt();
|
||||||
|
if (!(nbt instanceof NBTCompound)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList stringListTagOrNull = ((NBTCompound) nbt).getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
boolean newerThanOrEquals =
|
||||||
|
protocolPlayer
|
||||||
|
.getUser()
|
||||||
|
.getClientVersion()
|
||||||
|
.isNewerThanOrEquals(ClientVersion.V_1_14);
|
||||||
|
int value = newerThanOrEquals ? this.limit2 : this.limit;
|
||||||
|
if (stringListTagOrNull.size() <= value) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("pages", stringListTagOrNull.size()), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("max", value);
|
||||||
|
flagInfos[2] = FlagInfo.of("modern", newerThanOrEquals);
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
|
||||||
|
public class ItemCCheck extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
public ItemCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String normalizeEnchantmentName(String text) {
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
for (int index = 0; index < text.length(); index++) {
|
||||||
|
char value = text.charAt(index);
|
||||||
|
Integer value2 = Integer.valueOf(value);
|
||||||
|
if (testLimit(((int) value2))) {
|
||||||
|
stringBuilder.append(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean testLimit(int value) {
|
||||||
|
if (value < 32) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return switch (Character.getType((char) value)) {
|
||||||
|
case 0, 15, 16, 18, 19 -> false;
|
||||||
|
default -> true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean testText(String text) {
|
||||||
|
for (int index = 0; index < text.length(); index++) {
|
||||||
|
char value = text.charAt(index);
|
||||||
|
Integer value2 = Integer.valueOf(value);
|
||||||
|
if (!testLimit(((int) value2))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
this.enabled = this.testEnabled((String) "remove-ascii", ((boolean) matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
NBT nbt = nBTDecodeEvent.getNbt();
|
||||||
|
if (!(nbt instanceof NBTCompound)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList stringListTagOrNull = ((NBTCompound) nbt).getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
boolean matches = false;
|
||||||
|
for (int index = 0; index < stringListTagOrNull.size(); index++) {
|
||||||
|
NBTString nBTString = (NBTString) stringListTagOrNull.getTag(index);
|
||||||
|
String value = nBTString.getValue();
|
||||||
|
String value2 = nBTString.getValue();
|
||||||
|
if (!testText(value2)) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("pages", stringListTagOrNull.size()), null, null
|
||||||
|
};
|
||||||
|
flagInfos[1] = FlagInfo.of("page-index", index);
|
||||||
|
flagInfos[2] = FlagInfo.of("page-length", value.length());
|
||||||
|
if (this.flagViolation(nBTDecodeEvent, flagInfos)) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.enabled) {
|
||||||
|
nBTString.setValue(normalizeEnchantmentName(value));
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches ? CheckResult.CHANGE : CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
|
||||||
|
public class ItemDCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private int maxBytes;
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private boolean resize;
|
||||||
|
|
||||||
|
public ItemDCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = ((Integer) (int) 255);
|
||||||
|
String text = (String) "max-bytes";
|
||||||
|
String text2 = text;
|
||||||
|
this.maxBytes = this.calculateLimit(text2, ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((byte) 3);
|
||||||
|
String text3 = "resolved-tolerance";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.limit = this.calculateLimit(text4, ((int) value2));
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
String text5 = "resize";
|
||||||
|
text = text5;
|
||||||
|
String text6 = text;
|
||||||
|
this.resize = this.testEnabled(text6, ((boolean) matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
NBTCompound nBT = itemStackDecodeEvent.getItemStack().getNBT();
|
||||||
|
if (nBT == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList stringListTagOrNull = nBT.getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
boolean matches = false;
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
boolean resolved = ItemACheck.isResolved(itemStack);
|
||||||
|
for (int index = 0; index < stringListTagOrNull.size(); index++) {
|
||||||
|
NBTString nBTString = (NBTString) stringListTagOrNull.getTag(index);
|
||||||
|
byte[] bytes = nBTString.getValue().getBytes();
|
||||||
|
int value = bytes.length;
|
||||||
|
if (value > this.maxBytes) {
|
||||||
|
if (!resolved || value > this.maxBytes * this.limit) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[4];
|
||||||
|
flagInfos[0] = FlagInfo.of("pages", stringListTagOrNull.size());
|
||||||
|
flagInfos[1] = FlagInfo.of("page-index", index);
|
||||||
|
flagInfos[2] = FlagInfo.of("page-bytes", value);
|
||||||
|
flagInfos[3] = FlagInfo.of("resolved", resolved);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (this.resize) {
|
||||||
|
String text = new String(bytes, 0, this.maxBytes);
|
||||||
|
nBTString.setValue(text);
|
||||||
|
matches = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return matches ? CheckResult.CHANGE : CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,107 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.player.ProtocolPlayerImpl;
|
||||||
|
import it.ytnoos.lpx.utils.string.StringUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class ItemECheck extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private static final String[] TEXTS;
|
||||||
|
|
||||||
|
private boolean clear;
|
||||||
|
|
||||||
|
private Map<String, Integer> entries;
|
||||||
|
|
||||||
|
public ItemECheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
this.clear = this.testEnabled((String) "clear", ((boolean) matches));
|
||||||
|
HashMap entries2 = new HashMap();
|
||||||
|
this.entries = entries2;
|
||||||
|
String[] texts = TEXTS;
|
||||||
|
for (String text :
|
||||||
|
(Iterable<String>) ((Iterable) this.createValues((String) "occurrences", texts))) {
|
||||||
|
String[] texts2 = text.split(",");
|
||||||
|
if (texts2.length < 2) {
|
||||||
|
ProtocolPlayerImpl protocolPlayerImpl = (ProtocolPlayerImpl) this.player;
|
||||||
|
Logger logger = protocolPlayerImpl.getLpx().getLogger();
|
||||||
|
logger.warning(() -> text + " is not a valid ItemE parameter!");
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.entries.put(texts2[0], Integer.parseInt(texts2[1]));
|
||||||
|
} catch (NumberFormatException numberFormatException) {
|
||||||
|
ProtocolPlayerImpl protocolPlayerImpl2 = (ProtocolPlayerImpl) this.player;
|
||||||
|
protocolPlayerImpl2
|
||||||
|
.getLpx()
|
||||||
|
.getLogger()
|
||||||
|
.severe("Second parameter for ItemE must be a number!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
if (!(nBTDecodeEvent.getNbt() instanceof NBTCompound)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList stringListTagOrNull =
|
||||||
|
((NBTCompound) nBTDecodeEvent.getNbt()).getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < stringListTagOrNull.size(); index++) {
|
||||||
|
NBTString nBTString = (NBTString) stringListTagOrNull.getTag(index);
|
||||||
|
String value = nBTString.getValue();
|
||||||
|
for (Entry<String, Integer> entry : this.entries.entrySet()) {
|
||||||
|
Object key = entry.getKey();
|
||||||
|
CharSequence charSequence = (CharSequence) key;
|
||||||
|
CharSequence charSequence2 = ((CharSequence) value);
|
||||||
|
int value2 = StringUtils.calculateLimit(charSequence2, charSequence);
|
||||||
|
if (value2 > (Integer) entry.getValue()) {
|
||||||
|
if (this.clear) {
|
||||||
|
nBTString.setValue("");
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[5];
|
||||||
|
flagInfos[0] = FlagInfo.of("pages", stringListTagOrNull.size());
|
||||||
|
flagInfos[1] = FlagInfo.of("page-index", index);
|
||||||
|
flagInfos[2] = FlagInfo.of("page-length", value.getBytes().length);
|
||||||
|
flagInfos[3] = FlagInfo.of("occurrence", entry.getKey());
|
||||||
|
flagInfos[4] = FlagInfo.of("matches", value2);
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
String[] texts = new String[4];
|
||||||
|
texts[0] = "translate,3";
|
||||||
|
texts[1] = "with,3";
|
||||||
|
texts[2] = "extra,15";
|
||||||
|
texts[3] = "{,15";
|
||||||
|
TEXTS = texts;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
|
||||||
|
public class ItemFCheck extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private boolean replace;
|
||||||
|
|
||||||
|
public ItemFCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
this.replace = this.testEnabled((String) "replace", ((boolean) matches));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
if (!(nBTDecodeEvent.getNbt() instanceof NBTCompound)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList stringListTagOrNull =
|
||||||
|
((NBTCompound) nBTDecodeEvent.getNbt()).getStringListTagOrNull("pages");
|
||||||
|
if (stringListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (!this.replace) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < stringListTagOrNull.size(); index++) {
|
||||||
|
NBTString nBTString = (NBTString) stringListTagOrNull.getTag(index);
|
||||||
|
nBTString.setValue(nBTString.getValue().replace('.', '․'));
|
||||||
|
}
|
||||||
|
return CheckResult.CHANGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,195 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTString;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.player.ClientVersion;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
public class ItemGCheck extends AbstractCheck<NBTDecodeEvent> {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private int limit2;
|
||||||
|
|
||||||
|
private boolean enabled;
|
||||||
|
|
||||||
|
public ItemGCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit = checkConfiguration.getInt(this.createText((String) "max-translate"), 1);
|
||||||
|
checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit2 = checkConfiguration.getInt(this.createText((String) "max-keybind"), 1);
|
||||||
|
this.enabled =
|
||||||
|
this.player.getUser().getClientVersion().isOlderThan(ClientVersion.V_1_16)
|
||||||
|
&& PacketEvents.getAPI()
|
||||||
|
.getServerManager()
|
||||||
|
.getVersion()
|
||||||
|
.isNewerThanOrEquals(ServerVersion.V_1_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
if (protocolPlayer.usesComponents()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBT nbt = nBTDecodeEvent.getNbt();
|
||||||
|
return this.check((String) "", nbt, nBTDecodeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(String text, NBT nBT, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
if (nBT instanceof NBTString nBTString2) {
|
||||||
|
NBTString nBTString = nBTString2;
|
||||||
|
return this.check(text, nBTString, nBTDecodeEvent);
|
||||||
|
} else if (nBT instanceof NBTList) {
|
||||||
|
for (NBT nBT2 : ((Iterable<NBT>) ((Iterable<?>) ((NBTList) nBT).getTags()))) {
|
||||||
|
CheckResult checkResult = this.check(text, nBT2, nBTDecodeEvent);
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (nBT instanceof NBTCompound) {
|
||||||
|
for (Entry<String, NBT> entry : ((NBTCompound) nBT).getTags().entrySet()) {
|
||||||
|
String text2 = (String) entry.getKey();
|
||||||
|
Object value = entry.getValue();
|
||||||
|
NBT nBT3 = (NBT) value;
|
||||||
|
NBT nBT4 = nBT3;
|
||||||
|
String text3 = text2;
|
||||||
|
text2 = text3;
|
||||||
|
nBT3 = nBT4;
|
||||||
|
NBT nBT5 = nBT3;
|
||||||
|
String text4 = text2;
|
||||||
|
CheckResult checkResult2 = this.check(text4, nBT5, nBTDecodeEvent);
|
||||||
|
if (checkResult2 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(String text, NBTString nBTString, NBTDecodeEvent nBTDecodeEvent) {
|
||||||
|
String value = nBTString.getValue();
|
||||||
|
if (value.isEmpty() || value.charAt(0) == '"') {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (value.contains("{") && value.contains("}")) {
|
||||||
|
int value2 = this.limit + 1;
|
||||||
|
Integer value3 = ((Integer) value2);
|
||||||
|
String text2 = value;
|
||||||
|
String text3 = (String) "translate";
|
||||||
|
String text4 = text3;
|
||||||
|
String text5 = text2;
|
||||||
|
int value4 = this.calculateLimit(text5, text4, ((int) value3));
|
||||||
|
if (value4 == -1) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("identifier", text), null};
|
||||||
|
flagInfos[1] = FlagInfo.of("visited", "translate");
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (value4 > this.limit) {
|
||||||
|
int value5 = this.limit + 1;
|
||||||
|
Integer value6 = ((Integer) value5);
|
||||||
|
String text6 = "with";
|
||||||
|
text2 = value;
|
||||||
|
text3 = text6;
|
||||||
|
String text7 = text3;
|
||||||
|
String text8 = text2;
|
||||||
|
int value7 = this.calculateLimit(text8, text7, ((int) value6));
|
||||||
|
if (value7 == -1) {
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[] {FlagInfo.of("identifier", text), null};
|
||||||
|
flagInfos2[1] = FlagInfo.of("visited", "with");
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
if (value7 > this.limit) {
|
||||||
|
FlagInfo[] flagInfos3 =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", text), null, null};
|
||||||
|
flagInfos3[1] = FlagInfo.of("translate", value4);
|
||||||
|
flagInfos3[2] = FlagInfo.of("with", value7);
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos3);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int value8 = this.limit2 + 1;
|
||||||
|
Integer value9 = ((Integer) value8);
|
||||||
|
String text9 = "keybind";
|
||||||
|
text2 = value;
|
||||||
|
text3 = text9;
|
||||||
|
String text10 = text3;
|
||||||
|
String text11 = text2;
|
||||||
|
int value10 = this.calculateLimit(text11, text10, ((int) value9));
|
||||||
|
if (value10 == -1) {
|
||||||
|
FlagInfo[] flagInfos4 = new FlagInfo[] {FlagInfo.of("identifier", text), null};
|
||||||
|
flagInfos4[1] = FlagInfo.of("visited", "keybind");
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos4);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else if (value10 > this.limit2) {
|
||||||
|
FlagInfo[] flagInfos5 = new FlagInfo[] {FlagInfo.of("identifier", text), null};
|
||||||
|
flagInfos5[1] = FlagInfo.of("keybind", value10);
|
||||||
|
this.flagViolation(nBTDecodeEvent, flagInfos5);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateLimit(String text, String text2, int value) {
|
||||||
|
int value2 = 0;
|
||||||
|
int value3 = 0;
|
||||||
|
int value4 = 0;
|
||||||
|
int size = text2.length();
|
||||||
|
while (true) {
|
||||||
|
int value5 = text.indexOf(text2, value3);
|
||||||
|
value3 = value5;
|
||||||
|
if (value5 == -1) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
if (++value4 > 200) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
char value6 = value3 > 0 ? text.charAt(value3 - 1) : '{';
|
||||||
|
char value7 = value3 + size < text.length() ? text.charAt(value3 + size) : ' ';
|
||||||
|
boolean matches = value6 == '"' && (value7 == '"' || value7 == '\\');
|
||||||
|
boolean matches2 = matches;
|
||||||
|
if (!matches && this.enabled) {
|
||||||
|
matches2 = value6 == '\'' && value7 == '\'' || testState() && value7 == ':';
|
||||||
|
}
|
||||||
|
if (matches2) {
|
||||||
|
if (++value2 >= value) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
value3 += size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean testState() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,166 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.ComponentTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemLore;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.WrittenBookContent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.util.Filterable;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.Component;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.KeybindComponent;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.TranslatableComponent;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
public class ItemHCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private int limit2;
|
||||||
|
|
||||||
|
public ItemHCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit = checkConfiguration.getInt(this.createText((String) "max-translate"), 1);
|
||||||
|
checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit2 = checkConfiguration.getInt(this.createText((String) "max-keybind"), 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (!protocolPlayer.usesComponents()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
CheckResult checkResult = CheckResult.ALLOW;
|
||||||
|
Component component =
|
||||||
|
(Component) itemStack.getComponentOr(ComponentTypes.CUSTOM_NAME, null);
|
||||||
|
if (component != null) {
|
||||||
|
CheckResult checkResult2 =
|
||||||
|
this.check(component, (String) "custom_name", itemStackDecodeEvent);
|
||||||
|
checkResult = checkResult2;
|
||||||
|
if (checkResult2 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Component component2 = (Component) itemStack.getComponentOr(ComponentTypes.ITEM_NAME, null);
|
||||||
|
if (component2 != null) {
|
||||||
|
CheckResult checkResult3 =
|
||||||
|
this.check(component2, (String) "item_name", itemStackDecodeEvent);
|
||||||
|
checkResult = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemLore itemLore = (ItemLore) itemStack.getComponentOr(ComponentTypes.LORE, null);
|
||||||
|
if (itemLore != null) {
|
||||||
|
for (int index = 0; index < itemLore.getLines().size(); index++) {
|
||||||
|
Component component3 = itemLore.getLines().get(index);
|
||||||
|
Component component4 = (Component) component3;
|
||||||
|
int value = index;
|
||||||
|
String text2 = (String) "lore[" + value + "]";
|
||||||
|
Component component5 = component4;
|
||||||
|
component4 = component5;
|
||||||
|
Component component6 = component4;
|
||||||
|
CheckResult checkResult4 = this.check(component6, text2, itemStackDecodeEvent);
|
||||||
|
checkResult = checkResult4;
|
||||||
|
if (checkResult4 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WrittenBookContent writtenBookContent =
|
||||||
|
(WrittenBookContent)
|
||||||
|
itemStack.getComponentOr(ComponentTypes.WRITTEN_BOOK_CONTENT, null);
|
||||||
|
if (writtenBookContent != null) {
|
||||||
|
for (int index2 = 0; index2 < writtenBookContent.getPages().size(); index2++) {
|
||||||
|
Filterable filterable = (Filterable) writtenBookContent.getPages().get(index2);
|
||||||
|
Object raw = filterable.getRaw();
|
||||||
|
Component component7 = (Component) raw;
|
||||||
|
int value2 = index2;
|
||||||
|
String text3 = (String) "page[" + value2 + "]";
|
||||||
|
String text4 = text3;
|
||||||
|
Component component8 = component7;
|
||||||
|
component7 = component8;
|
||||||
|
Component component9 = component7;
|
||||||
|
CheckResult checkResult5 = this.check(component9, text4, itemStackDecodeEvent);
|
||||||
|
checkResult = checkResult5;
|
||||||
|
if (checkResult5 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
if (filterable.getFiltered() != null) {
|
||||||
|
Object filtered = filterable.getFiltered();
|
||||||
|
component7 = (Component) filtered;
|
||||||
|
int value3 = index2;
|
||||||
|
text3 = (String) "page_filtered[" + value3 + "]";
|
||||||
|
String text5 = text3;
|
||||||
|
Component component10 = component7;
|
||||||
|
component7 = component10;
|
||||||
|
Component component11 = component7;
|
||||||
|
CheckResult checkResult6 = this.check(component11, text5, itemStackDecodeEvent);
|
||||||
|
checkResult = checkResult6;
|
||||||
|
if (checkResult6 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
Component component, Object result, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
int[] values = new int[2];
|
||||||
|
this.handleLimits(component, values);
|
||||||
|
boolean matches = values[0] > this.limit;
|
||||||
|
boolean matches2 = values[1] > this.limit2;
|
||||||
|
if (!matches && !matches2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("identifier", result), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("translate", values[0]);
|
||||||
|
flagInfos[2] = FlagInfo.of("keybind", values[1]);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean testLimits(int[] values) {
|
||||||
|
return values[0] > this.limit || values[1] > this.limit2;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleLimits(Component component, int[] values) {
|
||||||
|
if (!this.testLimits(values)) {
|
||||||
|
if (component instanceof TranslatableComponent translatableComponent) {
|
||||||
|
values[(byte) 0]++;
|
||||||
|
for (Component component2 : translatableComponent.args()) {
|
||||||
|
if (this.testLimits(values)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handleLimits(component2, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (component instanceof KeybindComponent) {
|
||||||
|
values[(byte) 1]++;
|
||||||
|
}
|
||||||
|
for (Component component3 : component.children()) {
|
||||||
|
if (this.testLimits(values)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.handleLimits(component3, values);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.ComponentTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.FireworkExplosion;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemFireworks;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBT;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTIntArray;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTList;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class ItemJCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private int limit2;
|
||||||
|
|
||||||
|
public ItemJCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
FileConfiguration checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit = checkConfiguration.getInt(this.createText((String) "max-list"), 12);
|
||||||
|
checkConfiguration = this.getCheckConfiguration();
|
||||||
|
this.limit2 = checkConfiguration.getInt(this.createText((String) "max-array"), 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
CheckResult checkResult;
|
||||||
|
if (protocolPlayer.usesComponents()) {
|
||||||
|
checkResult = this.check(itemStack, itemStackDecodeEvent);
|
||||||
|
} else {
|
||||||
|
checkResult = this.check2(itemStack, itemStackDecodeEvent);
|
||||||
|
}
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
FireworkExplosion fireworkExplosion =
|
||||||
|
(FireworkExplosion)
|
||||||
|
itemStack.getComponentOr(ComponentTypes.FIREWORK_EXPLOSION, null);
|
||||||
|
if (fireworkExplosion != null) {
|
||||||
|
return this.check(fireworkExplosion, itemStackDecodeEvent);
|
||||||
|
}
|
||||||
|
ItemFireworks itemFireworks =
|
||||||
|
(ItemFireworks) itemStack.getComponentOr(ComponentTypes.FIREWORKS, null);
|
||||||
|
if (itemFireworks == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<FireworkExplosion> explosions = itemFireworks.getExplosions();
|
||||||
|
if (explosions.size() > this.limit) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("explosions", explosions.size())};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
for (FireworkExplosion fireworkExplosion2 : explosions) {
|
||||||
|
CheckResult checkResult = this.check(fireworkExplosion2, itemStackDecodeEvent);
|
||||||
|
if (checkResult != CheckResult.ALLOW) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
FireworkExplosion fireworkExplosion, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (fireworkExplosion.getColors().size() > this.limit2) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("colors", fireworkExplosion.getColors().size())};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else if (fireworkExplosion.getFadeColors().size() > this.limit2) {
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("fade-colors", fireworkExplosion.getFadeColors().size())
|
||||||
|
};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check2(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
if (nBT == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTCompound compoundTagOrNull = nBT.getCompoundTagOrNull("Explosion");
|
||||||
|
if (compoundTagOrNull != null) {
|
||||||
|
return this.check(compoundTagOrNull, itemStackDecodeEvent);
|
||||||
|
}
|
||||||
|
NBTCompound compoundTagOrNull2 = nBT.getCompoundTagOrNull("Fireworks");
|
||||||
|
if (compoundTagOrNull2 == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
NBTList compoundListTagOrNull = compoundTagOrNull2.getCompoundListTagOrNull("Explosions");
|
||||||
|
if (compoundListTagOrNull == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (compoundListTagOrNull.size() > this.limit) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("explosions", compoundListTagOrNull.size())};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
for (NBTCompound nBTCompound :
|
||||||
|
((Iterable<NBTCompound>) ((Iterable<?>) compoundListTagOrNull.getTags()))) {
|
||||||
|
CheckResult checkResult = this.check(nBTCompound, itemStackDecodeEvent);
|
||||||
|
if (checkResult != CheckResult.ALLOW) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(NBTCompound nBTCompound, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
NBTCompound nBTCompound2 = nBTCompound;
|
||||||
|
String text = (String) "Colors";
|
||||||
|
String text2 = text;
|
||||||
|
NBTCompound nBTCompound3 = nBTCompound2;
|
||||||
|
CheckResult checkResult = this.check(nBTCompound3, text2, itemStackDecodeEvent);
|
||||||
|
if (checkResult != CheckResult.ALLOW) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
String text3 = "FadeColors";
|
||||||
|
nBTCompound2 = nBTCompound;
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
NBTCompound nBTCompound4 = nBTCompound2;
|
||||||
|
return this.check(nBTCompound4, text4, itemStackDecodeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
NBTCompound nBTCompound, String text, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
NBT tagOrNull = nBTCompound.getTagOrNull(text);
|
||||||
|
if (tagOrNull instanceof NBTIntArray) {
|
||||||
|
int value = ((NBTIntArray) tagOrNull).getValue().length;
|
||||||
|
if (value > this.limit2) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of(text.toLowerCase(), value)};
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,843 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.item;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.ComponentTypes;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ChargedProjectiles;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemAdventurePredicate;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemAdventurePredicate.BlockPredicate;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemContainerContents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemProfile.Property;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.ItemTool;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.WritableBookContent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.component.builtin.item.WrittenBookContent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.util.Filterable;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.key.Key;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.Component;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.event.ClickEvent;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.event.ClickEvent.Action;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.event.HoverEvent;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.adventure.text.format.TextColor;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.examination.Examinable;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.examination.ExaminableProperty;
|
||||||
|
import it.ytnoos.lpx.lib.kyori.examination.Examiner;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class ItemKCheck extends AbstractCheck<ItemStackDecodeEvent> {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private int limit2;
|
||||||
|
|
||||||
|
private int limit3;
|
||||||
|
|
||||||
|
private int limit4;
|
||||||
|
|
||||||
|
private int limit5;
|
||||||
|
|
||||||
|
private int limit6;
|
||||||
|
|
||||||
|
private int limit7;
|
||||||
|
|
||||||
|
private int limit8;
|
||||||
|
|
||||||
|
private int limit9;
|
||||||
|
|
||||||
|
private int limit10;
|
||||||
|
|
||||||
|
public ItemKCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = Integer.valueOf((byte) 96);
|
||||||
|
String text = (String) "max-container-items";
|
||||||
|
String text2 = text;
|
||||||
|
this.limit = this.calculateLimit(text2, ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((short) 256);
|
||||||
|
String text3 = "max-total-nested-items";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.limit2 = this.calculateLimit(text4, ((int) value2));
|
||||||
|
Integer value3 = Integer.valueOf((byte) 16);
|
||||||
|
String text5 = "max-profile-properties";
|
||||||
|
text = text5;
|
||||||
|
String text6 = text;
|
||||||
|
this.limit3 = this.calculateLimit(text6, ((int) value3));
|
||||||
|
Integer value4 = Integer.valueOf((short) 8192);
|
||||||
|
String text7 = "max-profile-total-bytes";
|
||||||
|
text = text7;
|
||||||
|
String text8 = text;
|
||||||
|
this.limit4 = this.calculateLimit(text8, ((int) value4));
|
||||||
|
Integer value5 = Integer.valueOf((byte) 16);
|
||||||
|
String text9 = "max-charged-projectiles";
|
||||||
|
text = text9;
|
||||||
|
String text10 = text;
|
||||||
|
this.limit5 = this.calculateLimit(text10, ((int) value5));
|
||||||
|
Integer value6 = Integer.valueOf((byte) 96);
|
||||||
|
String text11 = "max-tool-rules";
|
||||||
|
text = text11;
|
||||||
|
String text12 = text;
|
||||||
|
this.limit6 = this.calculateLimit(text12, ((int) value6));
|
||||||
|
Integer value7 = Integer.valueOf((short) 192);
|
||||||
|
String text13 = "max-can-break-predicates";
|
||||||
|
text = text13;
|
||||||
|
String text14 = text;
|
||||||
|
this.limit7 = this.calculateLimit(text14, ((int) value7));
|
||||||
|
Integer value8 = Integer.valueOf((short) 256);
|
||||||
|
String text15 = "max-can-break-properties";
|
||||||
|
text = text15;
|
||||||
|
String text16 = text;
|
||||||
|
this.limit8 = this.calculateLimit(text16, ((int) value8));
|
||||||
|
Integer value9 = Integer.valueOf((byte) 100);
|
||||||
|
String text17 = "max-book-pages";
|
||||||
|
text = text17;
|
||||||
|
String text18 = text;
|
||||||
|
this.limit9 = this.calculateLimit(text18, ((int) value9));
|
||||||
|
Integer value10 = Integer.valueOf((short) 3072);
|
||||||
|
String text19 = "max-book-page-bytes";
|
||||||
|
text = text19;
|
||||||
|
String text20 = text;
|
||||||
|
this.limit10 = this.calculateLimit(text20, ((int) value10));
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (!protocolPlayer.usesComponents()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
ItemStack itemStack = itemStackDecodeEvent.getItemStack();
|
||||||
|
ItemKCheck.Counter counter = new ItemKCheck.Counter();
|
||||||
|
ItemStack itemStack2 = itemStack;
|
||||||
|
itemStack = itemStack2;
|
||||||
|
ItemStack itemStack3 = itemStack;
|
||||||
|
return this.check(itemStack3, counter, itemStackDecodeEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
ItemStack itemStack,
|
||||||
|
ItemKCheck.Counter counter,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (itemStack != null && !itemStack.isEmpty()) {
|
||||||
|
ItemStack itemStack2 = itemStack;
|
||||||
|
ItemStack itemStack3 = itemStack2;
|
||||||
|
CheckResult checkResult = this.check(itemStack3, itemStackDecodeEvent);
|
||||||
|
CheckResult checkResult2 = checkResult;
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
itemStack2 = itemStack;
|
||||||
|
ItemStack itemStack4 = itemStack2;
|
||||||
|
CheckResult checkResult3 = this.check2(itemStack4, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
itemStack2 = itemStack;
|
||||||
|
ItemKCheck.Counter counter2 = counter;
|
||||||
|
ItemKCheck.Counter counter3 = counter2;
|
||||||
|
ItemStack itemStack5 = itemStack2;
|
||||||
|
CheckResult checkResult4 = this.check2(itemStack5, counter3, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult4;
|
||||||
|
if (checkResult4 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
itemStack2 = itemStack;
|
||||||
|
ItemStack itemStack6 = itemStack2;
|
||||||
|
CheckResult checkResult5 = this.check3(itemStack6, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult5;
|
||||||
|
if (checkResult5 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
itemStack2 = itemStack;
|
||||||
|
ItemStack itemStack7 = itemStack2;
|
||||||
|
CheckResult checkResult6 = this.check4(itemStack7, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult6;
|
||||||
|
if (checkResult6 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
itemStack2 = itemStack;
|
||||||
|
counter2 = counter;
|
||||||
|
ItemKCheck.Counter counter4 = counter2;
|
||||||
|
ItemStack itemStack8 = itemStack2;
|
||||||
|
return this.check3(itemStack8, counter4, itemStackDecodeEvent);
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
WritableBookContent writableBookContent =
|
||||||
|
(WritableBookContent)
|
||||||
|
itemStack.getComponentOr(ComponentTypes.WRITABLE_BOOK_CONTENT, null);
|
||||||
|
if (writableBookContent != null) {
|
||||||
|
List<Filterable<String>> pages = writableBookContent.getPages();
|
||||||
|
if (pages.size() > this.limit9) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("identifier", "writable-book-pages"), null, null
|
||||||
|
};
|
||||||
|
flagInfos[1] = FlagInfo.of("pages", pages.size());
|
||||||
|
flagInfos[2] = FlagInfo.of("max-pages", this.limit9);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
for (int index = 0; index < pages.size(); index++) {
|
||||||
|
Filterable filterable = (Filterable) pages.get(index);
|
||||||
|
int value = index;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
Filterable filterable2 = filterable;
|
||||||
|
filterable = filterable2;
|
||||||
|
int value3 = ((int) value2);
|
||||||
|
Filterable filterable3 = filterable;
|
||||||
|
CheckResult checkResult =
|
||||||
|
this.check(
|
||||||
|
(String) "writable-book-page",
|
||||||
|
filterable3,
|
||||||
|
value3,
|
||||||
|
itemStackDecodeEvent);
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
WrittenBookContent writtenBookContent =
|
||||||
|
(WrittenBookContent)
|
||||||
|
itemStack.getComponentOr(ComponentTypes.WRITTEN_BOOK_CONTENT, null);
|
||||||
|
if (writtenBookContent == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<Filterable<Component>> pages2 = writtenBookContent.getPages();
|
||||||
|
if (pages2.size() > this.limit9) {
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "written-book-pages"), null, null};
|
||||||
|
flagInfos2[1] = FlagInfo.of("pages", pages2.size());
|
||||||
|
flagInfos2[2] = FlagInfo.of("max-pages", this.limit9);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
for (int index2 = 0; index2 < pages2.size(); index2++) {
|
||||||
|
Filterable filterable4 = (Filterable) pages2.get(index2);
|
||||||
|
int value4 = index2;
|
||||||
|
Integer value5 = ((Integer) value4);
|
||||||
|
Filterable filterable5 = filterable4;
|
||||||
|
filterable4 = filterable5;
|
||||||
|
int value6 = ((int) value5);
|
||||||
|
Filterable filterable6 = filterable4;
|
||||||
|
CheckResult checkResult2 =
|
||||||
|
this.check2(
|
||||||
|
(String) "written-book-page",
|
||||||
|
filterable6,
|
||||||
|
value6,
|
||||||
|
itemStackDecodeEvent);
|
||||||
|
if (checkResult2 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check2(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemProfile itemProfile =
|
||||||
|
(ItemProfile) itemStack.getComponentOr(ComponentTypes.PROFILE, null);
|
||||||
|
if (itemProfile == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<Property> properties = itemProfile.getProperties();
|
||||||
|
if (properties.size() > this.limit3) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "profile-properties"), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("properties", properties.size());
|
||||||
|
flagInfos[2] = FlagInfo.of("max-properties", this.limit3);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
int value = 0;
|
||||||
|
for (Property property : properties) {
|
||||||
|
String name = property.getName();
|
||||||
|
int value2 = value + this.calculateLimit(name);
|
||||||
|
String value3 = property.getValue();
|
||||||
|
value2 += this.calculateLimit(value3);
|
||||||
|
String signature = property.getSignature();
|
||||||
|
value = value2 + this.calculateLimit(signature);
|
||||||
|
}
|
||||||
|
if (value > this.limit4) {
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "profile-bytes"), null, null};
|
||||||
|
flagInfos2[1] = FlagInfo.of("bytes", value);
|
||||||
|
flagInfos2[2] = FlagInfo.of("max-bytes", this.limit4);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check2(
|
||||||
|
ItemStack itemStack,
|
||||||
|
ItemKCheck.Counter counter,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ChargedProjectiles chargedProjectiles =
|
||||||
|
(ChargedProjectiles)
|
||||||
|
itemStack.getComponentOr(ComponentTypes.CHARGED_PROJECTILES, null);
|
||||||
|
if (chargedProjectiles == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<ItemStack> items = chargedProjectiles.getItems();
|
||||||
|
if (items.size() > this.limit5) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "charged-projectiles"), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("projectiles", items.size());
|
||||||
|
flagInfos[2] = FlagInfo.of("max-projectiles", this.limit5);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
int size2 = items.size();
|
||||||
|
Integer value = ((Integer) size2);
|
||||||
|
int value2 = ((int) value);
|
||||||
|
CheckResult checkResult =
|
||||||
|
this.check(value2, (String) "charged-projectiles", counter, itemStackDecodeEvent);
|
||||||
|
CheckResult checkResult2 = checkResult;
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
for (ItemStack itemStack2 : items) {
|
||||||
|
CheckResult checkResult3 = this.check(itemStack2, counter, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check3(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemTool itemTool = (ItemTool) itemStack.getComponentOr(ComponentTypes.TOOL, null);
|
||||||
|
if (itemTool == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int size2 = itemTool.getRules().size();
|
||||||
|
if (size2 <= this.limit6) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("identifier", "tool-rules"), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("rules", size2);
|
||||||
|
flagInfos[2] = FlagInfo.of("max-rules", this.limit6);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check4(ItemStack itemStack, ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemAdventurePredicate itemAdventurePredicate =
|
||||||
|
(ItemAdventurePredicate) itemStack.getComponentOr(ComponentTypes.CAN_BREAK, null);
|
||||||
|
if (itemAdventurePredicate == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<BlockPredicate> predicates = itemAdventurePredicate.getPredicates();
|
||||||
|
if (predicates.size() > this.limit7) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "can-break-predicates"), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("predicates", predicates.size());
|
||||||
|
flagInfos[2] = FlagInfo.of("max-predicates", this.limit7);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
int value = 0;
|
||||||
|
Iterator<BlockPredicate> iterator2 = predicates.iterator();
|
||||||
|
while (iterator2.hasNext()) {
|
||||||
|
List<ItemAdventurePredicate.PropertyMatcher> properties =
|
||||||
|
((BlockPredicate) iterator2.next()).getProperties();
|
||||||
|
if (properties != null) {
|
||||||
|
value += properties.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (value <= this.limit8) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "can-break-properties"), null, null};
|
||||||
|
flagInfos2[1] = FlagInfo.of("properties", value);
|
||||||
|
flagInfos2[2] = FlagInfo.of("max-properties", this.limit8);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check3(
|
||||||
|
ItemStack itemStack,
|
||||||
|
ItemKCheck.Counter counter,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
ItemContainerContents itemContainerContents =
|
||||||
|
(ItemContainerContents) itemStack.getComponentOr(ComponentTypes.CONTAINER, null);
|
||||||
|
if (itemContainerContents == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
List<ItemStack> items = itemContainerContents.getItems();
|
||||||
|
if (items.size() > this.limit) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {FlagInfo.of("identifier", "container-items"), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("items", items.size());
|
||||||
|
flagInfos[2] = FlagInfo.of("max-items", this.limit);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
int size2 = items.size();
|
||||||
|
Integer value = ((Integer) size2);
|
||||||
|
int value2 = ((int) value);
|
||||||
|
CheckResult checkResult =
|
||||||
|
this.check(value2, (String) "container-items", counter, itemStackDecodeEvent);
|
||||||
|
CheckResult checkResult2 = checkResult;
|
||||||
|
if (checkResult == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
for (ItemStack itemStack2 : items) {
|
||||||
|
CheckResult checkResult3 = this.check(itemStack2, counter, itemStackDecodeEvent);
|
||||||
|
checkResult2 = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
int value,
|
||||||
|
Object result,
|
||||||
|
ItemKCheck.Counter counter,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
if (value <= 0) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
counter.limit += value;
|
||||||
|
if (counter.limit <= this.limit2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("identifier", result), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("total-nested-items", counter.limit);
|
||||||
|
flagInfos[2] = FlagInfo.of("max-total-nested-items", this.limit2);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check(
|
||||||
|
String text,
|
||||||
|
Filterable filterable,
|
||||||
|
int value,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
Object raw = filterable.getRaw();
|
||||||
|
String text2 = (String) raw;
|
||||||
|
int value2 = this.calculateLimit(text2);
|
||||||
|
if (value2 > this.limit10) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[4];
|
||||||
|
flagInfos[0] = FlagInfo.of("identifier", text);
|
||||||
|
flagInfos[1] = FlagInfo.of("page-index", value);
|
||||||
|
flagInfos[2] = FlagInfo.of("page-bytes", value2);
|
||||||
|
flagInfos[3] = FlagInfo.of("max-page-bytes", this.limit10);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
String text3 = (String) filterable.getFiltered();
|
||||||
|
if (text3 == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int value3 = this.calculateLimit(text3);
|
||||||
|
if (value3 <= this.limit10) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[4];
|
||||||
|
flagInfos2[0] = FlagInfo.of("identifier", text + "-filtered");
|
||||||
|
flagInfos2[1] = FlagInfo.of("page-index", value);
|
||||||
|
flagInfos2[2] = FlagInfo.of("page-bytes", value3);
|
||||||
|
flagInfos2[3] = FlagInfo.of("max-page-bytes", this.limit10);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CheckResult check2(
|
||||||
|
String text,
|
||||||
|
Filterable filterable,
|
||||||
|
int value,
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent) {
|
||||||
|
Object raw = filterable.getRaw();
|
||||||
|
Component component = (Component) raw;
|
||||||
|
int value2 = this.calculateLimit(component);
|
||||||
|
if (value2 > this.limit10) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[4];
|
||||||
|
flagInfos[0] = FlagInfo.of("identifier", text);
|
||||||
|
flagInfos[1] = FlagInfo.of("page-index", value);
|
||||||
|
flagInfos[2] = FlagInfo.of("page-bytes", value2);
|
||||||
|
flagInfos[3] = FlagInfo.of("max-page-bytes", this.limit10);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
Component component2 = (Component) filterable.getFiltered();
|
||||||
|
if (component2 == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
int value3 = this.calculateLimit(component2);
|
||||||
|
if (value3 <= this.limit10) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[4];
|
||||||
|
flagInfos2[0] = FlagInfo.of("identifier", text + "-filtered");
|
||||||
|
flagInfos2[1] = FlagInfo.of("page-index", value);
|
||||||
|
flagInfos2[2] = FlagInfo.of("page-bytes", value3);
|
||||||
|
flagInfos2[3] = FlagInfo.of("max-page-bytes", this.limit10);
|
||||||
|
this.flagViolation(itemStackDecodeEvent, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateLimit(Component component) {
|
||||||
|
int value = this.limit10 + 1;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return this.calculateLimit(component, ((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateLimit(Object result, int value2) {
|
||||||
|
if (result == null || value2 <= 0) {
|
||||||
|
return 0;
|
||||||
|
} else if (result instanceof String text) {
|
||||||
|
String text2 = text;
|
||||||
|
return Math.min(value2, this.calculateLimit(text2));
|
||||||
|
} else if (result instanceof Key key2) {
|
||||||
|
String text3 = key2.asString();
|
||||||
|
return Math.min(value2, this.calculateLimit(text3));
|
||||||
|
} else if (result instanceof TextColor textColor) {
|
||||||
|
String text4 = textColor.asHexString();
|
||||||
|
return Math.min(value2, this.calculateLimit(text4));
|
||||||
|
} else if (result instanceof ClickEvent clickEvent) {
|
||||||
|
Action action2 = clickEvent.action();
|
||||||
|
Integer value3 = ((Integer) value2);
|
||||||
|
int value4 = this.calculateLimit(action2, ((int) value3));
|
||||||
|
if (value4 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
String text5 = clickEvent.value();
|
||||||
|
int value5 = value2 - value4;
|
||||||
|
Integer value6 = ((Integer) value5);
|
||||||
|
return value4 + this.calculateLimit(text5, ((int) value6));
|
||||||
|
} else if (result instanceof HoverEvent hoverEvent) {
|
||||||
|
HoverEvent.Action action3 = hoverEvent.action();
|
||||||
|
Integer value7 = ((Integer) value2);
|
||||||
|
int value8 = this.calculateLimit(action3, ((int) value7));
|
||||||
|
if (value8 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
Object result2 = hoverEvent.value();
|
||||||
|
int value9 = value2 - value8;
|
||||||
|
Integer value10 = ((Integer) value9);
|
||||||
|
return value8 + this.calculateLimit(result2, ((int) value10));
|
||||||
|
} else if (result instanceof Optional optional) {
|
||||||
|
Object result3 = optional.orElse(null);
|
||||||
|
Integer value11 = ((Integer) value2);
|
||||||
|
return this.calculateLimit(result3, ((int) value11));
|
||||||
|
} else if (result instanceof Map entries) {
|
||||||
|
int value12 = 0;
|
||||||
|
for (Entry<Object, Object> entry :
|
||||||
|
((Iterable<Entry<Object, Object>>) ((Iterable<?>) entries.entrySet()))) {
|
||||||
|
Object key = entry.getKey();
|
||||||
|
int value13 = value2 - value12;
|
||||||
|
Integer value14 = ((Integer) value13);
|
||||||
|
int value15 = value12 + this.calculateLimit(key, ((int) value14));
|
||||||
|
value12 = value15;
|
||||||
|
if (value15 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
Object value16 = entry.getValue();
|
||||||
|
int value17 = value2 - value12;
|
||||||
|
Integer value18 = ((Integer) value17);
|
||||||
|
int value19 = value12 + this.calculateLimit(value16, ((int) value18));
|
||||||
|
value12 = value19;
|
||||||
|
if (value19 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value12;
|
||||||
|
} else if (result instanceof Iterable iterable) {
|
||||||
|
int value20 = 0;
|
||||||
|
for (Object result4 : iterable) {
|
||||||
|
int value21 = value2 - value20;
|
||||||
|
Integer value22 = ((Integer) value21);
|
||||||
|
int value23 = value20 + this.calculateLimit(result4, ((int) value22));
|
||||||
|
value20 = value23;
|
||||||
|
if (value23 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value20;
|
||||||
|
} else if (result instanceof Examinable examinable) {
|
||||||
|
int value24 = 0;
|
||||||
|
for (ExaminableProperty examinableProperty :
|
||||||
|
examinable.examinableProperties().toList()) {
|
||||||
|
String text6 = examinableProperty.name();
|
||||||
|
int value25 = value2 - value24;
|
||||||
|
Integer value26 = ((Integer) value25);
|
||||||
|
int value27 = value24 + this.calculateLimit(text6, ((int) value26));
|
||||||
|
value24 = value27;
|
||||||
|
if (value27 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
int value28 =
|
||||||
|
value24
|
||||||
|
+ Math.min(
|
||||||
|
value2 - value24,
|
||||||
|
(Integer)
|
||||||
|
examinableProperty.examine(
|
||||||
|
ItemKCheck.ComponentSizeExaminer.INSTANCE));
|
||||||
|
value24 = value28;
|
||||||
|
if (value28 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value24;
|
||||||
|
} else if (result.getClass().isArray()) {
|
||||||
|
int value29 = 0;
|
||||||
|
int length = Array.getLength(result);
|
||||||
|
for (int index = 0; index < length; index++) {
|
||||||
|
Object result5 = Array.get(result, index);
|
||||||
|
int value30 = value2 - value29;
|
||||||
|
Integer value31 = ((Integer) value30);
|
||||||
|
int value32 = value29 + this.calculateLimit(result5, ((int) value31));
|
||||||
|
value29 = value32;
|
||||||
|
if (value32 >= value2) {
|
||||||
|
return value2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value29;
|
||||||
|
} else if (result instanceof Enum enumValue) {
|
||||||
|
String text7 = enumValue.name();
|
||||||
|
return Math.min(value2, this.calculateLimit(text7));
|
||||||
|
} else {
|
||||||
|
if (!(result instanceof Number)
|
||||||
|
&& !(result instanceof Boolean)
|
||||||
|
&& !(result instanceof Character)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
String text8 = String.valueOf(result);
|
||||||
|
return Math.min(value2, this.calculateLimit(text8));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int calculateLimit(String text) {
|
||||||
|
return text == null ? 0 : text.getBytes(StandardCharsets.UTF_8).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class ComponentSizeExaminer implements Examiner<Integer> {
|
||||||
|
|
||||||
|
private static final ItemKCheck.ComponentSizeExaminer INSTANCE;
|
||||||
|
|
||||||
|
private ComponentSizeExaminer() {}
|
||||||
|
|
||||||
|
public Integer examine(String text, Stream stream) {
|
||||||
|
int value = calculateLimit(text);
|
||||||
|
for (ExaminableProperty examinableProperty :
|
||||||
|
(Iterable<ExaminableProperty>) ((Iterable) stream.toList())) {
|
||||||
|
String text2 = examinableProperty.name();
|
||||||
|
value = value + calculateLimit(text2) + (Integer) examinableProperty.examine(this);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(Object result) {
|
||||||
|
if (result == null) {
|
||||||
|
return 0;
|
||||||
|
} else if (result instanceof String text) {
|
||||||
|
String text2 = text;
|
||||||
|
return calculateLimit(text2);
|
||||||
|
} else if (result instanceof Key) {
|
||||||
|
String text3 = ((Key) result).asString();
|
||||||
|
return calculateLimit(text3);
|
||||||
|
} else if (result instanceof TextColor) {
|
||||||
|
String text4 = ((TextColor) result).asHexString();
|
||||||
|
return calculateLimit(text4);
|
||||||
|
} else if (result instanceof Enum) {
|
||||||
|
String text5 = ((Enum) result).name();
|
||||||
|
return calculateLimit(text5);
|
||||||
|
} else if (result instanceof Number
|
||||||
|
|| result instanceof Boolean
|
||||||
|
|| result instanceof Character) {
|
||||||
|
String text6 = String.valueOf(result);
|
||||||
|
return calculateLimit(text6);
|
||||||
|
} else if (result instanceof ClickEvent clickEvent) {
|
||||||
|
Action action2 = clickEvent.action();
|
||||||
|
int value2 = this.examine(action2);
|
||||||
|
String text7 = clickEvent.value();
|
||||||
|
return value2 + this.examine(text7);
|
||||||
|
} else if (result instanceof HoverEvent hoverEvent) {
|
||||||
|
HoverEvent.Action action3 = hoverEvent.action();
|
||||||
|
int value3 = this.examine(action3);
|
||||||
|
Object result2 = hoverEvent.value();
|
||||||
|
return value3 + this.examine(result2);
|
||||||
|
} else if (result instanceof Optional optional) {
|
||||||
|
Object result3 = optional.orElse(null);
|
||||||
|
return this.examine(result3);
|
||||||
|
} else if (result instanceof Examinable examinable) {
|
||||||
|
return (Integer) this.examine(examinable);
|
||||||
|
} else if (result instanceof Map entries) {
|
||||||
|
int value4 = 0;
|
||||||
|
for (Entry<Object, Object> entry :
|
||||||
|
((Iterable<Entry<Object, Object>>) ((Iterable<?>) entries.entrySet()))) {
|
||||||
|
Object key = entry.getKey();
|
||||||
|
int value5 = value4 + this.examine(key);
|
||||||
|
Object value6 = entry.getValue();
|
||||||
|
value4 = value5 + this.examine(value6);
|
||||||
|
}
|
||||||
|
return value4;
|
||||||
|
} else if (result instanceof Iterable iterable) {
|
||||||
|
int value7 = 0;
|
||||||
|
for (Object result4 : iterable) {
|
||||||
|
value7 += this.examine(result4);
|
||||||
|
}
|
||||||
|
return value7;
|
||||||
|
} else {
|
||||||
|
if (!result.getClass().isArray()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
int value8 = 0;
|
||||||
|
int length = Array.getLength(result);
|
||||||
|
for (int index = 0; index < length; index++) {
|
||||||
|
Object result5 = Array.get(result, index);
|
||||||
|
value8 += this.examine(result5);
|
||||||
|
}
|
||||||
|
return value8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(boolean matches) {
|
||||||
|
String text = String.valueOf(matches);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(boolean[] matchess) {
|
||||||
|
int value = matchess == null ? 0 : matchess.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(byte value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(byte[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(char value) {
|
||||||
|
String text = String.valueOf((char) value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(char[] values) {
|
||||||
|
int value;
|
||||||
|
if (values == null) {
|
||||||
|
value = 0;
|
||||||
|
} else {
|
||||||
|
String text = new String(values);
|
||||||
|
value = calculateLimit(text);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(double value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(double[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(float value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(float[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(int value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(int[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(long value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(long[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(short value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(short[] values) {
|
||||||
|
int value = values == null ? 0 : values.length;
|
||||||
|
Integer value2 = ((Integer) value);
|
||||||
|
return calculateLimit(((int) value2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer examine(String text) {
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int calculateLimit(int value) {
|
||||||
|
String text = String.valueOf(value);
|
||||||
|
return calculateLimit(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int calculateLimit(String text) {
|
||||||
|
return text == null ? 0 : text.getBytes(StandardCharsets.UTF_8).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
ItemKCheck.ComponentSizeExaminer componentSizeExaminer =
|
||||||
|
new ItemKCheck.ComponentSizeExaminer();
|
||||||
|
INSTANCE = componentSizeExaminer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Counter {
|
||||||
|
|
||||||
|
private int limit;
|
||||||
|
|
||||||
|
private Counter() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.netty;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.exception.PacketLimitException;
|
||||||
|
|
||||||
|
public class PacketLimitCheck extends AbstractCheck<PacketLimitException> {
|
||||||
|
|
||||||
|
private final boolean preVia;
|
||||||
|
|
||||||
|
public PacketLimitCheck(
|
||||||
|
ProtocolPlayer protocolPlayer, CheckOptions checkOptions, boolean preVia) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
this.preVia = preVia;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer, PacketLimitException packetLimitException) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("limit", packetLimitException.getLimit().getDescription()),
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
};
|
||||||
|
flagInfos[1] = FlagInfo.of("value", packetLimitException.getValue());
|
||||||
|
flagInfos[2] = FlagInfo.of("max", packetLimitException.getMax());
|
||||||
|
this.flagViolation(packetLimitException, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return this.preVia;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.netty;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.PacketEvents;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.manager.server.ServerVersion;
|
||||||
|
|
||||||
|
public class PacketSizeCheck extends AbstractCheck<ByteBuf> {
|
||||||
|
|
||||||
|
private int maxSize;
|
||||||
|
|
||||||
|
private final boolean preVia;
|
||||||
|
|
||||||
|
public PacketSizeCheck(
|
||||||
|
ProtocolPlayer protocolPlayer, CheckOptions checkOptions, boolean preVia) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
this.preVia = preVia;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Boolean matches = ((Boolean) (boolean) true);
|
||||||
|
String text = (String) "automatic";
|
||||||
|
String text2 = text;
|
||||||
|
int value;
|
||||||
|
if (this.testEnabled(text2, ((boolean) matches))) {
|
||||||
|
value = this.getMaxSize();
|
||||||
|
} else {
|
||||||
|
Integer value2 = ((Integer) 98304);
|
||||||
|
String text3 = "max";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
value = this.calculateLimit(text4, ((int) value2));
|
||||||
|
}
|
||||||
|
this.maxSize = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getMaxSize() {
|
||||||
|
ServerVersion version = PacketEvents.getAPI().getServerManager().getVersion();
|
||||||
|
if (version.isOlderThanOrEquals(ServerVersion.V_1_8_8)) {
|
||||||
|
return 8448;
|
||||||
|
} else {
|
||||||
|
return version.isOlderThanOrEquals(ServerVersion.V_1_12_2) ? 24576 : 98304;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(ProtocolPlayer protocolPlayer, ByteBuf byteBuf) {
|
||||||
|
long size = protocolPlayer.getLastReceivedPacket().getSize();
|
||||||
|
long value = this.maxSize;
|
||||||
|
if (!this.preVia) {
|
||||||
|
value *= 2L;
|
||||||
|
}
|
||||||
|
if (size >= 0L && size < value) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("size", size), null, null};
|
||||||
|
flagInfos[1] = FlagInfo.of("temp-max-size", value);
|
||||||
|
flagInfos[2] = FlagInfo.of("max-size", this.maxSize);
|
||||||
|
this.flagViolation(byteBuf, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return this.preVia;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
|
||||||
|
public class PayloadACheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
public PayloadACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
if (wrapperPlayClientPluginMessage.getChannelName() != null
|
||||||
|
&& !wrapperPlayClientPluginMessage.getChannelName().isEmpty()) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[0];
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.RollingIntervalCounter;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.check.BukkitCheckManager;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
import it.ytnoos.lpx.utils.TimeUtils;
|
||||||
|
|
||||||
|
public class PayloadBCheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
private long last;
|
||||||
|
|
||||||
|
private int delay;
|
||||||
|
|
||||||
|
private RollingIntervalCounter rollingIntervalCounter;
|
||||||
|
|
||||||
|
public PayloadBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Integer value = Integer.valueOf((short) 1000);
|
||||||
|
this.delay = this.calculateLimit((String) "delay", ((int) value));
|
||||||
|
Integer value2 = Integer.valueOf((byte) 15);
|
||||||
|
RollingIntervalCounter rollingIntervalCounter2 =
|
||||||
|
new RollingIntervalCounter(this.calculateLimit((String) "max", ((int) value2)));
|
||||||
|
this.rollingIntervalCounter = rollingIntervalCounter2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
String channelName = wrapperPlayClientPluginMessage.getChannelName();
|
||||||
|
if (channelName.equals("BungeeCord")) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (!BukkitCheckManager.VALUES.contains(channelName)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (this.rollingIntervalCounter.increment()) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of("pps", this.rollingIntervalCounter.getMaxCounter())
|
||||||
|
};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else if (this.rollingIntervalCounter.isOverLimit()) {
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
long value = this.last;
|
||||||
|
Long value2 = ((Long) value);
|
||||||
|
long value3 = TimeUtils.calculateTime(value2);
|
||||||
|
this.last = TimeUtils.current();
|
||||||
|
if (value3 < this.delay) {
|
||||||
|
FlagInfo[] flagInfos2 = new FlagInfo[] {FlagInfo.of("delay", value3)};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.check.BukkitCheckManager;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.inventory.ItemStack;
|
||||||
|
|
||||||
|
public class PayloadCCheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
public PayloadCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
if (!BukkitCheckManager.VALUES.contains(wrapperPlayClientPluginMessage.getChannelName())) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
ItemStack itemInHand = player.getInventory().getItemInHand();
|
||||||
|
if (itemInHand == null
|
||||||
|
|| !itemInHand.getType().name().contains("QUILL")
|
||||||
|
&& !itemInHand.getType().name().contains("WRITABLE")) {
|
||||||
|
FlagInfo[] flagInfos =
|
||||||
|
new FlagInfo[] {
|
||||||
|
FlagInfo.of(
|
||||||
|
"hand",
|
||||||
|
itemInHand == null ? "null" : itemInHand.getType().name())
|
||||||
|
};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.check.BukkitCheckManager;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.ItemStackDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.event.simple.NBTDecodeEvent;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.item.ItemStack;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.protocol.nbt.NBTCompound;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.PacketWrapper;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
import it.ytnoos.lpx.utils.PacketWrapperUtils;
|
||||||
|
|
||||||
|
public class PayloadDirectionCheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
private final boolean preVia;
|
||||||
|
|
||||||
|
private static final String TEXT = "exception";
|
||||||
|
|
||||||
|
public PayloadDirectionCheck(
|
||||||
|
ProtocolPlayer protocolPlayer, CheckOptions checkOptions, boolean preVia) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
this.preVia = preVia;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
if (!BukkitCheckManager.VALUES.contains(wrapperPlayClientPluginMessage.getChannelName())) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (!protocolPlayer.hasAnyCheck(ItemStackDecodeEvent.class, this.preVia)) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
PacketWrapper packetWrapper = null;
|
||||||
|
PacketWrapper packetWrapper2 = null;
|
||||||
|
try {
|
||||||
|
ByteBuf byteBuf = Unpooled.copiedBuffer(wrapperPlayClientPluginMessage.getData());
|
||||||
|
boolean matches = this.preVia;
|
||||||
|
Boolean matches2 = ((Boolean) matches);
|
||||||
|
ProtocolPlayer protocolPlayer2 = protocolPlayer;
|
||||||
|
ProtocolPlayer protocolPlayer3 = protocolPlayer2;
|
||||||
|
PacketWrapper packetWrapper3 =
|
||||||
|
PacketWrapperUtils.createPacketWrapper(
|
||||||
|
protocolPlayer3, byteBuf, ((boolean) matches2));
|
||||||
|
packetWrapper = packetWrapper3;
|
||||||
|
ItemStack itemStack = packetWrapper3.readItemStack();
|
||||||
|
NBTCompound nBT = itemStack.getNBT();
|
||||||
|
protocolPlayer.setProcessingPayload(true);
|
||||||
|
CheckResult checkResult = CheckResult.ALLOW;
|
||||||
|
if (nBT != null) {
|
||||||
|
NBTDecodeEvent nBTDecodeEvent =
|
||||||
|
new NBTDecodeEvent(wrapperPlayClientPluginMessage, null, nBT);
|
||||||
|
CheckResult checkResult2 =
|
||||||
|
protocolPlayer
|
||||||
|
.handleChecks(NBTDecodeEvent.class, nBTDecodeEvent, this.preVia)
|
||||||
|
.result();
|
||||||
|
checkResult = checkResult2;
|
||||||
|
if (checkResult2 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemStackDecodeEvent itemStackDecodeEvent =
|
||||||
|
new ItemStackDecodeEvent(wrapperPlayClientPluginMessage, null, itemStack);
|
||||||
|
CheckResult checkResult3 =
|
||||||
|
checkResult.merge(
|
||||||
|
protocolPlayer
|
||||||
|
.handleChecks(
|
||||||
|
ItemStackDecodeEvent.class,
|
||||||
|
itemStackDecodeEvent,
|
||||||
|
this.preVia)
|
||||||
|
.result());
|
||||||
|
checkResult = checkResult3;
|
||||||
|
if (checkResult3 == CheckResult.DENY) {
|
||||||
|
return checkResult;
|
||||||
|
}
|
||||||
|
if (checkResult == CheckResult.CHANGE) {
|
||||||
|
ByteBuf byteBuf2 = Unpooled.buffer();
|
||||||
|
boolean matches3 = this.preVia;
|
||||||
|
Boolean matches4 = ((Boolean) matches3);
|
||||||
|
protocolPlayer2 = protocolPlayer;
|
||||||
|
ProtocolPlayer protocolPlayer4 = protocolPlayer2;
|
||||||
|
PacketWrapper packetWrapper4 =
|
||||||
|
PacketWrapperUtils.createPacketWrapper(
|
||||||
|
protocolPlayer4, byteBuf2, ((boolean) matches4));
|
||||||
|
packetWrapper2 = packetWrapper4;
|
||||||
|
packetWrapper4.writeItemStack(itemStack);
|
||||||
|
ByteBufHelper.capacity(
|
||||||
|
packetWrapper2.buffer, ByteBufHelper.writerIndex(packetWrapper2.buffer));
|
||||||
|
wrapperPlayClientPluginMessage.setData(ByteBufHelper.array(packetWrapper2.buffer));
|
||||||
|
}
|
||||||
|
return checkResult;
|
||||||
|
} catch (Throwable throwable) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of(TEXT, throwable.getMessage())};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} finally {
|
||||||
|
protocolPlayer.setProcessingPayload(false);
|
||||||
|
PacketWrapper packetWrapper5 = packetWrapper;
|
||||||
|
PacketWrapperUtils.handlePacketWrapper(packetWrapper5);
|
||||||
|
PacketWrapper packetWrapper6 = packetWrapper2;
|
||||||
|
PacketWrapperUtils.handlePacketWrapper(packetWrapper6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isPreVia() {
|
||||||
|
return this.preVia;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
|
||||||
|
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
public class PayloadECheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
public PayloadECheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (!wrapperPlayClientPluginMessage.getChannelName().equals("REGISTER")) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
String text = "";
|
||||||
|
try {
|
||||||
|
String text2 = new String(wrapperPlayClientPluginMessage.getData());
|
||||||
|
text = text2;
|
||||||
|
String[] texts = text2.split("\u0000");
|
||||||
|
int value = texts.length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
String text3 = texts[index];
|
||||||
|
Class[] classs = new Class[] {String.class};
|
||||||
|
Method method = CraftPlayer.class.getMethod("addChannel", classs);
|
||||||
|
Object[] results = new Object[] {text3};
|
||||||
|
method.invoke(player, results);
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("channels", text)};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
}
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.payload;
|
||||||
|
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.netty.buffer.ByteBufHelper;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.util.Vector3i;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPluginMessage;
|
||||||
|
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class PayloadFCheck extends AbstractCheck<WrapperPlayClientPluginMessage> {
|
||||||
|
|
||||||
|
public PayloadFCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPluginMessage wrapperPlayClientPluginMessage) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
if (!wrapperPlayClientPluginMessage
|
||||||
|
.getChannelName()
|
||||||
|
.equalsIgnoreCase("purpur:beehive_c2s")) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
ByteBuf byteBuf = null;
|
||||||
|
try {
|
||||||
|
byteBuf = Unpooled.copiedBuffer(wrapperPlayClientPluginMessage.getData());
|
||||||
|
Vector3i vector3i = new Vector3i(ByteBufHelper.readLong(byteBuf));
|
||||||
|
if (!player.getWorld().isChunkLoaded(vector3i.getX() >> 4, vector3i.getZ() >> 4)) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("blockpos", vector3i)};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
FlagInfo[] flagInfos2 =
|
||||||
|
new FlagInfo[] {FlagInfo.of("exception", exception.getMessage())};
|
||||||
|
this.flagViolation(wrapperPlayClientPluginMessage, flagInfos2);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} finally {
|
||||||
|
if (byteBuf != null && byteBuf.refCnt() > 0) {
|
||||||
|
byteBuf.release();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.place;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.util.Vector3i;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
|
||||||
|
import it.ytnoos.lpx.utils.TimeUtils;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class PlaceACheck extends AbstractCheck<WrapperPlayClientPlayerBlockPlacement> {
|
||||||
|
|
||||||
|
private double value;
|
||||||
|
|
||||||
|
private long time;
|
||||||
|
|
||||||
|
public PlaceACheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Double value2 = ((Double) (double) 100.0);
|
||||||
|
String text = (String) "max";
|
||||||
|
String text2 = text;
|
||||||
|
this.value = this.calculateValue(text2, ((double) value2));
|
||||||
|
Long value3 = ((Long) 100L);
|
||||||
|
String text3 = "teleport-grace";
|
||||||
|
text = text3;
|
||||||
|
String text4 = text;
|
||||||
|
this.time = this.calculateTime(text4, ((long) value3));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPlayerBlockPlacement wrapperPlayClientPlayerBlockPlacement) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
long value2 = this.time + Math.max(0, (int) protocolPlayer.getPlayerPing());
|
||||||
|
long lastTeleport = protocolPlayer.getLastTeleport();
|
||||||
|
Long value3 = ((Long) lastTeleport);
|
||||||
|
if (TimeUtils.calculateTime(value3) < value2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Vector3i blockPosition = wrapperPlayClientPlayerBlockPlacement.getBlockPosition();
|
||||||
|
double x = blockPosition.getX();
|
||||||
|
double z = blockPosition.getZ();
|
||||||
|
if (x == -1.0 && z == -1.0) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Location location = player.getLocation();
|
||||||
|
double value4 = Math.abs(x - location.getX()) + Math.abs(z - location.getZ());
|
||||||
|
if (value4 > this.value) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[5];
|
||||||
|
flagInfos[0] = FlagInfo.of("x", x);
|
||||||
|
flagInfos[1] = FlagInfo.of("z", z);
|
||||||
|
flagInfos[2] = FlagInfo.of("player-x", location.getX());
|
||||||
|
flagInfos[3] = FlagInfo.of("player-z", location.getZ());
|
||||||
|
flagInfos[4] = FlagInfo.of("distance", (int) value4);
|
||||||
|
this.increaseBuffer(wrapperPlayClientPlayerBlockPlacement, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
this.decayBuffer();
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.place;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUpdateSign;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
public class PlaceBCheck extends AbstractCheck<WrapperPlayClientUpdateSign> {
|
||||||
|
|
||||||
|
private double max;
|
||||||
|
|
||||||
|
public PlaceBCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Double value = ((Double) (double) 70.0);
|
||||||
|
this.max = this.calculateValue((String) "max", ((double) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientUpdateSign wrapperPlayClientUpdateSign) {
|
||||||
|
String[] textLines = wrapperPlayClientUpdateSign.getTextLines();
|
||||||
|
int value = textLines.length;
|
||||||
|
for (int index = 0; index < value; index++) {
|
||||||
|
String text = textLines[index];
|
||||||
|
long value2 = text.getBytes(StandardCharsets.UTF_8).length;
|
||||||
|
if (value2 > this.max) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[] {FlagInfo.of("line", text), null};
|
||||||
|
flagInfos[1] = FlagInfo.of("line-size", value2);
|
||||||
|
this.flagViolation(wrapperPlayClientUpdateSign, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
package it.ytnoos.lpx.check.impl.place;
|
||||||
|
|
||||||
|
import it.ytnoos.lpx.api.check.CheckResult;
|
||||||
|
import it.ytnoos.lpx.api.check.FlagInfo;
|
||||||
|
import it.ytnoos.lpx.api.check.options.CheckOptions;
|
||||||
|
import it.ytnoos.lpx.api.player.ProtocolPlayer;
|
||||||
|
import it.ytnoos.lpx.check.AbstractCheck;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.util.Vector3i;
|
||||||
|
import it.ytnoos.lpx.lib.io.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
|
||||||
|
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
public class PlaceCCheck extends AbstractCheck<WrapperPlayClientPlayerDigging> {
|
||||||
|
|
||||||
|
private double max;
|
||||||
|
|
||||||
|
public PlaceCCheck(ProtocolPlayer protocolPlayer, CheckOptions checkOptions) {
|
||||||
|
super(protocolPlayer, checkOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadOptions() {
|
||||||
|
Double value = ((Double) (double) 50.0);
|
||||||
|
this.max = this.calculateValue((String) "max", ((double) value));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CheckResult check(
|
||||||
|
ProtocolPlayer protocolPlayer,
|
||||||
|
WrapperPlayClientPlayerDigging wrapperPlayClientPlayerDigging) {
|
||||||
|
Player player = (Player) protocolPlayer.getPlayer().orElse(null);
|
||||||
|
if (player == null) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else if (wrapperPlayClientPlayerDigging.getAction().ordinal() > 2) {
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
} else {
|
||||||
|
Location location = player.getLocation();
|
||||||
|
Vector3i blockPosition = wrapperPlayClientPlayerDigging.getBlockPosition();
|
||||||
|
double value = location.getX() - (blockPosition.getX() + 0.5);
|
||||||
|
double value2 = location.getY() - (blockPosition.getY() + 0.5) + 1.5;
|
||||||
|
double value3 = location.getZ() - (blockPosition.getZ() + 0.5);
|
||||||
|
double value4 = value * value + value2 * value2 + value3 * value3;
|
||||||
|
if (value4 > this.max) {
|
||||||
|
FlagInfo[] flagInfos = new FlagInfo[4];
|
||||||
|
flagInfos[0] = FlagInfo.of("distanceX", value);
|
||||||
|
flagInfos[1] = FlagInfo.of("distanceY", value2);
|
||||||
|
flagInfos[2] = FlagInfo.of("distanceZ", value3);
|
||||||
|
flagInfos[3] = FlagInfo.of("distance", (int) value4);
|
||||||
|
this.increaseBuffer(wrapperPlayClientPlayerDigging, flagInfos);
|
||||||
|
return CheckResult.DENY;
|
||||||
|
} else {
|
||||||
|
this.decayBuffer();
|
||||||
|
return CheckResult.ALLOW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loaded 100 of 2186 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user