Going to have to rewrite CBW
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
4
.idea/modules.xml
generated
4
.idea/modules.xml
generated
@@ -2,7 +2,9 @@
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Sentinel.iml" filepath="$PROJECT_DIR$/.idea/modules/Sentinel.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/'me.trouper'.Sentinel.main.iml" filepath="$PROJECT_DIR$/.idea/modules/'me.trouper'.Sentinel.main.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/'me.trouper'.Sentinel.test.iml" filepath="$PROJECT_DIR$/.idea/modules/'me.trouper'.Sentinel.test.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/IJ.IdeaProjects.Sentinel.main.iml" filepath="$PROJECT_DIR$/.idea/modules/IJ.IdeaProjects.Sentinel.main.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Sentinel.main.iml" filepath="$PROJECT_DIR$/.idea/modules/Sentinel.main.iml" />
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/modules/Sentinel.test.iml" filepath="$PROJECT_DIR$/.idea/modules/Sentinel.test.iml" />
|
||||
</modules>
|
||||
|
||||
4
.idea/modules/Sentinel.main.iml
generated
4
.idea/modules/Sentinel.main.iml
generated
@@ -11,4 +11,8 @@
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
152
build.gradle
152
build.gradle
@@ -3,18 +3,20 @@ import java.nio.file.Paths
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id("com.github.johnrengelman.shadow") version "8.1.1"
|
||||
id 'com.gradleup.shadow' version '9.0.0-beta10'
|
||||
}
|
||||
|
||||
group = project.group
|
||||
version = project.version
|
||||
|
||||
jar {
|
||||
from {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
configurations.runtimeClasspath.collect {
|
||||
it.isDirectory() ? it : zipTree(it)
|
||||
}
|
||||
def targetJavaVersion = 21
|
||||
java {
|
||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||
sourceCompatibility = javaVersion
|
||||
targetCompatibility = javaVersion
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
||||
if (JavaVersion.current() < javaVersion) {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,76 +38,91 @@ repositories {
|
||||
url = 'https://oss.sonatype.org/content/groups/public/'
|
||||
}
|
||||
maven {
|
||||
url = uri("https://repo.codemc.io/repository/maven-releases/")
|
||||
}
|
||||
maven {
|
||||
url = uri("https://repo.codemc.io/repository/maven-snapshots/")
|
||||
name = "CodeMC"
|
||||
url = uri("https://repo.codemc.io/repository/maven-public/")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.11.0")
|
||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.11.0")
|
||||
compileOnly "io.papermc.paper:paper-api:1.21.4-R0.1-SNAPSHOT"
|
||||
implementation 'com.google.code.gson:gson:2.10.1'
|
||||
implementation 'org.ow2.asm:asm-commons:9.5'
|
||||
implementation files("deps/PDK-1.4.0.jar")
|
||||
implementation "com.github.retrooper:packetevents-spigot:2.7.0"
|
||||
implementation("de.tr7zw:item-nbt-api:2.14.1")
|
||||
}
|
||||
|
||||
def targetJavaVersion = 21
|
||||
java {
|
||||
def javaVersion = JavaVersion.toVersion(targetJavaVersion)
|
||||
sourceCompatibility = javaVersion
|
||||
targetCompatibility = javaVersion
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(21))
|
||||
if (JavaVersion.current() < javaVersion) {
|
||||
toolchain.languageVersion = JavaLanguageVersion.of(targetJavaVersion)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
||||
options.release = targetJavaVersion
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register('copyDeps', Copy) {
|
||||
from configurations.runtimeClasspath
|
||||
into 'build/deps'
|
||||
include '*.jar'
|
||||
}
|
||||
|
||||
|
||||
processResources {
|
||||
def props = [version: version]
|
||||
inputs.properties props
|
||||
filteringCharset 'UTF-8'
|
||||
filesMatching('plugin.yml') {
|
||||
expand props
|
||||
expand(version: project.version)
|
||||
}
|
||||
}
|
||||
|
||||
compileJava.options.encoding("UTF-8")
|
||||
task cleanPluginYml {
|
||||
doLast {
|
||||
def jarFile = shadowJar.archiveFile.get().asFile
|
||||
def tempDir = file("$buildDir/tmpCleanJar")
|
||||
tempDir.mkdirs()
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
// Unpack the jar into a temporary directory
|
||||
copy {
|
||||
from zipTree(jarFile)
|
||||
into tempDir
|
||||
}
|
||||
|
||||
// Delete any plugin.yml files from anywhere in the unpacked directory
|
||||
fileTree(tempDir).matching {
|
||||
include '**/plugin.yml'
|
||||
}.each { file ->
|
||||
file.delete()
|
||||
}
|
||||
|
||||
// Repackage the jar without the plugin.yml files
|
||||
ant.zip(destfile: jarFile, basedir: tempDir)
|
||||
delete tempDir
|
||||
}
|
||||
}
|
||||
|
||||
tasks.shadowJar {
|
||||
task injectPluginYml {
|
||||
doLast {
|
||||
def jarFile = shadowJar.archiveFile.get().asFile
|
||||
def tempDir = file("$buildDir/tmpJar")
|
||||
tempDir.mkdirs()
|
||||
|
||||
// Unpack the jar that has been cleaned
|
||||
copy {
|
||||
from zipTree(jarFile)
|
||||
into tempDir
|
||||
}
|
||||
|
||||
// Copy the already filtered plugin.yml from processed resources
|
||||
copy {
|
||||
from file("$buildDir/resources/main/plugin.yml")
|
||||
into tempDir
|
||||
}
|
||||
|
||||
// Repackage the jar with the updated contents
|
||||
ant.zip(destfile: jarFile, basedir: tempDir)
|
||||
delete tempDir
|
||||
}
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
archiveClassifier.set('')
|
||||
minimize()
|
||||
|
||||
mergeServiceFiles()
|
||||
|
||||
exclude 'plugin.yml'
|
||||
|
||||
relocate("com.github.retrooper.packetevents", "me.trouper.sentinel.packetevents.api")
|
||||
relocate("io.github.retrooper.packetevents", "me.trouper.sentinel.packetevents.impl")
|
||||
relocate("de.tr7zw.changeme.nbtapi", "me.trouper.sentinel.nbtapi.api")
|
||||
|
||||
}
|
||||
|
||||
task obfuscate(type: JavaExec) {
|
||||
// Specify the main class in the obfuscator JAR (if required)
|
||||
|
||||
// Path to the obfuscator JAR
|
||||
classpath = files('obf/grunt-main.jar')
|
||||
|
||||
// Arguments to pass to the obfuscator (e.g., input and output directories)
|
||||
args = [
|
||||
'--config', '.\\obf\\config.json'
|
||||
]
|
||||
}
|
||||
|
||||
task copyLibs {
|
||||
doLast {
|
||||
@@ -143,6 +160,33 @@ task copyLibs {
|
||||
}
|
||||
}
|
||||
|
||||
task obfuscate(type: JavaExec) {
|
||||
// Path to the obfuscator JAR
|
||||
classpath = files('obf/grunt-main.jar')
|
||||
|
||||
// Arguments to pass to the obfuscator (e.g., input and output directories)
|
||||
args = [
|
||||
'--config', '.\\obf\\config.json'
|
||||
]
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
if (targetJavaVersion >= 10 || JavaVersion.current().isJava10Compatible()) {
|
||||
options.release = targetJavaVersion
|
||||
}
|
||||
}
|
||||
|
||||
compileJava.options.encoding("UTF-8")
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
dependsOn injectPluginYml
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,5 +1,5 @@
|
||||
name: SentinelAntiNuke
|
||||
version: '0.3.0'
|
||||
version: '0.3.1'
|
||||
main: me.trouper.sentinel.Sentinel
|
||||
api-version: 1.21
|
||||
authors: [ TheTrouper ]
|
||||
@@ -12,27 +12,20 @@ softdepend:
|
||||
- ViaBackwards
|
||||
- ViaRewind
|
||||
- Geyser-Spigot
|
||||
load: STARTUP
|
||||
load: POSTWORLD
|
||||
permissions:
|
||||
sentinel.admin:
|
||||
description: Allows access to all Sentinel admin commands.
|
||||
default: op
|
||||
children:
|
||||
sentinel.reload: true
|
||||
sentinel.config: true
|
||||
sentinel.debug: true
|
||||
sentinel.extras: true
|
||||
sentinel.staff:
|
||||
description: Allows access to Sentinel staff commands.
|
||||
default: false
|
||||
default: op
|
||||
children:
|
||||
sentinel.socialspy: true
|
||||
sentinel.false-positive: true
|
||||
sentinel.reload:
|
||||
description: Allows the user to reload the Sentinel plugin.
|
||||
default: false
|
||||
sentinel.config:
|
||||
description: Allows the user to modify the Sentinel configuration.
|
||||
default: false
|
||||
sentinel.false-positive:
|
||||
description: Allows the user to manage false positives.
|
||||
default: false
|
||||
@@ -47,7 +40,10 @@ permissions:
|
||||
default: false
|
||||
sentinel.debug:
|
||||
description: Allows the user to toggle debug mode.
|
||||
default: false
|
||||
default: op
|
||||
sentinel.extras:
|
||||
description: Sentinel Extra Features
|
||||
default: op
|
||||
sentinel.commandblock:
|
||||
description: Allows the user to manage command blocks.
|
||||
default: false
|
||||
@@ -130,6 +126,11 @@ commands:
|
||||
usage: /sentinel <reload|config|false-positive|debug|commandblock|socialspy>
|
||||
permission: sentinel.staff
|
||||
permission-message: You do not have permission to use this command.
|
||||
sentinelextras:
|
||||
usage: /sentinelextras [alfa|bravo|charlie|delta|echo|foxtrot|golf|hotel|india|juliett] <player>
|
||||
description: Extra features for sentinel.
|
||||
permission: sentinel.extra
|
||||
permission-message: You do not have permission to use this command.
|
||||
sentinelcallback:
|
||||
description: Callback command for Sentinel.
|
||||
usage: /callback <fpreport>
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
|
||||
# Plugin
|
||||
group = 'me.trouper'
|
||||
version = 0.3.0
|
||||
version = 0.3.1
|
||||
|
||||
# Minecraft
|
||||
mc_version = 1.21
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"Settings": {
|
||||
"Input": "./build/libs/Sentinel-0.3.0.jar",
|
||||
"Output": "./build/libs/Sentinel-0.3.0-obf.jar",
|
||||
"Input": "./build/libs/Sentinel-0.3.1.jar",
|
||||
"Output": "./build/libs/Sentinel-0.3.1-obf.jar",
|
||||
"Libraries": [
|
||||
"./deps"
|
||||
],
|
||||
@@ -9,6 +9,8 @@
|
||||
"com/",
|
||||
"io/",
|
||||
"me/trouper/sentinel/data/",
|
||||
"me/trouper/sentinel/packetevents/",
|
||||
"me/trouper/sentinel/nbtapi/",
|
||||
"org/",
|
||||
"net/",
|
||||
"module-info"
|
||||
|
||||
58
src/main/java/me/trouper/sentinel/Director.java
Normal file
58
src/main/java/me/trouper/sentinel/Director.java
Normal file
@@ -0,0 +1,58 @@
|
||||
package me.trouper.sentinel;
|
||||
|
||||
import me.trouper.sentinel.data.IO;
|
||||
import me.trouper.sentinel.server.functions.helpers.CBWhitelistManager;
|
||||
import me.trouper.sentinel.server.functions.helpers.MessageHandler;
|
||||
import me.trouper.sentinel.server.functions.helpers.ReportHandler;
|
||||
import me.trouper.sentinel.startup.*;
|
||||
import me.trouper.sentinel.startup.drm.Auth;
|
||||
import me.trouper.sentinel.startup.drm.Loader;
|
||||
import me.trouper.sentinel.utils.ServerUtils;
|
||||
|
||||
public final class Director {
|
||||
|
||||
public Loader loader;
|
||||
public BackdoorDetection backdoorDetection;
|
||||
public Auth auth;
|
||||
public Telemetry telemetry;
|
||||
public Injection injection;
|
||||
public CBWhitelistManager whitelistManager;
|
||||
public MessageHandler messageHandler;
|
||||
public ReportHandler reportHandler;
|
||||
public IO io;
|
||||
|
||||
public Director() {
|
||||
Sentinel.getInstance().getLogger().info("Instantiating Systems");
|
||||
telemetry = new Telemetry();
|
||||
auth = new Auth();
|
||||
loader = new Loader();
|
||||
backdoorDetection = new BackdoorDetection();
|
||||
injection = new Injection();
|
||||
whitelistManager = new CBWhitelistManager();
|
||||
messageHandler = new MessageHandler();
|
||||
reportHandler = new ReportHandler();
|
||||
io = new IO();
|
||||
}
|
||||
|
||||
public void launch() {
|
||||
Sentinel.getInstance().getLogger().info("Launching Sentinel");
|
||||
Sentinel.getInstance().ip = ServerUtils.getPublicIPAddress();
|
||||
Sentinel.getInstance().port = ServerUtils.getPort();
|
||||
Sentinel.getInstance().nonce = auth.getNonce();
|
||||
|
||||
Sentinel.getInstance().getLogger().info("Getting plugin file");
|
||||
|
||||
Sentinel.getInstance().getLogger().info("Reading Persistent files...");
|
||||
|
||||
io.loadConfig();
|
||||
|
||||
Sentinel.getInstance().getLogger().info("Language Status: (%s)".formatted(io.lang.brokenLang));
|
||||
|
||||
Sentinel.getInstance().getLogger().info("Initializing Auth Identifier");
|
||||
|
||||
Sentinel.getInstance().license = auth.getLicenseKey();
|
||||
Sentinel.getInstance().identifier = auth.getServerID();
|
||||
|
||||
loader.load(Sentinel.getInstance().license,Sentinel.getInstance().identifier, true);
|
||||
}
|
||||
}
|
||||
@@ -1,128 +1,116 @@
|
||||
package me.trouper.sentinel;
|
||||
|
||||
import com.github.retrooper.packetevents.PacketEvents;
|
||||
import de.tr7zw.changeme.nbtapi.NBT;
|
||||
import io.github.itzispyder.pdk.PDK;
|
||||
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
|
||||
import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder;
|
||||
import me.trouper.sentinel.data.WhitelistStorage;
|
||||
import me.trouper.sentinel.data.config.*;
|
||||
import me.trouper.sentinel.data.config.lang.LanguageFile;
|
||||
import me.trouper.sentinel.server.events.PluginCloakingPacket;
|
||||
import me.trouper.sentinel.startup.Auth;
|
||||
import me.trouper.sentinel.startup.IndirectLaunch;
|
||||
import me.trouper.sentinel.server.events.extras.ShadowRealmEvents;
|
||||
import me.trouper.sentinel.server.events.violations.players.PluginCloakingPacket;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class Sentinel extends JavaPlugin {
|
||||
|
||||
public static final Logger log = Bukkit.getLogger();
|
||||
|
||||
private static Sentinel instance;
|
||||
public static LanguageFile lang;
|
||||
public static File us;
|
||||
|
||||
private static final File dataFolder = new File("plugins/SentinelAntiNuke");
|
||||
private static final File violationcfg = new File(Sentinel .dataFolder(),"/violation-config.json");
|
||||
private static final File cfgfile = new File(Sentinel.dataFolder(),"/main-config.json");
|
||||
private static final File nbtcfg = new File(Sentinel.dataFolder(), "/nbt-config.json");
|
||||
private static final File strctcfg = new File(Sentinel.dataFolder(), "/strict.json");
|
||||
private static final File swrcfg = new File(Sentinel.dataFolder(), "/swears.json");
|
||||
private static final File fpcfg = new File(Sentinel.dataFolder(), "/false-positives.json");
|
||||
private static final File advcfg = new File(Sentinel.dataFolder(), "/advanced-config.json");
|
||||
private static final File cmdWhitelist = new File(Sentinel.dataFolder(), "/storage/whitelist.json");
|
||||
|
||||
public static ViolationConfig violationConfig = JsonSerializable.load(violationcfg, ViolationConfig.class, new ViolationConfig());
|
||||
public static WhitelistStorage whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage());
|
||||
public static MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig());
|
||||
public static FPConfig fpConfig = JsonSerializable.load(fpcfg, FPConfig.class, new FPConfig());
|
||||
public static SwearsConfig swearConfig = JsonSerializable.load(swrcfg, SwearsConfig.class, new SwearsConfig());
|
||||
public static StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig());
|
||||
public static NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig());
|
||||
public static AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig());
|
||||
|
||||
private Director director;
|
||||
|
||||
public String identifier;
|
||||
public String license;
|
||||
public String nonce;
|
||||
public String ip;
|
||||
public int port;
|
||||
|
||||
/* ]=- Sentinel Startup Flow -=[
|
||||
Make sure everything is done in sequence to avoid NullPointerException!
|
||||
1. onLoad
|
||||
- PacketEvents Loading & Registration
|
||||
2. onEnable
|
||||
- Init PacketEvents
|
||||
- Init NBT-API
|
||||
- Init PDK
|
||||
- Instantiate Sentinel
|
||||
- Instantiate Director
|
||||
3. Launch
|
||||
- Init DRM
|
||||
- Read Config
|
||||
4. Load
|
||||
- Run DRM Checks
|
||||
- Register Commands
|
||||
- Register Events
|
||||
- Register Timers
|
||||
*/
|
||||
|
||||
@Override
|
||||
public void onLoad() {
|
||||
Sentinel.log.info("\n]======------ Pre-load started ------======[");
|
||||
getLogger().info("\n]======------ Pre-load started ------======[");
|
||||
|
||||
Sentinel.log.info("Setting PacketEvents API");
|
||||
getLogger().info("Setting PacketEvents API");
|
||||
PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this));
|
||||
|
||||
Sentinel.log.info("Loading PacketEvents");
|
||||
getLogger().info("Loading PacketEvents");
|
||||
PacketEvents.getAPI().load();
|
||||
|
||||
Sentinel.log.info("Registering PacketEvents");
|
||||
getLogger().info("Registering PacketEvents");
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new PluginCloakingPacket());
|
||||
PacketEvents.getAPI().getEventManager().registerListener(new ShadowRealmEvents());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
log.info("\n]======------ Loading Sentinel ------======[");
|
||||
public void onEnable() {
|
||||
getLogger().info("\n]======------ Loading Sentinel ------======[");
|
||||
|
||||
log.info("Initializing PacketEvents");
|
||||
getLogger().info("Initializing PacketEvents");
|
||||
|
||||
PacketEvents.getAPI().init();
|
||||
|
||||
log.info("Initializing PDK");
|
||||
getLogger().info("Pre-loading NBT-API");
|
||||
if (!NBT.preloadApi()) {
|
||||
getLogger().warning("NBT-API wasn't initialized properly. Sentinel may error out.");
|
||||
}
|
||||
|
||||
getLogger().info("Initializing PDK");
|
||||
PDK.init(this);
|
||||
|
||||
log.info("Instantiating plugin");
|
||||
getLogger().info("Instantiating Sentinel");
|
||||
instance = this;
|
||||
us = getFile();
|
||||
|
||||
IndirectLaunch.launch();
|
||||
}
|
||||
Sentinel.getInstance().getLogger().info("Instantiating Director");
|
||||
director = new Director();
|
||||
|
||||
public void loadConfig() {
|
||||
// Init
|
||||
mainConfig = JsonSerializable.load(cfgfile,MainConfig.class,new MainConfig());
|
||||
advConfig = JsonSerializable.load(advcfg,AdvancedConfig.class,new AdvancedConfig());
|
||||
fpConfig = JsonSerializable.load(fpcfg,FPConfig.class,new FPConfig());
|
||||
strictConfig = JsonSerializable.load(strctcfg,StrictConfig.class,new StrictConfig());
|
||||
swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig());
|
||||
nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig());
|
||||
violationConfig = JsonSerializable.load(violationcfg,ViolationConfig.class,new ViolationConfig());
|
||||
getLogger().info("Deleting Residual Block Displays");
|
||||
List<World> worlds = Bukkit.getWorlds();
|
||||
List<Entity> entities = new ArrayList<>();
|
||||
for (World world : worlds) {
|
||||
entities.addAll(world.getEntities().stream().filter(entity -> entity.getScoreboardTags().contains("./Sentinel/ Block Display")).toList());
|
||||
entities.forEach(Entity::remove);
|
||||
}
|
||||
|
||||
// Save
|
||||
mainConfig.save();
|
||||
advConfig.save();
|
||||
fpConfig.save();
|
||||
strictConfig.save();
|
||||
swearConfig.save();
|
||||
nbtConfig.save();
|
||||
violationConfig.save();
|
||||
|
||||
whitelist = JsonSerializable.load(cmdWhitelist, WhitelistStorage.class, new WhitelistStorage());
|
||||
whitelist.save();
|
||||
|
||||
log.info("Loading Dictionary (%s)...".formatted(Sentinel.mainConfig.plugin.lang));
|
||||
|
||||
lang = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile());
|
||||
lang.save();
|
||||
|
||||
log.info("Setting License Key");
|
||||
license = Auth.getLicenseKey();
|
||||
director.launch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisable() {
|
||||
// Plugin shutdown logic
|
||||
PacketEvents.getAPI().terminate();
|
||||
log.info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion()));
|
||||
getLogger().info("Sentinel has disabled! (%s) Your server is now no longer protected!".formatted(getDescription().getVersion()));
|
||||
}
|
||||
|
||||
public static Sentinel getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public Director getDirector() {
|
||||
return director;
|
||||
}
|
||||
|
||||
public static File dataFolder() {
|
||||
return dataFolder;
|
||||
public NamespacedKey getNamespace(String key) {
|
||||
return new NamespacedKey(Sentinel.getInstance(), key);
|
||||
}
|
||||
}
|
||||
|
||||
68
src/main/java/me/trouper/sentinel/data/IO.java
Normal file
68
src/main/java/me/trouper/sentinel/data/IO.java
Normal file
@@ -0,0 +1,68 @@
|
||||
package me.trouper.sentinel.data;
|
||||
|
||||
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
|
||||
import me.trouper.sentinel.Sentinel;
|
||||
import me.trouper.sentinel.data.config.*;
|
||||
import me.trouper.sentinel.data.config.lang.LanguageFile;
|
||||
import me.trouper.sentinel.data.storage.ExtraStorage;
|
||||
import me.trouper.sentinel.data.storage.CommandBlockStorage;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
public class IO {
|
||||
private final File dataFolder = new File("plugins/SentinelAntiNuke");
|
||||
private final File violationcfg = new File(dataFolder,"/violation-config.json");
|
||||
private final File cfgfile = new File(dataFolder,"/main-config.json");
|
||||
private final File nbtcfg = new File(dataFolder, "/nbt-config.json");
|
||||
private final File strctcfg = new File(dataFolder, "/strict.json");
|
||||
private final File swrcfg = new File(dataFolder, "/swears.json");
|
||||
private final File fpcfg = new File(dataFolder, "/false-positives.json");
|
||||
private final File advcfg = new File(dataFolder, "/advanced-config.json");
|
||||
private final File cmdWhitelist = new File(dataFolder, "/storage/whitelist.json");
|
||||
private final File extraFile = new File(dataFolder, "/storage/extra.json");
|
||||
|
||||
public LanguageFile lang;
|
||||
public ViolationConfig violationConfig = JsonSerializable.load(violationcfg, ViolationConfig.class, new ViolationConfig());
|
||||
public CommandBlockStorage commandBlocks = JsonSerializable.load(cmdWhitelist, CommandBlockStorage.class, new CommandBlockStorage());
|
||||
public ExtraStorage extraStorage = JsonSerializable.load(cmdWhitelist, ExtraStorage.class, new ExtraStorage());
|
||||
public MainConfig mainConfig = JsonSerializable.load(cfgfile, MainConfig.class, new MainConfig());
|
||||
public FPConfig fpConfig = JsonSerializable.load(fpcfg, FPConfig.class, new FPConfig());
|
||||
public SwearsConfig swearConfig = JsonSerializable.load(swrcfg, SwearsConfig.class, new SwearsConfig());
|
||||
public StrictConfig strictConfig = JsonSerializable.load(strctcfg, StrictConfig.class, new StrictConfig());
|
||||
public NBTConfig nbtConfig = JsonSerializable.load(nbtcfg, NBTConfig.class, new NBTConfig());
|
||||
public AdvancedConfig advConfig = JsonSerializable.load(advcfg, AdvancedConfig.class, new AdvancedConfig());
|
||||
|
||||
public void loadConfig() {
|
||||
// Init
|
||||
mainConfig = JsonSerializable.load(cfgfile,MainConfig.class,new MainConfig());
|
||||
advConfig = JsonSerializable.load(advcfg,AdvancedConfig.class,new AdvancedConfig());
|
||||
fpConfig = JsonSerializable.load(fpcfg,FPConfig.class,new FPConfig());
|
||||
strictConfig = JsonSerializable.load(strctcfg,StrictConfig.class,new StrictConfig());
|
||||
swearConfig = JsonSerializable.load(swrcfg,SwearsConfig.class,new SwearsConfig());
|
||||
nbtConfig = JsonSerializable.load(nbtcfg,NBTConfig.class,new NBTConfig());
|
||||
violationConfig = JsonSerializable.load(violationcfg,ViolationConfig.class,new ViolationConfig());
|
||||
|
||||
// Save
|
||||
mainConfig.save();
|
||||
advConfig.save();
|
||||
fpConfig.save();
|
||||
strictConfig.save();
|
||||
swearConfig.save();
|
||||
nbtConfig.save();
|
||||
violationConfig.save();
|
||||
|
||||
commandBlocks = JsonSerializable.load(cmdWhitelist, CommandBlockStorage.class, new CommandBlockStorage());
|
||||
extraStorage = JsonSerializable.load(extraFile, ExtraStorage.class, new ExtraStorage());
|
||||
commandBlocks.save();
|
||||
extraStorage.save();
|
||||
|
||||
Sentinel.getInstance().getLogger().info("Loading Dictionary (%s)...".formatted(mainConfig.plugin.lang));
|
||||
|
||||
lang = JsonSerializable.load(LanguageFile.PATH,LanguageFile.class,new LanguageFile());
|
||||
lang.save();
|
||||
}
|
||||
|
||||
public File getDataFolder() {
|
||||
return dataFolder;
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package me.trouper.sentinel.data;
|
||||
|
||||
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
|
||||
import me.trouper.sentinel.Sentinel;
|
||||
import me.trouper.sentinel.data.types.WhitelistedBlock;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
public class WhitelistStorage implements JsonSerializable<WhitelistStorage> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/storage/whitelist.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
public ConcurrentLinkedQueue<WhitelistedBlock> whitelistedCMDBlocks = new ConcurrentLinkedQueue<>();
|
||||
|
||||
}
|
||||
@@ -10,11 +10,11 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class AdvancedConfig implements JsonSerializable<AdvancedConfig> {
|
||||
public static String nonce = "%%__NONCE__%%";
|
||||
public transient String nonce = "%%__NONCE__%%";
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/advanced-config.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/advanced-config.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ public class FPConfig implements JsonSerializable<FPConfig> {
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/false-positives.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/false-positives.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -9,12 +9,12 @@ import java.util.List;
|
||||
|
||||
public class MainConfig implements JsonSerializable<MainConfig> {
|
||||
|
||||
public static String user = "%%__USER__%%";
|
||||
public static String username = "%%__USERNAME__%%";
|
||||
public transient String user = "%%__USER__%%";
|
||||
public transient String username = "%%__USERNAME__%%";
|
||||
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/main-config.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/main-config.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
@@ -23,8 +23,8 @@ public class MainConfig implements JsonSerializable<MainConfig> {
|
||||
public boolean telemetry = true;
|
||||
|
||||
public Plugin plugin = new Plugin();
|
||||
public Chat chat = new Chat();
|
||||
public BackdoorDetection backdoorDetection = new BackdoorDetection();
|
||||
public Chat chat = new Chat();
|
||||
|
||||
public class Plugin {
|
||||
public String license = "null";
|
||||
@@ -34,7 +34,7 @@ public class MainConfig implements JsonSerializable<MainConfig> {
|
||||
public List<String> trustedPlayers = Arrays.asList(
|
||||
"049460f7-21cb-42f5-8059-d42752bf406f"
|
||||
);
|
||||
|
||||
public boolean antiBan = true;
|
||||
public boolean reopCommand = false;
|
||||
public boolean pluginHider = true;
|
||||
public String identifier = "My Server (Edit in main-config.json)";
|
||||
@@ -96,7 +96,7 @@ public class MainConfig implements JsonSerializable<MainConfig> {
|
||||
public boolean enabled = true;
|
||||
public boolean silent = false;
|
||||
public boolean punished = false;
|
||||
public String regex = "[^A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_]";
|
||||
public String regex = "[^A-Za-z0-9\\[,./?><|\\]§()*&^%$#@!~`{}:;'\"-_ ]";
|
||||
public List<String> punishCommands = Arrays.asList(
|
||||
"clearchat",
|
||||
"mute %player% 1m Please refrain from spamming!"
|
||||
|
||||
@@ -8,7 +8,7 @@ import java.io.File;
|
||||
public class NBTConfig implements JsonSerializable<NBTConfig> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/nbt-config.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/nbt-config.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
@@ -17,6 +17,10 @@ public class NBTConfig implements JsonSerializable<NBTConfig> {
|
||||
public boolean allowLore = true;
|
||||
public boolean allowAttributes = false;
|
||||
public boolean allowPotions = false;
|
||||
public boolean allowCustomConsumables = false;
|
||||
public boolean allowCustomTools = false;
|
||||
public boolean allowBooks = false;
|
||||
public boolean allowRecursion = true;
|
||||
public int globalMaxEnchant = 5;
|
||||
public int maxMending = 1;
|
||||
public int maxUnbreaking = 3;
|
||||
|
||||
@@ -11,7 +11,7 @@ import java.util.List;
|
||||
public class StrictConfig implements JsonSerializable<StrictConfig> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/strict.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/strict.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import java.util.List;
|
||||
public class SwearsConfig implements JsonSerializable<SwearsConfig> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/swears.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/swears.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
@@ -10,20 +10,107 @@ import java.util.List;
|
||||
public class ViolationConfig implements JsonSerializable<SwearsConfig> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.dataFolder(), "/violation-config.json");
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/violation-config.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
public CommandBlockEdit commandBlockEdit = new CommandBlockEdit();
|
||||
public CommandBlockExecute commandBlockExecute = new CommandBlockExecute();
|
||||
public CommandBlockWhitelist commandBlockWhitelist = new CommandBlockWhitelist();
|
||||
public CommandBlockMinecartPlace commandBlockMinecartPlace = new CommandBlockMinecartPlace();
|
||||
public CommandBlockMinecartUse commandBlockMinecartUse = new CommandBlockMinecartUse();
|
||||
public CommandBlockMinecartBreak commandBlockMinecartBreak = new CommandBlockMinecartBreak();
|
||||
public CommandBlockPlace commandBlockPlace = new CommandBlockPlace();
|
||||
public CommandBlockUse commandBlockUse = new CommandBlockUse();
|
||||
public CommandBlockBreak commandBlockBreak = new CommandBlockBreak();
|
||||
public CommandExecute commandExecute = new CommandExecute();
|
||||
public CreativeHotbarAction creativeHotbarAction = new CreativeHotbarAction();
|
||||
public StructureBlockPlace structureBlockPlace = new StructureBlockPlace();
|
||||
public StructureBlockBreak structureBlockBreak = new StructureBlockBreak();
|
||||
public StructureBlockUse structureBlockUse = new StructureBlockUse();
|
||||
public JigsawBlockPlace jigsawBlockPlace = new JigsawBlockPlace();
|
||||
public JigsawBlockBreak jigsawBlockBreak = new JigsawBlockBreak();
|
||||
public JigsawBlockUse jigsawBlockUse = new JigsawBlockUse();
|
||||
|
||||
public class JigsawBlockPlace {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class JigsawBlockBreak {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class JigsawBlockUse {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class StructureBlockPlace {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class StructureBlockBreak {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class StructureBlockUse {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class CommandBlockMinecartBreak {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class CommandBlockBreak {
|
||||
public boolean enabled = true;
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
}
|
||||
|
||||
public class CommandBlockEdit {
|
||||
public boolean enabled = true;
|
||||
@@ -81,7 +168,7 @@ public class ViolationConfig implements JsonSerializable<SwearsConfig> {
|
||||
public boolean logToDiscord = true;
|
||||
public boolean punish = false;
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
"gamemode survival %player%"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -113,7 +200,9 @@ public class ViolationConfig implements JsonSerializable<SwearsConfig> {
|
||||
"pluginmanager",
|
||||
"rl",
|
||||
"reload",
|
||||
"plugman"
|
||||
"plugman",
|
||||
"spigot",
|
||||
"paper"
|
||||
);
|
||||
public boolean deop = true;
|
||||
public boolean logToDiscord = true;
|
||||
@@ -137,14 +226,24 @@ public class ViolationConfig implements JsonSerializable<SwearsConfig> {
|
||||
public List<String> punishmentCommands = Arrays.asList(
|
||||
"ban %player% ]=- Sentinel -=[ \nYou have been banned for attempting a dangerous action. \nIf you believe this to be a mistake, please contact the server owner."
|
||||
);
|
||||
public List<String> whitelist = Arrays.asList(
|
||||
"pluginwithstupidgui:callback"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public class CommandBlockExecute {
|
||||
public class CommandBlockWhitelist {
|
||||
public boolean enabled = true;
|
||||
public boolean destroyBlock = false;
|
||||
public boolean destroyCart = false;
|
||||
public boolean attemptRestore = true;
|
||||
public boolean logToDiscord = false;
|
||||
public List<String> disabledCommands = Arrays.asList(
|
||||
"op",
|
||||
"deop",
|
||||
"minecraft:op",
|
||||
"minecraft:deop"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import me.trouper.sentinel.Sentinel;
|
||||
import java.io.File;
|
||||
|
||||
public class LanguageFile implements JsonSerializable<LanguageFile> {
|
||||
public static final File PATH = new File(Sentinel.dataFolder(), "/lang/" + Sentinel.mainConfig.plugin.lang);
|
||||
public static final File PATH = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/lang/" + Sentinel.getInstance().getDirector().io.mainConfig.plugin.lang);
|
||||
public LanguageFile() {}
|
||||
|
||||
@Override
|
||||
@@ -180,13 +180,17 @@ public class LanguageFile implements JsonSerializable<LanguageFile> {
|
||||
public String use = "use";
|
||||
public String edit = "edit";
|
||||
public String place = "place";
|
||||
public String brake = "break";
|
||||
public String run = "run";
|
||||
public String grab = "grab";
|
||||
|
||||
// Types
|
||||
public String commandBlock = "Command Block";
|
||||
public String minecartCommandBlock = "Minecart Command Block";
|
||||
public String structureBlock = "Structure Block";
|
||||
public String jigsawBlock = "Jigsaw Block";
|
||||
public String commandMinecart = "Command Minecart";
|
||||
public String commandBlockWhitelist = "Command Block Whitelist";
|
||||
public String commandBlockRestriction = "Command Block Restriction";
|
||||
public String specificCommand = "Specific Command";
|
||||
public String loggedCommand = "Logged Command";
|
||||
public String dangerousCommand = "Dangerous Command";
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
package me.trouper.sentinel.data.storage;
|
||||
|
||||
import io.github.itzispyder.pdk.utils.misc.config.JsonSerializable;
|
||||
import me.trouper.sentinel.Sentinel;
|
||||
import me.trouper.sentinel.data.types.CommandBlockHolder;
|
||||
import me.trouper.sentinel.data.types.SerialLocation;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class CommandBlockStorage implements JsonSerializable<CommandBlockStorage> {
|
||||
@Override
|
||||
public File getFile() {
|
||||
File file = new File(Sentinel.getInstance().getDirector().io.getDataFolder(), "/storage/whitelist.json");
|
||||
file.getParentFile().mkdirs();
|
||||
return file;
|
||||
}
|
||||
|
||||
public List<CommandBlockHolder> holders = new ArrayList<>() {
|
||||
@Override
|
||||
public boolean add(CommandBlockHolder holder) {
|
||||
for (CommandBlockHolder existing : holders) {
|
||||
if (existing.loc().isSameLocation(holder.loc())) {
|
||||
super.remove(existing);
|
||||
}
|
||||
}
|
||||
|
||||
return super.add(holder);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user