diff --git a/.gitignore b/.gitignore
index 3734b6f..b51359d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,140 +1,50 @@
-# User-specific stuff
-.idea/
-
-*.iml
-*.ipr
-*.iws
-
-# IntelliJ
-out/
-# mpeltonen/sbt-idea plugin
-.idea_modules/
-
-# JIRA plugin
-atlassian-ide-plugin.xml
-
-# Compiled class file
-*.class
-
-# Log file
-*.log
-
-# BlueJ files
-*.ctxt
-
-# Package Files #
-*.jar
-*.war
-*.nar
-*.ear
-*.zip
-*.tar.gz
-*.rar
-
-# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
-hs_err_pid*
-
-*~
-
-# temporary files which can be created if a process still has a handle open of a deleted file
-.fuse_hidden*
-
-# KDE directory preferences
-.directory
-
-# Linux trash folder which might appear on any partition or disk
-.Trash-*
-
-# .nfs files are created when an open file is removed but is still being accessed
-.nfs*
-
-# General
-.DS_Store
-.AppleDouble
-.LSOverride
-
-# Icon must end with two \r
-Icon
-
-# Thumbnails
-._*
-
-# Files that might appear in the root of a volume
-.DocumentRevisions-V100
-.fseventsd
-.Spotlight-V100
-.TemporaryItems
-.Trashes
-.VolumeIcon.icns
-.com.apple.timemachine.donotpresent
-
-# Directories potentially created on remote AFP share
-.AppleDB
-.AppleDesktop
-Network Trash Folder
-Temporary Items
-.apdisk
-
-# Windows thumbnail cache files
-Thumbs.db
-Thumbs.db:encryptable
-ehthumbs.db
-ehthumbs_vista.db
-
-# Dump file
-*.stackdump
-
-# Folder config file
-[Dd]esktop.ini
-
-# Recycle Bin used on file shares
-$RECYCLE.BIN/
-
-# Windows Installer files
-*.cab
-*.msi
-*.msix
-*.msm
-*.msp
-
-# Windows shortcuts
-*.lnk
-
+### Gradle ###
.gradle
build/
-
-# Ignore Gradle GUI config
-gradle-app.setting
-
-# Cache of project
-.gradletasknamecache
-
-**/build/
-
-# Common working directory
run/
+!gradle/wrapper/gradle-wrapper.jar
+!**/src/main/**/build/
+!**/src/test/**/build/
-# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
-!gradle-wrapper.jar
+### IntelliJ IDEA ###
+.idea/modules.xml
+.idea/jarRepositories.xml
+.idea/compiler.xml
+.idea/libraries/
+.idea/*
+*.iws
+*.iml
+*.ipr
+out/
+!**/src/main/**/out/
+!**/src/test/**/out/
-# Avoid committing large parts of the server
-server/.console_history
-server/banned-ips.json
-server/banned-players.json
-server/commands.yml
-server/config
-server/help.yml
-server/logs
-server/ops.json
-server/permissions.yml
-server/plugins/spark/tmp
-server/usercache.json
-server/version_history.json
-server/whitelist.json
-server/world
-server/world_nether
-server/world_the_end
+### Eclipse ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+.sts4-cache
+bin/
+!**/src/main/**/bin/
+!**/src/test/**/bin/
-# nothing to see here :3
-NEVEREVERCOMMITTHIS.sh
-uwu.txt
+### NetBeans ###
+/nbproject/private/
+/nbbuild/
+/nbdist/
+/.nb-gradle/
+
+### VS Code ###
+.vscode/
+
+### Mac OS ###
+.DS_Store
+
+### Java ###
+hs_err_pid*.log
+
+## Docker ##
+dist/volumes
diff --git a/README.md b/README.md
index 047a8d7..a425a25 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# PickShadow's server code
+# PickShadow Server Kit (PSSK)
This repository contains PickShadow's server-side code.
## Index
diff --git a/build.gradle b/build.gradle
index cd81c7b..1de2316 100644
--- a/build.gradle
+++ b/build.gradle
@@ -28,8 +28,8 @@ allprojects {
repositories {
mavenCentral()
maven {
- name = "staropensource-sosengine"
- url = "https://mvn.staropensource.de/sosengine"
+ name = "staropensource-engine"
+ url = "https://mvn.staropensource.de/engine"
}
maven {
name = "papermc-repo"
diff --git a/common/build.gradle b/common/build.gradle
new file mode 100644
index 0000000..bf91047
--- /dev/null
+++ b/common/build.gradle
@@ -0,0 +1,86 @@
+
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+import java.nio.file.Files
+
+
+
+// Plugins
+plugins {
+ id("java")
+ id("io.freefair.lombok") version("${pluginLombok}")
+ id("com.gorylenko.gradle-git-properties") version("${pluginGitProperties}")
+}
+
+// Dependencies
+dependencies {
+ // Lombok
+ compileOnly("org.projectlombok:lombok:${dependencyLombok}")
+ annotationProcessor("org.projectlombok:lombok:${dependencyLombok}")
+
+ // JetBrains Annotations
+ compileOnly("org.jetbrains:annotations:${dependencyJetbrainsAnnotations}")
+
+ // Libraries
+ compileOnly("de.staropensource.engine:base:${dependencyStarOpenSourceEngine}")
+}
+
+// Set Java version
+java {
+ toolchain.languageVersion.set(JavaLanguageVersion.of("${javaTarget}"))
+}
+
+// Git properties configuration
+// Allows us to embed git commit information in the plugin build
+gitProperties {
+ dotGitDirectory = file("${rootProject.rootDir}/.git")
+ failOnNoGitDirectory = false // Allow continuing if .git directory is missing for the few who use tarballs
+ extProperty = "gitProps"
+
+ dateFormat = "yyyy-MM-dd'T'HH:mmZ"
+ dateFormatTimeZone = "UTC"
+}
+
+tasks.register("writeGitProperties") { // This task's only purpose is to copy the git.properties from our git properties plugin to the resources directory so it's included in the final build
+ doLast {
+ File target = file("${project.projectDir}/src/main/resources/pickshadow-git.properties")
+ File source = file("${project.projectDir}/build/resources/main/git.properties")
+
+ target.delete()
+ source.renameTo(target)
+ }
+
+ outputs.upToDateWhen({ false }) // Force task execution
+}
+generateGitProperties.outputs.upToDateWhen({ false }) // Force task execution
+processResources.dependsOn(writeGitProperties) // Ensure git.properties file is present
+
+// Copy gradle.properties file for inclusion in final build
+tasks.register("copyGradleProperties") {
+ doFirst {
+ File target = file("${project.projectDir}/src/main/resources/pickshadow-gradle.properties")
+ File source = file(project(":").projectDir.getPath() + "/gradle.properties")
+ target.delete()
+ Files.copy(source.toPath(), target.toPath())
+ }
+
+ outputs.upToDateWhen({ false }) // Force task execution
+}
+processResources.dependsOn(copyGradleProperties)
diff --git a/common/gradle b/common/gradle
new file mode 120000
index 0000000..3337596
--- /dev/null
+++ b/common/gradle
@@ -0,0 +1 @@
+../gradle
\ No newline at end of file
diff --git a/common/gradlew b/common/gradlew
new file mode 120000
index 0000000..502f5a2
--- /dev/null
+++ b/common/gradlew
@@ -0,0 +1 @@
+../gradlew
\ No newline at end of file
diff --git a/common/gradlew.bat b/common/gradlew.bat
new file mode 120000
index 0000000..2840132
--- /dev/null
+++ b/common/gradlew.bat
@@ -0,0 +1 @@
+../gradlew.bat
\ No newline at end of file
diff --git a/common/src/main/java/de/jeremystartm/pickshadow/common/CommonLibrary.java b/common/src/main/java/de/jeremystartm/pickshadow/common/CommonLibrary.java
new file mode 100644
index 0000000..a23be4a
--- /dev/null
+++ b/common/src/main/java/de/jeremystartm/pickshadow/common/CommonLibrary.java
@@ -0,0 +1,66 @@
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.jeremystartm.pickshadow.common;
+
+import de.staropensource.engine.base.logging.Logger;
+import lombok.Getter;
+
+/**
+ * Initializes and manages the PickShadow Common Library.
+ *
+ * @since v1-release0
+ */
+@SuppressWarnings({ "JavadocDeclaration" })
+public final class CommonLibrary {
+ /**
+ * Contains the global instance of this class.
+ *
+ * @since v1-release0
+ * -- GETTER --
+ * Returns the global instance of this class.
+ *
+ * @return global instance
+ * @since v1-release0
+ */
+ @Getter
+ private static CommonLibrary instance = null;
+
+ /**
+ * Creates and initializes an instance of this class.
+ *
+ * @since v1-release0
+ */
+ private CommonLibrary() {
+ Logger.verb("Initializing the PickShadow Common Library");
+
+ PSSKInformation.update();
+ }
+
+ /**
+ * Initializes the common library,
+ * if it isn't already.
+ *
+ * @since v1-release0
+ */
+ public static void initialize() {
+ if (instance == null)
+ instance = new CommonLibrary();
+ }
+}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionInformation.java b/common/src/main/java/de/jeremystartm/pickshadow/common/PSSKInformation.java
similarity index 89%
rename from extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionInformation.java
rename to common/src/main/java/de/jeremystartm/pickshadow/common/PSSKInformation.java
index 894eca6..61cba18 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionInformation.java
+++ b/common/src/main/java/de/jeremystartm/pickshadow/common/PSSKInformation.java
@@ -17,14 +17,13 @@
* along with this program. If not, see .
*/
-package de.jeremystartm.pickshadow.extension;
+package de.jeremystartm.pickshadow.common;
-import de.staropensource.sosengine.base.logging.LoggerInstance;
-import de.staropensource.sosengine.base.type.VersionType;
-import de.staropensource.sosengine.base.utility.PropertiesReader;
+import de.staropensource.engine.base.logging.Logger;
+import de.staropensource.engine.base.type.VersionType;
+import de.staropensource.engine.base.utility.PropertiesReader;
import lombok.Getter;
-import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.InputStream;
@@ -42,15 +41,7 @@ import java.util.Properties;
* @since v1-alpha0
*/
@SuppressWarnings({ "JavadocDeclaration" })
-public final class ExtensionInformation {
- /**
- * Contains the {@link LoggerInstance} for this instance.
- *
- * @see LoggerInstance
- * @since v1-alpha2
- */
- private static final @NotNull LoggerInstance logger = new LoggerInstance.Builder().setClazz(ExtensionInformation.class).setOrigin("PSSE").build();
-
+public final class PSSKInformation {
/**
* Contains the extensions's version codename.
*
@@ -284,7 +275,7 @@ public final class ExtensionInformation {
*
* @since v1-alpha6
*/
- private ExtensionInformation() {}
+ private PSSKInformation() {}
/**
* Updates all variables.
@@ -295,14 +286,14 @@ public final class ExtensionInformation {
* @since v1-alpha1
*/
public static synchronized void update() {
- logger.diag("Updating extension information");
+ Logger.diag("Updating extension information");
// Load properties from bundled gradle.properties
Properties gradleProperties = new Properties();
- InputStream gradleStream = ExtensionInformation.class.getClassLoader().getResourceAsStream("psse-gradle.properties");
+ InputStream gradleStream = PSSKInformation.class.getClassLoader().getResourceAsStream("psse-gradle.properties");
if (gradleStream == null) {
- logger.crash("Unable to load build information: The bundled gradle.properties file could not be found.");
+ Logger.crash("Unable to load build information: The bundled gradle.properties file could not be found.");
return;
}
@@ -310,16 +301,16 @@ public final class ExtensionInformation {
gradleProperties.load(gradleStream);
gradleStream.close();
} catch (IOException exception) {
- logger.crash("Unable to load build information: InputStream 'gradleStream' failed", exception);
+ Logger.crash("Unable to load build information: InputStream 'gradleStream' failed", exception);
return;
}
// Load properties from bundled git.properties
// or fill in blank information if file missing
Properties gitProperties = new Properties();
- InputStream gitStream = ExtensionInformation.class.getClassLoader().getResourceAsStream("psse-git.properties");
+ InputStream gitStream = PSSKInformation.class.getClassLoader().getResourceAsStream("psse-git.properties");
if (gitStream == null) {
- logger.error("Unable to load build information: The bundled git.properties file could not be found. Did you download a tarball?");
+ Logger.error("Unable to load build information: The bundled git.properties file could not be found. Did you download a tarball?");
// Fake information
gitProperties.setProperty("git.total.commit.count", "0");
@@ -337,7 +328,7 @@ public final class ExtensionInformation {
gitProperties.load(gitStream);
gitStream.close();
} catch (IOException exception) {
- logger.crash("Unable to load build information: InputStream 'gitStream' failed", exception);
+ Logger.crash("Unable to load build information: InputStream 'gitStream' failed", exception);
return;
}
}
@@ -369,7 +360,7 @@ public final class ExtensionInformation {
calendar.setTime(date);
gitCommitTime = calendar.toZonedDateTime();
} catch (ParseException exception) {
- logger.crash("Unable to load build information: Can't parse \"" + gitParser.getString("git.commit.time") + "\" using format \"yyyy-MM-dd'T'HH:mmZ\"", exception);
+ Logger.crash("Unable to load build information: Can't parse \"" + gitParser.getString("git.commit.time") + "\" using format \"yyyy-MM-dd'T'HH:mmZ\"", exception);
}
gitCommitterName = gitParser.getString("git.commit.user.name");
gitCommitterEmail = gitParser.getString("git.commit.user.email");
diff --git a/common/src/main/java/de/jeremystartm/pickshadow/common/package-info.java b/common/src/main/java/de/jeremystartm/pickshadow/common/package-info.java
new file mode 100644
index 0000000..4c04f4f
--- /dev/null
+++ b/common/src/main/java/de/jeremystartm/pickshadow/common/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * Code commonly used across PSSK's codebase.
+ *
+ * @since v1-release0
+ */
+package de.jeremystartm.pickshadow.common;
diff --git a/common/src/main/java/de/jeremystartm/pickshadow/package-info.java b/common/src/main/java/de/jeremystartm/pickshadow/package-info.java
new file mode 100644
index 0000000..3625640
--- /dev/null
+++ b/common/src/main/java/de/jeremystartm/pickshadow/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+/**
+ * Everything related to the PickShadow Server Kit.
+ *
+ * @since v1-release0
+ */
+package de.jeremystartm.pickshadow;
diff --git a/common/src/main/java/module-info.java b/common/src/main/java/module-info.java
new file mode 100644
index 0000000..209731e
--- /dev/null
+++ b/common/src/main/java/module-info.java
@@ -0,0 +1,15 @@
+/**
+ * Code commonly used across PSSK's codebase.
+ *
+ * @since v1-release0
+ */
+module pickshadow.common {
+ // Libraries
+ requires sosengine.base;
+
+ // API access
+ exports de.jeremystartm.pickshadow.common;
+
+ // Reflection access
+ opens de.jeremystartm.pickshadow.common;
+}
diff --git a/common/src/main/javadoc/theme.css b/common/src/main/javadoc/theme.css
new file mode 120000
index 0000000..681484a
--- /dev/null
+++ b/common/src/main/javadoc/theme.css
@@ -0,0 +1 @@
+../../../../src/main/javadoc/theme.css
\ No newline at end of file
diff --git a/common/src/main/resources/.gitignore b/common/src/main/resources/.gitignore
new file mode 100644
index 0000000..0567e20
--- /dev/null
+++ b/common/src/main/resources/.gitignore
@@ -0,0 +1 @@
+*.properties
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..6562e9b
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,23 @@
+services:
+ postgresql-dev:
+ container_name: postgresql-dev
+ image: bitnami/postgresql:latest
+ restart: always
+ stop_grace_period: 10s
+ user: 0:0
+ environment:
+ - ALLOW_EMPTY_PASSWORD=yes
+ - POSTGRESQL_USERNAME=postgres
+ - POSTGRESQL_PASSWORD=postgres
+ - POSTGRESQL_POSTGRES_PASSWORD=postgres
+ volumes:
+ - ./dist/volumes/postgresql-dev/data:/bitnami/postgresql/data
+ networks:
+ - development
+ ports:
+ - 127.0.0.1:5432:5432
+
+networks:
+ development:
+ name: development
+ external: false
diff --git a/extension/build.gradle b/extension/build.gradle
index 75ad362..9a8bc80 100644
--- a/extension/build.gradle
+++ b/extension/build.gradle
@@ -1,7 +1,3 @@
-import io.papermc.paperweight.userdev.ReobfArtifactConfiguration
-
-import java.nio.file.Files
-
/*
* PICKSHADOW SERVER KIT SOURCE FILE
* Copyright (c) 2024 The PickShadow Server Kit authors
@@ -21,13 +17,14 @@ import java.nio.file.Files
* along with this program. If not, see .
*/
+import io.papermc.paperweight.userdev.ReobfArtifactConfiguration
+
// Plugins
plugins {
id("java")
id("io.freefair.lombok") version("${pluginLombok}")
id("io.papermc.paperweight.userdev") version("${pluginPaperweight}")
id("io.github.goooler.shadow") version("${pluginShadow}")
- id("com.gorylenko.gradle-git-properties") version("${pluginGitProperties}")
id("xyz.jpenilla.run-paper") version("${pluginRunTask}")
}
@@ -41,7 +38,8 @@ dependencies {
compileOnly("org.jetbrains:annotations:${dependencyJetbrainsAnnotations}")
// Libraries
- compileOnly("de.staropensource.sosengine:base:${dependencyStarOpenSourceEngine}")
+ compileOnly("de.staropensource.engine:base:${dependencyStarOpenSourceEngine}")
+ runtimeOnly("de.staropensource.enginemc:platform-bukkit:${dependencyStarOpenSourceEngineMC}")
implementation("com.google.code.gson:gson:${dependencyGson}")
// Server
@@ -54,6 +52,9 @@ dependencies {
// Bukkit libraries
implementation("fr.mrmicky:fastboard:${dependencyFastboard}")
+
+ // Project
+ implementation(project(":common"))
}
// Set Java version
@@ -68,44 +69,6 @@ processResources {
}
}
-// Git properties configuration
-// Allows us to embed git commit information in the plugin build
-gitProperties {
- dotGitDirectory = file("${rootProject.rootDir}/.git")
- failOnNoGitDirectory = false // Allow continuing if .git directory is missing for the few who use tarballs
- extProperty = "gitProps"
-
- dateFormat = "yyyy-MM-dd'T'HH:mmZ"
- dateFormatTimeZone = "UTC"
-}
-
-tasks.register("writeGitProperties") { // This task's only purpose is to copy the git.properties from our git properties plugin to the resources directory so it's included in the final build
- doLast {
- File target = file("${project.projectDir}/src/main/resources/psse-git.properties")
- File source = file("${project.projectDir}/build/resources/main/git.properties")
-
- target.delete()
- source.renameTo(target)
- }
-
- outputs.upToDateWhen({ false }) // Force task execution
-}
-generateGitProperties.outputs.upToDateWhen({ false }) // Force task execution
-processResources.dependsOn(writeGitProperties) // Ensure git.properties file is present
-
-// Copy gradle.properties file for inclusion in final build
-tasks.register("copyGradleProperties") {
- doFirst {
- File target = file("${project.projectDir}/src/main/resources/psse-gradle.properties")
- File source = file(project(":").projectDir.getPath() + "/gradle.properties")
- target.delete()
- Files.copy(source.toPath(), target.toPath())
- }
-
- outputs.upToDateWhen({ false }) // Force task execution
-}
-processResources.dependsOn(copyGradleProperties)
-
// Configure paperweight
paperweight {
reobfArtifactConfiguration = ReobfArtifactConfiguration.getMOJANG_PRODUCTION()
@@ -114,14 +77,19 @@ paperweight {
// Configure server
runServer {
minecraftVersion("${minecraftVersion}")
- systemProperty("file.encoding", "UTF-8")
- systemProperty("com.mojang.eula.agree", "true")
- systemProperty("sosengine.base.loggerLevel", "diagnostic")
+
+ jvmArguments.addAll(
+ "-Dfile.encoding=UTF-8",
+ "-Dcom.mojang.eula.agree=true",
+ "-Dsosengine.base.logLevel=diagnostic",
+ "-Dpickshadow.extension.enabledModes=general,survival,survivalcheat"
+ )
downloadPlugins {
- modrinth("freedomchat", "${downloadFreedomChat}")
url("${downloadEngineMC}")
url("${downloadLuckPerms}")
+ url("${downloadSpark}")
+ modrinth("freedomchat", "${downloadFreedomChat}")
}
doFirst {
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/BuildOptions.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/BuildOptions.java
new file mode 100644
index 0000000..a18a2fc
--- /dev/null
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/BuildOptions.java
@@ -0,0 +1,108 @@
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.jeremystartm.pickshadow.extension;
+
+import org.bukkit.potion.PotionEffectType;
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+/**
+ * Provides an ugly way to choose
+ * what to put into the final,
+ * compiled bytecode.
+ *
+ * Seriously, why doesn't Java
+ * have a macro processor. It
+ * would've been so useful!
+ *
+ * @since v1-release0
+ */
+public final class BuildOptions {
+ // -----> Settings
+ /**
+ * Contains an array of all bad effects.
+ *
+ * @since v1-release0
+ */
+ public static final @NotNull List<@NotNull PotionEffectType> SETTINGS_EFFECTS_BAD = List.of(
+ PotionEffectType.SLOWNESS,
+ PotionEffectType.MINING_FATIGUE,
+ PotionEffectType.INSTANT_DAMAGE,
+ PotionEffectType.NAUSEA,
+ PotionEffectType.BLINDNESS,
+ PotionEffectType.HUNGER,
+ PotionEffectType.WEAKNESS,
+ PotionEffectType.POISON,
+ PotionEffectType.UNLUCK,
+ PotionEffectType.BAD_OMEN,
+ PotionEffectType.DARKNESS,
+ PotionEffectType.TRIAL_OMEN,
+ PotionEffectType.RAID_OMEN,
+ PotionEffectType.INFESTED
+ );
+ /**
+ * Contains an array of all damaging effects.
+ *
+ * @since v1-release0
+ */
+ public static final @NotNull List<@NotNull PotionEffectType> SETTINGS_EFFECTS_DAMAGING = List.of(
+ PotionEffectType.INSTANT_DAMAGE,
+ PotionEffectType.HUNGER,
+ PotionEffectType.POISON
+ );
+
+ // -----> Fixes and unfixes
+ /**
+ * Unfixes MC-212 (fixed in 24w45a),
+ * which allows players to avoid fall
+ * damage if they disconnect and then
+ * reconnect before hitting the ground.
+ *
+ * @see MC-212 on the Minecraft bug tracker
+ * @see 24w45a on the Minecraft Wiki
+ * @since v1-release0
+ */
+ public static final boolean UNFIX_FALLDAMAGE_CANCELLING = true;
+
+ // -----> Small stuff
+ /**
+ * Hides all messages starting with {@code #}.
+ *
+ * This allows commenting commands and
+ * messages easily. To circumvent it,
+ * just type {@code #} instead.
+ *
+ * @since v1-release0
+ */
+ public static final boolean SMALLSTUFF_CHAT_COMMENTS = true;
+
+ /**
+ * Enables stonecutter damage.
+ *
+ * I mean seriously, this thing has rotating blades.
+ * That Mojang decided not to add damage to it is
+ * embarrassing. Or can it cause animal cruelty,
+ * is it that Mojang?
+ *
+ * @since v1-release0
+ */
+ public static final boolean SMALLSTUFF_STONECUTTER_DAMAGE = true;
+}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/Extension.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/Extension.java
index a1d2353..5c48bbe 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/Extension.java
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/Extension.java
@@ -19,14 +19,24 @@
package de.jeremystartm.pickshadow.extension;
+import de.jeremystartm.pickshadow.common.CommonLibrary;
import de.jeremystartm.pickshadow.extension.api.entity.player.PlayerDataFactory;
import de.jeremystartm.pickshadow.extension.api.translation.TranslationManager;
+import de.jeremystartm.pickshadow.extension.command.general.AnnounceCommand;
+import de.jeremystartm.pickshadow.extension.command.general.replacement.GamemodeCommand;
+import de.jeremystartm.pickshadow.extension.command.general.replacement.HelpCommand;
+import de.jeremystartm.pickshadow.extension.command.general.replacement.MessageCommand;
+import de.jeremystartm.pickshadow.extension.command.survivalcheat.FeedCommand;
+import de.jeremystartm.pickshadow.extension.command.survivalcheat.HealCommand;
+import de.jeremystartm.pickshadow.extension.command.survivalcheat.ToggleDownfallCommand;
import de.jeremystartm.pickshadow.extension.command.general.*;
import de.jeremystartm.pickshadow.extension.command.survival.HomeCommand;
import de.jeremystartm.pickshadow.extension.listener.ChatListener;
import de.jeremystartm.pickshadow.extension.listener.ConnectionListener;
-import de.staropensource.sosengine.base.logging.LoggerInstance;
-import de.staropensource.sosengine.base.utility.Miscellaneous;
+import de.jeremystartm.pickshadow.extension.misc.BukkitLoggingAdapter;
+import de.jeremystartm.pickshadow.extension.misc.Scheduler;
+import de.staropensource.engine.base.logging.Logger;
+import de.staropensource.engine.base.utility.Miscellaneous;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
@@ -51,13 +61,6 @@ public final class Extension extends JavaPlugin {
@Getter
private static Extension instance = null;
- /**
- * Contains the logger instance for this instance.
- *
- * @since v1-release0
- */
- private final LoggerInstance logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").build();
-
/**
* Creates and initializes an instance of this class.
*
@@ -67,6 +70,7 @@ public final class Extension extends JavaPlugin {
instance = this;
}
+ // -----> Extension (de)initialization
/**
* Called after the plugin has been loaded.
*
@@ -74,25 +78,28 @@ public final class Extension extends JavaPlugin {
*/
@Override
public void onLoad() {
- logger.info("Bootstrapping");
+ // Fix logging adapter
+ Logger.setLoggingAdapter(new BukkitLoggingAdapter());
+
+ Logger.info("Bootstrapping");
// Check for NMS
try {
Class.forName("net.minecraft.server.MinecraftServer");
} catch (Exception exception) {
- logger.crash("This Bukkit implementation does not run on NMS.\nPSSE is designed to only run on NMS-based server software.\nYou may need to rewrite certain parts of PSSE so it can run on non-NMS server software.", exception);
+ Logger.crash("This Bukkit implementation does not run on NMS.\nPSSE is designed to only run on NMS-based server software.\nYou may need to rewrite certain parts of PSSE so it can run on non-NMS server software.", exception);
return;
}
// Load classes
+ CommonLibrary.initialize();
new ExtensionConfiguration().loadConfiguration();
- ExtensionInformation.update();
TranslationManager.loadTranslations();
TranslationManager.processTranslations();
//TabListHandler.initialize();
PlayerDataFactory.initialize();
- logger.info("Bootstrapped in " + Miscellaneous.measureExecutionTime(() -> {}) + "ms");
+ Logger.info("Bootstrapped in " + Miscellaneous.measureExecutionTime(() -> {}) + "ms");
}
/**
@@ -102,25 +109,49 @@ public final class Extension extends JavaPlugin {
*/
@Override
public void onEnable() {
- logger.info("Initializing");
+ Logger.info("Initializing");
try {
- logger.info("Initialized in " + Miscellaneous.measureExecutionTime(() -> {
- logger.verb("Registering commands");
+ Logger.info("Initialized in " + Miscellaneous.measureExecutionTime(() -> {
+ Logger.verb("Checking environment");
+ // Check for PaperMC
+ if (!isPaper())
+ Logger.crash("PaperMC classes weren't detected.\nYour server likely isn't running PaperMC or a fork of it.\nPSSE only supports PaperMC-based Minecraft servers.");
+ // Check for Folia
+ if (isFolia())
+ Logger.warn("Folia classes were detected.\nFolia support is experimental. Everything *should* work, but nothing is guaranteed. Here be dragons!");
+ else
+ Logger.verb("Folia classes weren't detected.\nFolia or a fork of it doesn't seem to be installed.");
+
+ Logger.verb("Registering commands");
+
+ new GamemodeCommand();
+ new HelpCommand();
+ new MessageCommand();
+
new AnnounceCommand();
new ClearChatCommand();
new ExtensionCommand();
- new HomeCommand();
+ new LanguageCommand();
new LinkCommand();
- new MessageCommand();
- new ToggleDownfallCommand();
new TrollCommand();
- logger.verb("Registering listeners");
+
+ new HomeCommand();
+
+
+ new FeedCommand();
+ new HealCommand();
+ new ToggleDownfallCommand();
+
+ Logger.verb("Registering listeners");
Bukkit.getPluginManager().registerEvents(new ConnectionListener(), this);
Bukkit.getPluginManager().registerEvents(new ChatListener(), this);
+
+ Logger.verb("Starting schedulers");
+ Bukkit.getServer().getGlobalRegionScheduler().runAtFixedRate(Extension.getInstance(), Scheduler::server, 1L, 1L);
}) + "ms");
} catch (Exception exception) {
- logger.crash("Initialization failed", exception);
+ Logger.crash("Initialization failed", exception);
}
}
@@ -131,7 +162,41 @@ public final class Extension extends JavaPlugin {
*/
@Override
public void onDisable() {
- logger.info("Shutting down");
- logger.info("Shut down in " + Miscellaneous.measureExecutionTime(() -> {}) + "ms");
+ Logger.info("Shutting down");
+ Logger.info("Shut down in " + Miscellaneous.measureExecutionTime(() -> {}) + "ms");
+ }
+
+ // -----> Utility methods
+ /**
+ * Checks if PaperMC's
+ * {@code PaperBootstrap}
+ * class is present.
+ *
+ * @return {@code true} if present, {@code false} otherwise
+ * @since v1-release0
+ */
+ public static boolean isPaper() {
+ try {
+ Class.forName("io.papermc.paper.PaperBootstrap");
+ return true;
+ } catch (ClassNotFoundException exception) {
+ return false;
+ }
+ }
+ /**
+ * Checks if Folia's
+ * {@code RegionizedServer}
+ * class is present.
+ *
+ * @return {@code true} if present, {@code false} otherwise
+ * @since v1-release0
+ */
+ public static boolean isFolia() {
+ try {
+ Class.forName("io.papermc.paper.threadedregions.RegionizedServer");
+ return true;
+ } catch (ClassNotFoundException exception) {
+ return false;
+ }
}
}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionConfiguration.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionConfiguration.java
index 08c7eb4..bf551bf 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionConfiguration.java
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/ExtensionConfiguration.java
@@ -20,8 +20,8 @@
package de.jeremystartm.pickshadow.extension;
import de.jeremystartm.pickshadow.extension.api.command.completion.StaticTabCompletion;
-import de.staropensource.sosengine.base.implementable.Configuration;
-import de.staropensource.sosengine.base.utility.PropertiesReader;
+import de.staropensource.engine.base.implementable.Configuration;
+import de.staropensource.engine.base.utility.PropertiesReader;
import lombok.Getter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -56,33 +56,62 @@ public final class ExtensionConfiguration extends Configuration {
/**
- * If enabled, allows for unintentional behaviour
- * and excess logging. Unless you want to debug or work
+ * Contains whether to allow unintentional behaviour
+ * and excess logging.
+ *
+ * Unless you want to debug or work
* on a sensitive part of the engine, don't enable this!
*
* @since v1-release0
* -- GETTER --
- * Gets the value for {@link #debug}.
+ * Returns whether to allow unintentional behaviour
+ * and excess logging.
+ *
+ * Unless you want to debug or work
+ * on a sensitive part of the engine, don't enable this!
*
- * @return variable value
- * @see #debug
+ * @return debugging flag state
* @since v1-release0
*/
private boolean debug;
/**
- * Causes {@link StaticTabCompletion} to print lots debugging information.
+ * Contains whether or not the tab completioning process
+ * should be logged by {@link StaticTabCompletion}.
*
* @since v1-release0
* -- GETTER --
- * Gets the value for {@link #debugStaticCompletion}.
+ * Contains whether or not the tab completioning process
+ * should be logged by {@link StaticTabCompletion}.
*
- * @return variable value
- * @see #debugStaticCompletion
+ * @return detailed tab completioning logging
* @since v1-release0
*/
private boolean debugStaticCompletion;
+
+ /**
+ * Contains an array of all
+ * enabled extension modes.
+ *
+ * Extension modes control what methods
+ * will be available and how the server
+ * will be controlled by the extension.
+ *
+ * @since v1-release0
+ * -- GETTER --
+ * Returns an array of all
+ * enabled extension modes.
+ *
+ * Extension modes control what methods
+ * will be available and how the server
+ * will be controlled by the extension.
+ *
+ * @return enabled extension modes
+ * @since v1-release0
+ */
+ private String[] enabledModes;
+
/**
* Creates and initializes an instance of this class.
*
@@ -90,8 +119,6 @@ public final class ExtensionConfiguration extends Configuration {
* @since v1-release0
*/
ExtensionConfiguration() {
- super("PSSE");
-
instance = this;
// Load default configuration
@@ -105,6 +132,8 @@ public final class ExtensionConfiguration extends Configuration {
switch (property) {
case "debug" -> debug = parser.getBoolean(group + property);
case "debugStaticCompletion" -> debugStaticCompletion = parser.getBoolean(group + property);
+
+ case "enabledModes" -> enabledModes = parser.getString(group + property).split(",");
}
} catch (NullPointerException ignored) {}
}
@@ -123,6 +152,8 @@ public final class ExtensionConfiguration extends Configuration {
public void loadDefaultConfiguration() {
debug = false;
debugStaticCompletion = false;
+
+ enabledModes = new String[]{ "general" };
}
/** {@inheritDoc} */
@@ -131,6 +162,8 @@ public final class ExtensionConfiguration extends Configuration {
return switch (setting) {
case "debug" -> debug;
case "debugStaticCompletion" -> debugStaticCompletion;
+
+ case "enabledModes" -> enabledModes;
default -> null;
};
}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBase.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBase.java
index a9c5abb..dc7b836 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBase.java
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBase.java
@@ -19,48 +19,129 @@
package de.jeremystartm.pickshadow.extension.api.command;
+import de.jeremystartm.pickshadow.extension.ExtensionConfiguration;
import de.jeremystartm.pickshadow.extension.api.translation.LanguageString;
import de.jeremystartm.pickshadow.extension.api.translation.TranslationManager;
+import de.staropensource.engine.base.logging.Logger;
+import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.command.*;
+import org.bukkit.craftbukkit.command.ServerCommandSender;
import org.bukkit.util.StringUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.List;
/**
* Abstract class for implementing commands.
+ *
+ * @since v1-release0
*/
+@Getter
public abstract class CommandBase implements CommandExecutor {
+ /**
+ * Contains a list of all registered commands.
+ *
+ * @since v1-release0
+ */
+ private static final @NotNull List<@NotNull CommandBase> REGISTERED = new ArrayList<>();
+
+ /**
+ * Contains a {@link CommandExecutor} implementation
+ * for disabled commands (caused by a disabled mode).
+ *
+ * @see ExtensionConfiguration#getEnabledModes()
+ * @since v1-release0
+ */
+ public static final @NotNull CommandExecutor disallowedExecutor = (sender, command, alias, arguments) -> {
+ sender.sendRichMessage(TranslationManager.get(LanguageString.ERROR_INVALID_MODE, sender, true));
+ return true;
+ };
+
+ /**
+ * Contains a list of all {@link Command}s this
+ * command has been registered for.
+ *
+ * @since v1-release0
+ */
+ private final @NotNull List<@NotNull PluginCommand> commands = new ArrayList<>();
+
/**
* Initializes this abstract class
* and registers the command.
*
+ * @param mode mode to register this command in
* @param commands all commands this class should handle
* @throws IllegalArgumentException if a command does not exist
* @since v1-release0
*/
- public CommandBase(@NotNull String... commands) throws IllegalArgumentException {
+ public CommandBase(@NotNull String mode, @NotNull String... commands) throws IllegalArgumentException {
+ boolean disallowedByMode = !Arrays.stream(ExtensionConfiguration.getInstance().getEnabledModes()).toList().contains(mode);
+
for (String command : commands) {
PluginCommand pluginCommand = Bukkit.getPluginCommand(command);
if (pluginCommand == null)
throw new IllegalArgumentException("Command registration failed: The command \"" + command + "\" does not exist");
- pluginCommand.setExecutor(this);
- pluginCommand.setTabCompleter(new TabCompleter() {
- @Override
- public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
- return StringUtil.copyPartialMatches(args[args.length - 1], getCompletion().complete(sender, label, args), new ArrayList<>());
- }
- });
+ if (disallowedByMode) {
+ pluginCommand.setExecutor(disallowedExecutor);
+ pluginCommand.setTabCompleter(null);
+ } else {
+ pluginCommand.setExecutor(this);
+ pluginCommand.setTabCompleter(new TabCompleter() {
+ @Override
+ public @NotNull List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) {
+ return StringUtil.copyPartialMatches(args[args.length - 1], getCompletion().complete(sender, label, args), new ArrayList<>());
+ }
+ });
+ }
+
+ this.commands.add(pluginCommand);
}
+
+ REGISTERED.add(this);
+ }
+
+ /**
+ * Initializes this abstract class
+ * and registers the command.
+ *
+ * Using this constructor instead of
+ * {@link #CommandBase(String, String...)}
+ * causes the creation of a dummy command
+ * which must be registered manually.
+ * Not recommended, use only when needed.
+ *
+ * @since v1-release0
+ */
+ public CommandBase() {
+ REGISTERED.add(this);
}
/** {@inheritDoc} */
@Override
public final boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) {
- invoke(sender, command, alias, args);
+ try {
+ invoke(sender, command, alias, args);
+ } catch (Exception exception) {
+ Logger.crash(
+ "Command /"
+ + command.getName()
+ + " (under alias /"
+ + alias
+ + ") failed for sender "
+ + sender.getName()
+ + " (console="
+ + (sender instanceof ConsoleCommandSender)
+ + ") with the following arguments:\n"
+ + Arrays.toString(args),
+ exception,
+ false);
+ sender.sendRichMessage(TranslationManager.get(LanguageString.ERROR_UNKNOWN, sender, true));
+ }
return true;
}
@@ -69,11 +150,13 @@ public abstract class CommandBase implements CommandExecutor {
*
* @since v1-release0
*/
+ @SuppressWarnings("NullableProblems") // intentional, see CommandBaseWithNull
public abstract void invoke(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] arguments);
/**
* Provides tab completions for this command.
*
+ * @return completion
* @since v1-release0
*/
public abstract @NotNull TabCompletion getCompletion();
@@ -85,10 +168,13 @@ public abstract class CommandBase implements CommandExecutor {
*
* @param sender sender to check
* @param permission permission to check for
- * @return return?
+ * @return {@code true} if the permission is missing, {@code false} otherwise
* @since v1-release0
*/
protected static boolean checkPermission(@NotNull CommandSender sender, @NotNull String permission) {
+ if (sender instanceof ServerCommandSender)
+ return false;
+
if (!sender.hasPermission(permission)) {
sender.sendRichMessage(
TranslationManager.get(LanguageString.ERROR_MISSING_PERM, sender, true)
@@ -99,4 +185,14 @@ public abstract class CommandBase implements CommandExecutor {
return false;
}
+
+ /**
+ * Returns a list of all registered commands.
+ *
+ * @return list of registered commands
+ * @since v1-release0
+ */
+ public static List<@NotNull CommandBase> getREGISTERED() {
+ return Collections.unmodifiableList(REGISTERED);
+ }
}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBaseWithNull.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBaseWithNull.java
new file mode 100644
index 0000000..5fa09d0
--- /dev/null
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/CommandBaseWithNull.java
@@ -0,0 +1,60 @@
+/*
+ * PICKSHADOW SERVER KIT SOURCE FILE
+ * Copyright (c) 2024 The PickShadow Server Kit authors
+ * Licensed under the GNU Affero General Public License v3
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+package de.jeremystartm.pickshadow.extension.api.command;
+
+import de.jeremystartm.pickshadow.extension.api.command.completion.StubTabCompletion;
+import lombok.Getter;
+import org.bukkit.command.*;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+/**
+ * Abstract class for implementing commands
+ * without the {@code command} parameter.
+ *
+ * @since v1-release0
+ */
+@Getter
+public abstract class CommandBaseWithNull extends CommandBase {
+ /**
+ * Initializes this abstract class
+ * and registers the command.
+ *
+ * @since v1-release0
+ */
+ public CommandBaseWithNull() {}
+
+ /**
+ * Executes this command.
+ *
+ * @since v1-release0
+ */
+ public abstract void invoke(@NotNull CommandSender sender, @Nullable Command command, @NotNull String alias, @NotNull String[] arguments);
+
+ /**
+ * Provides tab completions for this command.
+ *
+ * @return completion
+ * @since v1-release0
+ */
+ public @NotNull TabCompletion getCompletion() {
+ return StubTabCompletion.completion();
+ }
+}
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/completion/StaticTabCompletion.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/completion/StaticTabCompletion.java
index 524566c..09257db 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/completion/StaticTabCompletion.java
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/command/completion/StaticTabCompletion.java
@@ -21,7 +21,7 @@ package de.jeremystartm.pickshadow.extension.api.command.completion;
import de.jeremystartm.pickshadow.extension.ExtensionConfiguration;
import de.jeremystartm.pickshadow.extension.api.command.TabCompletion;
-import de.staropensource.sosengine.base.logging.LoggerInstance;
+import de.staropensource.engine.base.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
@@ -37,13 +37,6 @@ import java.util.*;
* @since v1-release0
*/
public final class StaticTabCompletion implements TabCompletion {
- /**
- * Contains the logger instance for this instance.
- *
- * @since v1-release0
- */
- private final @NotNull LoggerInstance logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").setMetadata(String.valueOf(hashCode())).build();
-
/**
* Creates and initializes an instance of this class.
*
@@ -68,7 +61,7 @@ public final class StaticTabCompletion implements TabCompletion {
@Override
public @NotNull List<@NotNull String> complete(@NotNull CommandSender sender, @NotNull String alias, @NotNull String[] arguments) {
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("complete(sender=" + sender.getName() + " alias=" + alias + " arguments=" + Arrays.toString(arguments) + ")");
+ Logger.diag("complete(sender=" + sender.getName() + " alias=" + alias + " arguments=" + Arrays.toString(arguments) + ")");
try {
// Get correct alias or return empty list
@@ -79,26 +72,26 @@ public final class StaticTabCompletion implements TabCompletion {
return List.of();
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion() && alias.isEmpty())
- logger.diag("Alias has been corrected");
+ Logger.diag("Alias has been corrected");
// Get and add completions
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Compiling completions");
+ Logger.diag("Compiling completions");
List<@NotNull String> output = new ArrayList<>(getCompletions(sender, alias, arguments.length - 1));
// Get and add alias-wide completions
if (completions.get(alias).containsKey(-1)) {
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Compiling alias-wide completions");
+ Logger.diag("Compiling alias-wide completions");
output.addAll(getCompletions(sender, alias, -1));
}
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("=== Completion finished");
+ Logger.diag("=== Completion finished");
return output;
} catch (Exception exception) {
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Caught " + exception.getClass().getName() + ", returning error list");
+ Logger.diag("Caught " + exception.getClass().getName() + ", returning error list");
return Arrays.stream(new String[]{ "An error occurred" }).toList();
}
}
@@ -116,7 +109,7 @@ public final class StaticTabCompletion implements TabCompletion {
List<@NotNull String> output = new ArrayList<>();
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("getCompletions(sender=" + sender.getName() + " alias=" + alias + " index=" + index + ")");
+ Logger.diag("getCompletions(sender=" + sender.getName() + " alias=" + alias + " index=" + index + ")");
if (!completions.get(alias).containsKey(index))
return List.of();
@@ -126,7 +119,7 @@ public final class StaticTabCompletion implements TabCompletion {
// Empty index, display player list
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Index is null, getting player list");
+ Logger.diag("Index is null, getting player list");
for (Player player : Bukkit.getOnlinePlayers())
output.add(player.getName());
@@ -136,15 +129,15 @@ public final class StaticTabCompletion implements TabCompletion {
// put these lines into Objects#requireNonNull so that the code is still fairly readable
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Index is map, getting arguments");
+ Logger.diag("Index is map, getting arguments");
for (String argument : completions.get(alias).get(index).keySet())
if (sender.hasPermission(completions.get(alias).get(index).get(argument))) {
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Adding completion argument \"" + argument + "\"");
+ Logger.diag("Adding completion argument \"" + argument + "\"");
output.add(argument);
} else if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("Permission is missing, skipping completion argument \"" + argument + "\"");
+ Logger.diag("Permission is missing, skipping completion argument \"" + argument + "\"");
}
return output;
@@ -230,7 +223,7 @@ public final class StaticTabCompletion implements TabCompletion {
*/
private void createIndex(@NotNull String alias, @Range(from = -1, to = Integer.MAX_VALUE) int index) {
if (ExtensionConfiguration.getInstance().isDebugStaticCompletion())
- logger.diag("createIndex(alias=" + alias + " index=" + index + ")");
+ Logger.diag("createIndex(alias=" + alias + " index=" + index + ")");
try {
if (completions.get(alias).get(index) == null)
throw new IndexOutOfBoundsException();
diff --git a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/entity/player/PlayerData.java b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/entity/player/PlayerData.java
index 7dea5ce..efa3d37 100644
--- a/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/entity/player/PlayerData.java
+++ b/extension/src/main/java/de/jeremystartm/pickshadow/extension/api/entity/player/PlayerData.java
@@ -19,12 +19,11 @@
package de.jeremystartm.pickshadow.extension.api.entity.player;
-
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
-import de.jeremystartm.pickshadow.extension.misc.TabListHandler;
-import de.staropensource.sosengine.base.logging.LoggerInstance;
+import de.jeremystartm.pickshadow.extension.misc.Scheduler;
+import de.staropensource.engine.base.logging.Logger;
import fr.mrmicky.fastboard.adventure.FastBoard;
import lombok.AccessLevel;
import lombok.Getter;
@@ -33,6 +32,7 @@ import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
@@ -45,19 +45,16 @@ import static java.util.Map.entry;
@Getter
@SuppressWarnings({ "JavadocDeclaration" })
public final class PlayerData {
- /**
- * Contains the logger instance for this instance.
- *
- * @since v1-release0
- */
- private final LoggerInstance logger;
-
/**
* Contains the associated {@link Player}.
+ *
+ * Will be saved.
*
* @since v1-release0
* -- GETTER --
* Returns the associated {@link Player}.
+ *
+ * Will be saved.
*
* @return associated {@link Player}
* @since v1-release0
@@ -67,15 +64,21 @@ public final class PlayerData {
/**
* Contains the player list scoreboard.
+ *
+ * Will not be saved.
*
* @since v1-release0
* -- GETTER --
* Returns the player list scoreboard.
+ *
+ * Will not be saved.
*
* @return player list scoreboard
* @since v1-release0
* -- SETTER --
* Sets the player list scoreboard.
+ *
+ * Will not be saved.
*
* @param playerListScoreboard new player list scoreboard
* @since v1-release0
@@ -83,20 +86,88 @@ public final class PlayerData {
@ApiStatus.Experimental
private @NotNull FastBoard playerListScoreboard;
+ /**
+ * Contains the preferred language
+ * the player has set.
+ *
+ * Will be saved.
+ *
+ * @since v1-release0
+ * -- GETTER --
+ * Returns the preferred language
+ * the player has set.
+ *
+ * Will be saved.
+ *
+ * @return preferred language
+ * @since v1-release0
+ * -- SETTER --
+ * Sets the preferred language
+ * the player has set.
+ *
+ * Will be saved.
+ *
+ * @param language new preferred language
+ * @since v1-release0
+ */
+ private String language;
+
/**
* Contains when the player has
* first been seen on the server.
+ *
+ * Will be saved.
*
* @since v1-release0
* -- GETTER --
* Returns when the player has
* first been seen on the server.
+ *
+ * Will be saved.
*
* @return first played date and time
* @since v1-release0
*/
private ZonedDateTime firstSeen;
+ /**
+ * Contains the UUID of the player
+ * this player has messaged last.
+ *
+ * Will be saved.
+ *
+ * @since v1-release0
+ * -- GETTER --
+ * Returns the UUID of the player
+ * this player has messaged last.
+ *
+ * Will be saved.
+ *
+ * @return UUID of the player last messaged
+ * @since v1-release0
+ */
+ private UUID lastMessaged;
+
+ /**
+ * Contains the state for
+ * stone cutter damage, as
+ * assigned by the {@link Scheduler}.
+ *
+ * Will not be saved.
+ *
+ * @since v1-release0
+ * -- GETTER --
+ * Returns the state for
+ * stone cutter damage, as
+ * assigned by the {@link Scheduler}.
+ *
+ * Will not be saved.
+ *
+ * @return stone cutter damage state
+ * @since v1-release0
+ */
+ private int stonecutterDamageState = -1;
+
/**
* Creates and initializes an instance of this class.
*
@@ -107,11 +178,13 @@ public final class PlayerData {
* @since v1-release0
*/
PlayerData(@NotNull Player player) {
- this.player = player;
- this.logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").setMetadata(player.getName()).build();
+ Logger.info("Initializing fresh player data for player " + player.getName() + " [" + player.getUniqueId() + "]");
+ this.player = player;
//TabListHandler.getInstance().initializeTabList(this);
+ language = "en";
firstSeen = ZonedDateTime.now();
+ lastMessaged = null;
}
/**
@@ -124,12 +197,14 @@ public final class PlayerData {
* @param firstSeen when the player was first seen
* @since v1-release0
*/
- private PlayerData(@NotNull Player player, @NotNull ZonedDateTime firstSeen) {
- this.player = player;
- this.logger = new LoggerInstance.Builder().setClazz(getClass()).setOrigin("PSSE").setMetadata(player.getName()).build();
+ private PlayerData(@NotNull Player player, @NotNull String language, @NotNull ZonedDateTime firstSeen, @Nullable UUID lastMessaged) {
+ Logger.info("Initializing player data from existing data for player " + player.getName() + " [" + player.getUniqueId() + "]");
- TabListHandler.getInstance().initializeTabList(this);
+ this.player = player;
+ //TabListHandler.getInstance().initializeTabList(this);
+ this.language = language;
this.firstSeen = firstSeen;
+ this.lastMessaged = lastMessaged;
}
/**
@@ -152,7 +227,9 @@ public final class PlayerData {
return new PlayerData(
player,
- ZonedDateTime.parse(data.get("firstPlayed"))
+ data.get("language"),
+ ZonedDateTime.parse(data.get("firstPlayed")),
+ data.get("lastMessaged").isBlank() ? null : UUID.fromString(data.get("lastMessaged"))
);
} catch (Exception exception) {
if (exception instanceof JsonSyntaxException)
@@ -172,7 +249,9 @@ public final class PlayerData {
return new Gson().toJson(
Map.ofEntries(
entry("playerUUID", player.getUniqueId().toString()),
- entry("firstPlayed", firstSeen.format(DateTimeFormatter.ISO_ZONED_DATE_TIME))
+ entry("language", language),
+ entry("firstPlayed", firstSeen.format(DateTimeFormatter.ISO_ZONED_DATE_TIME)),
+ entry("lastMessaged", lastMessaged == null ? "" : lastMessaged.toString())
),
new TypeToken