forked from upstream/Maintenance
Compare commits
59
Commits
localization
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dbdf811ae5 | ||
|
|
0518f848e1 | ||
|
|
4ebfa8c750 | ||
|
|
ea51ea9c63 | ||
|
|
3049f17250 | ||
|
|
619da4abee | ||
|
|
bb838fd4dd | ||
|
|
695404ce5c | ||
|
|
fd30fa4da6 | ||
|
|
3aad351c7b | ||
|
|
95492fe0e1 | ||
|
|
11b8fd2861 | ||
|
|
b9fdc90f7f | ||
|
|
acc5d89263 | ||
|
|
46b9dc4e04 | ||
|
|
5d37138b64 | ||
|
|
83f3a850c5 | ||
|
|
b58cb9709b | ||
|
|
00f6b25a67 | ||
|
|
e5fd9e6f37 | ||
|
|
051d916f87 | ||
|
|
b1ace71d4b | ||
|
|
da6fef8906 | ||
|
|
f6ad07a115 | ||
|
|
9072e03f79 | ||
|
|
946c1a7f72 | ||
|
|
572fc63162 | ||
|
|
87aedfaa3b | ||
|
|
8aba97d60d | ||
|
|
04d85b9c3c | ||
|
|
0603a17b5e | ||
|
|
3cd689f15d | ||
|
|
6c28d31fec | ||
|
|
1988b0284b | ||
|
|
c7f3dc72d4 | ||
|
|
9767322376 | ||
|
|
0e50c39100 | ||
|
|
ad2228b9c4 | ||
|
|
90e880500a | ||
|
|
15c3d9c111 | ||
|
|
ec55606737 | ||
|
|
a7438ca297 | ||
|
|
65d68982f9 | ||
|
|
03f0368c10 | ||
|
|
c16637ee36 | ||
|
|
7034bb85f5 | ||
|
|
38b142e8c9 | ||
|
|
2af4929c3a | ||
|
|
035b720369 | ||
|
|
8a106e4b34 | ||
|
|
f4a34041b8 | ||
|
|
ceb812e025 | ||
|
|
5058e851d8 | ||
|
|
ba04bae7bf | ||
|
|
d1abdd496e | ||
|
|
956e7bb3ef | ||
|
|
171e1368f4 | ||
|
|
0fff12f368 | ||
|
|
a9d052eabb |
No files matched your search
+51
-6
@@ -1,15 +1,60 @@
|
||||
# Maintenance Changelog
|
||||
This file contains update logs for this project. The top may contain a `Unreleased` section, gathering update logs for a future update during development.
|
||||
|
||||
## 5.1.1 - October 17th 2026
|
||||
|
||||
### Changed
|
||||
- Velocity/Bungee: Timer commands now accept `global` as the server argument, with an optional mode: `/maintenance starttimer global [mode] <time>`, `/maintenance scheduletimer global [mode] <time> <duration>`, `/maintenance endtimer global <time>`
|
||||
- Timer durations now also accept days, e.g. `2d` or `1d12h`
|
||||
- Folia: Now supports timers
|
||||
|
||||
### Fixed
|
||||
- Folia: Fixed the update check stalling the global region thread
|
||||
- Velocity/Bungee: Fixed the `redis.enabled` confg key
|
||||
- Velocity/Bungee: `/maintenance reload` now keeps the maintenance status from Redis instead of overriding it with the local config
|
||||
- Velocity/Bungee: Fixed `/maintenance aborttimer` tab completion not suggesting servers with running timers
|
||||
|
||||
---
|
||||
## 5.1.0 - May 17th 2026
|
||||
|
||||
### Changed
|
||||
- Made Discord webhooks configurable separately from command messages, including a new `%TIMESTAMP%` parameter for Discord timestamps (e.g. `<t:%TIMESTAMP%:R>`)
|
||||
|
||||
### Fixed
|
||||
- Velocity/Bungee: Fixed proxied-maintenance-servers config loading
|
||||
---
|
||||
## 5.0.0 - April 17th 2026
|
||||
|
||||
This update removes *a lot* of legacy code, making the code-base a great bit more simple and a lot more performant.
|
||||
|
||||
### Requirements
|
||||
- The Paper part now **requires at least Paper 1.20.1** and no longer supports Spigot
|
||||
- The universal jar has been removed. Each platform now has its own jar (that is as small as possible)
|
||||
- Maintenance now **requires at least Java 21**
|
||||
|
||||
### Changed
|
||||
- **Added mode-based maintenance messages** for `ping-message`, `player-count-message`, and `player-list-hover-message`
|
||||
- You can have different MOTDs depending on the pre-configured mode, e.g. a generic `default` or one for `upcoming-release`.
|
||||
- Updated proxy/global toggle syntax: `/maintenance on [mode]`
|
||||
- For proxy servers: `/maintenance on global [mode]`, `/maintenance on <server> [mode]`
|
||||
- Other updated commands: `/maintenance motd [timer] [mode]`, `/maintenance setmotd [timer] [mode] ...`, `/maintenance removemotd [timer] [mode] ...`
|
||||
- **Added `webhook` config option for Discord webhooks** when the maintenance status changes, a timer is started or a join is blocked
|
||||
- **Added `%REASON%` variable to messages**, using the `active-reason` config option. This allows for dynamic MOTD and other messages via a quick command without modifying the messages themselves
|
||||
- Can be changed via the `/maintenance setreason <reason>` command
|
||||
- **Added `/maintenance status` command** on Paper/Sponge to display the current maintenance status as well as any running start or end timers.
|
||||
- Velocity/Bungee: **The existing timer command now displays start and end timers** for proxied servers.
|
||||
- Velocity/Bungee: **Replaced `mysql` section with `redis`**. This is a more suitable database for such reading and sharing of data and no longer means some server pings can take multiple seconds, if you have multiple proxies linked
|
||||
|
||||
### Fixed
|
||||
- Velocity/Bungee: Fixed the `/maintenance schedule` command for single servers having swapped time arguments
|
||||
---
|
||||
## 4.3.0 - September 17th 2024
|
||||
## Unreleased
|
||||
### Changed
|
||||
* Added alternative player count and player list hover message for when endtimers are running, similar to the existing ping messages setting. They are disabled by default and can be found in their `player-count-message` and `player-list-hover-message` config sections
|
||||
* All timer commands now accept durations like `2h30m`, `1h30m5s`, or `90s`. The default behavior without units will still be in minutes
|
||||
* The language defaults will not automatically update, you might want to manually update the command help strings or just delete your language file
|
||||
* The language defaults will *not* automatically update the command help messages
|
||||
* Slightly reorganized the configuration file (it will be automatically migrated on startup, but new sections will be slapped at the bottom of the file)
|
||||
* The `fallback` field now also null values next to an empty array for disabling the feature
|
||||
* The `fallback` field now also accepts null values next to an empty array for disabling the feature
|
||||
* Updated language files from [Crowdin](https://crowdin.com/translate/maintenance)
|
||||
|
||||
### Fixed
|
||||
@@ -65,8 +110,8 @@ This file contains update logs for this project. The top may contain a `Unreleas
|
||||
### Changed
|
||||
* Added support for hex colors in messages and replaced the component parsing with adventure-minimessage
|
||||
* This means that section symbols (`§`) are no longer the intended/supported format
|
||||
* You can use the following page to edit and preview formatted text: https://webui.adventure.kyori.net/
|
||||
* You can find full documentation on the format (including normal colors and formatting, rgb, click/hover events, and more) here: https://docs.adventure.kyori.net/minimessage/format
|
||||
* You can use the following page to edit and preview formatted text: https://webui.advntr.dev/
|
||||
* You can find full documentation on the format (including normal colors and formatting, rgb, click/hover events, and more) here: https://docs.papermc.io/adventure/minimessage/format/
|
||||
* Your config and language file will be updated to the new format automatically, you won't have to change anything manually!
|
||||
* Note that the player count and player count hover messages do not support rgb colors
|
||||
* Updated Sponge module to SpongeAPI v8 (Minecraft 1.15+)
|
||||
@@ -328,4 +373,4 @@ This file contains update logs for this project. The top may contain a `Unreleas
|
||||
### Fixed
|
||||
* Fixed some permission and message bugs
|
||||
* Fixed problems with adding and removing players from the maintenance whitelist
|
||||
* Fixed update checks
|
||||
* Fixed update checks
|
||||
@@ -0,0 +1,14 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
- package-ecosystem: "gradle"
|
||||
cooldown:
|
||||
default-days: 7
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "monthly"
|
||||
@@ -7,20 +7,22 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: gradle/actions/wrapper-validation@v3
|
||||
- uses: actions/checkout@v7
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4
|
||||
- name: Set up Gradle
|
||||
uses: gradle/actions/setup-gradle@v6
|
||||
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v6
|
||||
with:
|
||||
java-version: 17
|
||||
java-version: 21
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Upload a Build Artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@v7
|
||||
with:
|
||||
name: Maintenance Files
|
||||
path: build/libs
|
||||
@@ -2,6 +2,7 @@
|
||||
build/
|
||||
.gradle
|
||||
bin/
|
||||
run/
|
||||
tmp/
|
||||
*.tmp
|
||||
*.bak
|
||||
|
||||
@@ -14,7 +14,7 @@ Its features include:
|
||||
* Nearly all messages are editable via the language file, given in a multitude of different languages
|
||||
* Features specifically for Bungee/Velocity
|
||||
* Only want to enable maintenance on a single server? You can also do so by using the `/maintenance <on/off> <servername>` command
|
||||
* Link multiple proxy instances through a MySQL database connection, so you don't have to change maintenance on each proxy by hand
|
||||
* Link multiple proxy instances through a Redis connection, so you don't have to change maintenance status or whitelisted players on each proxy by hand
|
||||
* Use PlaceholderAPI placeholders with the [**MaintenanceAddon**](https://hangar.papermc.io/kennytv/MaintenanceAddon) (for Velocity and Bungee)
|
||||
|
||||
A full list of commands, permissions and configuration options can be found in the wiki listed below.
|
||||
@@ -33,7 +33,7 @@ Join [our Discord](https://discord.gg/vGCUzHq) if you want to get the proofreade
|
||||
Adding translations for languages not yet listed is always appreciated as well!
|
||||
|
||||
## Compiling
|
||||
To create a working jar yourself, simply clone the project and compile it with Gradle (`gradlew build`).
|
||||
To create a working jar yourself, simply clone the project and compile it with Gradle (`gradlew build`). To compile, you need a JDK 21+ (although it targets 17).
|
||||
|
||||
## License
|
||||
This project is licensed under the [GNU General Public License v3](LICENSE.txt).
|
||||
@@ -1,24 +0,0 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
// Shade and relocate adventure in an extra module, so that common/the rest can directly depend on a
|
||||
// relocated adventure without breaking native platform's adventure usage with project wide relocation
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.bundles.adventure) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
exclude("net.kyori", "adventure-bom")
|
||||
exclude("com.google.code.gson", "gson")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
@@ -1,20 +0,0 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.adventurePlatformBukkit) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
@@ -1,20 +0,0 @@
|
||||
plugins {
|
||||
id("com.gradleup.shadow")
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.adventurePlatformBungee) {
|
||||
exclude("net.kyori", "adventure-api")
|
||||
}
|
||||
}
|
||||
|
||||
publishShadowJar()
|
||||
Whitespace-only changes.
@@ -4,9 +4,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
api(projects.maintenanceApi)
|
||||
compileOnly(projects.adventure.adventureApi) {
|
||||
targetConfiguration = "shadow"
|
||||
}
|
||||
compileOnly(libs.adventureApi)
|
||||
}
|
||||
|
||||
java {
|
||||
|
||||
+3
-9
@@ -15,17 +15,11 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.server;
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class DummyServer implements Server {
|
||||
private final String name;
|
||||
|
||||
public DummyServer(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
public record DummyServer(String name) implements Server {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -18,23 +18,26 @@
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.api.Maintenance;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Set;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface MaintenanceProxy extends Maintenance {
|
||||
|
||||
/**
|
||||
* Enables/disables maintenance mode on a proxied server.
|
||||
* If enabled, all non-permitted players will be kicked.
|
||||
* If MySQL is enabled, it will also be written into the database.
|
||||
* If Redis is enabled, it will also be written into the database.
|
||||
*
|
||||
* @param server server to apply the maintenance status to
|
||||
* @param maintenance true to enable, false to disable maintenance mode
|
||||
* @return true if the mode was changed
|
||||
* @see #getServer(String)
|
||||
*/
|
||||
boolean setMaintenanceToServer(Server server, boolean maintenance);
|
||||
boolean setMaintenanceToServer(Server server, boolean maintenance, @Nullable String mode);
|
||||
|
||||
default boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
return setMaintenanceToServer(server, maintenance, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param server server to check
|
||||
@@ -59,6 +62,18 @@ public interface MaintenanceProxy extends Maintenance {
|
||||
@Nullable
|
||||
Server getServer(String server);
|
||||
|
||||
/**
|
||||
* Returns a wrapped {@link Server} object of a proxied server, or a dummy server if not registered.
|
||||
*
|
||||
* @param serverName name of the proxied server
|
||||
* @return wrapped server object, or a dummy if not registered
|
||||
* @see Server#isRegisteredServer()
|
||||
*/
|
||||
default Server getServerOrDummy(final String serverName) {
|
||||
final Server server = getServer(serverName);
|
||||
return server != null ? server : new DummyServer(serverName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently registered proxied servers.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.api.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
/**
|
||||
* Wrapper for a proxied server.
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package eu.kennytv.maintenance.api;
|
||||
|
||||
import eu.kennytv.maintenance.api.event.manager.EventManager;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Maintenance {
|
||||
|
||||
@@ -25,13 +26,18 @@ public interface Maintenance {
|
||||
* Enables/disables maintenance mode.
|
||||
* If enabled, all non-permitted players will be kicked.
|
||||
* <p>
|
||||
* If using the BungeeCord version and MySQL is enabled,
|
||||
* If using the BungeeCord version and Redis is enabled,
|
||||
* it will also be written into the database.
|
||||
* </p>
|
||||
*
|
||||
* @param maintenance true to enable, false to disable maintenance mode
|
||||
* @param mode mode, used for custom messages
|
||||
*/
|
||||
void setMaintenance(boolean maintenance);
|
||||
void setMaintenance(boolean maintenance, @Nullable String mode);
|
||||
|
||||
default void setMaintenance(boolean maintenance) {
|
||||
setMaintenance(maintenance, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if maintenance is currently enabled
|
||||
|
||||
@@ -19,16 +19,39 @@ package eu.kennytv.maintenance.api;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface Settings {
|
||||
|
||||
/**
|
||||
* Note that the value might need a few seconds to update, if you're on BungeeCord with MySQL enabled
|
||||
* Returns whether maintenance is currently enabled.
|
||||
*
|
||||
* @return true if maintenance is currently enabled
|
||||
*/
|
||||
boolean isMaintenance();
|
||||
|
||||
/**
|
||||
* Returns the current active maintenance mode, or null is set to default.
|
||||
* Used when getting MOTD/player count messages.
|
||||
*
|
||||
* @return the current active maintenance mode, or null if set to default
|
||||
*/
|
||||
@Nullable String activeMode();
|
||||
|
||||
/**
|
||||
* Returns the reason for the current active mode.
|
||||
*
|
||||
* @return variable reason for the current active mode, or empty if no reason is set
|
||||
*/
|
||||
String activeReason();
|
||||
|
||||
/**
|
||||
* Sets the reason for the current active mode, used in %REASON% message placeholders.
|
||||
*
|
||||
* @param reason reason to set for the current active mode, or null to remove the reason
|
||||
*/
|
||||
void setActiveReason(@Nullable String reason);
|
||||
|
||||
/**
|
||||
* @return true if custom ping messages during maintenance should be used
|
||||
*/
|
||||
@@ -73,8 +96,8 @@ public interface Settings {
|
||||
*
|
||||
* @param name name of the player to remove with original lower-/uppercase letters
|
||||
* @return true if removing the player was successful
|
||||
* @deprecated if a player changes their name, the list will still contain the old one
|
||||
* @see #removeWhitelistedPlayer(UUID)
|
||||
* @deprecated if a player changes their name, the list will still contain the old one
|
||||
*/
|
||||
@Deprecated
|
||||
boolean removeWhitelistedPlayer(String name);
|
||||
|
||||
@@ -22,17 +22,5 @@ import eu.kennytv.maintenance.api.event.manager.MaintenanceEvent;
|
||||
/**
|
||||
* Notification event fired when maintenance mode has been changed.
|
||||
*/
|
||||
public final class MaintenanceChangedEvent implements MaintenanceEvent {
|
||||
private final boolean maintenance;
|
||||
|
||||
public MaintenanceChangedEvent(final boolean maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if maintenance has been enabled, false otherwise
|
||||
*/
|
||||
public boolean isMaintenance() {
|
||||
return maintenance;
|
||||
}
|
||||
public record MaintenanceChangedEvent(boolean isMaintenance) implements MaintenanceEvent {
|
||||
}
|
||||
@@ -8,5 +8,6 @@ repositories {
|
||||
|
||||
dependencies {
|
||||
// version must be manually kept in sync with the one in root project settings.gradle.kts
|
||||
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.0")
|
||||
implementation("com.gradleup.shadow:shadow-gradle-plugin:9.6.1")
|
||||
implementation("com.gradleup.nmcp:com.gradleup.nmcp.gradle.plugin:1.6.2")
|
||||
}
|
||||
@@ -6,12 +6,12 @@ import org.gradle.jvm.toolchain.JavaLanguageVersion
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import java.io.ByteArrayOutputStream
|
||||
|
||||
fun Project.publishShadowJar() {
|
||||
configurePublication {
|
||||
artifact(tasks["shadowJar"])
|
||||
artifact(tasks["sourcesJar"])
|
||||
artifact(tasks["javadocJar"])
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,14 +30,7 @@ private fun Project.configurePublication(configurer: MavenPublication.() -> Unit
|
||||
}
|
||||
|
||||
fun Project.latestCommitHash(): String {
|
||||
val byteOut = ByteArrayOutputStream()
|
||||
exec {
|
||||
return providers.exec {
|
||||
commandLine = listOf("git", "rev-parse", "--short", "HEAD")
|
||||
standardOutput = byteOut
|
||||
}
|
||||
return byteOut.toString(Charsets.UTF_8.name()).trim()
|
||||
}
|
||||
|
||||
fun JavaPluginExtension.javaTarget(version: Int) {
|
||||
toolchain.languageVersion.set(JavaLanguageVersion.of(version))
|
||||
}.standardOutput.asBytes.get().toString(Charsets.UTF_8).trim()
|
||||
}
|
||||
@@ -2,13 +2,16 @@ plugins {
|
||||
`java-library`
|
||||
`maven-publish`
|
||||
signing
|
||||
id("com.gradleup.nmcp")
|
||||
}
|
||||
|
||||
tasks {
|
||||
// Variable replacements
|
||||
processResources {
|
||||
val ver = project.version.toString()
|
||||
val desc = project.description
|
||||
filesMatching(listOf("plugin.yml", "bungee.yml", "META-INF/sponge_plugins.json")) {
|
||||
expand("version" to project.version, "description" to project.description)
|
||||
expand(mapOf("version" to ver, "description" to desc))
|
||||
}
|
||||
}
|
||||
javadoc {
|
||||
@@ -25,8 +28,10 @@ tasks {
|
||||
}
|
||||
|
||||
java {
|
||||
javaTarget(8)
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
signing {
|
||||
@@ -43,6 +48,11 @@ publishing {
|
||||
name.set("Maintenance")
|
||||
description.set("Paper plugin to enable maintenance mode on your Minecraft server.")
|
||||
url.set("https://github.com/kennytv/Maintenance")
|
||||
scm {
|
||||
url.set("https://github.com/kennytv/Maintenance")
|
||||
connection.set("scm:git:https://github.com/kennytv/Maintenance.git")
|
||||
developerConnection.set("scm:git:ssh://git@github.com/kennytv/Maintenance.git")
|
||||
}
|
||||
licenses {
|
||||
license {
|
||||
name.set("GNU GPLv3")
|
||||
@@ -57,15 +67,4 @@ publishing {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!name.startsWith("adventure")) {
|
||||
repositories.maven {
|
||||
name = "OSSRH"
|
||||
url = uri("https://s01.oss.sonatype.org/content/repositories/snapshots/")
|
||||
credentials {
|
||||
username = System.getenv("OSSRH_USERNAME")
|
||||
password = System.getenv("OSSRH_PASSWORD")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.named
|
||||
|
||||
plugins {
|
||||
id("maintenance.base-conventions")
|
||||
@@ -24,6 +23,10 @@ tasks {
|
||||
publishShadowJar()
|
||||
|
||||
fun ShadowJar.configureRelocations() {
|
||||
relocate("com.zaxxer.hikari", "eu.kennytv.maintenance.lib.hikari")
|
||||
relocate("org.bstats", "eu.kennytv.maintenance.lib.bstats")
|
||||
|
||||
// Proxy
|
||||
relocate("redis.client", "eu.kennytv.maintenance.lib.redis.client")
|
||||
relocate("org.json", "eu.kennytv.maintenance.lib.json")
|
||||
relocate("org.apache.commons.pool2", "eu.kennytv.maintenance.lib.apache.commons.pool2")
|
||||
}
|
||||
+24
-10
@@ -1,8 +1,10 @@
|
||||
import org.gradle.api.plugins.JavaPlugin.TEST_IMPLEMENTATION_CONFIGURATION_NAME
|
||||
import org.gradle.api.plugins.JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME
|
||||
|
||||
plugins {
|
||||
base
|
||||
id("maintenance.build-logic")
|
||||
id("com.gradleup.nmcp.aggregation") version "1.6.2"
|
||||
}
|
||||
|
||||
allprojects {
|
||||
@@ -16,20 +18,15 @@ val platforms = setOf(
|
||||
projects.maintenanceBungee,
|
||||
projects.maintenanceSponge,
|
||||
projects.maintenanceVelocity
|
||||
).map { it.dependencyProject }
|
||||
).map { it.path }
|
||||
|
||||
val special = setOf(
|
||||
projects.maintenance,
|
||||
projects.maintenanceApi,
|
||||
projects.maintenanceApiProxy,
|
||||
projects.adventure,
|
||||
projects.adventure.adventureApi,
|
||||
projects.adventure.adventurePlatformBukkit,
|
||||
projects.adventure.adventurePlatformBungee,
|
||||
).map { it.dependencyProject }
|
||||
projects.maintenanceApiProxy
|
||||
).map { it.path }
|
||||
|
||||
subprojects {
|
||||
when (this) {
|
||||
when (path) {
|
||||
in platforms -> plugins.apply("maintenance.platform-conventions")
|
||||
in special -> plugins.apply("maintenance.base-conventions")
|
||||
else -> plugins.apply("maintenance.standard-conventions")
|
||||
@@ -38,5 +35,22 @@ subprojects {
|
||||
dependencies {
|
||||
TEST_IMPLEMENTATION_CONFIGURATION_NAME(rootProject.libs.bundles.junit)
|
||||
TEST_IMPLEMENTATION_CONFIGURATION_NAME(rootProject.libs.snakeyaml)
|
||||
TEST_RUNTIME_ONLY_CONFIGURATION_NAME("org.junit.platform:junit-platform-launcher")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
allprojects {
|
||||
nmcpAggregation(project(path))
|
||||
}
|
||||
}
|
||||
|
||||
nmcpAggregation {
|
||||
centralPortal {
|
||||
username = System.getenv("MAVEN_CENTRAL_USERNAME")
|
||||
password = System.getenv("MAVEN_CENTRAL_PASSWORD")
|
||||
publishingType = "USER_MANAGED"
|
||||
publicationName = "maintenance:$version"
|
||||
publishingTimeout = java.time.Duration.ZERO
|
||||
}
|
||||
}
|
||||
+14
-3
@@ -1,8 +1,19 @@
|
||||
dependencies {
|
||||
implementation(projects.maintenanceCoreProxy)
|
||||
implementation(projects.adventure.adventurePlatformBungee) {
|
||||
targetConfiguration = "shadow"
|
||||
}
|
||||
implementation(libs.bstatsBungee)
|
||||
compileOnly(libs.bungee)
|
||||
}
|
||||
|
||||
tasks {
|
||||
shadowJar {
|
||||
relocate("net.kyori", "eu.kennytv.maintenance.lib.kyori")
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(libs.bundles.adventureBungee) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("org.slf4j", "slf4j-api")
|
||||
exclude("net.kyori", "adventure-bom")
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,6 @@ import eu.kennytv.maintenance.core.proxy.util.ProxyOfflineSenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -50,6 +48,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.imageio.ImageIO;
|
||||
import net.kyori.adventure.platform.bungeecord.BungeeAudiences;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.Favicon;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
@@ -118,9 +118,9 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
|
||||
@Override
|
||||
protected void kickPlayers(final Server server, final Server fallback) {
|
||||
// Kick players from a proxied server
|
||||
final ServerInfo fallbackServer = fallback != null ? ((BungeeServer) fallback).getServer() : null;
|
||||
final ServerInfo fallbackServer = fallback != null ? ((BungeeServer) fallback).server() : null;
|
||||
final boolean checkForFallback = fallbackServer != null && !isMaintenance(fallback);
|
||||
for (final ProxiedPlayer player : ((BungeeServer) server).getServer().getPlayers()) {
|
||||
for (final ProxiedPlayer player : ((BungeeServer) server).server().getPlayers()) {
|
||||
if (!hasPermission(player, "bypass") && !settingsProxy.isWhitelisted(player.getUniqueId())) {
|
||||
if (checkForFallback && fallbackServer.canAccess(player)) {
|
||||
audiences.player(player).sendMessage(settingsProxy.getMessage("singleMaintenanceActivated", "%SERVER%", server.getName()));
|
||||
@@ -137,7 +137,7 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
|
||||
@Override
|
||||
protected void kickPlayersTo(final Server server) {
|
||||
// Kick all players to a single waiting server
|
||||
final ServerInfo serverInfo = ((BungeeServer) server).getServer();
|
||||
final ServerInfo serverInfo = ((BungeeServer) server).server();
|
||||
// Notifications done in global method
|
||||
for (final ProxiedPlayer player : getProxy().getPlayers()) {
|
||||
if (hasPermission(player, "bypass") || settingsProxy.isWhitelisted(player.getUniqueId())) continue;
|
||||
@@ -167,7 +167,7 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
final ProfileLookup profile = doUUIDLookup(name);
|
||||
return new ProxyOfflineSenderInfo(profile.getUuid(), profile.getName());
|
||||
return new ProxyOfflineSenderInfo(profile.uuid(), profile.name());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -195,7 +195,7 @@ public final class MaintenanceBungeePlugin extends MaintenanceProxyPlugin {
|
||||
@Override
|
||||
@Nullable
|
||||
public String getServerNameOf(final SenderInfo sender) {
|
||||
final ProxiedPlayer player = getProxy().getPlayer(sender.getUuid());
|
||||
final ProxiedPlayer player = getProxy().getPlayer(sender.uuid());
|
||||
if (player == null || player.getServer() == null) return null;
|
||||
return player.getServer().getInfo().getName();
|
||||
}
|
||||
|
||||
+2
-1
@@ -22,6 +22,7 @@ import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.command.MaintenanceProxyCommand;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
@@ -40,7 +41,7 @@ public final class MaintenanceBungeeCommand extends MaintenanceProxyCommand {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final Map.Entry<String, ServerInfo> entry : plugin.getProxy().getServers().entrySet()) {
|
||||
final String serverName = entry.getValue().getName();
|
||||
if (entry.getKey().toLowerCase().startsWith(s) && !plugin.getSettingsProxy().getMaintenanceServers().contains(serverName)) {
|
||||
if (entry.getKey().toLowerCase(Locale.ROOT).startsWith(s) && !plugin.getSettingsProxy().getMaintenanceServers().contains(serverName)) {
|
||||
list.add(serverName);
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -24,7 +24,7 @@ import eu.kennytv.maintenance.bungee.util.BungeeServer;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.listener.ProxyJoinListenerBase;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.ProxyServer;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
import net.md_5.bungee.api.event.ServerConnectEvent;
|
||||
@@ -48,13 +48,13 @@ public final class ServerConnectListener extends ProxyJoinListenerBase implement
|
||||
final BungeeSenderInfo player = new BungeeSenderInfo(event.getPlayer());
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("Join permission check for " + event.getPlayer().getName()
|
||||
+ " - Permission: " + player.hasMaintenancePermission("bypass") + ", whitelist: " + settings.isWhitelisted(player.getUuid()));
|
||||
+ " - Permission: " + player.hasMaintenancePermission("bypass") + ", whitelist: " + settings.isWhitelisted(player.uuid()));
|
||||
}
|
||||
|
||||
if (shouldKick(player)) {
|
||||
final Server waitingServer = shouldConnectToWaitingServer(player);
|
||||
if (waitingServer != null) {
|
||||
event.setTarget(((BungeeServer) waitingServer).getServer());
|
||||
event.setTarget(((BungeeServer) waitingServer).server());
|
||||
player.send(settings.getMessage("sentToWaitingServer"));
|
||||
|
||||
if (plugin.isDebug()) {
|
||||
@@ -67,7 +67,7 @@ public final class ServerConnectListener extends ProxyJoinListenerBase implement
|
||||
|
||||
player.disconnect(settings.getKickMessage());
|
||||
if (settings.isJoinNotifications()) {
|
||||
broadcastJoinNotification(player.getName());
|
||||
broadcastJoinNotification(player.name());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -83,7 +83,7 @@ public final class ServerConnectListener extends ProxyJoinListenerBase implement
|
||||
final BungeeSenderInfo player = new BungeeSenderInfo(proxiedPlayer);
|
||||
final ServerConnectResult connectResult = serverConnect(player, new BungeeServer(event.getTarget()), normalServerConnect);
|
||||
if (plugin.isDebug()) {
|
||||
plugin.getLogger().info("Connectresult for " + player.getName() + " to " + event.getTarget().getName() + ": " + connectResult);
|
||||
plugin.getLogger().info("Connectresult for " + player.name() + " to " + event.getTarget().getName() + ": " + connectResult);
|
||||
}
|
||||
|
||||
if (connectResult.isCancelled()) {
|
||||
@@ -94,7 +94,7 @@ public final class ServerConnectListener extends ProxyJoinListenerBase implement
|
||||
player.disconnect(settings.getKickMessage());
|
||||
}
|
||||
} else if (connectResult.getTarget() != null) {
|
||||
event.setTarget(((BungeeServer) connectResult.getTarget()).getServer());
|
||||
event.setTarget(((BungeeServer) connectResult.getTarget()).server());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,7 +105,7 @@ public final class ServerConnectListener extends ProxyJoinListenerBase implement
|
||||
|
||||
@Override
|
||||
protected void broadcastJoinNotification(final String name, final Server server) {
|
||||
sendJoinMessage(((BungeeServer) server).getServer().getPlayers(), name);
|
||||
sendJoinMessage(((BungeeServer) server).server().getPlayers(), name);
|
||||
}
|
||||
|
||||
private void sendJoinMessage(final Iterable<ProxiedPlayer> players, final String name) {
|
||||
|
||||
@@ -21,7 +21,7 @@ import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.bungee.MaintenanceBungeePlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.CommandSender;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.api.connection.Connection;
|
||||
@@ -37,12 +37,12 @@ public final class BungeeSenderInfo implements ProxySenderInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return sender instanceof ProxiedPlayer ? ((ProxiedPlayer) sender).getUniqueId() : null;
|
||||
public UUID uuid() {
|
||||
return sender instanceof ProxiedPlayer proxiedPlayer ? proxiedPlayer.getUniqueId() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
public String name() {
|
||||
return sender.getName();
|
||||
}
|
||||
|
||||
@@ -67,13 +67,13 @@ public final class BungeeSenderInfo implements ProxySenderInfo {
|
||||
|
||||
@Override
|
||||
public boolean canAccess(final Server server) {
|
||||
return ((BungeeServer) server).getServer().canAccess(sender);
|
||||
return ((BungeeServer) server).server().canAccess(sender);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(final Component component) {
|
||||
if (sender instanceof Connection) {
|
||||
((Connection) sender).disconnect(ComponentUtil.toBadComponent(component));
|
||||
if (sender instanceof Connection connection) {
|
||||
connection.disconnect(ComponentUtil.toBadComponent(component));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,17 +18,12 @@
|
||||
package eu.kennytv.maintenance.bungee.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.config.ServerInfo;
|
||||
import net.md_5.bungee.api.connection.ProxiedPlayer;
|
||||
|
||||
public final class BungeeServer implements Server {
|
||||
private final ServerInfo server;
|
||||
|
||||
public BungeeServer(final ServerInfo server) {
|
||||
this.server = server;
|
||||
}
|
||||
public record BungeeServer(ServerInfo server) implements Server {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
@@ -52,8 +47,4 @@ public final class BungeeServer implements Server {
|
||||
public boolean isRegisteredServer() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ServerInfo getServer() {
|
||||
return server;
|
||||
}
|
||||
}
|
||||
@@ -17,8 +17,8 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.bungee.util;
|
||||
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
import net.md_5.bungee.api.chat.BaseComponent;
|
||||
import net.md_5.bungee.api.chat.TextComponent;
|
||||
import net.md_5.bungee.chat.ComponentSerializer;
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
dependencies {
|
||||
api(projects.maintenanceApiProxy)
|
||||
api(projects.maintenanceCore)
|
||||
implementation(libs.hikariCP)
|
||||
|
||||
// Try to reasonably minimize it...
|
||||
implementation(libs.jedis) {
|
||||
exclude("com.google.code.gson", "gson")
|
||||
exclude("org.slf4j", "slf4j-api")
|
||||
}
|
||||
|
||||
compileOnly(libs.luckperms)
|
||||
compileOnly(libs.guava)
|
||||
compileOnly(libs.gson)
|
||||
|
||||
+86
-45
@@ -28,14 +28,15 @@ import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.proxy.runnable.SingleMaintenanceScheduleRunnable;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProfileLookup;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.RateLimitedException;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.Duration;
|
||||
@@ -46,6 +47,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.regex.Pattern;
|
||||
import org.jetbrains.annotations.Blocking;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -54,7 +57,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @since 3.0
|
||||
*/
|
||||
public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implements MaintenanceProxy {
|
||||
private final Map<String, Task> serverTasks = new HashMap<>();
|
||||
private static final Pattern USERNAME_PATTERN = Pattern.compile("^[A-Za-z0-9_.]{1,16}$");
|
||||
private final Map<String, MaintenanceRunnableBase> serverTasks = new HashMap<>();
|
||||
protected SettingsProxy settingsProxy;
|
||||
|
||||
protected MaintenanceProxyPlugin(final String version, final ServerType serverType) {
|
||||
@@ -64,49 +68,54 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
@Override
|
||||
public void disable() {
|
||||
super.disable();
|
||||
if (settingsProxy.getMySQL() != null) {
|
||||
settingsProxy.getMySQL().close();
|
||||
if (settingsProxy.redisHandler() != null) {
|
||||
settingsProxy.redisHandler().close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
if (settingsProxy.hasMySQL()) {
|
||||
settingsProxy.setMaintenanceToSQL(maintenance);
|
||||
}
|
||||
super.setMaintenance(maintenance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenance(final Server server) {
|
||||
return settingsProxy.isMaintenance(server.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance, @Nullable final String mode) {
|
||||
if (maintenance) {
|
||||
if (!settingsProxy.addMaintenanceServer(server.getName())) {
|
||||
return false;
|
||||
if (settingsProxy.addMaintenanceServer(server.getName(), mode)) {
|
||||
serverActions(server, true);
|
||||
return true;
|
||||
}
|
||||
} else if (!settingsProxy.removeMaintenanceServer(server.getName())) {
|
||||
return mode != null && settingsProxy.setMaintenanceServerMode(server.getName(), mode);
|
||||
}
|
||||
|
||||
if (!settingsProxy.removeMaintenanceServer(server.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
serverActions(server, maintenance);
|
||||
|
||||
for (final String command : (maintenance ? settingsProxy.getCommandsOnMaintenanceEnable(server) : settingsProxy.getCommandsOnMaintenanceDisable(server))) {
|
||||
try {
|
||||
executeConsoleCommand(command.replace("%SERVER%", server.getName()));
|
||||
} catch (final Exception e) {
|
||||
getLogger().severe("Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
serverActions(server, false);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setMaintenanceToServer(final Server server, final boolean maintenance) {
|
||||
return setMaintenanceToServer(server, maintenance, null);
|
||||
}
|
||||
|
||||
public boolean setMaintenanceModeToServer(final Server server, @Nullable final String mode) {
|
||||
if (!settingsProxy.isMaintenance(server.getName())) {
|
||||
return false;
|
||||
}
|
||||
return settingsProxy.setMaintenanceServerMode(server.getName(), mode);
|
||||
}
|
||||
|
||||
public @Nullable String activeMode(final Server server) {
|
||||
return settingsProxy.activeMode(server.getName());
|
||||
}
|
||||
|
||||
public void serverActions(final Server server, final boolean maintenance) {
|
||||
if (server == null) return;
|
||||
if (server == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip to the even fire for dummy servers
|
||||
if (server.isRegisteredServer()) {
|
||||
@@ -126,6 +135,19 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
}
|
||||
|
||||
eventManager.callEvent(new ServerMaintenanceChangedEvent(server, maintenance));
|
||||
if (maintenance) {
|
||||
sendWebhookMessage("webhookSingleMaintenanceActivated", DiscordWebhook.EventType.MAINTENANCE_ENABLED, "%SERVER%", server.getName());
|
||||
} else {
|
||||
sendWebhookMessage("webhookSingleMaintenanceDeactivated", DiscordWebhook.EventType.MAINTENANCE_DISABLED, "%SERVER%", server.getName());
|
||||
}
|
||||
|
||||
for (final String command : (maintenance ? settingsProxy.getCommandsOnMaintenanceEnable(server) : settingsProxy.getCommandsOnMaintenanceDisable(server))) {
|
||||
try {
|
||||
executeConsoleCommand(command.replace("%SERVER%", server.getName()));
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.SEVERE, "Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,28 +155,45 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
return serverTasks.containsKey(server.getName());
|
||||
}
|
||||
|
||||
public boolean hasServerTasks() {
|
||||
return !serverTasks.isEmpty();
|
||||
}
|
||||
|
||||
public Map<String, MaintenanceRunnableBase> getServerTasks() {
|
||||
return serverTasks;
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase getServerTask(final String server) {
|
||||
return serverTasks.get(server);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getMaintenanceServers() {
|
||||
return Collections.unmodifiableSet(settingsProxy.getMaintenanceServers());
|
||||
}
|
||||
|
||||
public void cancelSingleTask(final Server server) {
|
||||
final Task task = serverTasks.remove(server.getName());
|
||||
final MaintenanceRunnableBase task = serverTasks.remove(server.getName());
|
||||
if (task != null) {
|
||||
task.cancel();
|
||||
task.getTask().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, (int) duration.getSeconds(), enable, server);
|
||||
serverTasks.put(server.getName(), runnable.getTask());
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable, @Nullable final String mode) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceRunnable(this, settingsProxy, (int) duration.getSeconds(), enable, server, mode);
|
||||
serverTasks.put(server.getName(), runnable);
|
||||
return runnable;
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase scheduleSingleMaintenanceRunnable(final Server server, final Duration enableIn, final Duration maintenanceDuration) {
|
||||
public MaintenanceRunnableBase startSingleMaintenanceRunnable(final Server server, final Duration duration, final boolean enable) {
|
||||
return startSingleMaintenanceRunnable(server, duration, enable, null);
|
||||
}
|
||||
|
||||
public MaintenanceRunnableBase scheduleSingleMaintenanceRunnable(final Server server, final Duration enableIn,
|
||||
final Duration maintenanceDuration, @Nullable final String mode) {
|
||||
final MaintenanceRunnableBase runnable = new SingleMaintenanceScheduleRunnable(this, settingsProxy,
|
||||
(int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), server);
|
||||
serverTasks.put(server.getName(), runnable.getTask());
|
||||
(int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), server, mode);
|
||||
serverTasks.put(server.getName(), runnable);
|
||||
return runnable;
|
||||
}
|
||||
|
||||
@@ -192,15 +231,17 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
@Blocking
|
||||
@Nullable
|
||||
protected ProfileLookup doUUIDLookup(final String name) throws IOException {
|
||||
ProfileLookup profileLookup;
|
||||
try {
|
||||
profileLookup = doUUIDLookupMojangAPI(name);
|
||||
} catch (RateLimitedException e) {
|
||||
// Use fallback API if rate limit is reached
|
||||
profileLookup = doUUIDLookupAshconAPI(name);
|
||||
ProfileLookup profileLookup = null;
|
||||
if (USERNAME_PATTERN.matcher(name).matches()) {
|
||||
try {
|
||||
profileLookup = doUUIDLookupMojangAPI(name);
|
||||
} catch (RateLimitedException e) {
|
||||
// Use fallback API if rate limit is reached
|
||||
profileLookup = doUUIDLookupAshconAPI(name);
|
||||
}
|
||||
}
|
||||
|
||||
if (settingsProxy.isFallbackToOfflineUUID() && profileLookup == null) {
|
||||
if (profileLookup == null && settingsProxy.isFallbackToOfflineUUID()) {
|
||||
// Use offline uuid
|
||||
return new ProfileLookup(UUID.nameUUIDFromBytes(("OfflinePlayer:" + name).getBytes(StandardCharsets.UTF_8)), name);
|
||||
}
|
||||
@@ -213,7 +254,7 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
*/
|
||||
@Nullable
|
||||
private ProfileLookup doUUIDLookupMojangAPI(final String name) throws IOException {
|
||||
final URL url = new URL("https://api.mojang.com/users/profiles/minecraft/" + name);
|
||||
final URL url = URI.create("https://api.mojang.com/users/profiles/minecraft/" + name).toURL();
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
connection.setRequestMethod("GET");
|
||||
|
||||
@@ -241,7 +282,7 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
*/
|
||||
@Nullable
|
||||
private ProfileLookup doUUIDLookupAshconAPI(final String name) throws IOException {
|
||||
final URL url = new URL("https://api.ashcon.app/mojang/v2/user/" + name);
|
||||
final URL url = URI.create("https://api.ashcon.app/mojang/v2/user/" + name).toURL();
|
||||
final HttpURLConnection connection = (HttpURLConnection) url.openConnection();
|
||||
|
||||
if (connection.getResponseCode() == 403) {
|
||||
@@ -279,4 +320,4 @@ public abstract class MaintenanceProxyPlugin extends MaintenancePlugin implement
|
||||
protected abstract void kickPlayersTo(Server server);
|
||||
|
||||
protected abstract void kickPlayersFromProxy();
|
||||
}
|
||||
}
|
||||
@@ -17,88 +17,55 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.MaintenanceProxy;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.proxy.mysql.MySQL;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import eu.kennytv.maintenance.core.proxy.redis.RedisHandler;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SettingsProxy extends Settings {
|
||||
private final MaintenanceProxyPlugin proxyPlugin;
|
||||
private Set<String> maintenanceServers;
|
||||
|
||||
private Map<String, String> maintenanceServers;
|
||||
private List<String> fallbackServers;
|
||||
private String waitingServer;
|
||||
private boolean fallbackToOfflineUUID;
|
||||
|
||||
private Map<String, List<String>> commandsOnMaintenanceEnable;
|
||||
private Map<String, List<String>> commandsOnMaintenanceDisable;
|
||||
private String mySQLTable;
|
||||
private String serverTable;
|
||||
private String maintenanceQuery;
|
||||
private String serverQuery;
|
||||
private MySQL mySQL;
|
||||
|
||||
private long millisecondsToCheck;
|
||||
private long lastMySQLCheck;
|
||||
private long lastServerCheck;
|
||||
private RedisHandler redisHandler;
|
||||
|
||||
public SettingsProxy(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin);
|
||||
this.proxyPlugin = plugin;
|
||||
}
|
||||
|
||||
private void setupMySQL() {
|
||||
plugin.getLogger().info("Trying to open database connection... (also, you can simply ignore the SLF4J soft-warning if it shows up)");
|
||||
final ConfigSection section = config.getSection("mysql");
|
||||
if (section == null) {
|
||||
plugin.getLogger().warning("Section missing: mysql");
|
||||
return;
|
||||
}
|
||||
|
||||
mySQL = new MySQL(plugin.getLogger(),
|
||||
section.getString("host"),
|
||||
section.getInt("port"),
|
||||
section.getString("username"),
|
||||
section.getString("password"),
|
||||
section.getString("database"),
|
||||
section.getBoolean("use-ssl", true));
|
||||
|
||||
// Varchar as the value regarding the possibility of saving stuff like the motd as well in future updates
|
||||
mySQLTable = section.getString("table", "maintenance_settings");
|
||||
serverTable = section.getString("servertable", "maintenance_servers");
|
||||
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + mySQLTable + " (setting VARCHAR(16) PRIMARY KEY, value VARCHAR(255))");
|
||||
mySQL.executeUpdate("CREATE TABLE IF NOT EXISTS " + serverTable + " (server VARCHAR(64) PRIMARY KEY)");
|
||||
maintenanceQuery = "SELECT * FROM " + mySQLTable + " WHERE setting = ?";
|
||||
serverQuery = "SELECT * FROM " + serverTable;
|
||||
plugin.getLogger().info("Done!");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadExtraSettings() {
|
||||
// Open database connection if enabled and not already done
|
||||
if (!hasMySQL() && config.getBoolean("mysql.use-mysql")) {
|
||||
try {
|
||||
setupMySQL();
|
||||
} catch (final Exception e) {
|
||||
mySQL = null;
|
||||
plugin.getLogger().warning("Error while trying do open database connection!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
// Open Redis connection if enabled and not already done
|
||||
final ConfigSection redisSection = config.getSection("redis");
|
||||
if (!hasRedis() && redisSection.getBoolean("enabled")) {
|
||||
connectToRedis(redisSection.getString("uri"));
|
||||
}
|
||||
if (hasRedis()) {
|
||||
maintenance = redisHandler.loadMaintenanceStatus();
|
||||
activeMode = normalizeMode(redisHandler.loadGlobalMode());
|
||||
maintenanceServers = redisHandler.loadMaintenanceServers();
|
||||
}
|
||||
|
||||
final Object fallback = config.getObject("fallback");
|
||||
fallbackServers = fallback instanceof String ? Collections.singletonList((String) fallback) : config.getStringList("fallback", Collections.emptyList());
|
||||
fallbackServers = fallback instanceof String s ? Collections.singletonList(s) : config.getStringList("fallback", Collections.emptyList());
|
||||
|
||||
waitingServer = config.getString("waiting-server", "");
|
||||
if (waitingServer.isEmpty() || waitingServer.equalsIgnoreCase("none")) {
|
||||
@@ -118,55 +85,36 @@ public final class SettingsProxy extends Settings {
|
||||
commandsOnMaintenanceDisable.put(key.toLowerCase(Locale.ROOT), disableCommandsSection.getStringList(key));
|
||||
}
|
||||
|
||||
if (hasMySQL()) {
|
||||
maintenance = loadMaintenance();
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
|
||||
final long configValue = config.getInt("mysql.update-interval");
|
||||
// Even if set to 0, only check every 500 millis
|
||||
millisecondsToCheck = configValue > 0 ? configValue * 1000 : 500;
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
} else {
|
||||
final List<String> list = config.getStringList("proxied-maintenance-servers");
|
||||
maintenanceServers = list == null ? new HashSet<>() : new HashSet<>(list);
|
||||
if (!hasRedis()) {
|
||||
final ConfigSection maintenanceServersSection = config.getSection("proxied-maintenance-servers");
|
||||
maintenanceServers = new LinkedHashMap<>();
|
||||
for (final Map.Entry<String, ?> entry : maintenanceServersSection.getValues().entrySet()) {
|
||||
if (entry.getKey() != null) {
|
||||
maintenanceServers.put(entry.getKey(), normalizeServerMode(entry.getValue()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMaintenance() {
|
||||
if (hasMySQL() && System.currentTimeMillis() - lastMySQLCheck > millisecondsToCheck) {
|
||||
final boolean databaseValue = loadMaintenance();
|
||||
if (databaseValue != maintenance) {
|
||||
maintenance = databaseValue;
|
||||
plugin.serverActions(maintenance);
|
||||
}
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
private void connectToRedis(final String redisUri) {
|
||||
redisHandler = new RedisHandler((MaintenanceProxyPlugin) plugin, this);
|
||||
try {
|
||||
redisHandler.setup(redisUri);
|
||||
} catch (final Exception e) {
|
||||
plugin.getLogger().log(Level.SEVERE, "Error while trying to open Redis connection!", e);
|
||||
e.printStackTrace();
|
||||
redisHandler.close();
|
||||
redisHandler = null;
|
||||
}
|
||||
return maintenance;
|
||||
}
|
||||
|
||||
public boolean isMaintenance(final String serverName) {
|
||||
if (hasMySQL() && System.currentTimeMillis() - lastServerCheck > millisecondsToCheck) {
|
||||
final Set<String> databaseValue = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.equals(databaseValue)) {
|
||||
// Enable maintenance on yet unlisted servers
|
||||
for (final String s : databaseValue) {
|
||||
if (!maintenanceServers.contains(s)) {
|
||||
proxyPlugin.serverActions(proxyPlugin.getServer(s), true);
|
||||
}
|
||||
}
|
||||
// Disable maintenance on now unlisted servers
|
||||
for (final String s : maintenanceServers) {
|
||||
if (!databaseValue.contains(s)) {
|
||||
proxyPlugin.serverActions(proxyPlugin.getServer(s), false);
|
||||
}
|
||||
}
|
||||
maintenanceServers = databaseValue;
|
||||
}
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
}
|
||||
return maintenanceServers.contains(serverName);
|
||||
return maintenanceServers.containsKey(serverName);
|
||||
}
|
||||
|
||||
public @Nullable String activeMode(final String serverName) {
|
||||
final String mode = maintenanceServers.get(serverName);
|
||||
return mode == null || mode.equals("default") ? null : mode;
|
||||
}
|
||||
|
||||
public Component getServerKickMessage(final String server) {
|
||||
@@ -174,101 +122,154 @@ public final class SettingsProxy extends Settings {
|
||||
if (message == null) {
|
||||
message = getLanguageString("singleMaintenanceKick", "%SERVER%", server);
|
||||
}
|
||||
return parse(plugin.replacePingVariables(message));
|
||||
return parse(plugin.replacePingVariables(message, activeMode(server)));
|
||||
}
|
||||
|
||||
// Full = being kicked from the proxy, not just a proxied server
|
||||
public Component getFullServerKickMessage(final String server) {
|
||||
String message = getLanguageStringOrNull("singleMaintenanceKicksComplete." + server, "%SERVER%", server);
|
||||
if (message == null) {
|
||||
message = getLanguageString("singleMaintenanceKickComplete", "%SERVER%", server);
|
||||
}
|
||||
return parse(plugin.replacePingVariables(message));
|
||||
return parse(plugin.replacePingVariables(message, activeMode(server)));
|
||||
}
|
||||
|
||||
public boolean hasMySQL() {
|
||||
return mySQL != null;
|
||||
public boolean hasRedis() {
|
||||
return redisHandler != null;
|
||||
}
|
||||
|
||||
void setMaintenanceToSQL(final boolean maintenance) {
|
||||
plugin.async(() -> {
|
||||
final String s = String.valueOf(maintenance);
|
||||
mySQL.executeUpdate("INSERT INTO " + mySQLTable + " (setting, value) VALUES (?, ?) ON DUPLICATE KEY UPDATE value = ?", "maintenance", s, s);
|
||||
lastMySQLCheck = System.currentTimeMillis();
|
||||
});
|
||||
}
|
||||
|
||||
boolean addMaintenanceServer(final String server) {
|
||||
if (hasMySQL()) {
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.add(server)) return false;
|
||||
plugin.async(() -> mySQL.executeUpdate("INSERT INTO " + serverTable + " (server) VALUES (?)", server));
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
@Override
|
||||
protected void loadWhitelistedPlayers() {
|
||||
if (hasRedis()) {
|
||||
redisHandler.loadPlayers(getWhitelistedPlayers());
|
||||
} else {
|
||||
super.loadWhitelistedPlayers();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance, @Nullable final String mode) {
|
||||
super.setMaintenance(maintenance, mode);
|
||||
if (hasRedis()) {
|
||||
redisHandler.set(maintenance, mode != null ? mode : "default");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveMode(@Nullable final String activeMode) {
|
||||
super.setActiveMode(activeMode);
|
||||
if (hasRedis() && isMaintenance()) {
|
||||
redisHandler.set(true, activeMode != null ? activeMode : "default");
|
||||
}
|
||||
}
|
||||
|
||||
public void setActiveModeDirect(@Nullable final String activeMode) {
|
||||
super.setActiveMode(activeMode);
|
||||
}
|
||||
|
||||
public void setMaintenanceDirect(final boolean maintenance, @Nullable final String mode) {
|
||||
super.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
|
||||
if (super.addWhitelistedPlayer(uuid, name)) {
|
||||
if (hasRedis()) {
|
||||
redisHandler.addPlayer(uuid, name);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean addWhitelistedPlayerDirect(final UUID uuid, final String name) {
|
||||
return super.addWhitelistedPlayer(uuid, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeWhitelistedPlayer(final UUID uuid) {
|
||||
if (super.removeWhitelistedPlayer(uuid)) {
|
||||
if (hasRedis()) {
|
||||
redisHandler.removePlayer(uuid);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean removeWhitelistedPlayerDirect(final UUID uuid) {
|
||||
return super.removeWhitelistedPlayer(uuid);
|
||||
}
|
||||
|
||||
boolean addMaintenanceServer(final String server, @Nullable final String mode) {
|
||||
final String normalizedMode = normalizeServerMode(mode);
|
||||
if (hasRedis()) {
|
||||
if (redisHandler.addServer(server, normalizedMode)) {
|
||||
maintenanceServers.put(server, normalizedMode);
|
||||
return true;
|
||||
}
|
||||
} else if (maintenanceServers.putIfAbsent(server, normalizedMode) == null) {
|
||||
saveServersToConfig();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean setMaintenanceServerMode(final String server, @Nullable final String mode) {
|
||||
final String normalizedMode = normalizeServerMode(mode);
|
||||
final String oldMode = maintenanceServers.get(server);
|
||||
if (oldMode == null || oldMode.equals(normalizedMode)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maintenanceServers.put(server, normalizedMode);
|
||||
if (hasRedis()) {
|
||||
redisHandler.setServerMode(server, normalizedMode);
|
||||
} else {
|
||||
if (!maintenanceServers.add(server)) return false;
|
||||
saveServersToConfig();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean removeMaintenanceServer(final String server) {
|
||||
if (hasMySQL()) {
|
||||
maintenanceServers = loadMaintenanceServersFromSQL();
|
||||
if (!maintenanceServers.remove(server)) return false;
|
||||
|
||||
plugin.async(() -> mySQL.executeUpdate("DELETE FROM " + serverTable + " WHERE server = ?", server));
|
||||
lastServerCheck = System.currentTimeMillis();
|
||||
} else {
|
||||
if (!maintenanceServers.remove(server)) return false;
|
||||
|
||||
if (hasRedis()) {
|
||||
if (redisHandler.removeServer(server)) {
|
||||
maintenanceServers.remove(server);
|
||||
return true;
|
||||
}
|
||||
} else if (maintenanceServers.remove(server) != null) {
|
||||
saveServersToConfig();
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Set<String> loadMaintenanceServersFromSQL() {
|
||||
final Set<String> maintenanceServers = new HashSet<>();
|
||||
mySQL.executeQuery(serverQuery, rs -> {
|
||||
try {
|
||||
while (rs.next()) {
|
||||
maintenanceServers.add(rs.getString("server"));
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
plugin.getLogger().warning("An error occured while trying to get the list of single servers with maintenance!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
return maintenanceServers;
|
||||
public boolean addMaintenanceServerDirect(final String server, @Nullable final String mode) {
|
||||
return maintenanceServers.put(server, normalizeServerMode(mode)) == null;
|
||||
}
|
||||
|
||||
private boolean loadMaintenance() {
|
||||
final boolean[] databaseValue = {false};
|
||||
mySQL.executeQuery(maintenanceQuery, rs -> {
|
||||
try {
|
||||
if (rs.next()) {
|
||||
databaseValue[0] = Boolean.parseBoolean(rs.getString("value"));
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
plugin.getLogger().warning("An error occured while trying to get the maintenance value from the database!");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, "maintenance");
|
||||
return databaseValue[0];
|
||||
public boolean removeMaintenanceServerDirect(final String server) {
|
||||
return maintenanceServers.remove(server) != null;
|
||||
}
|
||||
|
||||
public void setMaintenanceServerModeDirect(final String server, @Nullable final String mode) {
|
||||
if (maintenanceServers.containsKey(server)) {
|
||||
maintenanceServers.put(server, normalizeServerMode(mode));
|
||||
}
|
||||
}
|
||||
|
||||
private void saveServersToConfig() {
|
||||
config.set("proxied-maintenance-servers", new ArrayList<>(maintenanceServers));
|
||||
config.set("proxied-maintenance-servers", new LinkedHashMap<>(maintenanceServers));
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public Set<String> getMaintenanceServers() {
|
||||
return maintenanceServers;
|
||||
return maintenanceServers.keySet();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Server getFallbackServer() {
|
||||
for (final String fallbackServer : fallbackServers) {
|
||||
final Server server = proxyPlugin.getServer(fallbackServer);
|
||||
final Server server = ((MaintenanceProxy) plugin).getServer(fallbackServer);
|
||||
if (server != null && !isMaintenance(server.getName())) {
|
||||
return server;
|
||||
}
|
||||
@@ -286,7 +287,7 @@ public final class SettingsProxy extends Settings {
|
||||
}
|
||||
|
||||
public List<String> getCommandsOnMaintenanceEnable(final Server server) {
|
||||
final List<String> enableCommands = commandsOnMaintenanceEnable.getOrDefault("all", new ArrayList<>());
|
||||
final List<String> enableCommands = new ArrayList<>(commandsOnMaintenanceEnable.getOrDefault("all", Collections.emptyList()));
|
||||
final List<String> serverEnableCommands = commandsOnMaintenanceEnable.get(server.getName().toLowerCase(Locale.ROOT));
|
||||
if (serverEnableCommands != null) {
|
||||
enableCommands.addAll(serverEnableCommands);
|
||||
@@ -295,7 +296,7 @@ public final class SettingsProxy extends Settings {
|
||||
}
|
||||
|
||||
public List<String> getCommandsOnMaintenanceDisable(final Server server) {
|
||||
final List<String> disableCommands = commandsOnMaintenanceDisable.getOrDefault("all", new ArrayList<>());
|
||||
final List<String> disableCommands = new ArrayList<>(commandsOnMaintenanceDisable.getOrDefault("all", Collections.emptyList()));
|
||||
final List<String> serverDisableCommands = commandsOnMaintenanceDisable.get(server.getName().toLowerCase(Locale.ROOT));
|
||||
if (serverDisableCommands != null) {
|
||||
disableCommands.addAll(serverDisableCommands);
|
||||
@@ -303,8 +304,15 @@ public final class SettingsProxy extends Settings {
|
||||
return disableCommands;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
MySQL getMySQL() {
|
||||
return mySQL;
|
||||
public @Nullable RedisHandler redisHandler() {
|
||||
return redisHandler;
|
||||
}
|
||||
|
||||
private static String normalizeServerMode(@Nullable final Object mode) {
|
||||
if (mode == null) {
|
||||
return "default";
|
||||
}
|
||||
final String value = String.valueOf(mode).toLowerCase(Locale.ROOT);
|
||||
return value.isBlank() ? "default" : value;
|
||||
}
|
||||
}
|
||||
+3
-2
@@ -26,6 +26,7 @@ import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
private final MaintenanceProxyPlugin plugin;
|
||||
@@ -40,7 +41,7 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
@Override
|
||||
protected void addToggleAndTimerCommands() {
|
||||
add(new SingleToggleCommand(plugin), "on", "off");
|
||||
add(new StatusCommand(plugin), "status");
|
||||
add(new ProxyStatusCommand(plugin), "status");
|
||||
|
||||
add(new SingleStarttimerCommand(plugin), "starttimer", "start");
|
||||
add(new SingleEndtimerCommand(plugin), "endtimer", "end");
|
||||
@@ -52,7 +53,7 @@ public abstract class MaintenanceProxyCommand extends MaintenanceCommand {
|
||||
public List<String> getMaintenanceServersCompletion(final String s) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String server : settingsBungee.getMaintenanceServers()) {
|
||||
if (server.toLowerCase().startsWith(s)) {
|
||||
if (server.toLowerCase(Locale.ROOT).startsWith(s)) {
|
||||
list.add(server);
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -20,6 +20,8 @@ package eu.kennytv.maintenance.core.proxy.command;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ProxyCommandInfo extends CommandInfo {
|
||||
protected final MaintenanceProxyPlugin plugin;
|
||||
@@ -33,4 +35,10 @@ public abstract class ProxyCommandInfo extends CommandInfo {
|
||||
protected SettingsProxy getSettings() {
|
||||
return plugin.getSettingsProxy();
|
||||
}
|
||||
|
||||
protected List<String> getModesCompletion() {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
}
|
||||
+14
-1
@@ -22,8 +22,10 @@ import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class AbortSingleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -67,6 +69,17 @@ public final class AbortSingleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1]) : Collections.emptyList();
|
||||
if (args.length != 2 || !sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final String prefix = args[1].toLowerCase(Locale.ROOT);
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final String server : plugin.getServerTasks().keySet()) {
|
||||
if (server.toLowerCase(Locale.ROOT).startsWith(prefix)) {
|
||||
list.add(server);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.Map;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class ProxyStatusCommand extends ProxyCommandInfo {
|
||||
|
||||
public ProxyStatusCommand(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin, "singleserver.status");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
final MaintenanceRunnable task = plugin.getCurrentTask();
|
||||
if (task != null) {
|
||||
final String key = task.shouldEnable() ? "maintenanceStatusOffWithStartTimer" : "maintenanceStatusOnWithEndTimer";
|
||||
sender.send(getMessage(key, "%TIME%", task.getTime()));
|
||||
} else {
|
||||
sender.send(getMessage(plugin.isMaintenance() ? "maintenanceStatusOn" : "maintenanceStatusOff"));
|
||||
}
|
||||
|
||||
if (getSettings().getMaintenanceServers().isEmpty() && !plugin.hasServerTasks()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEmpty"));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceList"));
|
||||
// Enabled servers first
|
||||
for (final String server : getSettings().getMaintenanceServers()) {
|
||||
final MaintenanceRunnableBase serverTask = plugin.getServerTask(server);
|
||||
if (serverTask != null) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntryWithEndTimer", "%SERVER%", server, "%TIME%", serverTask.getTime()));
|
||||
continue;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceListEntry", "%SERVER%", server));
|
||||
}
|
||||
|
||||
// Then enabling tasks
|
||||
for (final Map.Entry<String, MaintenanceRunnableBase> entry : plugin.getServerTasks().entrySet()) {
|
||||
final MaintenanceRunnableBase serverTask = entry.getValue();
|
||||
if (serverTask.shouldEnable()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntryWithStartTimer", "%SERVER%", entry.getKey(), "%TIME%", serverTask.getTime()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getHelpMessage() {
|
||||
return getMessage("helpStatus");
|
||||
}
|
||||
}
|
||||
+72
-35
@@ -21,10 +21,14 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class SingleEndtimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -40,49 +44,82 @@ public final class SingleEndtimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (!plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
sender.send(getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
endGlobal(sender, args[1]);
|
||||
} else if (args.length == 3) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
endGlobal(sender, args[2]);
|
||||
} else {
|
||||
endSingle(sender, args[1], args[2]);
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, false);
|
||||
sender.send(getMessage(
|
||||
"singleEndtimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void endGlobal(final SenderInfo sender, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (!plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
|
||||
final Component message = getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
private void endSingle(final SenderInfo sender, final String serverArg, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, false);
|
||||
final Component message = getMessage(
|
||||
"singleEndtimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
);
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookSingleEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
if (args.length != 2) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer") && plugin.isMaintenance()) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
}
|
||||
+80
-43
@@ -23,8 +23,11 @@ import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleScheduleTimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -40,56 +43,90 @@ public final class SingleScheduleTimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 3) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
scheduleGlobal(sender, null, args[1], args[2]);
|
||||
} else if (args.length == 4 || args.length == 5) {
|
||||
final String mode = args.length == 5 ? args[2] : null;
|
||||
final String enableInArg = args.length == 5 ? args[3] : args[2];
|
||||
final String durationArg = args.length == 5 ? args[4] : args[3];
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
scheduleGlobal(sender, mode, enableInArg, durationArg);
|
||||
} else {
|
||||
scheduleSingle(sender, args[1], mode, enableInArg, durationArg);
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.scheduleMaintenanceRunnable(duration, enableIn);
|
||||
sender.send(getMessage(
|
||||
"scheduletimerStarted",
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds())
|
||||
));
|
||||
} else if (args.length == 4) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[3], false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.scheduleSingleMaintenanceRunnable(server, enableIn, duration);
|
||||
sender.send(getMessage(
|
||||
"singleScheduletimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds()),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void scheduleGlobal(final SenderInfo sender, @Nullable final String mode, final String enableInArg, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, enableInArg);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.scheduleMaintenanceRunnable(enableIn, duration, mode);
|
||||
sender.send(getMessage(
|
||||
"scheduletimerStarted",
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds())
|
||||
));
|
||||
}
|
||||
|
||||
private void scheduleSingle(final SenderInfo sender, final String serverArg, @Nullable final String mode,
|
||||
final String enableInArg, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration enableIn = plugin.getCommandManager().parseDurationAndCheckTask(sender, enableInArg, false);
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (enableIn == null || duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.scheduleSingleMaintenanceRunnable(server, enableIn, duration, mode);
|
||||
sender.send(getMessage(
|
||||
"singleScheduletimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%DURATION%", plugin.getFormattedTime((int) duration.getSeconds()),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
return sender.hasMaintenancePermission("timer") ? getModesCompletion() : Collections.emptyList();
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer") && plugin.getServer(args[1]) != null) {
|
||||
return getModesCompletion();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+82
-36
@@ -21,10 +21,15 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.time.Duration;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleStarttimerCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -40,49 +45,90 @@ public final class SingleStarttimerCommand extends ProxyCommandInfo {
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[1]);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
startGlobal(sender, null, args[1]);
|
||||
} else if (args.length == 3 || args.length == 4) {
|
||||
final String mode = args.length == 4 ? args[2] : null;
|
||||
final String durationArg = args.length == 4 ? args[3] : args[2];
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
startGlobal(sender, mode, durationArg);
|
||||
} else {
|
||||
startSingle(sender, args[1], mode, durationArg);
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true);
|
||||
sender.send(getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
} else if (args.length == 3) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, args[2], false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, args[1]);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, true);
|
||||
sender.send(getMessage(
|
||||
"singleStarttimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
));
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private void startGlobal(final SenderInfo sender, @Nullable final String mode, final String durationArg) {
|
||||
if (checkPermission(sender, "timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
if (plugin.isMaintenance()) {
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true, mode);
|
||||
final Component message = getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
private void startSingle(final SenderInfo sender, final String serverArg, @Nullable final String mode, final String durationArg) {
|
||||
if (checkPermission(sender, "singleserver.timer")) return;
|
||||
|
||||
final Duration duration = plugin.getCommandManager().parseDurationAndCheckTask(sender, durationArg, false);
|
||||
if (duration == null) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Server server = plugin.getCommandManager().checkSingleTimerServerArg(sender, serverArg);
|
||||
if (server == null) return;
|
||||
if (plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
final MaintenanceRunnableBase runnable = plugin.startSingleMaintenanceRunnable(server, duration, true, mode);
|
||||
final Component message = getMessage(
|
||||
"singleStarttimerStarted",
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName()
|
||||
);
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookSingleStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", runnable.getTime(),
|
||||
"%SERVER%", server.getName(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
return args.length == 2 && sender.hasMaintenancePermission("singleserver.timer") ? plugin.getCommandManager().getServersCompletion(args[1].toLowerCase()) : Collections.emptyList();
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("timer")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer")) {
|
||||
suggestions.addAll(plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT)));
|
||||
}
|
||||
return suggestions;
|
||||
}
|
||||
if (args.length == 3) {
|
||||
if (args[1].equalsIgnoreCase("global")) {
|
||||
return sender.hasMaintenancePermission("timer") ? getModesCompletion() : Collections.emptyList();
|
||||
}
|
||||
if (sender.hasMaintenancePermission("singleserver.timer") && plugin.getServer(args[1]) != null) {
|
||||
return getModesCompletion();
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+106
-32
@@ -17,14 +17,15 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.DummyServer;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.server.DummyServer;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class SingleToggleCommand extends ProxyCommandInfo {
|
||||
|
||||
@@ -39,48 +40,121 @@ public final class SingleToggleCommand extends ProxyCommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 0 || args.length > 3) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
if (args.length == 1) {
|
||||
if (checkPermission(sender, "toggle")) return;
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
toggleGlobal(sender, maintenance, null);
|
||||
return;
|
||||
}
|
||||
|
||||
final String server = args[1];
|
||||
final String mode = args.length == 3 ? args[2] : null;
|
||||
if (server.equalsIgnoreCase("global")) {
|
||||
if (!maintenance && args.length == 3) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.setMaintenance(maintenance);
|
||||
} else if (args.length == 2) {
|
||||
if (checkPermission(sender, "singleserver.toggle")) return;
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
Server server = plugin.getServer(args[1]);
|
||||
if (server == null) {
|
||||
if (maintenance) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
// Let servers be removed from the maintenance list, even if they don't exist on the proxy
|
||||
server = new DummyServer(args[1]);
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
toggleGlobal(sender, maintenance, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!maintenance && args.length != 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
toggleServer(sender, maintenance, server, mode);
|
||||
}
|
||||
|
||||
private void toggleGlobal(final SenderInfo sender, final boolean maintenance, final String mode) {
|
||||
if (checkPermission(sender, "toggle")) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance && plugin.isMaintenance()) {
|
||||
if (mode != null) {
|
||||
plugin.getSettings().setActiveMode(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.setMaintenanceToServer(server, maintenance)) {
|
||||
if (!sender.isPlayer() || !server.getName().equals(plugin.getServerNameOf(sender))) {
|
||||
sender.send(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated", "%SERVER%", server.getName()));
|
||||
}
|
||||
} else {
|
||||
sender.send(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
sender.send(getMessage("alreadyEnabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
private void toggleServer(final SenderInfo sender, final boolean maintenance, final String serverArg, final String mode) {
|
||||
if (checkPermission(sender, "singleserver.toggle")) {
|
||||
return;
|
||||
}
|
||||
|
||||
Server server = plugin.getServer(serverArg);
|
||||
if (server == null) {
|
||||
if (maintenance) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
// Let servers be removed from the maintenance list, even if they don't exist on the proxy
|
||||
server = new DummyServer(serverArg);
|
||||
if (!plugin.isMaintenance(server)) {
|
||||
sender.send(getMessage("serverNotFound"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (maintenance && plugin.isMaintenance(server) && mode != null) {
|
||||
if (plugin.setMaintenanceModeToServer(server, mode)) {
|
||||
return;
|
||||
}
|
||||
sender.send(getMessage("singleServerAlreadyEnabled", "%SERVER%", server.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
if (plugin.setMaintenanceToServer(server, maintenance, mode)) {
|
||||
if (!sender.isPlayer() || !server.getName().equals(plugin.getServerNameOf(sender))) {
|
||||
sender.send(getMessage(maintenance ? "singleMaintenanceActivated" : "singleMaintenanceDeactivated", "%SERVER%", server.getName()));
|
||||
}
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
sender.send(getMessage(maintenance ? "singleServerAlreadyEnabled" : "singleServerAlreadyDisabled", "%SERVER%", server.getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2 || !sender.hasMaintenancePermission("singleserver.toggle")) return Collections.emptyList();
|
||||
return args[0].equalsIgnoreCase("off") ? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase())
|
||||
: plugin.getCommandManager().getServersCompletion(args[1].toLowerCase());
|
||||
if (args.length == 2) {
|
||||
final List<String> suggestions = new ArrayList<>();
|
||||
if (sender.hasMaintenancePermission("toggle") && args[0].equalsIgnoreCase("on")) {
|
||||
suggestions.add("global");
|
||||
}
|
||||
|
||||
if (!sender.hasMaintenancePermission("singleserver.toggle")) {
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
final List<String> serverSuggestions = args[0].equalsIgnoreCase("off")
|
||||
? plugin.getCommandManager().getMaintenanceServersCompletion(args[1].toLowerCase(Locale.ROOT))
|
||||
: plugin.getCommandManager().getServersCompletion(args[1].toLowerCase(Locale.ROOT));
|
||||
suggestions.addAll(serverSuggestions);
|
||||
return suggestions;
|
||||
}
|
||||
|
||||
if (args.length == 3 && args[0].equalsIgnoreCase("on") && (sender.hasMaintenancePermission("toggle") || sender.hasMaintenancePermission("singleserver.toggle"))) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -24,6 +24,7 @@ import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ProxySenderInfo;
|
||||
import eu.kennytv.maintenance.core.proxy.util.ServerConnectResult;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
@@ -48,7 +49,7 @@ public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
protected ServerConnectResult serverConnect(final ProxySenderInfo sender, final Server target, final boolean normalServerConnect) {
|
||||
// Check waiting server for global maintenance
|
||||
if (settings.isMaintenance()) {
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) return ALLOWED;
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())) return ALLOWED;
|
||||
|
||||
final Server waitingServer = shouldConnectToWaitingServer(sender);
|
||||
// Should never be null, but just in case
|
||||
@@ -70,13 +71,13 @@ public abstract class ProxyJoinListenerBase extends JoinListenerBase {
|
||||
|
||||
// Single server maintenance
|
||||
if (!settings.isMaintenance(target.getName())) return ALLOWED;
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())
|
||||
|| sender.hasMaintenancePermission("singleserver.bypass." + target.getName().toLowerCase())) {
|
||||
if (sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())
|
||||
|| sender.hasMaintenancePermission("singleserver.bypass." + target.getName().toLowerCase(Locale.ROOT))) {
|
||||
return ALLOWED;
|
||||
}
|
||||
|
||||
if (settings.isJoinNotifications()) {
|
||||
broadcastJoinNotification(sender.getName(), target);
|
||||
broadcastJoinNotification(sender.name(), target);
|
||||
}
|
||||
|
||||
if (normalServerConnect) {
|
||||
|
||||
@@ -1,112 +0,0 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.mysql;
|
||||
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public final class MySQL {
|
||||
private final Logger logger;
|
||||
private final HikariDataSource hikariDataSource;
|
||||
|
||||
public MySQL(final Logger logger, final String hostname, final int port, final String username, final String password, final String database, final boolean useSSL) {
|
||||
this.logger = logger;
|
||||
|
||||
final HikariConfig hikariConfig = new HikariConfig();
|
||||
hikariConfig.setMaximumPoolSize(10);
|
||||
hikariConfig.addDataSourceProperty("serverName", hostname);
|
||||
hikariConfig.addDataSourceProperty("user", username);
|
||||
hikariConfig.addDataSourceProperty("password", password);
|
||||
|
||||
String urlProperty = "jdbc:mysql://" + hostname + ":" + port + "/" + database;
|
||||
if (!useSSL) {
|
||||
urlProperty += "?useSSL=false";
|
||||
}
|
||||
hikariConfig.addDataSourceProperty("url", urlProperty);
|
||||
|
||||
hikariConfig.setJdbcUrl(urlProperty);
|
||||
hikariConfig.setDataSourceClassName(findDriver("com.mysql.jdbc.jdbc2.optional.MysqlDataSource", "com.mysql.cj.jdbc.MysqlDataSource", "org.mariadb.jdbc.MariaDbDataSource"));
|
||||
hikariDataSource = new HikariDataSource(hikariConfig);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private String findDriver(final String... classNames) {
|
||||
for (final String name : classNames) {
|
||||
try {
|
||||
Class.forName(name);
|
||||
return name;
|
||||
} catch (final ClassNotFoundException ignored) {
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No sql driver class found");
|
||||
}
|
||||
|
||||
public void executeUpdate(final String query, final Consumer<Integer> callback, final Object... objects) {
|
||||
try (final Connection connection = hikariDataSource.getConnection()) {
|
||||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
|
||||
int current = 1;
|
||||
for (final Object object : objects) {
|
||||
preparedStatement.setObject(current, object);
|
||||
current++;
|
||||
}
|
||||
|
||||
callback.accept(preparedStatement.executeUpdate());
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.log(Level.SEVERE, "Error while executing update method: " + query);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeQuery(final String query, final Consumer<ResultSet> callback, final Object... objects) {
|
||||
try (final Connection connection = hikariDataSource.getConnection()) {
|
||||
try (final PreparedStatement preparedStatement = connection.prepareStatement(query)) {
|
||||
int current = 1;
|
||||
for (final Object object : objects) {
|
||||
preparedStatement.setObject(current, object);
|
||||
current++;
|
||||
}
|
||||
|
||||
try (final ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||
callback.accept(resultSet);
|
||||
}
|
||||
}
|
||||
} catch (final SQLException e) {
|
||||
logger.log(Level.SEVERE, "Error while executing query method: " + query);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void executeUpdate(final String query, final Object... objects) {
|
||||
executeUpdate(query, res -> {
|
||||
}, objects);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
hikariDataSource.close();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,258 @@
|
||||
package eu.kennytv.maintenance.core.proxy.redis;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.SettingsProxy;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.logging.Level;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import redis.clients.jedis.ConnectionPoolConfig;
|
||||
import redis.clients.jedis.RedisClient;
|
||||
import redis.clients.jedis.StreamEntryID;
|
||||
import redis.clients.jedis.params.XReadParams;
|
||||
import redis.clients.jedis.resps.StreamEntry;
|
||||
|
||||
public final class RedisHandler {
|
||||
|
||||
private static final String REDIS_STREAM_KEY = "maintenance:stream";
|
||||
private static final String REDIS_MAINTENANCE_KEY = "maintenance:status";
|
||||
private static final String REDIS_MODE_KEY = "maintenance:mode";
|
||||
private static final String REDIS_SERVERS_KEY = "maintenance:servers";
|
||||
private static final String REDIS_SERVER_MODES_KEY = "maintenance:server_modes";
|
||||
private static final String REDIS_WHITELIST_KEY = "maintenance:whitelist";
|
||||
|
||||
private static final String MSG_TYPE_MAINTENANCE_UPDATE = "status";
|
||||
private static final String MSG_TYPE_SERVER_ADD = "server_add";
|
||||
private static final String MSG_TYPE_SERVER_REMOVE = "server_remove";
|
||||
private static final String MSG_TYPE_PLAYER_ADD = "player_add";
|
||||
private static final String MSG_TYPE_PLAYER_REMOVE = "player_remove";
|
||||
private static final String MSG_TYPE = "type";
|
||||
private static final String MSG_VALUE = "val";
|
||||
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
private final MaintenanceProxyPlugin plugin;
|
||||
private final SettingsProxy settings;
|
||||
private RedisClient client;
|
||||
private StreamEntryID lastStreamId = new StreamEntryID();
|
||||
|
||||
public RedisHandler(final MaintenanceProxyPlugin plugin, final SettingsProxy settings) {
|
||||
this.plugin = plugin;
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public void setup(final String redisUri) {
|
||||
plugin.getLogger().info("Trying to open Redis connection...");
|
||||
|
||||
final ConnectionPoolConfig poolConfig = new ConnectionPoolConfig();
|
||||
poolConfig.setMaxWait(Duration.ofSeconds(5));
|
||||
poolConfig.setMaxTotal(2);
|
||||
client = RedisClient.builder().poolConfig(poolConfig).fromURI(URI.create(redisUri)).build();
|
||||
|
||||
// Get the latest stream ID to only receive new messages
|
||||
final List<StreamEntry> messages = client.xrevrange(REDIS_STREAM_KEY, (StreamEntryID) null, null, 1);
|
||||
if (!messages.isEmpty()) {
|
||||
lastStreamId = messages.getFirst().getID();
|
||||
}
|
||||
|
||||
running.set(true);
|
||||
plugin.async(this::listenToStream);
|
||||
|
||||
plugin.getLogger().info("Connected to Redis!");
|
||||
}
|
||||
|
||||
public boolean loadMaintenanceStatus() {
|
||||
return Boolean.parseBoolean(client.get(REDIS_MAINTENANCE_KEY));
|
||||
}
|
||||
|
||||
public @Nullable String loadGlobalMode() {
|
||||
return client.get(REDIS_MODE_KEY);
|
||||
}
|
||||
|
||||
public Map<String, String> loadMaintenanceServers() {
|
||||
final Set<String> servers = client.smembers(REDIS_SERVERS_KEY);
|
||||
final Map<String, String> serverModes = new HashMap<>();
|
||||
if (servers == null) {
|
||||
return serverModes;
|
||||
}
|
||||
|
||||
final Map<String, String> persistedModes = client.hgetAll(REDIS_SERVER_MODES_KEY);
|
||||
for (final String server : servers) {
|
||||
serverModes.put(server, normalizeMode(persistedModes.get(server)));
|
||||
}
|
||||
return serverModes;
|
||||
}
|
||||
|
||||
public void loadPlayers(final Map<UUID, String> players) {
|
||||
for (final Map.Entry<String, String> entry : client.hgetAll(REDIS_WHITELIST_KEY).entrySet()) {
|
||||
players.put(UUID.fromString(entry.getKey()), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public void set(final boolean maintenance, final String mode) {
|
||||
client.set(REDIS_MAINTENANCE_KEY, Boolean.toString(maintenance));
|
||||
client.set(REDIS_MODE_KEY, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_MAINTENANCE_UPDATE,
|
||||
MSG_VALUE, Boolean.toString(maintenance),
|
||||
"mode", mode
|
||||
));
|
||||
}
|
||||
|
||||
public boolean addServer(final String server, final String mode) {
|
||||
if (client.sadd(REDIS_SERVERS_KEY, server) < 1) {
|
||||
return false;
|
||||
}
|
||||
client.hset(REDIS_SERVER_MODES_KEY, server, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_SERVER_ADD,
|
||||
MSG_VALUE, server,
|
||||
"mode", mode
|
||||
));
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setServerMode(final String server, final String mode) {
|
||||
client.hset(REDIS_SERVER_MODES_KEY, server, mode);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_SERVER_ADD,
|
||||
MSG_VALUE, server,
|
||||
"mode", mode
|
||||
));
|
||||
}
|
||||
|
||||
public boolean removeServer(final String server) {
|
||||
if (client.srem(REDIS_SERVERS_KEY, server) < 1) {
|
||||
return false;
|
||||
}
|
||||
client.hdel(REDIS_SERVER_MODES_KEY, server);
|
||||
send(MSG_TYPE_SERVER_REMOVE, server);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void addPlayer(final UUID uuid, final String name) {
|
||||
final String value = uuid.toString();
|
||||
client.hset(REDIS_WHITELIST_KEY, value, name);
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(
|
||||
MSG_TYPE, MSG_TYPE_PLAYER_ADD,
|
||||
MSG_VALUE, value,
|
||||
"name", name
|
||||
));
|
||||
}
|
||||
|
||||
public void removePlayer(final UUID uuid) {
|
||||
final String value = uuid.toString();
|
||||
client.hdel(REDIS_WHITELIST_KEY, value);
|
||||
send(MSG_TYPE_PLAYER_REMOVE, value);
|
||||
}
|
||||
|
||||
private void send(final String type, final String value) {
|
||||
client.xadd(REDIS_STREAM_KEY, StreamEntryID.NEW_ENTRY, Map.of(MSG_TYPE, type, MSG_VALUE, value));
|
||||
}
|
||||
|
||||
private void listenToStream() {
|
||||
while (running.get()) {
|
||||
try {
|
||||
final List<Map.Entry<String, List<StreamEntry>>> result = client.xread(
|
||||
XReadParams.xReadParams().block(5000),
|
||||
Map.of(REDIS_STREAM_KEY, lastStreamId)
|
||||
);
|
||||
if (result != null) {
|
||||
for (final Map.Entry<String, List<StreamEntry>> streamEntries : result) {
|
||||
for (final StreamEntry entry : streamEntries.getValue()) {
|
||||
plugin.sync(() -> processStreamMessage(entry));
|
||||
lastStreamId = entry.getID();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
if (running.get()) {
|
||||
plugin.getLogger().log(Level.WARNING, "Error reading from Redis stream", e);
|
||||
try {
|
||||
Thread.sleep(1000); // retry
|
||||
} catch (final InterruptedException ignored) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void processStreamMessage(final StreamEntry message) {
|
||||
final Map<String, String> body = message.getFields();
|
||||
final String type = body.get(MSG_TYPE);
|
||||
if (type == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final String value = body.get(MSG_VALUE);
|
||||
switch (type) {
|
||||
case MSG_TYPE_MAINTENANCE_UPDATE -> handleStatus(value, body.get("mode"));
|
||||
case MSG_TYPE_SERVER_ADD -> handleServerStatus(value, body.get("mode"), true, "Server added to maintenance via Redis: ");
|
||||
case MSG_TYPE_SERVER_REMOVE -> handleServerStatus(value, null, false, "Server removed from maintenance via Redis: ");
|
||||
case MSG_TYPE_PLAYER_ADD -> handlePlayerAdd(value, body.get("name"));
|
||||
case MSG_TYPE_PLAYER_REMOVE -> handlePlayerRemove(value);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleStatus(final String value, @Nullable final String mode) {
|
||||
final boolean maintenance = Boolean.parseBoolean(value);
|
||||
if (settings.isMaintenance() != maintenance) {
|
||||
plugin.getLogger().info("Maintenance status updated via Redis: " + maintenance);
|
||||
settings.setMaintenanceDirect(maintenance, mode);
|
||||
plugin.serverActions(maintenance);
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance && !normalizeMode(mode).equals(normalizeMode(settings.activeMode()))) {
|
||||
settings.setActiveModeDirect(mode);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleServerStatus(final String value, @Nullable final String mode, final boolean maintenance, final String log) {
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean success;
|
||||
if (maintenance) {
|
||||
success = settings.addMaintenanceServerDirect(value, mode);
|
||||
settings.setMaintenanceServerModeDirect(value, mode);
|
||||
} else {
|
||||
success = settings.removeMaintenanceServerDirect(value);
|
||||
}
|
||||
|
||||
if (success) {
|
||||
plugin.getLogger().info(log + value);
|
||||
final Server server = plugin.getServerOrDummy(value);
|
||||
plugin.serverActions(server, maintenance);
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePlayerAdd(final String uuid, final String name) {
|
||||
settings.addWhitelistedPlayerDirect(UUID.fromString(uuid), name);
|
||||
}
|
||||
|
||||
private void handlePlayerRemove(final String value) {
|
||||
settings.removeWhitelistedPlayerDirect(UUID.fromString(value));
|
||||
}
|
||||
|
||||
public void close() {
|
||||
running.set(false);
|
||||
if (client != null) {
|
||||
client.close();
|
||||
client = null;
|
||||
}
|
||||
}
|
||||
|
||||
private String normalizeMode(@Nullable final String mode) {
|
||||
return mode == null || mode.isBlank() ? "default" : mode.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
}
|
||||
+13
-4
@@ -17,19 +17,23 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.MaintenanceProxy;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnableBase;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
protected final Server server;
|
||||
protected final String mode;
|
||||
|
||||
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable, final Server server) {
|
||||
public SingleMaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds,
|
||||
final boolean enable, final Server server, @Nullable final String mode) {
|
||||
super(plugin, settings, seconds, enable);
|
||||
this.server = server;
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -39,7 +43,12 @@ public class SingleMaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
|
||||
@Override
|
||||
protected void finish() {
|
||||
((MaintenanceProxy) plugin).setMaintenanceToServer(server, enable);
|
||||
final MaintenanceProxyPlugin proxyPlugin = (MaintenanceProxyPlugin) plugin;
|
||||
proxyPlugin.setMaintenanceToServer(server, enable, mode);
|
||||
// Make sure no-ops have the platform task cancelled as well
|
||||
if (proxyPlugin.getServerTasks().remove(server.getName(), this)) {
|
||||
getTask().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+5
-3
@@ -21,14 +21,16 @@ import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class SingleMaintenanceScheduleRunnable extends SingleMaintenanceRunnable {
|
||||
private final int maintenanceDurationSeconds;
|
||||
|
||||
public SingleMaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final int maintenanceDuration, final Server server) {
|
||||
super(plugin, settings, seconds, true, server);
|
||||
public SingleMaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds,
|
||||
final int maintenanceDuration, final Server server, @Nullable final String mode) {
|
||||
super(plugin, settings, seconds, true, server, mode);
|
||||
this.maintenanceDurationSeconds = maintenanceDuration;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,20 +19,5 @@ package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ProfileLookup {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public ProfileLookup(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public record ProfileLookup(UUID uuid, String name) {
|
||||
}
|
||||
+2
-19
@@ -18,18 +18,11 @@
|
||||
package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class ProxyOfflineSenderInfo implements ProxySenderInfo {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public ProxyOfflineSenderInfo(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
public record ProxyOfflineSenderInfo(UUID uuid, String name) implements ProxySenderInfo {
|
||||
|
||||
@Override
|
||||
public boolean canAccess(final Server server) {
|
||||
@@ -40,16 +33,6 @@ public final class ProxyOfflineSenderInfo implements ProxySenderInfo {
|
||||
public void disconnect(final Component component) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
return false;
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ package eu.kennytv.maintenance.core.proxy.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.proxy.Server;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public interface ProxySenderInfo extends SenderInfo {
|
||||
|
||||
|
||||
@@ -16,9 +16,10 @@ sourceSets {
|
||||
|
||||
dependencies {
|
||||
api(projects.maintenanceApi)
|
||||
api(projects.adventure.adventureApi) {
|
||||
targetConfiguration = "shadow"
|
||||
}
|
||||
compileOnlyApi(libs.adventureApi)
|
||||
compileOnlyApi(libs.adventureTextMinimessage)
|
||||
compileOnlyApi(libs.adventureTextSerializerPlain)
|
||||
compileOnlyApi(libs.adventureTextSerializerLegacy)
|
||||
compileOnly(libs.luckperms)
|
||||
compileOnly(libs.serverlistplus)
|
||||
compileOnly(libs.guava)
|
||||
|
||||
@@ -32,12 +32,11 @@ import eu.kennytv.maintenance.core.dump.PluginDump;
|
||||
import eu.kennytv.maintenance.core.hook.ServerListPlusHook;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceScheduleRunnable;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import eu.kennytv.maintenance.core.util.Version;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.BufferedReader;
|
||||
@@ -47,7 +46,7 @@ import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.net.URI;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
@@ -62,6 +61,8 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Pattern;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class MaintenancePlugin implements Maintenance {
|
||||
@@ -96,19 +97,9 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
settings.setMaintenance(maintenance);
|
||||
settings.getConfig().set("maintenance-enabled", maintenance);
|
||||
settings.saveConfig();
|
||||
public void setMaintenance(final boolean maintenance, final String mode) {
|
||||
settings.setMaintenance(maintenance, mode);
|
||||
serverActions(maintenance);
|
||||
|
||||
for (final String command : (maintenance ? settings.getCommandsOnMaintenanceEnable() : settings.getCommandsOnMaintenanceDisable())) {
|
||||
try {
|
||||
executeConsoleCommand(command);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.SEVERE, "Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void serverActions(final boolean maintenance) {
|
||||
@@ -119,22 +110,56 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
serverListPlusHook.setEnabled(!maintenance);
|
||||
}
|
||||
|
||||
if (maintenance) {
|
||||
broadcast(settings.getMessage("maintenanceActivated"));
|
||||
if (settings.isKickOnlinePlayers()) {
|
||||
kickPlayers();
|
||||
}
|
||||
} else {
|
||||
broadcast(settings.getMessage("maintenanceDeactivated"));
|
||||
broadcast(maintenance ? settings.getMessage("maintenanceActivated") : settings.getMessage("maintenanceDeactivated"));
|
||||
if (maintenance && settings.isKickOnlinePlayers()) {
|
||||
kickPlayers();
|
||||
}
|
||||
|
||||
eventManager.callEvent(new MaintenanceChangedEvent(maintenance));
|
||||
if (maintenance) {
|
||||
sendWebhookMessage("webhookMaintenanceActivated", DiscordWebhook.EventType.MAINTENANCE_ENABLED);
|
||||
} else {
|
||||
sendWebhookMessage("webhookMaintenanceDeactivated", DiscordWebhook.EventType.MAINTENANCE_DISABLED);
|
||||
}
|
||||
|
||||
for (final String command : (maintenance ? settings.getCommandsOnMaintenanceEnable() : settings.getCommandsOnMaintenanceDisable())) {
|
||||
try {
|
||||
executeConsoleCommand(command);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.SEVERE, "Error while executing extra maintenance " + (maintenance ? "enable" : "disable") + " command: " + command, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public String replacePingVariables(String component) {
|
||||
public void sendWebhookMessage(final String messageKey, final DiscordWebhook.EventType eventType, final String... replacements) {
|
||||
if (!settings.isWebhookEnabled() || !settings.isWebhookEventEnabled(eventType.configKey())) {
|
||||
return;
|
||||
}
|
||||
|
||||
async(() -> {
|
||||
try {
|
||||
DiscordWebhook.sendMessage(settings.getWebhookMessage(messageKey, replacements), eventType, settings);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.WARNING, "Could not send Discord webhook message", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getTargetTimestamp(final Duration duration) {
|
||||
return Long.toString((System.currentTimeMillis() + duration.toMillis()) / TimeUnit.SECONDS.toMillis(1));
|
||||
}
|
||||
|
||||
public String replacePingVariables(final String component) {
|
||||
return replacePingVariables(component, settings.activeMode());
|
||||
}
|
||||
|
||||
public String replacePingVariables(String component, @Nullable final String mode) {
|
||||
if (component.contains("%TIMER%")) {
|
||||
component = component.replace("%TIMER%", getTimerMessage());
|
||||
}
|
||||
final String reason = settings.activeReason() == null ? "" : settings.activeReason();
|
||||
component = component.replace("%REASON%", reason);
|
||||
component = component.replace("%MODE%", mode == null ? "default" : mode);
|
||||
component = component.replace("%ONLINE%", String.valueOf(getOnlinePlayers()));
|
||||
component = component.replace("%MAX%", String.valueOf(getMaxPlayers()));
|
||||
return component;
|
||||
@@ -168,14 +193,18 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
|
||||
private void append(final StringBuilder builder, final String timeUnit, final int time) {
|
||||
if (time == 0) return;
|
||||
if (builder.length() != 0) {
|
||||
if (!builder.isEmpty()) {
|
||||
builder.append(' ');
|
||||
}
|
||||
builder.append(time).append(' ').append(settings.language.getString(time == 1 ? timeUnit : timeUnit + "s"));
|
||||
}
|
||||
|
||||
public void startMaintenanceRunnable(final Duration duration, final boolean enable) {
|
||||
runnable = new MaintenanceRunnable(this, settings, (int) duration.getSeconds(), enable);
|
||||
startMaintenanceRunnable(duration, enable, null);
|
||||
}
|
||||
|
||||
public void startMaintenanceRunnable(final Duration duration, final boolean enable, @Nullable final String mode) {
|
||||
runnable = new MaintenanceRunnable(this, settings, (int) duration.getSeconds(), enable, mode);
|
||||
// Save the endtimer to be able to continue it after a server stop
|
||||
if (settings.isSaveEndtimerOnStop() && !runnable.shouldEnable()) {
|
||||
settings.setSavedEndtimer(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(runnable.getSecondsLeft()));
|
||||
@@ -183,7 +212,11 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
public void scheduleMaintenanceRunnable(final Duration enableIn, final Duration maintenanceDuration) {
|
||||
runnable = new MaintenanceScheduleRunnable(this, settings, (int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds());
|
||||
scheduleMaintenanceRunnable(enableIn, maintenanceDuration, null);
|
||||
}
|
||||
|
||||
public void scheduleMaintenanceRunnable(final Duration enableIn, final Duration maintenanceDuration, @Nullable final String mode) {
|
||||
runnable = new MaintenanceScheduleRunnable(this, settings, (int) enableIn.getSeconds(), (int) maintenanceDuration.getSeconds(), mode);
|
||||
}
|
||||
|
||||
public boolean updateAvailable() {
|
||||
@@ -227,7 +260,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
if (compare < 0) {
|
||||
getLogger().warning("Newest version available: Version " + newestVersion + ", you're on " + version);
|
||||
} else if (compare > 0) {
|
||||
if (version.getTag().equalsIgnoreCase("snapshot")) {
|
||||
if (version.getTag() != null && !version.getTag().isBlank()) {
|
||||
getLogger().info("You're running a development version, please report bugs on the Discord server (https://discord.gg/vGCUzHq) or the GitHub issue tracker (https://github.com/kennytv/Maintenance/issues)");
|
||||
} else {
|
||||
getLogger().info("You're running a version, that doesn't exist!");
|
||||
@@ -237,11 +270,9 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
public boolean installUpdate() throws Exception {
|
||||
// Sponge and Velocity need their own jar
|
||||
final String platformInfix = serverType == ServerType.VELOCITY ? "Velocity-" : serverType == ServerType.SPONGE ? "Sponge-" : "";
|
||||
final String fileName = "Maintenance-" + platformInfix + newestVersion + ".jar";
|
||||
final String fileName = "Maintenance-" + serverType.name() + "-" + newestVersion + ".jar";
|
||||
final Path tempFilePath = Paths.get(getPluginFolder() + "Maintenance.tmp");
|
||||
final URLConnection connection = new URL("https://github.com/kennytv/Maintenance/releases/download/" + newestVersion + "/" + fileName).openConnection();
|
||||
final URLConnection connection = URI.create("https://github.com/kennytv/Maintenance/releases/download/" + newestVersion + "/" + fileName).toURL().openConnection();
|
||||
try (final BufferedInputStream is = new BufferedInputStream(connection.getInputStream());
|
||||
final BufferedOutputStream os = new BufferedOutputStream(Files.newOutputStream(tempFilePath))) {
|
||||
writeFile(is, os);
|
||||
@@ -273,8 +304,10 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
}
|
||||
|
||||
private void checkNewestVersion() throws Exception {
|
||||
final URLConnection connection = new URL("https://hangar.papermc.io/api/v1/projects/Maintenance/latestrelease").openConnection();
|
||||
final URLConnection connection = URI.create("https://hangar.papermc.io/api/v1/projects/Maintenance/latestrelease").toURL().openConnection();
|
||||
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
|
||||
connection.setConnectTimeout(5_000);
|
||||
connection.setReadTimeout(10_000);
|
||||
try (final BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
|
||||
final String newVersionString = reader.readLine();
|
||||
final Version newVersion = new Version(newVersionString);
|
||||
@@ -287,7 +320,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
public String pasteDump() {
|
||||
final MaintenanceDump dump = new MaintenanceDump(this, settings);
|
||||
try {
|
||||
final HttpURLConnection connection = (HttpURLConnection) new URL("https://api.pastes.dev/post").openConnection();
|
||||
final HttpURLConnection connection = (HttpURLConnection) URI.create("https://api.pastes.dev/post").toURL().openConnection();
|
||||
connection.setDoOutput(true);
|
||||
connection.setRequestMethod("POST");
|
||||
connection.setRequestProperty("User-Agent", "Maintenance/" + getVersion());
|
||||
@@ -328,8 +361,7 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
try {
|
||||
loadIcon(file);
|
||||
} catch (final Exception e) {
|
||||
getLogger().log(Level.WARNING, "Could not load the 'maintenance-icon.png' file!");
|
||||
e.printStackTrace();
|
||||
getLogger().log(Level.WARNING, "Could not load the 'maintenance-icon.png' file!", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,6 +406,10 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
return runnable != null;
|
||||
}
|
||||
|
||||
public @Nullable MaintenanceRunnable getCurrentTask() {
|
||||
return runnable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Settings getSettings() {
|
||||
return settings;
|
||||
@@ -436,6 +472,10 @@ public abstract class MaintenancePlugin implements Maintenance {
|
||||
return "plugins/";
|
||||
}
|
||||
|
||||
public void sync(final Runnable runnable) {
|
||||
async(runnable);
|
||||
}
|
||||
|
||||
public abstract void async(Runnable runnable);
|
||||
|
||||
protected abstract void executeConsoleCommand(String command);
|
||||
|
||||
@@ -20,11 +20,8 @@ package eu.kennytv.maintenance.core;
|
||||
import eu.kennytv.maintenance.api.event.MaintenanceReloadedEvent;
|
||||
import eu.kennytv.maintenance.core.config.Config;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.config.DisplayedMessages;
|
||||
import eu.kennytv.maintenance.core.util.ServerType;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -32,33 +29,43 @@ import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.logging.Level;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer;
|
||||
import net.kyori.adventure.text.serializer.plain.PlainTextComponentSerializer;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
public static final String NEW_LINE_REPLACEMENT = "<br>";
|
||||
private static final int CONFIG_VERSION = 9;
|
||||
private static final int LANGUAGE_VERSION = 2;
|
||||
private static final Random RANDOM = new Random();
|
||||
private static final int CONFIG_VERSION = 12;
|
||||
private static final int LANGUAGE_VERSION = 5;
|
||||
protected final MaintenancePlugin plugin;
|
||||
private final Map<UUID, String> whitelistedPlayers = new HashMap<>();
|
||||
private final String[] unsupportedFields;
|
||||
protected boolean maintenance;
|
||||
protected String activeMode;
|
||||
protected String activeReason;
|
||||
private Set<Integer> broadcastIntervals;
|
||||
private List<String> pingMessages;
|
||||
private List<String> timerSpecificPingMessages;
|
||||
private DisplayedMessages pingMessages;
|
||||
private DisplayedMessages timerSpecificPingMessages;
|
||||
private List<String> commandsOnMaintenanceEnable;
|
||||
private List<String> commandsOnMaintenanceDisable;
|
||||
private String legacyParsedPlayerCountMessage;
|
||||
private String legacyParsedTimerPlayerCountMessage;
|
||||
private List<String> legacyParsedPlayerCountHoverLines;
|
||||
private List<String> legacyParsedTimerPlayerCountHoverLines;
|
||||
private DisplayedMessages legacyParsedPlayerCountMessages;
|
||||
private DisplayedMessages legacyParsedTimerPlayerCountMessages;
|
||||
private DisplayedMessages legacyParsedPlayerCountHoverLines;
|
||||
private DisplayedMessages legacyParsedTimerPlayerCountHoverLines;
|
||||
private String prefixString;
|
||||
private String plainTextPrefix;
|
||||
private String languageName;
|
||||
private boolean enablePingMessages;
|
||||
private boolean customPlayerCountMessage;
|
||||
@@ -71,6 +78,13 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
private boolean debug;
|
||||
private long savedEndtimer;
|
||||
|
||||
// Webhook settings
|
||||
private boolean webhookEnabled;
|
||||
private Set<String> webhookEnabledEvents;
|
||||
private String webhookUrl;
|
||||
private String webhookUsername;
|
||||
private String webhookAvatarUrl;
|
||||
|
||||
protected Config config;
|
||||
protected Config language;
|
||||
protected Config whitelist;
|
||||
@@ -118,6 +132,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
}
|
||||
|
||||
prefixString = language.getString("prefix");
|
||||
plainTextPrefix = PlainTextComponentSerializer.plainText().serialize(parse(prefixString));
|
||||
|
||||
plugin.getEventManager().callEvent(new MaintenanceReloadedEvent());
|
||||
}
|
||||
@@ -160,6 +175,9 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
if (file.exists()) return;
|
||||
|
||||
try (final InputStream in = plugin.getResource(fileName)) {
|
||||
if (in == null) {
|
||||
throw new IOException("No bundled language file " + fileName);
|
||||
}
|
||||
Files.copy(in, file.toPath());
|
||||
} catch (final IOException e) {
|
||||
plugin.getLogger().warning("Unable to provide language " + languageName);
|
||||
@@ -178,14 +196,16 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
final ConfigSection pingMessageSection = config.getSection("ping-message");
|
||||
enablePingMessages = pingMessageSection.getBoolean("enabled", true);
|
||||
// Can't store this pre-parsed as components because gradients will break replacements
|
||||
pingMessages = loadPingMessages(pingMessageSection.getStringList("messages"));
|
||||
pingMessages = loadPingMessages(pingMessageSection.getSection("messages"));
|
||||
if (pingMessageSection.getBoolean("enable-timer-specific-messages")) {
|
||||
timerSpecificPingMessages = loadPingMessages(pingMessageSection.getStringList("timer-messages"));
|
||||
timerSpecificPingMessages = loadPingMessages(pingMessageSection.getSection("timer-messages"));
|
||||
} else {
|
||||
timerSpecificPingMessages = null;
|
||||
}
|
||||
|
||||
maintenance = config.getBoolean("maintenance-enabled");
|
||||
activeMode = normalizeMode(config.getString("active-mode"));
|
||||
activeReason = normalizeReason(config.getString("active-reason"));
|
||||
commandsOnMaintenanceEnable = config.getStringList("commands-on-maintenance-enable");
|
||||
commandsOnMaintenanceDisable = config.getStringList("commands-on-maintenance-disable");
|
||||
customMaintenanceIcon = config.getBoolean("custom-maintenance-icon");
|
||||
@@ -196,34 +216,35 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
if (plugin.getServerType() != ServerType.SPONGE) {
|
||||
final ConfigSection playerCountMessageSection = config.getSection("player-count-message");
|
||||
customPlayerCountMessage = playerCountMessageSection.getBoolean("enabled");
|
||||
legacyParsedPlayerCountMessage = toLegacy(parse(getConfigMessage(playerCountMessageSection, "message")));
|
||||
legacyParsedPlayerCountMessages = loadPlayerCountMessages(playerCountMessageSection.getSection("messages"));
|
||||
if (playerCountMessageSection.getBoolean("enable-timer-specific-message")) {
|
||||
legacyParsedTimerPlayerCountMessage = toLegacy(parse(getConfigMessage(playerCountMessageSection, "timer-message")));
|
||||
legacyParsedTimerPlayerCountMessages = loadPlayerCountMessages(playerCountMessageSection.getSection("timer-messages"));
|
||||
} else {
|
||||
legacyParsedTimerPlayerCountMessage = null;
|
||||
legacyParsedTimerPlayerCountMessages = null;
|
||||
}
|
||||
}
|
||||
|
||||
final ConfigSection listHoverMessageSection = config.getSection("player-list-hover-message");
|
||||
customPlayerCountHoverMessage = listHoverMessageSection.getBoolean("enabled");
|
||||
legacyParsedPlayerCountHoverLines = new ArrayList<>();
|
||||
for (final String line : listHoverMessageSection.getString("message").split("<br>")) {
|
||||
legacyParsedPlayerCountHoverLines.add(toLegacy(parse(line)));
|
||||
}
|
||||
legacyParsedPlayerCountHoverLines = loadPlayerCountHoverMessages(listHoverMessageSection.getSection("messages"));
|
||||
if (listHoverMessageSection.getBoolean("enable-timer-specific-message")) {
|
||||
legacyParsedTimerPlayerCountHoverLines = new ArrayList<>();
|
||||
for (final String line : listHoverMessageSection.getString("timer-message").split("<br>")) {
|
||||
legacyParsedTimerPlayerCountHoverLines.add(toLegacy(parse(line)));
|
||||
}
|
||||
legacyParsedTimerPlayerCountHoverLines = loadPlayerCountHoverMessages(listHoverMessageSection.getSection("timer-messages"));
|
||||
} else {
|
||||
legacyParsedTimerPlayerCountHoverLines = null;
|
||||
}
|
||||
|
||||
languageName = config.getString("language").toLowerCase();
|
||||
languageName = config.getString("language").toLowerCase(Locale.ROOT);
|
||||
kickOnlinePlayers = config.getBoolean("kick-online-players", true);
|
||||
updateChecks = config.getBoolean("update-checks", true);
|
||||
debug = config.getBoolean("debug");
|
||||
|
||||
final ConfigSection webhookSection = config.getSection("webhook");
|
||||
webhookEnabled = webhookSection.getBoolean("enabled");
|
||||
webhookEnabledEvents = new HashSet<>(webhookSection.getStringList("enabled-events"));
|
||||
webhookUrl = webhookSection.getString("url", "");
|
||||
webhookUsername = webhookSection.getString("username", "Maintenance");
|
||||
webhookAvatarUrl = webhookSection.getString("avatar-url", "");
|
||||
|
||||
final ConfigSection section = config.getSection("continue-endtimer-after-restart");
|
||||
saveEndtimerOnStop = section.getBoolean("enabled");
|
||||
savedEndtimer = section.getLong("end");
|
||||
@@ -232,6 +253,12 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.loadMaintenanceIcon();
|
||||
}
|
||||
|
||||
loadWhitelistedPlayers();
|
||||
|
||||
loadExtraSettings();
|
||||
}
|
||||
|
||||
protected void loadWhitelistedPlayers() {
|
||||
whitelistedPlayers.clear();
|
||||
for (final Map.Entry<String, Object> entry : whitelist.getValues().entrySet()) {
|
||||
try {
|
||||
@@ -240,15 +267,15 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.getLogger().warning("Invalid WhitelistedPlayers entry: " + entry.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
loadExtraSettings();
|
||||
}
|
||||
|
||||
private void updatePluginDirectory() {
|
||||
// All plugin identifiers were changed to 'Maintenance' ('maintenance' for Sponge and Velocity) in 3.0.5
|
||||
String oldDirName = "Maintenance" + plugin.getServerType();
|
||||
if (plugin.getServerType() == ServerType.SPONGE || plugin.getServerType() == ServerType.VELOCITY) {
|
||||
oldDirName = oldDirName.toLowerCase();
|
||||
oldDirName = oldDirName.toLowerCase(Locale.ROOT);
|
||||
} else if (plugin.getServerType() == ServerType.PAPER) {
|
||||
oldDirName = "MaintenanceSpigot";
|
||||
}
|
||||
|
||||
final File oldDir = new File(plugin.getDataFolder().getParentFile(), oldDirName);
|
||||
@@ -287,6 +314,35 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
config.move("enable-playercounthovermessage", "player-list-hover-message.enabled");
|
||||
config.move("playercounthovermessage", "player-list-hover-message.message");
|
||||
}
|
||||
if (version < 11) {
|
||||
config.move("player-count-message.message", "player-count-message.messages.default");
|
||||
config.move("player-count-message.timer-message", "player-count-message.timer-messages.default");
|
||||
|
||||
config.move("player-list-hover-message.message", "player-list-hover-message.messages.default");
|
||||
config.move("player-list-hover-message.timer-message", "player-list-hover-message.timer-messages.default");
|
||||
|
||||
migrateModeSection("ping-message.messages");
|
||||
migrateModeSection("ping-message.timer-messages");
|
||||
migrateModeSection("player-count-message.messages");
|
||||
migrateModeSection("player-count-message.timer-messages");
|
||||
migrateModeSection("player-list-hover-message.messages");
|
||||
migrateModeSection("player-list-hover-message.timer-messages");
|
||||
|
||||
final Object proxiedMaintenanceServers = config.getObject("proxied-maintenance-servers");
|
||||
if (proxiedMaintenanceServers instanceof List<?> list) {
|
||||
final Map<String, String> migratedServers = new LinkedHashMap<>();
|
||||
for (final Object entry : list) {
|
||||
if (entry != null) {
|
||||
migratedServers.put(String.valueOf(entry), "default");
|
||||
}
|
||||
}
|
||||
config.set("proxied-maintenance-servers", migratedServers);
|
||||
}
|
||||
}
|
||||
if (version < 12) {
|
||||
// Fix typo in the shipped config key :>
|
||||
config.move("redis.enables", "redis.enabled");
|
||||
}
|
||||
|
||||
createFile("config-new.yml", "config.yml");
|
||||
final File file = new File(plugin.getDataFolder(), "config-new.yml");
|
||||
@@ -318,11 +374,10 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
plugin.getLogger().info("Updating language file to the latest version...");
|
||||
if (version < 1) {
|
||||
for (final Map.Entry<String, Object> entry : language.getValues().entrySet()) {
|
||||
if (!(entry.getValue() instanceof String)) {
|
||||
if (!(entry.getValue() instanceof String value)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = (String) entry.getValue();
|
||||
value = value.replace("&8[&eMaintenance&8] ", "<prefix>");
|
||||
value = legacyToMinimessage(value);
|
||||
value = value.replace("%NEWLINE%", NEW_LINE_REPLACEMENT);
|
||||
@@ -358,6 +413,17 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return serialized.replaceAll("</[a-z_]+>", "");
|
||||
}
|
||||
|
||||
private void migrateModeSection(final String path) {
|
||||
final Object section = config.getObject(path);
|
||||
if (section == null || section instanceof Map<?, ?>) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Map<String, Object> map = new LinkedHashMap<>();
|
||||
map.put("default", section);
|
||||
config.set(path, map);
|
||||
}
|
||||
|
||||
private String getConfigMessage(final ConfigSection section, final String path) {
|
||||
final String s = section.getString(path);
|
||||
if (s == null) {
|
||||
@@ -390,6 +456,25 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return replaceNewlineVar(s).replace("<prefix>", prefixString);
|
||||
}
|
||||
|
||||
public String getWebhookMessage(final String path, final String... replacements) {
|
||||
String s = language.getString(path);
|
||||
if (s == null) {
|
||||
plugin.getLogger().warning("The language file is missing the following webhook message: " + path);
|
||||
return path;
|
||||
}
|
||||
if (replacements.length != 0) {
|
||||
if (replacements.length % 2 != 0) {
|
||||
throw new IllegalArgumentException("Invalid replacement count: " + replacements.length);
|
||||
}
|
||||
|
||||
for (int i = 0; i < replacements.length; i += 2) {
|
||||
final String key = replacements[i];
|
||||
s = s.replace(key, replacements[i + 1]);
|
||||
}
|
||||
}
|
||||
return replaceNewlineVar(s);
|
||||
}
|
||||
|
||||
public @Nullable String getLanguageStringOrNull(final String path, final String... replacements) {
|
||||
return language.contains(path) ? getLanguageString(path, replacements) : null;
|
||||
}
|
||||
@@ -400,24 +485,53 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
|
||||
// TODO Cache platform components if there are no replacements
|
||||
public Component getRandomPingMessage() {
|
||||
if (plugin.isTaskRunning() && !plugin.getRunnable().shouldEnable()
|
||||
&& hasTimerSpecificPingMessages() && !timerSpecificPingMessages.isEmpty()) {
|
||||
return getPingMessage(timerSpecificPingMessages);
|
||||
}
|
||||
return pingMessages.isEmpty() ? Component.empty() : getPingMessage(pingMessages);
|
||||
return getRandomPingMessage(activeMode);
|
||||
}
|
||||
|
||||
private Component getPingMessage(final List<String> list) {
|
||||
final String component = list.size() == 1 ? list.get(0) : list.get(RANDOM.nextInt(list.size()));
|
||||
return parse(plugin.replacePingVariables(component));
|
||||
public Component getRandomPingMessage(@Nullable final String mode) {
|
||||
if (plugin.isTaskRunning() && !plugin.getRunnable().shouldEnable() && hasTimerSpecificPingMessages()) {
|
||||
return getPingMessage(timerSpecificPingMessages, mode);
|
||||
}
|
||||
return pingMessages.isEmpty() ? Component.empty() : getPingMessage(pingMessages, mode);
|
||||
}
|
||||
|
||||
private List<String> loadPingMessages(final List<String> list) {
|
||||
final List<String> components = new ArrayList<>(list.size());
|
||||
for (final String s : list) {
|
||||
components.add(replaceNewlineVar(s));
|
||||
private Component getPingMessage(final DisplayedMessages list, @Nullable final String mode) {
|
||||
final String component = list.getRandomEntry(mode);
|
||||
return parse(plugin.replacePingVariables(component, mode));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPingMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> list.add(replaceNewlineVar(s)));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPlayerCountHoverMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> {
|
||||
// Split into separate messages (one per player entry)
|
||||
for (final String line : s.split("<br>")) {
|
||||
list.add(toLegacy(parse(line)));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private DisplayedMessages loadPlayerCountMessages(final ConfigSection section) {
|
||||
return loadDisplayedMessages(section, (list, s) -> list.add(toLegacy(parse(s))));
|
||||
}
|
||||
|
||||
private DisplayedMessages loadDisplayedMessages(final ConfigSection section, final BiConsumer<List<String>, String> messageFunction) {
|
||||
final Map<String, List<String>> modes = new HashMap<>(section.getKeys().size());
|
||||
for (final Map.Entry<String, Object> entry : section.getValues().entrySet()) {
|
||||
final List<String> components = new ArrayList<>();
|
||||
if (entry.getValue() instanceof String s) {
|
||||
messageFunction.accept(components, s);
|
||||
} else if (entry.getValue() instanceof List<?> list) {
|
||||
//noinspection unchecked
|
||||
for (final String s : ((Iterable<String>) list)) {
|
||||
messageFunction.accept(components, s);
|
||||
}
|
||||
}
|
||||
modes.put(entry.getKey(), components);
|
||||
}
|
||||
return components;
|
||||
return new DisplayedMessages(modes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -445,18 +559,19 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return false;
|
||||
}
|
||||
|
||||
whitelistedPlayers.remove(uuid);
|
||||
whitelist.remove(uuid.toString());
|
||||
saveWhitelistedPlayers();
|
||||
return true;
|
||||
return removeWhitelistedPlayer(uuid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addWhitelistedPlayer(final UUID uuid, final String name) {
|
||||
final boolean added = whitelistedPlayers.put(uuid, name) == null;
|
||||
final boolean added = !name.equals(whitelistedPlayers.put(uuid, name));
|
||||
if (!added) {
|
||||
return false;
|
||||
}
|
||||
|
||||
whitelist.set(uuid.toString(), name);
|
||||
saveWhitelistedPlayers();
|
||||
return added;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -474,8 +589,47 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return maintenance;
|
||||
}
|
||||
|
||||
public void setMaintenance(final boolean maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
@Override
|
||||
public @Nullable String activeMode() {
|
||||
return activeMode;
|
||||
}
|
||||
|
||||
public void setActiveMode(@Nullable final String activeMode) {
|
||||
final String normalized = normalizeMode(activeMode);
|
||||
if (Objects.equals(this.activeMode, normalized)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeMode = normalized;
|
||||
config.set("active-mode", normalized != null ? normalized : "default");
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String activeReason() {
|
||||
return activeReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setActiveReason(@Nullable final String reason) {
|
||||
final String normalized = normalizeReason(reason);
|
||||
if (Objects.equals(this.activeReason, normalized)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.activeReason = normalized;
|
||||
config.set("active-reason", normalized);
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
public void setMaintenance(final boolean maintenance, @Nullable final String mode) {
|
||||
if (this.maintenance != maintenance) {
|
||||
this.maintenance = maintenance;
|
||||
config.set("maintenance-enabled", maintenance);
|
||||
this.activeMode = normalizeMode(mode);
|
||||
config.set("active-mode", this.activeMode != null ? this.activeMode : "default");
|
||||
saveConfig();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -532,7 +686,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return config;
|
||||
}
|
||||
|
||||
public List<String> getPingMessages() {
|
||||
public DisplayedMessages getPingMessages() {
|
||||
return pingMessages;
|
||||
}
|
||||
|
||||
@@ -544,7 +698,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return commandsOnMaintenanceDisable;
|
||||
}
|
||||
|
||||
public @Nullable List<String> getTimerSpecificPingMessages() {
|
||||
public @Nullable DisplayedMessages getTimerSpecificPingMessages() {
|
||||
return timerSpecificPingMessages;
|
||||
}
|
||||
|
||||
@@ -552,16 +706,50 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return broadcastIntervals;
|
||||
}
|
||||
|
||||
public boolean isWebhookEnabled() {
|
||||
return webhookEnabled;
|
||||
}
|
||||
|
||||
public boolean isWebhookEventEnabled(final String event) {
|
||||
return webhookEnabledEvents.contains(event);
|
||||
}
|
||||
|
||||
public String getWebhookUrl() {
|
||||
return webhookUrl;
|
||||
}
|
||||
|
||||
public String getWebhookUsername() {
|
||||
return webhookUsername;
|
||||
}
|
||||
|
||||
public String getWebhookAvatarUrl() {
|
||||
return webhookAvatarUrl;
|
||||
}
|
||||
|
||||
public String getPlainTextPrefix() {
|
||||
return plainTextPrefix;
|
||||
}
|
||||
|
||||
public String getLegacyParsedPlayerCountMessage() {
|
||||
final String message = timerDependent(legacyParsedPlayerCountMessage, legacyParsedTimerPlayerCountMessage);
|
||||
return plugin.replacePingVariables(message);
|
||||
return getLegacyParsedPlayerCountMessage(activeMode);
|
||||
}
|
||||
|
||||
public String getLegacyParsedPlayerCountMessage(@Nullable final String mode) {
|
||||
final DisplayedMessages messages = timerDependent(legacyParsedPlayerCountMessages, legacyParsedTimerPlayerCountMessages);
|
||||
final String message = messages.getRandomEntry(mode);
|
||||
return plugin.replacePingVariables(message, mode);
|
||||
}
|
||||
|
||||
public String[] getLegacyParsedPlayerCountHoverLines() {
|
||||
final List<String> lines = timerDependent(legacyParsedPlayerCountHoverLines, legacyParsedTimerPlayerCountHoverLines);
|
||||
return getLegacyParsedPlayerCountHoverLines(activeMode);
|
||||
}
|
||||
|
||||
public String[] getLegacyParsedPlayerCountHoverLines(@Nullable final String mode) {
|
||||
final DisplayedMessages messages = timerDependent(legacyParsedPlayerCountHoverLines, legacyParsedTimerPlayerCountHoverLines);
|
||||
final List<String> lines = messages.getMessages(mode);
|
||||
final String[] parsedLines = new String[lines.size()];
|
||||
for (int i = 0; i < lines.size(); i++) {
|
||||
parsedLines[i] = plugin.replacePingVariables(lines.get(i));
|
||||
parsedLines[i] = plugin.replacePingVariables(lines.get(i), mode);
|
||||
}
|
||||
return parsedLines;
|
||||
}
|
||||
@@ -595,7 +783,7 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
}
|
||||
|
||||
/*
|
||||
* Note on why this even exists: Yaml will force save all strings containing line breaks '\n' in this rather chunky format:
|
||||
* Note on why this even exists: YAML will force save all strings containing line breaks '\n' in this rather chunky format:
|
||||
* key: |-
|
||||
* First line text
|
||||
* Second line text.
|
||||
@@ -608,6 +796,17 @@ public class Settings implements eu.kennytv.maintenance.api.Settings {
|
||||
return s.replace(NEW_LINE_REPLACEMENT, "\n");
|
||||
}
|
||||
|
||||
protected @Nullable String normalizeMode(@Nullable final String mode) {
|
||||
if (mode == null || mode.isBlank() || mode.equalsIgnoreCase("default")) {
|
||||
return null;
|
||||
}
|
||||
return mode.toLowerCase(Locale.ROOT);
|
||||
}
|
||||
|
||||
private String normalizeReason(@Nullable final String reason) {
|
||||
return reason == null || reason.isBlank() ? "" : reason;
|
||||
}
|
||||
|
||||
protected void loadExtraSettings() {
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.command;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
@@ -28,8 +28,10 @@ import eu.kennytv.maintenance.core.command.subcommand.MotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ReloadCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.RemoveMotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ScheduleTimerCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.SetReasonCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.SetMotdCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.StarttimerCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.StatusCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.ToggleCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.UpdateCommand;
|
||||
import eu.kennytv.maintenance.core.command.subcommand.WhitelistAddCommand;
|
||||
@@ -74,6 +76,7 @@ public abstract class MaintenanceCommand {
|
||||
add(new SetMotdCommand(plugin), "setmotd");
|
||||
add(new RemoveMotdCommand(plugin), "removemotd");
|
||||
add(new MotdCommand(plugin), "motd");
|
||||
add(new SetReasonCommand(plugin), "setreason");
|
||||
|
||||
add(new UpdateCommand(plugin), "update", "forceupdate");
|
||||
add(new DumpCommand(plugin), "dump");
|
||||
@@ -97,7 +100,7 @@ public abstract class MaintenanceCommand {
|
||||
return;
|
||||
}
|
||||
|
||||
final CommandInfo command = commandExecutors.get(args[0].toLowerCase());
|
||||
final CommandInfo command = commandExecutors.get(args[0].toLowerCase(Locale.ROOT));
|
||||
if (command == null) {
|
||||
help.sendUsage(sender);
|
||||
return;
|
||||
@@ -112,7 +115,7 @@ public abstract class MaintenanceCommand {
|
||||
|
||||
public List<String> getSuggestions(final SenderInfo sender, final String[] args) {
|
||||
if (!sender.hasMaintenancePermission("command") || args.length == 0) return Collections.emptyList();
|
||||
final String s = args[0].toLowerCase();
|
||||
final String s = args[0].toLowerCase(Locale.ROOT);
|
||||
if (args.length == 1) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (final Map.Entry<String, CommandInfo> entry : commandExecutors.entrySet()) {
|
||||
@@ -129,6 +132,24 @@ public abstract class MaintenanceCommand {
|
||||
return info != null && info.hasPermission(sender) ? info.getTabCompletion(sender, args) : Collections.emptyList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a user given time like {@code 2d}, {@code 2d12h}, {@code 1h5m}, or {@code 30s} to an ISO-8601 duration string.
|
||||
* Days are supported in addition to hours, minutes, and seconds.
|
||||
*
|
||||
* @return ISO duration string
|
||||
*/
|
||||
private static String toIsoDuration(final String time) {
|
||||
final String upper = time.toUpperCase(Locale.ROOT);
|
||||
final int dayIndex = upper.indexOf('D');
|
||||
if (dayIndex == -1) {
|
||||
return "PT" + upper;
|
||||
}
|
||||
|
||||
final String days = upper.substring(0, dayIndex + 1);
|
||||
final String rest = upper.substring(dayIndex + 1);
|
||||
return rest.isEmpty() ? "P" + days : "P" + days + "T" + rest;
|
||||
}
|
||||
|
||||
public @Nullable Duration parseDurationAndCheckTask(final SenderInfo sender, final String time, final boolean taskCheck) {
|
||||
final Duration duration;
|
||||
if (plugin.isNumeric(time)) {
|
||||
@@ -136,8 +157,7 @@ public abstract class MaintenanceCommand {
|
||||
duration = Duration.ofMinutes(Integer.parseInt(time));
|
||||
} else {
|
||||
try {
|
||||
// Only accept hours, minutes, and seconds
|
||||
duration = Duration.parse("PT" + time.toUpperCase(Locale.ROOT));
|
||||
duration = Duration.parse(toIsoDuration(time));
|
||||
} catch (final DateTimeParseException e) {
|
||||
return null;
|
||||
}
|
||||
@@ -168,6 +188,7 @@ public abstract class MaintenanceCommand {
|
||||
|
||||
protected void addToggleAndTimerCommands() {
|
||||
add(new ToggleCommand(plugin), "on", "off");
|
||||
add(new StatusCommand(plugin), "status");
|
||||
|
||||
add(new StarttimerCommand(plugin), "starttimer", "start");
|
||||
add(new EndtimerCommand(plugin), "endtimer", "end");
|
||||
|
||||
@@ -20,12 +20,14 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import static eu.kennytv.maintenance.core.util.ComponentUtil.clickEvent;
|
||||
|
||||
public final class DumpCommand extends CommandInfo {
|
||||
private long lastDump;
|
||||
@@ -57,7 +59,7 @@ public final class DumpCommand extends CommandInfo {
|
||||
sender.sendPrefixedRich("<red><click:open_url:'" + url + "'>" + url + "</click>");
|
||||
if (sender.isPlayer()) {
|
||||
final TextComponent text = Component.text().content("Click here to copy the link").color(NamedTextColor.GRAY)
|
||||
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, url))
|
||||
.clickEvent(clickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, url))
|
||||
.hoverEvent(HoverEvent.showText(Component.text("Click here to copy the link to your clipboard").color(NamedTextColor.GREEN)))
|
||||
.build();
|
||||
sender.send(plugin.prefix().append(text));
|
||||
|
||||
+8
-2
@@ -19,9 +19,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class EndtimerCommand extends CommandInfo {
|
||||
|
||||
@@ -44,6 +45,11 @@ public final class EndtimerCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, false);
|
||||
sender.send(getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
|
||||
final Component message = getMessage("endtimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookEndtimerStarted", DiscordWebhook.EventType.ENDTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ import com.google.common.base.Preconditions;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class HelpCommand extends CommandInfo {
|
||||
private static final int COMMANDS_PER_PAGE = 8;
|
||||
|
||||
+49
-10
@@ -19,10 +19,14 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MotdCommand extends CommandInfo {
|
||||
|
||||
@@ -32,21 +36,29 @@ public final class MotdCommand extends CommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 1) {
|
||||
sendList(sender, getSettings().getPingMessages());
|
||||
} else if (args.length == 2 && args[1].equalsIgnoreCase("timer")) {
|
||||
int indexOffset = 1;
|
||||
boolean timer = false;
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
sendList(sender, getSettings().getTimerSpecificPingMessages());
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
timer = true;
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length > indexOffset + 1) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final String mode = args.length == indexOffset + 1 ? args[indexOffset].toLowerCase(Locale.ROOT) : "default";
|
||||
final ConfigSection section = getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages");
|
||||
sendList(sender, getModeMessages(section, mode));
|
||||
}
|
||||
|
||||
private void sendList(final SenderInfo sender, final List<String> list) {
|
||||
private void sendList(final SenderInfo sender, @Nullable final List<String> list) {
|
||||
if (list == null || list.isEmpty()) {
|
||||
sender.send(getMessage("motdListEmpty"));
|
||||
return;
|
||||
@@ -55,16 +67,43 @@ public final class MotdCommand extends CommandInfo {
|
||||
sender.send(getMessage("motdList"));
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
sender.sendRich("<aqua>" + (i + 1) + "<dark_gray><st>---------");
|
||||
sender.sendRich(list.get(i));
|
||||
sender.sendRich(list.get(i).replace("<br>", "\n"));
|
||||
}
|
||||
sender.sendRich("<dark_gray><st>----------");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2 || !getSettings().hasTimerSpecificPingMessages()) {
|
||||
if (args.length < 2 || args.length > 3) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList("timer");
|
||||
|
||||
if (args.length == 2) {
|
||||
final List<String> list = new ArrayList<>();
|
||||
if (getSettings().hasTimerSpecificPingMessages()) {
|
||||
list.add("timer");
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection("messages").getKeys());
|
||||
modes.remove("default");
|
||||
list.addAll(modes);
|
||||
return list;
|
||||
}
|
||||
|
||||
if (!args[1].equalsIgnoreCase("timer") || !getSettings().hasTimerSpecificPingMessages()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection("timer-messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private @Nullable List<String> getModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value instanceof String s) {
|
||||
return Collections.singletonList(s);
|
||||
}
|
||||
return section.getStringList(mode);
|
||||
}
|
||||
}
|
||||
+68
-15
@@ -22,10 +22,10 @@ import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.config.ConfigSection;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class RemoveMotdCommand extends CommandInfo {
|
||||
|
||||
@@ -34,32 +34,49 @@ public final class RemoveMotdCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, String[] args) {
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
int indexOffset = 1;
|
||||
boolean timerPingMessages = false;
|
||||
if (args.length == 3 && args[1].equalsIgnoreCase("timer")) {
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
indexOffset++;
|
||||
timerPingMessages = true;
|
||||
}
|
||||
if (checkArgs(sender, args, 2)) return;
|
||||
if (!plugin.isNumeric(args[1])) {
|
||||
|
||||
if (args.length <= indexOffset) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
String mode = "default";
|
||||
if (!plugin.isNumeric(args[indexOffset])) {
|
||||
mode = args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length != indexOffset + 1 || !plugin.isNumeric(args[indexOffset])) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Settings settings = getSettings();
|
||||
final ConfigSection section = settings.getConfig().getSection("ping-message");
|
||||
final List<String> pingMessages = section.getStringList(timerPingMessages ? "timer-messages" : "messages");
|
||||
if (pingMessages.size() < 2) {
|
||||
final ConfigSection messageSection = section.getSection(timerPingMessages ? "timer-messages" : "messages");
|
||||
final List<String> pingMessages = getModeMessages(messageSection, mode);
|
||||
if (pingMessages.isEmpty()) {
|
||||
sender.send(getMessage("motdListEmpty"));
|
||||
return;
|
||||
}
|
||||
if (mode.equals("default") && pingMessages.size() < 2) {
|
||||
sender.send(getMessage("removeMotdError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final int index = Integer.parseInt(args[1]);
|
||||
final int index = Integer.parseInt(args[indexOffset]);
|
||||
if (index == 0 || index > pingMessages.size()) {
|
||||
sender.send(getMessage("setMotdIndexError",
|
||||
"%MOTDS%", Integer.toString(pingMessages.size()),
|
||||
@@ -67,24 +84,60 @@ public final class RemoveMotdCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<String> pingComponents = timerPingMessages ? settings.getTimerSpecificPingMessages() : settings.getPingMessages();
|
||||
pingComponents.remove(index - 1);
|
||||
pingMessages.remove(index - 1);
|
||||
section.set(timerPingMessages ? "timer-messages" : "messages", pingMessages);
|
||||
if (pingMessages.isEmpty()) {
|
||||
messageSection.remove(mode);
|
||||
} else {
|
||||
messageSection.set(mode, pingMessages);
|
||||
}
|
||||
settings.saveConfig();
|
||||
sender.send(getMessage("removedMotd", "%INDEX%", args[1]));
|
||||
settings.reloadConfigs();
|
||||
sender.send(getMessage("removedMotd", "%INDEX%", Integer.toString(index)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length == 2 || (args.length == 3 && args[1].equalsIgnoreCase("timer"))) {
|
||||
final int size = (args.length == 3 ? plugin.getSettings().getTimerSpecificPingMessages() : plugin.getSettings().getPingMessages()).size();
|
||||
final int indexOffset;
|
||||
final boolean timer;
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
timer = true;
|
||||
indexOffset = 2;
|
||||
} else {
|
||||
timer = false;
|
||||
indexOffset = 1;
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 && !plugin.isNumeric(args[indexOffset])) {
|
||||
return getModeCompletions(timer);
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 || (args.length == indexOffset + 2 && !plugin.isNumeric(args[indexOffset]))) {
|
||||
final String mode = plugin.isNumeric(args[indexOffset]) ? "default" : args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
final int size = getModeMessages(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages"), mode).size();
|
||||
final List<String> list = new ArrayList<>(size);
|
||||
for (int i = 1; i <= size; i++) {
|
||||
list.add(Integer.toString(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<String> getModeCompletions(final boolean timer) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private List<String> getModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value == null) {
|
||||
return List.of();
|
||||
}
|
||||
if (value instanceof String s) {
|
||||
return new ArrayList<>(Collections.singletonList(s));
|
||||
}
|
||||
return new ArrayList<>(section.getStringList(mode));
|
||||
}
|
||||
}
|
||||
+76
-29
@@ -26,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import static eu.kennytv.maintenance.core.Settings.NEW_LINE_REPLACEMENT;
|
||||
|
||||
@@ -36,28 +37,41 @@ public final class SetMotdCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, String[] args) {
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
int indexOffset = 1;
|
||||
boolean timerPingMessages = false;
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
if (args.length > indexOffset && args[indexOffset].equalsIgnoreCase("timer")) {
|
||||
if (!getSettings().hasTimerSpecificPingMessages()) {
|
||||
sender.send(getMessage("timerMotdDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
// remove the "timer" off the args to keep the rest the code cleaner
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
indexOffset++;
|
||||
timerPingMessages = true;
|
||||
}
|
||||
if (args.length < 4 || !plugin.isNumeric(args[1])) {
|
||||
|
||||
if (args.length <= indexOffset + 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
String mode = "default";
|
||||
if (!plugin.isNumeric(args[indexOffset])) {
|
||||
mode = args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
indexOffset++;
|
||||
}
|
||||
|
||||
if (args.length <= indexOffset + 2 || !plugin.isNumeric(args[indexOffset])) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final Settings settings = getSettings();
|
||||
final List<String> pingComponents = timerPingMessages ? settings.getTimerSpecificPingMessages() : settings.getPingMessages();
|
||||
final ConfigSection section = settings.getConfig().getSection("ping-message");
|
||||
final List<String> pingMessages = section.getStringList(timerPingMessages ? "timer-messages" : "messages");
|
||||
final int index = Integer.parseInt(args[1]);
|
||||
final ConfigSection messageSection = section.getSection(timerPingMessages ? "timer-messages" : "messages");
|
||||
final List<String> pingMessages = getOrCreateModeMessages(messageSection, mode);
|
||||
|
||||
final int index = Integer.parseInt(args[indexOffset]);
|
||||
if (index == 0 || index > pingMessages.size() + 1) {
|
||||
sender.send(getMessage("setMotdIndexError",
|
||||
"%MOTDS%", Integer.toString(pingMessages.size()),
|
||||
@@ -65,63 +79,96 @@ public final class SetMotdCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!plugin.isNumeric(args[2])) {
|
||||
if (!plugin.isNumeric(args[indexOffset + 1])) {
|
||||
sender.send(getMessage("setMotdLineError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final int line = Integer.parseInt(args[2]);
|
||||
final int line = Integer.parseInt(args[indexOffset + 1]);
|
||||
if (line != 1 && line != 2) {
|
||||
sender.send(getMessage("setMotdLineError"));
|
||||
return;
|
||||
}
|
||||
|
||||
final String message = String.join(" ", Arrays.copyOfRange(args, 3, args.length));
|
||||
final String message = String.join(" ", Arrays.copyOfRange(args, indexOffset + 2, args.length));
|
||||
final String oldMessage = index > pingMessages.size() ? "" : pingMessages.get(index - 1);
|
||||
final String newMessage;
|
||||
if (line == 1) {
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT) ?
|
||||
message + NEW_LINE_REPLACEMENT + oldMessage.split(NEW_LINE_REPLACEMENT, 2)[1] : message;
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT)
|
||||
? message + NEW_LINE_REPLACEMENT + oldMessage.split(NEW_LINE_REPLACEMENT, 2)[1]
|
||||
: message;
|
||||
} else {
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT) ?
|
||||
oldMessage.split(NEW_LINE_REPLACEMENT, 2)[0] + NEW_LINE_REPLACEMENT + message : oldMessage + NEW_LINE_REPLACEMENT + message;
|
||||
newMessage = oldMessage.contains(NEW_LINE_REPLACEMENT)
|
||||
? oldMessage.split(NEW_LINE_REPLACEMENT, 2)[0] + NEW_LINE_REPLACEMENT + message
|
||||
: oldMessage + NEW_LINE_REPLACEMENT + message;
|
||||
}
|
||||
|
||||
// Replace component in config and the cached list
|
||||
final String componentString = newMessage.replace(NEW_LINE_REPLACEMENT, "\n");
|
||||
if (index > pingMessages.size()) {
|
||||
pingMessages.add(newMessage);
|
||||
pingComponents.add(componentString);
|
||||
} else {
|
||||
pingMessages.set(index - 1, newMessage);
|
||||
pingComponents.set(index - 1, componentString);
|
||||
}
|
||||
|
||||
section.set(timerPingMessages ? "timer-messages" : "messages", pingMessages);
|
||||
messageSection.set(mode, pingMessages);
|
||||
settings.saveConfig();
|
||||
settings.reloadConfigs();
|
||||
|
||||
sender.send(settings.getMessage(
|
||||
"setMotd",
|
||||
"%LINE%", args[2],
|
||||
"%INDEX%", args[1],
|
||||
"%MOTD%", componentString
|
||||
"%LINE%", Integer.toString(line),
|
||||
"%INDEX%", Integer.toString(index),
|
||||
"%MOTD%", newMessage.replace(NEW_LINE_REPLACEMENT, "\n")
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, String[] args) {
|
||||
boolean timer = false;
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
final int indexOffset;
|
||||
final boolean timer;
|
||||
if (args.length > 1 && args[1].equalsIgnoreCase("timer")) {
|
||||
args = plugin.removeArrayIndex(args, 1);
|
||||
timer = true;
|
||||
indexOffset = 2;
|
||||
} else {
|
||||
timer = false;
|
||||
indexOffset = 1;
|
||||
}
|
||||
if (args.length == 3) return Arrays.asList("1", "2");
|
||||
if (args.length == 2) {
|
||||
|
||||
if (args.length == indexOffset + 2) {
|
||||
return Arrays.asList("1", "2");
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1 && !plugin.isNumeric(args[indexOffset])) {
|
||||
return getModeCompletions(timer);
|
||||
}
|
||||
|
||||
if (args.length == indexOffset + 1) {
|
||||
final String mode = plugin.isNumeric(args[indexOffset]) ? "default" : args[indexOffset].toLowerCase(Locale.ROOT);
|
||||
final ConfigSection section = getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages");
|
||||
final int size = getOrCreateModeMessages(section, mode).size();
|
||||
final List<String> list = new ArrayList<>();
|
||||
for (int i = 1; i <= (timer ? getSettings().getTimerSpecificPingMessages() : getSettings().getPingMessages()).size() + 1; i++) {
|
||||
for (int i = 1; i <= size + 1; i++) {
|
||||
list.add(String.valueOf(i));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<String> getModeCompletions(final boolean timer) {
|
||||
final List<String> modes = new ArrayList<>(getSettings().getConfig().getSection("ping-message").getSection(timer ? "timer-messages" : "messages").getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
|
||||
private List<String> getOrCreateModeMessages(final ConfigSection section, final String mode) {
|
||||
final Object value = section.getObject(mode);
|
||||
if (value == null) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
if (value instanceof String s) {
|
||||
return new ArrayList<>(Collections.singletonList(s));
|
||||
}
|
||||
return new ArrayList<>(section.getStringList(mode));
|
||||
}
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public final class SetReasonCommand extends CommandInfo {
|
||||
|
||||
public SetReasonCommand(final MaintenancePlugin plugin) {
|
||||
super(plugin, "setreason");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (args.length < 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final String value = String.join(" ", java.util.Arrays.copyOfRange(args, 1, args.length));
|
||||
final String reason;
|
||||
if (value.equalsIgnoreCase("none") || value.equalsIgnoreCase("clear") || value.equals("-")) {
|
||||
reason = null;
|
||||
} else {
|
||||
reason = value;
|
||||
}
|
||||
|
||||
getSettings().setActiveReason(reason);
|
||||
sender.send(getMessage("setReason", "%REASON%", reason == null ? "-" : reason));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
return Collections.singletonList("none");
|
||||
}
|
||||
}
|
||||
+8
-2
@@ -19,9 +19,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class StarttimerCommand extends CommandInfo {
|
||||
|
||||
@@ -44,6 +45,11 @@ public final class StarttimerCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
plugin.startMaintenanceRunnable(duration, true);
|
||||
sender.send(getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime()));
|
||||
|
||||
final Component message = getMessage("starttimerStarted", "%TIME%", plugin.getRunnable().getTime());
|
||||
sender.send(message);
|
||||
plugin.sendWebhookMessage("webhookStarttimerStarted", DiscordWebhook.EventType.STARTTIMER_STARTED,
|
||||
"%TIME%", plugin.getRunnable().getTime(),
|
||||
"%TIMESTAMP%", plugin.getTargetTimestamp(duration));
|
||||
}
|
||||
}
|
||||
+19
-14
@@ -15,28 +15,33 @@
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.proxy.command.subcommand;
|
||||
package eu.kennytv.maintenance.core.command.subcommand;
|
||||
|
||||
import eu.kennytv.maintenance.core.proxy.MaintenanceProxyPlugin;
|
||||
import eu.kennytv.maintenance.core.proxy.command.ProxyCommandInfo;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.runnable.MaintenanceRunnable;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class StatusCommand extends ProxyCommandInfo {
|
||||
public final class StatusCommand extends CommandInfo {
|
||||
|
||||
public StatusCommand(final MaintenanceProxyPlugin plugin) {
|
||||
super(plugin, "singleserver.status");
|
||||
public StatusCommand(final MaintenancePlugin plugin) {
|
||||
super(plugin, "status");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (getSettings().getMaintenanceServers().isEmpty()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEmpty"));
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage("singleServerMaintenanceList"));
|
||||
for (final String server : getSettings().getMaintenanceServers()) {
|
||||
sender.send(getMessage("singleServerMaintenanceListEntry", "%SERVER%", server));
|
||||
final MaintenanceRunnable task = plugin.getCurrentTask();
|
||||
if (task != null) {
|
||||
final String key = task.shouldEnable() ? "maintenanceStatusOffWithStartTimer" : "maintenanceStatusOnWithEndTimer";
|
||||
sender.send(getMessage(key, "%TIME%", task.getTime()));
|
||||
} else {
|
||||
sender.send(getMessage(plugin.isMaintenance() ? "maintenanceStatusOn" : "maintenanceStatusOff"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component getHelpMessage() {
|
||||
return getMessage("helpGlobalStatus");
|
||||
}
|
||||
}
|
||||
+37
-2
@@ -20,6 +20,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
public final class ToggleCommand extends CommandInfo {
|
||||
|
||||
@@ -29,14 +33,45 @@ public final class ToggleCommand extends CommandInfo {
|
||||
|
||||
@Override
|
||||
public void execute(final SenderInfo sender, final String[] args) {
|
||||
if (checkArgs(sender, args, 1)) return;
|
||||
if (args.length == 0 || args.length > 2) {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean maintenance = args[0].equalsIgnoreCase("on");
|
||||
final String mode;
|
||||
if (maintenance && args.length == 2) {
|
||||
mode = args[1].toLowerCase(Locale.ROOT);
|
||||
} else if (!maintenance && args.length == 1) {
|
||||
mode = null;
|
||||
} else if (maintenance) {
|
||||
mode = null;
|
||||
} else {
|
||||
sender.send(getHelpMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
if (maintenance == plugin.isMaintenance()) {
|
||||
if (mode != null) {
|
||||
plugin.getSettings().setActiveMode(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
sender.send(getMessage(maintenance ? "alreadyEnabled" : "alreadyDisabled"));
|
||||
return;
|
||||
}
|
||||
|
||||
plugin.setMaintenance(maintenance);
|
||||
plugin.setMaintenance(maintenance, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getTabCompletion(final SenderInfo sender, final String[] args) {
|
||||
if (args.length != 2 || !args[0].equalsIgnoreCase("on")) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
final List<String> modes = new ArrayList<>(getSettings().getPingMessages().getKeys());
|
||||
modes.remove("default");
|
||||
return modes;
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -20,11 +20,11 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
|
||||
public final class UpdateCommand extends CommandInfo {
|
||||
|
||||
|
||||
+3
-3
@@ -99,10 +99,10 @@ public final class WhitelistAddCommand extends CommandInfo {
|
||||
}
|
||||
|
||||
private void addPlayerToWhitelist(final SenderInfo sender, final SenderInfo selected) {
|
||||
if (getSettings().addWhitelistedPlayer(selected.getUuid(), selected.getName())) {
|
||||
sender.send(getMessage("whitelistAdded", "%PLAYER%", selected.getName()));
|
||||
if (getSettings().addWhitelistedPlayer(selected.uuid(), selected.name())) {
|
||||
sender.send(getMessage("whitelistAdded", "%PLAYER%", selected.name()));
|
||||
} else {
|
||||
sender.send(getMessage("whitelistAlreadyAdded", "%PLAYER%", selected.getName()));
|
||||
sender.send(getMessage("whitelistAlreadyAdded", "%PLAYER%", selected.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -20,10 +20,10 @@ package eu.kennytv.maintenance.core.command.subcommand;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.command.CommandInfo;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class WhitelistCommand extends CommandInfo {
|
||||
|
||||
|
||||
+6
-5
@@ -24,6 +24,7 @@ import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
@@ -50,9 +51,9 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
if (args.length != 2) return Collections.emptyList();
|
||||
|
||||
final List<String> list = new ArrayList<>();
|
||||
String matchNameLowerCase = args[1].toLowerCase();
|
||||
String matchNameLowerCase = args[1].toLowerCase(Locale.ROOT);
|
||||
for (final String name : getSettings().getWhitelistedPlayers().values()) {
|
||||
if (name.toLowerCase().startsWith(matchNameLowerCase)) {
|
||||
if (name.toLowerCase(Locale.ROOT).startsWith(matchNameLowerCase)) {
|
||||
list.add(name);
|
||||
}
|
||||
}
|
||||
@@ -70,7 +71,7 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
return;
|
||||
}
|
||||
|
||||
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
|
||||
removePlayerFromWhitelist(sender, selected.uuid(), selected.name());
|
||||
});
|
||||
}
|
||||
|
||||
@@ -79,13 +80,13 @@ public final class WhitelistRemoveCommand extends CommandInfo {
|
||||
if (selected == null) {
|
||||
removePlayerFromWhitelist(sender, uuid, uuid.toString());
|
||||
} else {
|
||||
removePlayerFromWhitelist(sender, selected.getUuid(), selected.getName());
|
||||
removePlayerFromWhitelist(sender, selected.uuid(), selected.name());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removePlayerFromWhitelist(final SenderInfo sender, final UUID uuid, final String toReplace) {
|
||||
if (getSettings().removeWhitelistedPlayer(uuid)) {
|
||||
if (plugin.getSettings().removeWhitelistedPlayer(uuid)) {
|
||||
sender.send(getMessage("whitelistRemoved", "%PLAYER%", toReplace));
|
||||
} else {
|
||||
sender.send(getMessage("whitelistNotFound"));
|
||||
|
||||
@@ -17,10 +17,8 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
@@ -40,18 +38,20 @@ import org.yaml.snakeyaml.Yaml;
|
||||
public final class Config extends ConfigSection {
|
||||
|
||||
private static final String AWESOME_HEADER =
|
||||
"###################################################################################################################\n" +
|
||||
"# __ __ _ _ _ _ _ #\n" +
|
||||
"# | \\/ | __ _(_)_ __ | |_ ___ _ __ __ _ _ __ ___ ___ | |__ _ _ | | _____ _ __ _ __ _ _| |___ __ #\n" +
|
||||
"# | |\\/| |/ _` | | '_ \\| __/ _ \\ '_ \\ / _` | '_ \\ / __/ _ \\ | '_ \\| | | | | |/ / _ \\ '_ \\| '_ \\| | | | __\\ \\ / / #\n" +
|
||||
"# | | | | (_| | | | | | || __/ | | | (_| | | | | (_| __/ | |_) | |_| | | < __/ | | | | | | |_| | |_ \\ V / #\n" +
|
||||
"# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, |\\__| \\_/ #\n" +
|
||||
"# |___/ |___/ #\n" +
|
||||
"###################################################################################################################\n" +
|
||||
"# You can report bugs here: https://github.com/kennytv/Maintenance/issues\n" +
|
||||
"# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq\n" +
|
||||
"# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.adventure.kyori.net/ to edit and preview the formatted text.\n" +
|
||||
"# For a full list of formats and fancy examples of MiniMessage, see https://docs.adventure.kyori.net/minimessage/format.html\n";
|
||||
"""
|
||||
###################################################################################################################
|
||||
# __ __ _ _ _ _ _ #
|
||||
# | \\/ | __ _(_)_ __ | |_ ___ _ __ __ _ _ __ ___ ___ | |__ _ _ | | _____ _ __ _ __ _ _| |___ __ #
|
||||
# | |\\/| |/ _` | | '_ \\| __/ _ \\ '_ \\ / _` | '_ \\ / __/ _ \\ | '_ \\| | | | | |/ / _ \\ '_ \\| '_ \\| | | | __\\ \\ / / #
|
||||
# | | | | (_| | | | | | || __/ | | | (_| | | | | (_| __/ | |_) | |_| | | < __/ | | | | | | |_| | |_ \\ V / #
|
||||
# |_| |_|\\__,_|_|_| |_|\\__\\___|_| |_|\\__,_|_| |_|\\___\\___| |_.__/ \\__, | |_|\\_\\___|_| |_|_| |_|\\__, |\\__| \\_/ #
|
||||
# |___/ |___/ #
|
||||
###################################################################################################################
|
||||
# You can report bugs here: https://github.com/kennytv/Maintenance/issues
|
||||
# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.advntr.dev/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
""";
|
||||
private final Yaml yaml = createYaml();
|
||||
private final File file;
|
||||
private final Set<String> unsupportedFields;
|
||||
@@ -61,11 +61,11 @@ public final class Config extends ConfigSection {
|
||||
public Config(final File file, final String... unsupportedFields) {
|
||||
super(null, "");
|
||||
this.file = file;
|
||||
this.unsupportedFields = unsupportedFields.length == 0 ? Collections.emptySet() : Sets.newHashSet(unsupportedFields);
|
||||
this.unsupportedFields = unsupportedFields.length == 0 ? Collections.emptySet() : Set.of(unsupportedFields);
|
||||
}
|
||||
|
||||
public void load() throws IOException {
|
||||
final String data = new String(Files.readAllBytes(this.file.toPath()), StandardCharsets.UTF_8);
|
||||
final String data = Files.readString(this.file.toPath());
|
||||
final Map<String, Object> map = yaml.load(data);
|
||||
this.values = map != null ? map : new LinkedHashMap<>();
|
||||
this.comments = ConfigSerializer.deserializeComments(data);
|
||||
@@ -101,12 +101,11 @@ public final class Config extends ConfigSection {
|
||||
}
|
||||
|
||||
public void saveTo(final File file) throws IOException {
|
||||
final byte[] bytes = toString().getBytes(StandardCharsets.UTF_8);
|
||||
if (file.getParentFile() != null) {
|
||||
file.getParentFile().mkdirs();
|
||||
}
|
||||
file.createNewFile();
|
||||
Files.write(file.toPath(), bytes);
|
||||
Files.writeString(file.toPath(), toString());
|
||||
}
|
||||
|
||||
public void replaceComments(final Config fromConfig) {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -36,7 +35,7 @@ public class ConfigSection {
|
||||
protected Map<String, Object> values;
|
||||
|
||||
ConfigSection(final Config root, final String currentPath) {
|
||||
this(root, currentPath, new HashMap<>());
|
||||
this(root, currentPath, new LinkedHashMap<>());
|
||||
}
|
||||
|
||||
ConfigSection(final Config root, final String currentPath, final Map<String, Object> values) {
|
||||
@@ -63,20 +62,18 @@ public class ConfigSection {
|
||||
|
||||
@Nullable
|
||||
public Object getObject(final String key, final Object def) {
|
||||
int nextSeparatorIndex = -1;
|
||||
int sectionStartIndex;
|
||||
final String[] parts = key.split("\\.");
|
||||
ConfigSection section = this;
|
||||
while ((nextSeparatorIndex = key.indexOf('.', sectionStartIndex = nextSeparatorIndex + 1)) != -1) {
|
||||
section = section.getSection(key.substring(sectionStartIndex, nextSeparatorIndex));
|
||||
if (section == null) return def;
|
||||
for (int i = 0; i < parts.length - 1; i++) {
|
||||
section = section.getSection(parts[i]);
|
||||
if (section == null) {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
final String subKey = key.substring(sectionStartIndex);
|
||||
if (section == this) {
|
||||
final Object result = values.get(subKey);
|
||||
return result != null ? result : def;
|
||||
}
|
||||
return section.getObject(subKey, def);
|
||||
final String valueKey = parts[parts.length - 1];
|
||||
final Object o = section.values.get(valueKey);
|
||||
return o != null ? o : def;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -164,7 +161,7 @@ public class ConfigSection {
|
||||
@Nullable
|
||||
public String getString(final String key, @Nullable final String def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof String ? (String) o : def;
|
||||
return o instanceof String s ? s : def;
|
||||
}
|
||||
|
||||
public int getInt(final String key) {
|
||||
@@ -173,7 +170,7 @@ public class ConfigSection {
|
||||
|
||||
public int getInt(final String key, final int def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number ? ((Number) o).intValue() : def;
|
||||
return o instanceof Number number ? number.intValue() : def;
|
||||
}
|
||||
|
||||
public double getDouble(final String key) {
|
||||
@@ -182,7 +179,7 @@ public class ConfigSection {
|
||||
|
||||
public double getDouble(final String key, final double def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number ? ((Number) o).doubleValue() : def;
|
||||
return o instanceof Number number ? number.doubleValue() : def;
|
||||
}
|
||||
|
||||
public long getLong(final String key) {
|
||||
@@ -191,7 +188,7 @@ public class ConfigSection {
|
||||
|
||||
public long getLong(final String key, final long def) {
|
||||
final Object o = getObject(key);
|
||||
return o instanceof Number ? ((Number) o).longValue() : def;
|
||||
return o instanceof Number number ? number.longValue() : def;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -253,6 +250,6 @@ public class ConfigSection {
|
||||
}
|
||||
|
||||
protected String getFullKeyInPath(final String key) {
|
||||
return currentPath.isEmpty() ? key : currentPath + "." + key;
|
||||
return currentPath.isEmpty() ? key : currentPath + '.' + key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.config;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class DisplayedMessages {
|
||||
|
||||
private static final Random RANDOM = new Random();
|
||||
private final Map<String, List<String>> messages;
|
||||
private final List<String> defaultMessages;
|
||||
|
||||
public DisplayedMessages(final Map<String, List<String>> messages) {
|
||||
this.messages = messages;
|
||||
this.defaultMessages = messages.get("default");
|
||||
}
|
||||
|
||||
public List<String> getMessages(@Nullable final String key) {
|
||||
Preconditions.checkNotNull(defaultMessages, "no default message configured in messages list");
|
||||
if (key == null || messages.size() == 1) {
|
||||
return defaultMessages;
|
||||
}
|
||||
return messages.getOrDefault(key, defaultMessages);
|
||||
}
|
||||
|
||||
public String getRandomEntry(@Nullable final String key) {
|
||||
final List<String> messages = getMessages(key);
|
||||
return messages.get(RANDOM.nextInt(messages.size()));
|
||||
}
|
||||
|
||||
public List<String> getDefaultMessages() {
|
||||
return defaultMessages;
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return messages.isEmpty();
|
||||
}
|
||||
|
||||
public Set<String> getKeys() {
|
||||
return messages.keySet();
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import eu.kennytv.maintenance.core.Settings;
|
||||
import java.io.File;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class MaintenanceDump {
|
||||
@@ -35,12 +36,8 @@ public final class MaintenanceDump {
|
||||
general = new ServerDump(plugin.getVersion(), plugin.getServerType().toString(), plugin.getServerVersion(), plugin.getMaintenanceServersDump());
|
||||
|
||||
configuration = new LinkedHashMap<>(settings.getConfig().getValues());
|
||||
final Object o = configuration.get("mysql");
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
map.keySet().removeIf(key -> !key.equals("use-mysql") && !key.equals("update-interval"));
|
||||
configuration.put("mysql", map);
|
||||
}
|
||||
addDBSettings("redis", "enabled");
|
||||
redact("webhook", "url");
|
||||
configuration.put("whitelisted-players", settings.getWhitelistedPlayers());
|
||||
configuration.put("icon-exists", new File(plugin.getDataFolder(), "maintenance-icon.png").exists());
|
||||
|
||||
@@ -48,4 +45,28 @@ public final class MaintenanceDump {
|
||||
jsonObject.add("plugins", MaintenancePlugin.GSON.toJsonTree(plugin.getPlugins()));
|
||||
plugins = jsonObject;
|
||||
}
|
||||
|
||||
private void redact(final String key, final String... subKeys) {
|
||||
final Object o = configuration.get(key);
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
for (final String subKey : subKeys) {
|
||||
final Object value = map.get(subKey);
|
||||
if (value != null) {
|
||||
map.put(subKey, value.toString().isEmpty() ? "" : "<redacted>");
|
||||
}
|
||||
}
|
||||
configuration.put(key, map);
|
||||
}
|
||||
}
|
||||
|
||||
private void addDBSettings(final String key, final String... allowedSubKeys) {
|
||||
final Set<String> allowedSubKeysSet = Set.of(allowedSubKeys);
|
||||
final Object o = configuration.get(key);
|
||||
if (o instanceof Map) {
|
||||
final Map<String, Object> map = new LinkedHashMap<>(((Map<String, Object>) o));
|
||||
map.keySet().removeIf(subKey -> !allowedSubKeysSet.contains(subKey));
|
||||
configuration.put(key, map);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,7 @@ package eu.kennytv.maintenance.core.dump;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class PluginDump {
|
||||
private final String name;
|
||||
private final String version;
|
||||
private final List<String> authors;
|
||||
|
||||
public record PluginDump(String name, String version, List<String> authors) {
|
||||
public PluginDump(final String name, final String version, final List<String> authors) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
|
||||
@@ -19,17 +19,5 @@ package eu.kennytv.maintenance.core.dump;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@SuppressWarnings({"FieldCanBeLocal", "unused"})
|
||||
public final class ServerDump {
|
||||
private final String pluginVersion;
|
||||
private final String platform;
|
||||
private final String serverVersion;
|
||||
private final List<String> maintenance;
|
||||
|
||||
public ServerDump(final String pluginVersion, final String platform, final String serverVersion, final List<String> maintenance) {
|
||||
this.pluginVersion = pluginVersion;
|
||||
this.platform = platform;
|
||||
this.serverVersion = serverVersion;
|
||||
this.maintenance = maintenance;
|
||||
}
|
||||
public record ServerDump(String pluginVersion, String platform, String serverVersion, List<String> maintenance) {
|
||||
}
|
||||
@@ -24,10 +24,10 @@ public final class ServerListPlusHook {
|
||||
private final ServerListPlusCore serverListPlusCore;
|
||||
|
||||
public ServerListPlusHook(final Object serverListPlus) {
|
||||
if (!(serverListPlus instanceof ServerListPlusPlugin)) {
|
||||
if (!(serverListPlus instanceof ServerListPlusPlugin serverListPlusPlugin)) {
|
||||
throw new IllegalArgumentException("Couldn't parse ServerListPlus instance!");
|
||||
}
|
||||
this.serverListPlusCore = ((ServerListPlusPlugin) serverListPlus).getCore();
|
||||
this.serverListPlusCore = serverListPlusPlugin.getCore();
|
||||
}
|
||||
|
||||
public void setEnabled(final boolean enable) {
|
||||
|
||||
@@ -19,17 +19,19 @@ package eu.kennytv.maintenance.core.listener;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.DiscordWebhook;
|
||||
import eu.kennytv.maintenance.core.util.SenderInfo;
|
||||
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.TextComponent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.ClickEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.event.HoverEvent;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.NamedTextColor;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.format.TextDecoration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import static eu.kennytv.maintenance.core.util.ComponentUtil.clickEvent;
|
||||
|
||||
public abstract class JoinListenerBase {
|
||||
protected final MaintenancePlugin plugin;
|
||||
@@ -48,13 +50,16 @@ public abstract class JoinListenerBase {
|
||||
* @return true if the sender should be kicked
|
||||
*/
|
||||
protected boolean shouldKick(final SenderInfo sender, final boolean updateCheck) {
|
||||
if (!settings.isMaintenance() || sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.getUuid())) {
|
||||
if (!settings.isMaintenance() || sender.hasMaintenancePermission("bypass") || settings.isWhitelisted(sender.uuid())) {
|
||||
if (updateCheck) {
|
||||
updateCheck(sender);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (settings.isWebhookEnabled()) {
|
||||
plugin.sendWebhookMessage("webhookJoinNotification", DiscordWebhook.EventType.BLOCKED_JOIN, "%PLAYER%", sender.name());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,19 +69,19 @@ public abstract class JoinListenerBase {
|
||||
|
||||
protected void updateCheck(final SenderInfo sender) {
|
||||
if (!settings.hasUpdateChecks()) return;
|
||||
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.getUuid())) return;
|
||||
if (!sender.hasPermission("maintenance.admin") || notifiedPlayers.contains(sender.uuid())) return;
|
||||
plugin.async(() -> {
|
||||
if (!plugin.updateAvailable()) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifiedPlayers.add(sender.getUuid());
|
||||
notifiedPlayers.add(sender.uuid());
|
||||
sender.sendPrefixedRich("<red>There is a newer version available: <green>Version " + plugin.getNewestVersion() + "<red>, you're on <green>" + plugin.getVersion());
|
||||
|
||||
final TextComponent text = Component.text().content("Download it at: ").color(NamedTextColor.RED)
|
||||
.append(Component.text().content(MaintenancePlugin.HANGAR_URL).color(NamedTextColor.GOLD))
|
||||
.append(Component.text().content(" (CLICK ME)").color(NamedTextColor.GRAY).decorate(TextDecoration.BOLD))
|
||||
.clickEvent(ClickEvent.clickEvent(ClickEvent.Action.OPEN_URL, MaintenancePlugin.HANGAR_URL))
|
||||
.clickEvent(clickEvent(ClickEvent.Action.OPEN_URL, MaintenancePlugin.HANGAR_URL))
|
||||
.hoverEvent(HoverEvent.showText(Component.text("Download the latest version").color(NamedTextColor.GREEN)))
|
||||
.build();
|
||||
sender.send(plugin.prefix().append(text));
|
||||
|
||||
@@ -19,17 +19,24 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class MaintenanceRunnable extends MaintenanceRunnableBase {
|
||||
protected final String mode;
|
||||
|
||||
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable) {
|
||||
this(plugin, settings, seconds, enable, null);
|
||||
}
|
||||
|
||||
public MaintenanceRunnable(final MaintenancePlugin plugin, final Settings settings, final int seconds, final boolean enable, @Nullable final String mode) {
|
||||
super(plugin, settings, seconds, enable);
|
||||
this.mode = mode;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finish() {
|
||||
plugin.setMaintenance(enable);
|
||||
plugin.setMaintenance(enable, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.core.util.Task;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public abstract class MaintenanceRunnableBase implements Runnable {
|
||||
protected final MaintenancePlugin plugin;
|
||||
|
||||
+7
-2
@@ -19,14 +19,19 @@ package eu.kennytv.maintenance.core.runnable;
|
||||
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import java.time.Duration;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public final class MaintenanceScheduleRunnable extends MaintenanceRunnable {
|
||||
private final int maintenanceDuration;
|
||||
|
||||
public MaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int secondsToEnable, final int maintenanceDuration) {
|
||||
super(plugin, settings, secondsToEnable, true);
|
||||
this(plugin, settings, secondsToEnable, maintenanceDuration, null);
|
||||
}
|
||||
|
||||
public MaintenanceScheduleRunnable(final MaintenancePlugin plugin, final Settings settings, final int secondsToEnable, final int maintenanceDuration, @Nullable final String mode) {
|
||||
super(plugin, settings, secondsToEnable, true, mode);
|
||||
this.maintenanceDuration = maintenanceDuration;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of Maintenance - https://github.com/kennytv/Maintenance
|
||||
* Copyright (C) 2018-2024 kennytv (https://github.com/kennytv)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||
|
||||
public final class ComponentUtil {
|
||||
|
||||
private static final MethodHandle LEGACY_CLICK_EVENT = legacyClickEvent();
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public static ClickEvent clickEvent(final ClickEvent.Action action, final String value) {
|
||||
if (LEGACY_CLICK_EVENT != null) {
|
||||
try {
|
||||
return (ClickEvent) LEGACY_CLICK_EVENT.invoke(action, value);
|
||||
} catch (final Throwable e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
return ClickEvent.clickEvent(action, ClickEvent.Payload.string(value));
|
||||
}
|
||||
|
||||
private static @Nullable MethodHandle legacyClickEvent() {
|
||||
try {
|
||||
return MethodHandles.publicLookup().unreflect(ClickEvent.class.getDeclaredMethod("clickEvent", ClickEvent.Action.class, String.class));
|
||||
} catch (final NoSuchMethodException | IllegalAccessException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import eu.kennytv.maintenance.core.Settings;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.http.HttpClient;
|
||||
import java.net.http.HttpRequest;
|
||||
import java.net.http.HttpResponse;
|
||||
|
||||
public final class DiscordWebhook {
|
||||
|
||||
private static final int COLOR_MAINTENANCE_ENABLED = 0xED4245; // Red
|
||||
private static final int COLOR_MAINTENANCE_DISABLED = 0x57F287; // Green
|
||||
private static final int COLOR_STARTTIMER = 0xFEE75C; // Yellow
|
||||
private static final int COLOR_ENDTIMER = 0x5865F2; // Blue
|
||||
private static final int COLOR_BLOCKED_JOIN = 0xE67E22; // Orange
|
||||
|
||||
public static void sendMessage(final String message, final EventType event, final Settings settings) throws IOException, InterruptedException {
|
||||
final JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("username", settings.getWebhookUsername());
|
||||
|
||||
final String avatarUrl = settings.getWebhookAvatarUrl();
|
||||
if (!avatarUrl.isEmpty()) {
|
||||
jsonObject.addProperty("avatar_url", avatarUrl);
|
||||
}
|
||||
|
||||
final JsonObject embed = new JsonObject();
|
||||
embed.addProperty("description", message);
|
||||
embed.addProperty("color", getColorForEvent(event));
|
||||
|
||||
final JsonArray embeds = new JsonArray();
|
||||
embeds.add(embed);
|
||||
jsonObject.add("embeds", embeds);
|
||||
|
||||
try (final HttpClient client = HttpClient.newHttpClient()) {
|
||||
final HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(settings.getWebhookUrl()))
|
||||
.header("Content-Type", "application/json")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(jsonObject.toString()))
|
||||
.build();
|
||||
client.send(request, HttpResponse.BodyHandlers.discarding());
|
||||
}
|
||||
}
|
||||
|
||||
private static int getColorForEvent(final EventType event) {
|
||||
return switch (event) {
|
||||
case MAINTENANCE_ENABLED -> COLOR_MAINTENANCE_ENABLED;
|
||||
case MAINTENANCE_DISABLED -> COLOR_MAINTENANCE_DISABLED;
|
||||
case STARTTIMER_STARTED -> COLOR_STARTTIMER;
|
||||
case ENDTIMER_STARTED -> COLOR_ENDTIMER;
|
||||
case BLOCKED_JOIN -> COLOR_BLOCKED_JOIN;
|
||||
};
|
||||
}
|
||||
|
||||
public enum EventType {
|
||||
MAINTENANCE_ENABLED("maintenance_status"),
|
||||
MAINTENANCE_DISABLED("maintenance_status"),
|
||||
STARTTIMER_STARTED("starttimer_started"),
|
||||
ENDTIMER_STARTED("endtimer_started"),
|
||||
BLOCKED_JOIN("blocked_join");
|
||||
|
||||
private final String configKey;
|
||||
|
||||
EventType(final String configKey) {
|
||||
this.configKey = configKey;
|
||||
}
|
||||
|
||||
public String configKey() {
|
||||
return configKey;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,28 +17,10 @@
|
||||
*/
|
||||
package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public final class DummySenderInfo implements SenderInfo {
|
||||
private final UUID uuid;
|
||||
private final String name;
|
||||
|
||||
public DummySenderInfo(final UUID uuid, final String name) {
|
||||
this.uuid = uuid;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public UUID getUuid() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
public record DummySenderInfo(UUID uuid, String name) implements SenderInfo {
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(final String permission) {
|
||||
|
||||
@@ -19,15 +19,15 @@ package eu.kennytv.maintenance.core.util;
|
||||
|
||||
import eu.kennytv.maintenance.api.MaintenanceProvider;
|
||||
import eu.kennytv.maintenance.core.MaintenancePlugin;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.Component;
|
||||
import eu.kennytv.maintenance.lib.kyori.adventure.text.minimessage.MiniMessage;
|
||||
import java.util.UUID;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||
|
||||
public interface SenderInfo {
|
||||
|
||||
UUID getUuid();
|
||||
UUID uuid();
|
||||
|
||||
String getName();
|
||||
String name();
|
||||
|
||||
boolean hasPermission(String permission);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ package eu.kennytv.maintenance.core.util;
|
||||
public enum ServerType {
|
||||
|
||||
BUNGEE("Bungee"),
|
||||
SPIGOT("Spigot"),
|
||||
PAPER("Paper"),
|
||||
SPONGE("Sponge"),
|
||||
VELOCITY("Velocity");
|
||||
|
||||
|
||||
@@ -89,8 +89,7 @@ public final class Version implements Comparable<Version> {
|
||||
@Override
|
||||
public boolean equals(final Object o) {
|
||||
if (o == this) return true;
|
||||
if (!(o instanceof Version)) return false;
|
||||
final Version other = (Version) o;
|
||||
if (!(o instanceof Version other)) return false;
|
||||
return version.equals(other.version);
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,8 @@
|
||||
###################################################################################################################
|
||||
# You can report bugs here: https://github.com/kennytv/Maintenance/issues
|
||||
# If you need any other help/support, you can also join my Discord server: https://discord.gg/vGCUzHq
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.adventure.kyori.net/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
# The config and language files use MiniMessage, NOT legacy text for input. Use https://webui.advntr.dev/ to edit and preview the formatted text.
|
||||
# For a full list of formats and fancy examples of MiniMessage, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
|
||||
# Changes the language of command feedback/messages.
|
||||
# If you find missing translations or want to contribute, see https://crowdin.com/project/maintenance
|
||||
@@ -20,10 +20,19 @@ language: en
|
||||
# Enables maintenance mode.
|
||||
maintenance-enabled: false
|
||||
|
||||
# The currently active maintenance mode key (used for mode-specific messages/icons).
|
||||
# Use 'default' or leave empty to use fallback messages.
|
||||
active-mode: default
|
||||
|
||||
# Value for the %REASON% placeholder in maintenance messages.
|
||||
# This can be changed via /maintenance setreason <text>.
|
||||
active-reason: ""
|
||||
|
||||
# Enables maintenance on certain servers managed by your proxy instance(s).
|
||||
# The value is the mode key used for ping/player count messages for that server.
|
||||
proxied-maintenance-servers:
|
||||
- PaperServer1
|
||||
# - AnotherServer
|
||||
PaperServer1: default
|
||||
# AnotherServer: release
|
||||
|
||||
# If maintenance is enabled on a proxied server with players on it, they will be sent to the fallback server instead of being kicked off the network.
|
||||
# If the fallback server is not reachable/not set, they will just be kicked off the network.
|
||||
@@ -36,35 +45,53 @@ waiting-server: ""
|
||||
|
||||
# The message (MOTD) shown in the multiplayer server list motd when maintenance is enabled.
|
||||
# If you put in multiple entries, one of them will be chosen randomly on every ping.
|
||||
# If running an endtimer, the time left can be displayed by including '%TIMER%' in a ping message.
|
||||
# The type of mode can be defined in the command, or will be the default mode.
|
||||
ping-message:
|
||||
enabled: true
|
||||
# Always uses 'default' if not defined in the command or not present in the config.
|
||||
# Additional examples could look as follows:
|
||||
# default:
|
||||
# - "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>We will be back soon!"
|
||||
# - "<red>Wooow you found our secondary MOTD!"
|
||||
# reason:
|
||||
# - "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>%REASON%"
|
||||
# release:
|
||||
# - "<gold>We're currently preparing the release, come back soon!"
|
||||
messages:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>We will be back soon!"
|
||||
default:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#0fffff>We will be back soon!"
|
||||
# If set to true and an endtimer is currently running, a message from this pool will be chosen
|
||||
# instead of the ones above, so you can have different messages for when an endtimer is running/not running.
|
||||
enable-timer-specific-messages: true
|
||||
# If running an endtimer, the time left can be displayed by including '%TIMER%' in a ping message.
|
||||
timer-messages:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#fffff>Come back in:</gradient> <color:#aa55ee>%TIMER%"
|
||||
default:
|
||||
- "<red>Currently under maintenance<br><gradient:#fbffc2:#fffff>Come back in:</gradient> <color:#aa55ee>%TIMER%"
|
||||
|
||||
# If enabled, the message below will be shown in the top right corner of the server in the server list, where the player count would normally be displayed.
|
||||
# Same as the ping-message, you can define messages for different modes.
|
||||
# You can use '%ONLINE%' and '%MAX%' if you want to include the player count in a custom message (e.g. "Maintenance %ONLINE%/%MAX%").
|
||||
# DOES NOT SUPPORT RGB!
|
||||
player-count-message:
|
||||
enabled: true
|
||||
message: "<dark_red>Maintenance"
|
||||
messages:
|
||||
default: "<dark_red>Maintenance"
|
||||
# If set to true and an endtimer is currently running, the timer message will be used instead of the normal one.
|
||||
enable-timer-specific-message: false
|
||||
timer-message: "<dark_red>Come back in: <yellow>%TIMER%"
|
||||
timer-messages:
|
||||
default: "<dark_red>Come back in: <yellow>%TIMER%"
|
||||
|
||||
# Is shown when you move your mouse above the text in the top right corner of the server in the server list, where the player count would normally be displayed.
|
||||
# Same as the ping-message, you can define messages for different modes.
|
||||
# DOES NOT SUPPORT RGB!
|
||||
player-list-hover-message:
|
||||
enabled: true
|
||||
message: "<red>Currently under<br><red>maintenance"
|
||||
messages:
|
||||
default: "<red>Currently under<br><red>maintenance"
|
||||
# If set to true and an endtimer is currently running, the timer message will be used instead of the normal one.
|
||||
enable-timer-specific-message: false
|
||||
timer-message: "<red>Come back in:<br><red><yellow>%TIMER%"
|
||||
timer-messages:
|
||||
default: "<red>Come back in:<br><red><yellow>%TIMER%"
|
||||
|
||||
# Any extra commands inside the arrays will be executed when maintenance is enabled/disabled.
|
||||
# Example: commands-on-maintenance-enable: ["say hello!", "stop"]
|
||||
@@ -104,23 +131,27 @@ continue-endtimer-after-restart:
|
||||
# If using the timer command: In what intervalls before enabling/disabling maintenance there will be a broadcast.
|
||||
timer-broadcast-for-seconds: [1200, 900, 600, 300, 120, 60, 30, 20, 10, 5, 4, 3, 2, 1]
|
||||
|
||||
# If you have 2 or more proxy instances, the database connection will make sure all proxies
|
||||
# have the same maintenance status, so you won't have to enable/disable it on every proxy by hand.
|
||||
mysql:
|
||||
use-mysql: false
|
||||
host: host
|
||||
port: 3306
|
||||
database: database
|
||||
username: username
|
||||
password: password
|
||||
# Requests to the database will only be made at least x seconds after the last request,
|
||||
# so there won't be a request on every single ping on a server with many players.
|
||||
#
|
||||
# Set this to 0 to make a database request on (almost) every single ping.
|
||||
# (0 is not recommended if having more than a hundred concurrent players, then I'd recommend keeping it from 10-60).
|
||||
update-interval: 15
|
||||
# If you for some reason cannot establish SSL connections to your database, you may disable it here (not recommended).
|
||||
use-ssl: true
|
||||
# Allows sending a Discord webhook on certain events.
|
||||
webhook:
|
||||
enabled: false
|
||||
# Possible values: maintenance_status, starttimer_started, endtimer_started, blocked_join
|
||||
enabled-events: ["maintenance_status", "starttimer_started", "endtimer_started"]
|
||||
# Copy and paste the webhook url from Server Settings --> Apps Integrations --> Webhooks
|
||||
url: ""
|
||||
# The username displayed for the webhook bot message.
|
||||
username: "Maintenance"
|
||||
# The avatar URL used for the webhook bot message. Leave empty to use the default Discord webhook avatar.
|
||||
avatar-url: ""
|
||||
|
||||
# If you have 2 or more proxy instances, the Redis connection will make sure all proxies
|
||||
# have the same maintenance status (global as well as per server) and whitelisted players,
|
||||
# so you won't have to update these on every proxy by hand.
|
||||
redis:
|
||||
enabled: false
|
||||
# Make sure your Redis instance is properly protected.
|
||||
# URI format: redis[s]://[[username][:password]@][host][:port][/db-number]
|
||||
# E.g. an SSL connection to a password protected redis could look like this: "rediss://user:password@127.0.0.1:6379"
|
||||
uri: "redis://localhost:6379"
|
||||
|
||||
# If disabled, you will no longer receive any messages if there is an update.
|
||||
# Not recommended to disable, as new versions generally tend to run better and with fewer bugs.
|
||||
@@ -128,4 +159,4 @@ mysql:
|
||||
update-checks: true
|
||||
|
||||
# Used for autoupdating the config, do not change this value.
|
||||
config-version: 9
|
||||
config-version: 12
|
||||
@@ -0,0 +1,124 @@
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>No tens permís per executar aquesta ordre."
|
||||
kickmessage: "<red>El servidor està en manteniment!<br>Torna-ho a provar més tard!"
|
||||
maintenanceActivated: "<prefix><gold>El mode de manteniment s'ha activat."
|
||||
maintenanceDeactivated: "<prefix><gold>El mode de manteniment s'ha desactivat."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>El manteniment ja està activat!"
|
||||
alreadyDisabled: "<prefix><red>El manteniment ja està desactivat!"
|
||||
endtimerBroadcast: "<prefix><gray>El mode de manteniment es desactivarà en <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment es desactivarà en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El mode de manteniment s'activarà en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment s'activarà en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>El mode de manteniment s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>Ja hi ha un temporitzador programat!"
|
||||
timerNotRunning: "<prefix><red>No hi ha cap temporitzador en marxa."
|
||||
timerCancelled: "<prefix><red>S'ha cancel·lat el temporitzador actual."
|
||||
timerTooLong: "<prefix><red>La durada ha de ser inferior a 28 dies!"
|
||||
timerMotdDisabled: "<prefix><red>Has de configurar 'enable-timerspecific-messages' a 'true' al fitxer de configuració per utilitzar/editar missatges MOTD específics del temporitzador."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>ha intentat unir-se al servidor."
|
||||
motdList: "<prefix><gray>Llista dels teus missatges MOTD de manteniment:"
|
||||
motdListEmpty: "<prefix><red>No tens cap missatge MOTD de manteniment configurat!"
|
||||
reload: "<prefix><green>S'han recarregat la configuració, la llista de jugadors permitits, el fitxer d'idioma i la icona de manteniment."
|
||||
removedMotd: "<prefix><green>S'ha eliminat el missatge MOTD número %INDEX%."
|
||||
removeMotdError: "<prefix><red>Només tens un missatge MOTD, no en pots eliminar cap!"
|
||||
setMotd: "<prefix><green>S'ha configurat la línia %LINE% del missatge MOTD de manteniment %INDEX% a %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Actualment tens %MOTDS% missatges MOTD, has de triar un número entre 1 i %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>El segon argument ha de ser el número de línia (1 o 2)!"
|
||||
updateDownloading: "<prefix><red><bold>S'està descarregant l'actualització..."
|
||||
updateFailed: "<prefix><dark_red><bold>L'actualització ha fallat!"
|
||||
updateFinished: "<prefix><green><bold>L'actualització s'ha completat! Per evitar problemes amb tasques i completar l'actualització, has de reiniciar el servidor!"
|
||||
whitelistedPlayers: "<prefix><gold>Jugadors permesos durant el manteniment:"
|
||||
whitelistedPlayersFormat: "<dark_gray>- <yellow>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>S'ha afegit <aqua>%PLAYER% <green>a la llista blanca de manteniment!"
|
||||
whitelistAlreadyAdded: "<prefix><aqua>%PLAYER% <red>ja està a la llista blanca de manteniment!"
|
||||
whitelistRemoved: "<prefix><green>S'ha eliminat <aqua>%PLAYER% <green>de la llista blanca de manteniment!"
|
||||
whitelistNotFound: "<prefix><red>Aquest jugador no està a la llista blanca de manteniment!"
|
||||
whitelistEmpty: "<prefix><red>La llista blanca de manteniment està buida! Utilitza <yellow>/maintenance add <player/uuid> <red>per afegir algú!"
|
||||
playerNotFound: "<prefix><red>No s'ha trobat cap jugador amb aquest nom al servidor."
|
||||
playerNotFoundUuid: "<prefix><red>No s'ha trobat cap jugador amb aquesta UUID."
|
||||
playerNotOnline: "<prefix><red>No hi ha cap jugador en línia amb aquest nom."
|
||||
offlinePlayerFetchError: "<prefix><red>Hi ha hagut un error en obtenir les dades del jugador fora de línia. Torna-ho a provar més tard."
|
||||
invalidUuid: "<prefix><red>Format d'UUID no vàlid!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Se t'ha enviat a un servidor d'espera!"
|
||||
forceWaitingServer: "<prefix><red>No pots abandonar el servidor d'espera mentre el manteniment estigui actiu!"
|
||||
serverNotFound: "<prefix><red>No hi ha cap servidor amb aquest nom registrat al proxy!"
|
||||
singleTimerAlreadyRunning: "<prefix><red>Ja hi ha un temporitzador programat per a aquest servidor!"
|
||||
singleTimerCancelled: "<prefix><red>S'ha cancel·lat el temporitzador actual per al servidor <yellow>%SERVER%<red>."
|
||||
singleTimerNotRunning: "<prefix><red>No hi ha cap temporitzador en marxa per a aquest servidor."
|
||||
singleEndtimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% es desactivarà en <gold>%TIME%<gray>."
|
||||
singleEndtimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% es desactivarà en <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME%<gray>."
|
||||
singleStarttimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
singleScheduletimerStarted: "<prefix><green>Temporitzador iniciat: <gray>El mode de manteniment al servidor %SERVER% s'activarà en <gold>%TIME% <gray>i durarà <gold>%DURATION%<gray>."
|
||||
singleMaintenanceKick: "<prefix><red>El servidor %SERVER% està en manteniment! Torna-ho a provar més tard!"
|
||||
singleMaintenanceKickComplete: "<red>El servidor %SERVER% està en manteniment!<br>Pots tornar a connectar-te per anar a un altre servidor!"
|
||||
singleMaintenanceActivated: "<prefix><gold>El mode de manteniment s'ha activat al servidor <yellow>%SERVER%<gold>."
|
||||
singleMaintenanceDeactivated: "<prefix><gold>El mode de manteniment s'ha desactivat al servidor <yellow>%SERVER%<gold>."
|
||||
singleServerAlreadyEnabled: "<prefix><red>El manteniment ja està activat al servidor <yellow>%SERVER%<red>!"
|
||||
singleServerAlreadyDisabled: "<prefix><red>El manteniment ja està desactivat al servidor <yellow>%SERVER%<red>!"
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidors proxy que tenen el manteniment activat:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>No hi ha cap servidor proxy en manteniment."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "segon"
|
||||
seconds: "segons"
|
||||
minute: "minut"
|
||||
minutes: "minuts"
|
||||
hour: "hora"
|
||||
hours: "hores"
|
||||
helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MAX% <dark_gray>]========"
|
||||
helpPageNotFound: "<prefix><red>No hi ha cap pàgina amb aquest número!"
|
||||
helpNextPage: "<gray>Fes servir <aqua>/maintenance help %PAGE% <gray>per anar a la següent pàgina d'ajuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Si està actiu, cancel·la el temporitzador actual)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <desactivar en> <gray>(Després del temps indicat, p. ex. 1h5m, es desactivarà el manteniment)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <activar en> <gray>(Després del temps indicat, p. ex. 1h5m, s'activarà el manteniment)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <activar en> <durada del manteniment> <gray>(Després del temps indicat, p. ex. 1h5m, s'activarà el manteniment)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Activa el registre de depuració)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Extreu informació del servidor, útil per informes d'errors)"
|
||||
helpHelp: "<gold>/maintenance help [pàgina] <gray>(Mostra aquesta finestra d'ajuda)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Mostra els missatges MOTD de manteniment. Si s'especifica 'timer', es mostraran els MOTD del temporitzador)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <índex> <gray>(Elimina un missatge MOTD de manteniment. Si s'usa 'timer', s'eliminarà un missatge específic del temporitzador)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <índex> <1/2> <missatge> <gray>(Configura un missatge MOTD per al manteniment. Si s'usa 'timer', es configurarà un missatge específic del temporitzador)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recarrega el fitxer de configuració, la llista de permitits i la icona del servidor)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Descarrega la versió més recent del plugin al servidor)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Mostra tots els jugadors permitits durant el manteniment)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nom/uuid> <gray>(Afegeix el jugador a la llista de permitits del manteniment)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nom/uuid> <gray>(Elimina el jugador de la llista de permitits del manteniment)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <gray>(Si està actiu, cancel·la el temporitzador del servidor)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Mostra tots els servidors proxy en manteniment)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Du har ikke tilladelse til at udføre denne kommando."
|
||||
kickmessage: "<red>Serveren er i øjeblikket under vedligeholdelse!<br>Prøv igen senere!"
|
||||
maintenanceActivated: "<prefix><gold>Vedligeholdelsestilstand er nu aktiveret."
|
||||
maintenanceDeactivated: "<prefix><gold>Vedligeholdelsestilstand er nu deaktiveret."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Vedligeholdelsestilstand er allerede aktiveret!"
|
||||
alreadyDisabled: "<prefix><red>Vedligeholdelsestilstand er allerede deaktiveret!"
|
||||
endtimerBroadcast: "<prefix><gray>Vedligeholdelsestilstand vil blive deaktiveret om <gold>%TIME%<gray>."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Genindlæs konfigurationsfilen, hvidlistede spillere, sp
|
||||
removedMotd: "<prefix><green>Slet motd nummer %INDEX%."
|
||||
removeMotdError: "<prefix><red>Du har kun én motd, så du kan ikke slette nogen!"
|
||||
setMotd: "<prefix><green>Angiv linje %LINE% af %INDEX%. vedligeholdelses motd til %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Du har %MOTDS% motds, så du skal angive et nummer mellem 1 og %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Det andet argument skal være linjenummer (1 or 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Downloader opdatering..."
|
||||
@@ -44,7 +49,7 @@ whitelistEmpty: "<prefix><red>Vedligeholdelseshvidlisten er tom! Brug <yellow>/m
|
||||
playerNotFound: "<prefix><red>Ingen spillere med dette navn har spillet på denne server før."
|
||||
playerNotFoundUuid: "<prefix><red>Ingen spiller med den uuid kunne findes."
|
||||
playerNotOnline: "<prefix><red>Der er ingen spiller online med det navn."
|
||||
offlinePlayerFetchError: "<prefix><red>There was an error while fetching offline player. Please try again later."
|
||||
offlinePlayerFetchError: "<prefix><red>Der opstod en fejl under hentning af offline afspiller. Prøv igen senere."
|
||||
invalidUuid: "<prefix><red>Ugyldigt uuid-format!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Du er blevet sendt til en venteserver!"
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Vedligeholdelsestilstand er allerede
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxyservere, der har Vedligeholdelsestilstand aktiveret:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Der er ingen proxy-servere, der er under vedligeholdelse."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "sekund"
|
||||
seconds: "sekunder"
|
||||
minute: "minut"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [page] <gray>(Viser dette smukke hjælpevindu
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Viser den aktuelle vedligeholdelses motds. Hvis 'timer' er angivet, bliver dennes motds vist)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Sletter en vedligeholdelses motd. Hvis 'timer' er angivet, vil en tidsspecifik pingbesked blive slettet)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Angiver en motd for vedligeholdelsestilstand. Hvis 'timer' er angivet, vil en tidsspecifik pingbesked blive angivet)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Genindlæser konfigurationsfilen, hvidlisten og serverikonet)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Aktiverer/deaktiverer vedligeholdelsestilstand)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Downloader den nyeste version af plugin'et på din server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Viser alle hvidlistede spillere for vedligeholdelsestilstand)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Tilføjer spilleren til vedligeholdelseshvidlisten, så de kan forbinde til serveren, selvom vedligeholdelsestilstand er aktiveret)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Sletter spilleren fra vedligeholdelseshvidlisten)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Hvis timeren kører, vil den blive afbrudt)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Aktiverer/deaktiverer vedligeholdelsestilstand)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Viser alle proxyservere, der har Vedligeholdelsestilstand aktiveret)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Du hast nicht die erforderliche Berechtigung, um diesen Befehl auszuführen."
|
||||
kickmessage: "<red>Der Server befindet sich momentan im Wartungsmodus!<br>Bitte versuche es später nochmal!"
|
||||
maintenanceActivated: "<prefix><gold>Der Wartungsmodus ist jetzt aktiviert."
|
||||
maintenanceDeactivated: "<prefix><gold>Der Wartungsmodus ist nun deaktiviert."
|
||||
maintenanceStatusOn: "<prefix><gold>Wartungsmodus ist derzeit <green>aktiviert<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Wartungsmodus ist momentan <red>deaktiviert<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Wartungsmodus ist momentan <green>aktiviert <grey>und wird deaktiviert in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Wartungsmodus ist momentan <red>deaktiviert <grey>und wird aktiviert in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Der Wartungsmodus ist bereits aktiviert!"
|
||||
alreadyDisabled: "<prefix><red>Der Wartungsmodus ist bereits deaktiviert!"
|
||||
endtimerBroadcast: "<prefix><gray>Der Wartungsmodus wird deaktiviert in: <gold>%TIME%<gray>."
|
||||
@@ -26,9 +30,10 @@ joinNotification: "<prefix><yellow>%PLAYER% <red>hat versucht dem Server beizutr
|
||||
motdList: "<prefix><gray>Liste deiner Motds, die während Maintenance angezeigt werden:"
|
||||
motdListEmpty: "<prefix><red>Du hast keine Maintenance MOTDs gesetzt!"
|
||||
reload: "<prefix><green>Die Config, die Liste der Spieler die während Maintenance beitreten können, die Sprachdateien und das Icon, das während der Maintenance angezeigt wird, wurden reloaded."
|
||||
removedMotd: "<prefix><green>Removed motd number %INDEX%."
|
||||
removedMotd: "<prefix><green>Die %INDEX%. Maintenance MOTD wurde entfernt."
|
||||
removeMotdError: "<prefix><red>Du hast nur eine Maintenance MOTD eingestellt, daher kannst du auch keine entfernen!"
|
||||
setMotd: "<prefix><green>Die %LINE%. Zeile der %INDEX%. Maintenance MOTD wurde geändert zu: %MOTD%"
|
||||
setReason: "<prefix><green>Grund für die Wartung gesetzt auf: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Momentan gibt es %MOTDS% MOTDs, du musst also eine Zahl, die zwischen 1 und %NEWAMOUNT% liegt, wählen."
|
||||
setMotdLineError: "<prefix><red>Das zweite Argument des Befehls muss die Zeilennummer sein (1 oder 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Das Update wird heruntergeladen..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Der Wartungsmodus ist bereits aus auf
|
||||
singleServerMaintenanceList: "<prefix><gray>Unterserver, die im Wartungsmodus sind:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Es befindet sich momentan kein Unterserver im Wartungsmodus."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>startet in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>endet in <gold>%TIME%"
|
||||
second: "Sekunde"
|
||||
seconds: "Sekunden"
|
||||
minute: "Minute"
|
||||
@@ -84,21 +91,34 @@ helpScheduleTimer: "<gold>/maintenance scheduletimer <Aktiviere in> <Wartungsdau
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Aktiviert Debug Nachrichten in der Konsole)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Sammelt wichtige Informationen für Bugreports)"
|
||||
helpHelp: "<gold>/maintenance help [Seite] <gray>(Zeigt diese wunderschöne Hilfe)"
|
||||
helpMotd: "<gold>/maintenance motd [Timer] <gray>(Zeigt die momentan gesetzten Maintenance Motds an. Mit dem 'timer' Argument werden die timerspezifischen Motds angezeigt)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [Timer] <Index> <gray>(Entfernt eine Maintenance Motd. Mit dem 'timer' Argument wird eine timerspezifischen Motd entfernt)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [Timer] <Index> <1/2> <Nachricht> <gray>(Setzte eine Motd für den Wartungsmodus. Mit dem 'timer' Argument wird eine timerspezifische Motd gesetzt)"
|
||||
helpMotd: "<gold>/maintenance motd [Timer] [Modus] <gray>(Zeigt die momentan gesetzten Maintenance Motds an. Mit dem 'timer' Argument werden die timerspezifischen Motds angezeigt)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [Timer] [Modus] <Index> <gray>(Entfernt eine Maintenance Motd. Mit dem 'timer' Argument wird eine timerspezifischen Motd entfernt)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [Timer] [Modus] <Index> <1/2> <Nachricht> <gray>(Setzte eine Motd für den Wartungsmodus. Mit dem 'timer' Argument wird eine timerspezifische Motd gesetzt)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Setzt oder löscht den %REASON% Platzhalter)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Lädt Config, Language und Whitelist Dateien sowie das Maintenance Icon neu)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Aktiviert/deaktiviert den Wartungsmodus)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Zeigt den aktuellen Wartungsstatus und alle laufenden Timer an)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Aktiviert/deaktiviert den Wartungsmodus mit einem optionalen Anzeigemodus beim Aktivieren)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Sucht nach neuen Updates für das Plugin und lädt diese auf den Server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Zeigt alle gewhitelisteten Spieler für den Wartungsmodus an)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <Name/UUID> <gray>(Whitelistet einen Spieler für den Wartungsmodus, sodass dieser während Wartungen den Server betreten kann)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <Name/UUID> <gray>(Entfernt einen Spieler aus der Wartungsmodus Whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [Server] <gray>(Falls momentan ein Timer läuft, wird dieser abgebrochen)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [Server] <Deaktiviere in> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus deaktiviert)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [Server] <Aktiviere in> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus aktiviert)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [Server] <Starte in> <Wartungsdauer> <gray>(Sobald der Timer, bspw. 1h5m, abläuft wird der Wartungsmodus für die gegebene Länge aktiviert)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [Server] <gray>(Aktiviert/deaktiviert den Wartungsmodus)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Aktiviert/deaktiviert den Wartungsmodus global oder auf einem bestimmten Server mit optionalem Anzeigemodus beim Aktivieren)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Zeigt alle Server an, auf denen momentan der Wartungsmodus aktiviert ist)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Wartungsmodus aktiviert.**"
|
||||
webhookMaintenanceDeactivated: "**Wartungsmodus deaktiviert.**"
|
||||
webhookStarttimerStarted: "Der Wartungsmodus wird aktiviert in <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Der Wartungsmodus wird deaktiviert in <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Beitritt gesperrt: `%PLAYER%` hat versucht, während den Wartungsarbeiten beizutreten."
|
||||
webhookSingleMaintenanceActivated: "Der Wartungsmodus wurde aktiviert auf `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Der Wartungsmodus wurde deaktiviert auf `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Der Wartungsmodus wird aktiviert auf `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Der Wartungsmodus wird deaktiviert auf `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 4
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>You do not have the permission to execute that command."
|
||||
kickmessage: "<red>The server is currently under maintenance!<br>Try again later!"
|
||||
maintenanceActivated: "<prefix><gold>Maintenance mode is now activated."
|
||||
maintenanceDeactivated: "<prefix><gold>Maintenance mode is now deactivated."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Maintenance is already enabled!"
|
||||
alreadyDisabled: "<prefix><red>Maintenance is already disabled!"
|
||||
endtimerBroadcast: "<prefix><gray>Maintenance mode will be disabled in <gold>%TIME%<gray>."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Reloaded config, whitelistedplayers, language file and t
|
||||
removedMotd: "<prefix><green>Removed motd number %INDEX%."
|
||||
removeMotdError: "<prefix><red>You only have one motd, so you cannot remove any!"
|
||||
setMotd: "<prefix><green>Set line %LINE% of the %INDEX%. maintenance motd to %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>You currently have %MOTDS% motds, so you have to pick a number between 1 and %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>The second argument has to be the line number (1 or 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Downloading update..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Maintenance is already disabled on se
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxied servers, that have maintenance enabled:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>There are no proxied servers that are under maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "second"
|
||||
seconds: "seconds"
|
||||
minute: "minute"
|
||||
@@ -84,21 +91,34 @@ helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance du
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Enables some debug logging)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Dumps some server information, used for bug reports)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Shows this beautiful help window)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Removes a maintenance motd. If using 'timer' as an argument, a timerspecific pingmessage will be removed)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Sets a motd for maintenance mode. If using 'timer' as an argument, a timerspecific pingmessage will be set)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] [mode] <gray>(Lists maintenance motds. If 'timer' is used, timer-specific motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] [mode] <index> <gray>(Removes a maintenance motd in the selected mode)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] [mode] <index> <1/2> <message> <gray>(Sets a maintenance motd in the selected mode)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Reloads the config file, whitelist file and the server-icon)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Enables/disables maintenance mode)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Remotely downloads the newest version of the plugin onto your server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Shows all whitelisted players for the maintenance mode)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Removes the player from the maintenance whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(If running, the current timer will be aborted)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Enables/disables maintenance mode)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lists all proxied servers, that are currently under maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,39 +1,44 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<prefix><dark_red>No tienes permiso para ejecutar este comando."
|
||||
kickmessage: "<red>¡El servidor se encuentra en mantenimiento!<br>¡Intentalo de nuevo más tarde!"
|
||||
maintenanceActivated: "<prefix><gold>Mantenimiento <gray>activado."
|
||||
maintenanceDeactivated: "<prefix><gold>Modo mantenimiento desactivado."
|
||||
alreadyEnabled: "<prefix><gray>¡Modo mantenimiento se encuentra habilitado!"
|
||||
alreadyDisabled: "<prefix><gray>¡Modo mantenimiento se encuentra deshabilitado!"
|
||||
maintenanceActivated: "<prefix><gold>Modo Mantenimiento activado."
|
||||
maintenanceDeactivated: "<prefix><gold>Modo Mantenimiento desactivado."
|
||||
maintenanceStatusOn: "<prefix><gold>El modo de mantenimiento está actualmente <green>activado<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>El modo de mantenimiento está actualmente <red>desactivado<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>El modo de mantenimiento está actualmente <green>habilitado <grey>y se desactivará en <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>El modo de mantenimiento está actualmente <red>desactivado <grey>y se activará en <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>¡Modo mantenimiento ya está activado!"
|
||||
alreadyDisabled: "<prefix><red>¡Modo mantenimiento ya está desactivado!"
|
||||
endtimerBroadcast: "<prefix><gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El modo mantenimiento se habilitara en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
endtimerStarted: "<prefix><green>Temporizador iniciado: <gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Temporizador iniciado: <gray>El modo mantenimiento se activará en <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME% <gray>y durará <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><gray>Temporizador iniciado: El modo mantenimiento se activará en <gold>%TIME% <gray>y durará <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>Ya hay un temporizador programado!"
|
||||
timerNotRunning: "<prefix><gray>Actualmente no hay temporizador."
|
||||
timerAlreadyRunning: "<prefix><red>¡Ya hay un temporizador programado!"
|
||||
timerNotRunning: "<prefix><red>Actualmente no hay ningún temporizador."
|
||||
timerCancelled: "<prefix><red>El Temporizador actual ha sido deshabilitado."
|
||||
timerTooLong: "<prefix><gray>El numero debe ser menor a 40320 <dark_gray>(<gold>28 días<dark_gray>)"
|
||||
timerMotdDisabled: "<prefix><red>Tienes que configurar <green>'enable-timerspecific-messages'<red> en la configuración en <green>'true'<red>, si quieres usar / editar motdspecers específicos."
|
||||
timerTooLong: "<prefix><red>¡La duración debe ser menor a 28 días!"
|
||||
timerMotdDisabled: "<prefix><red>Debes configurar 'enable-timerspecific-messages' en la configuración a 'true', si quieres usar/editar motds por temporizador."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><red>%PLAYER% <gray>Intenta unirse al servidor."
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>intentó unirse al servidor."
|
||||
motdList: "<prefix><gray>Lista de motds de mantenimiento:"
|
||||
motdListEmpty: "<prefix><red>¡No tiene ningún motd(s<dark_gray>) de mantenimiento establecido!"
|
||||
motdListEmpty: "<prefix><red>¡No tienes ningún motd(s) de mantenimiento establecido!"
|
||||
reload: "<prefix><green>Configuracion recargada"
|
||||
removedMotd: "<prefix><green>Numero de motd eliminado <gold>%INDEX%<green>."
|
||||
removeMotdError: "<prefix>&Solo tienes un motd, por lo que no puedes eliminar ninguno!"
|
||||
setMotd: "<prefix><green>Establecer linea <gold>%LINE%<green> sobre <gold>%INDEX%<green>. Para mantenimiento para %MOTD%"
|
||||
setReason: "<prefix><green>Se estableció el motivo de mantenimiento a: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><green>Actualmente tiene <gold>%MOTDS%<green> Motd(s<dark_gray>), por lo que debe elegir un número entre 1 y %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><gray>El segundo argumento tiene que ser el numero de línea.(1 ó 2<dark_gray>)!"
|
||||
updateDownloading: "<prefix><green>Descargando actualización..."
|
||||
updateFailed: "<prefix><red>Actualizacion fallida!"
|
||||
updateFinished: "<prefix><green>La actualización fue exitosa!, debes reiniciar el servidor!"
|
||||
updateFinished: "<prefix><green><bold>The update was successful! To prevent issues with tasks and to complete the update, you have to restart the server!"
|
||||
whitelistedPlayers: "<prefix><gold>Jugadores en lista blanca:"
|
||||
whitelistedPlayersFormat: "<gray>- <green>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>%PLAYER% <gray>Añadido a la lista de mantenimiento!"
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><gray>El modo mantenimiento se encuentra d
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidores proxy, que tienen habilitado el mantenimiento:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>No hay servidores proxy que están en mantenimiento."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <yellow>Abriendo <grey>%SERVER% <yellow>en <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <yellow>Cerrando <aqua>%SERVER% <yellow>en <gold>%TIME%"
|
||||
second: "Segundo"
|
||||
seconds: "Segundos"
|
||||
minute: "Minuto"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><gray>No hay pagina con ese número."
|
||||
helpNextPage: "<gray>Utilice <aqua>/maintenance help %PAGE% <gray>Para pasar a la siguiente ventana de ayuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <dark_gray>(<gray>Si se ejecuta, se abortará el temporizador actual<dark_gray>)"
|
||||
helpEndtimer: ""
|
||||
helpStarttimer: ""
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray> (Después del tiempo establecido, ej. 1h5m, el modo de mantenimiento será desactivado)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(Después del tiempo indicado, ej: 1h5m, El modo mantenimiento se habilita.)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(Después del tiempo indicado, ej. 1h5m, el modo mantenimiento se habilitará.)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Activa algunos registros de depuración)"
|
||||
helpDump: "<gold>/maintenance dump <dark_gray>(<gray>Descarga información del servidor, usada para informes de errores<dark_gray>)"
|
||||
helpHelp: "<gold>/maintenance help [page] <dark_gray>(<gray>Muestra la pagina de ayuda<dark_gray>)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <dark_gray>(<gray>Enumera los motivos de mantenimiento establecidos actualmente. Si se especifica el 'temporizador', se muestran los motivos del temporizador<dark_gray>)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <dark_gray>(<gray>Elimina un mantenimiento motd. Si se usa 'timer' como argumento, se eliminará un pingmessage de temporizador específico<dark_gray>)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <dark_gray>(<gray>Establece un motd para el modo de mantenimiento. Si usa 'timer' como argumento, se establecerá un mensaje de ping específico para el tiempo<dark_gray>)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Configura o reestablece el valor por defecto de %REASON%)"
|
||||
helpReload: "<gold>/maintenance reload <dark_gray>(<gray>Vuelve a cargar el archivo de configuración, el archivo de la lista blanca y el ícono del servidor<dark_gray>)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <dark_gray>(<gray>Habilita / deshabilita el modo de mantenimiento<dark_gray>)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Muestra el estado de mantenimiento actual y cualquier temporizador activo)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Habilita/desactiva el modo de mantenimiento con un modo de visualización opcional al habilitar)"
|
||||
helpUpdate: "<gold>/maintenance update <dark_gray>(<gray>Descarga de forma remota la versión más reciente del complemento en su servidor<dark_gray>)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <dark_gray>(<gray>Muestra todos los jugadores en lista blanca para el modo de mantenimiento<dark_gray>)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <dark_gray>(<gray>Agrega al jugador a la lista blanca de mantenimiento, para que puedan unirse al servidor aunque el mantenimiento esté habilitado<dark_gray>)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <dark_gray>(<gray>Quita al jugador de la lista blanca de mantenimiento<dark_gray>)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <dark_gray>(<gray>Si está funcionando, se abortará el temporizador actual<dark_gray>)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <dark_gray>(<gray>Habilita / deshabilita el modo de mantenimiento<dark_gray>)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [servidor|global] [mode] <gray> (Habilita/desactiva el modo de mantenimiento globalmente o en un servidor específico con un modo de visualización opcional al habilitar)"
|
||||
helpStatus: "<gold>/maintenance status <dark_gray>(<gray>Enumera todos los servidores proxy, que están actualmente en mantenimiento<dark_gray>)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Modo de mantenimiento activado.**"
|
||||
webhookMaintenanceDeactivated: "**Modo de mantenimiento desactivado.**"
|
||||
webhookStarttimerStarted: "<prefix><gray>El modo mantenimiento se activará en <gold>%TIME%<gray>`)."
|
||||
webhookEndtimerStarted: "<prefix><gray>El modo mantenimiento se desactivará en <gold>%TIME%<gray>`)."
|
||||
webhookJoinNotification: "Bloqueado: `%PLAYER%` intentó unirse durante el mantenimiento."
|
||||
webhookSingleMaintenanceActivated: "Modo de mantenimiento activado en %SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Modo de mantenimiento desactivado en `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "El modo de mantenimiento se activará en `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "El modo de mantenimiento se desactivará en `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Vous n'avez pas la permission d'exécuter cette commande."
|
||||
kickmessage: "<red>Le serveur est actuellement en maintenance !<br>Réessayez plus tard !"
|
||||
maintenanceActivated: "<prefix><gold>Le mode maintenance est maintenant activé."
|
||||
maintenanceDeactivated: "<prefix><gold>Le mode maintenance est maintenant désactivé."
|
||||
maintenanceStatusOn: "<prefix><gold>Le mode maintenance est actuellement <green>activé<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Le mode maintenance est actuellement <red>désactivé<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Le mode maintenance est actuellement <green>activé<grey> et sera désactivé dans <gold>%TIME%"
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Le mode maintenance est actuellement <red>désactivé<grey> et sera activé dans <gold>%TIME%"
|
||||
alreadyEnabled: "<prefix><red>La maintenance est déjà activée !"
|
||||
alreadyDisabled: "<prefix><red>La maintenance est déjà désactivée !"
|
||||
endtimerBroadcast: "<prefix><gray>Le mode maintenance sera désactivé dans <gold>%TIME%<gray>."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Fichier de configuration, liste blanche (whitelist) des
|
||||
removedMotd: "<prefix><green>Numéro de motd supprimé %INDEX%."
|
||||
removeMotdError: "<prefix><red>Vous n’avez qu’un motd, vous ne pouvez donc pas en supprimer !"
|
||||
setMotd: "<prefix><green>Ligne %LINE% du motd %INDEX%. fixée à %MOTD%"
|
||||
setReason: "<prefix><green>Raison de la maintenance configurée à : <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Vous avez actuellement %MOTDS% motd(s), vous devez donc choisir un nombre compris entre 1 et %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Le deuxième argument doit être le numéro de ligne (1 ou 2) !"
|
||||
updateDownloading: "<prefix><red><bold>Téléchargement de la mise à jour..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>La maintenance est déjà désactivé
|
||||
singleServerMaintenanceList: "<prefix><gray>Serveurs proxy ayant la maintenance activée :"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Il n'y a pas de serveurs proxy en maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>comme dans <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>termine dans <gold>%TIME%"
|
||||
second: "seconde"
|
||||
seconds: "secondes"
|
||||
minute: "minute"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [page] <gray>(Montre cette belle fenêtre d'a
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Répertorie les paramètres de maintenance actuellement définis. Si vous spécifiez 'timer', les mots de la minuterie seront affichés)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Supprime un motd de maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique au temporisateur sera supprimé)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Définit un motd pour le mode maintenance. Si vous utilisez 'timer' comme argument, un message ping spécifique à un temporisateur sera défini)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(définit ou efface la valeur du placeholder %REASON%)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recharge le fichier de configuration, la liste blanche, le fichier de langue et l'icône du serveur)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Active/désactive le mode maintenance)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Affiche les états de maintenance et les minuteurs actifs)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Active/désactive le mode maintenance)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Télécharge la dernière version du plugin sur votre serveur)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Affiche les joueurs de la liste blanche pour le mode maintenance)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Ajoute un joueur à la liste blanche de maintenance afin qu'il puisse rejoindre le serveur même si la maintenance est activée)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Supprime un joueur de la liste blanche de maintenance)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Si en cours d'exécution, le minuteur actuel sera abandonné)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [serveur] <activer dans> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera désactiver)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [serveur] <activer dans> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera activé)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [serveur] <activer dans> <durée de maintenance> <gray>(Après le temps imparti, ex. 1h5m, le mode maintenance sera activé)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Active/désactive le mode maintenance)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Active/désactive le mode maintenance globalement, ou sur un serveur spécifique avec un mode d'affichage facultatif lors de l'activation)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Répertorie tous les serveurs mandatés actuellement en maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "\n\n**Mode maintenance activé.**"
|
||||
webhookMaintenanceDeactivated: "\n\n**Mode maintenance désactivé.**"
|
||||
webhookStarttimerStarted: "Le mode maintenance sera activé dans <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookEndtimerStarted: "Le mode maintenance sera désactivé dans <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookJoinNotification: "Connexion bloquée : `%PLAYER%` a cherché à rejoindre durant une maintenance."
|
||||
webhookSingleMaintenanceActivated: "Mode maintenance activé sur `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Mode maintenance désactivé sur `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Le mode maintenance sera activé sur `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Le mode maintenance sera désactivé sur `%SERVER%` <t:%TIMESTAMP%:R>(`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Nincs engedélyed a parancs használatához."
|
||||
kickmessage: "<red>A szerver karbantartás alatt áll!<br>Próbáld újra később!"
|
||||
maintenanceActivated: "<prefix><gold>Karbantartás elindítva."
|
||||
maintenanceDeactivated: "<prefix><gold>Karbantartás befejezve."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Már engedélyezve van!"
|
||||
alreadyDisabled: "<prefix><red>Már le van tiltva!"
|
||||
endtimerBroadcast: "<prefix><gray>Felléphetsz <gold>%TIME%<gray> múlva."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Újratöltve."
|
||||
removedMotd: "<prefix><green>Motd szám törölve: %INDEX%."
|
||||
removeMotdError: "<prefix><red>Csak egy motd van,nem törölheted!"
|
||||
setMotd: "<prefix><green>Sor %LINE% beállítva %INDEX%-re. motd %MOTD%-ra"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Csak %MOTDS%-d van, úgyhogy válassz egy számot 1 és %NEWAMOUNT% között."
|
||||
setMotdLineError: "<prefix><red>Ennek egy sornak kell lennie (1 vagy 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Frissítés letöltése..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>A karbantartás már le van tiltva a(
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxy szerverek,karbantartási móddal engedélyezve:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nincsenek proxy szerverek karbantartás alatt."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "másodperc"
|
||||
seconds: "másodperc"
|
||||
minute: "perc"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Nincs ilyen oldal!"
|
||||
helpNextPage: "<gray>Használd a <aqua>/maintenance help %PAGE% <gray>parancsot,hogy lapozz."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Az időzítő,ha fut nem lesz figelembe vévve)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(Azután a megadott időben pl. 1h5m, a karbantartásnak vége lesz)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(Azután a megadott időben pl. 1h5m, karbantartás elkezdödik)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(Azután a megadott időben pl. 1h5m, a karbantartás elkezdödik)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Hibakeresés bekapcsolása)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(A hibajelentési előzményeket törli)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Megjelenítí a segítség ablakot)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Megjeleníti a motd-ket)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Törli a megadott motd-t)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Beállít egy motd-t)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Újratölti a plugint)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Karbantartás mód ki-be kapcsolása)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Frissíti a plugin verziót)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Megmutatja a karbantartás fehérlistázottak listáját)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Hozzáadja a játékost a karbantartás fehérlistához)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Kitörli a játékost a karbantartás fehérlistáról)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Ha van karbantartás,akkor figyelmen kívül veszi az időzítőt)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Ki-be kapcsolja a karbantartás módot)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Kiírja az összes proxy szervert, ami karbantartás alatt van)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,19 +1,23 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Non hai i permessi necessari per eseguire quel comando."
|
||||
noPermission: "<red>Non hai il permesso per eseguire questo comando."
|
||||
kickmessage: "<red>Il server è momentaneamente in manutenzione!<br>Riprova più tardi!"
|
||||
maintenanceActivated: "<prefix><gold>Modalità manutenzione ora attivata."
|
||||
maintenanceDeactivated: "<prefix><gold>Modalità manutenzione ora disattivata."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>La modalità manutenzione è già attiva!"
|
||||
alreadyDisabled: "<prefix><red>La modalità mantenzione è già disattivata!"
|
||||
alreadyDisabled: "<prefix><red>La modalità manutenzione è già disattivata!"
|
||||
endtimerBroadcast: "<prefix><gray>La modalità manutenzione verrà disattivata tra <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione verrà disattivata tra <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>La modalità manutenzione verrà attivata tra <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione verrà attivata tra <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>La modalità manutenzione sarà abilitata tra <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Timer avviato: la modalità di manutenzione <gray>sarà abilitata in <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>C'è già un timer programmato!"
|
||||
timerNotRunning: "<prefix><red>Non c'è nessun timer attivo al momento."
|
||||
@@ -23,18 +27,19 @@ timerMotdDisabled: "<prefix><red>Devi impostare 'enable-timerspecific-messages'
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>ha tentato di accedere al server."
|
||||
motdList: "<prefix><gray>Lista delle tue motds di manutenzione:"
|
||||
motdListEmpty: "<prefix><red>Non hai ancora nessuna motds di manutenzione!"
|
||||
reload: "<prefix><green>Ricaricata config, whitelistedplayers, file dei linguaggi e la icona di manutenzione."
|
||||
removedMotd: "<prefix><green>Rimossa motd numero %INDEX%."
|
||||
removeMotdError: "<prefix><red>Hai soltanto una motd, quindi non puoi rimuoverla!"
|
||||
setMotd: "<prefix><green>Impostata linea %LINE% in %INDEX%. motd manutenzione a %MOTD%"
|
||||
setMotdIndexError: "<prefix><red>Hai attualmente %MOTDS% motds, quindi devi scegliere un numero fra 1 e %NEWAMOUNT%."
|
||||
motdList: "<prefix><gray>Lista delle tue MOTD di manutenzione:"
|
||||
motdListEmpty: "<prefix><red>Non hai ancora nessuna MOTD di manutenzione!"
|
||||
reload: "<prefix><green>Ricaricata config, whitelistedplayers, file dei linguaggi e l'icona di manutenzione."
|
||||
removedMotd: "<prefix><green>Rimossa MOTD numero %INDEX%."
|
||||
removeMotdError: "<prefix><red>Hai soltanto una MOTD, quindi non puoi rimuoverla!"
|
||||
setMotd: "<prefix><green>Impostata MOTD di manutenzione numero %INDEX%, linea %LINE% a: %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Hai attualmente %MOTDS% MOTD, devi scegliere un numero tra 1 e %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Il secondo argomento deve corrispondere alla linea (1 o 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Scaricando aggiornamento..."
|
||||
updateDownloading: "<prefix><red><bold> Sto scaricando l'aggiornamento..."
|
||||
updateFailed: "<prefix><dark_red><bold>Aggiornamento non riuscito!"
|
||||
updateFinished: "<prefix><green><bold>L'aggiornamento è completato! Per prevenire problemi e completare l'aggiornamento dovresti riavviare il server!"
|
||||
whitelistedPlayers: "<prefix><gold>Player in whitelist per la manutenzione:"
|
||||
whitelistedPlayers: "<prefix><gold>Giocatori in whitelist per la manutenzione:"
|
||||
whitelistedPlayersFormat: "<dark_gray>- <yellow>%NAME% <dark_gray>(<gray>%UUID%<dark_gray>)"
|
||||
whitelistAdded: "<prefix><green>Aggiunto <aqua>%PLAYER% <green>alla whitelist della manutenzione!"
|
||||
whitelistAlreadyAdded: "<prefix><aqua>%PLAYER% <red>è già nella whitelist della manutenzione!"
|
||||
@@ -42,32 +47,34 @@ whitelistRemoved: "<prefix><green>Rimosso <aqua>%PLAYER% <green>dalla lista dell
|
||||
whitelistNotFound: "<prefix><red>Questo giocatore non fa parte della whitelist della manutenzione!"
|
||||
whitelistEmpty: "<prefix><red>La whitelist di manutenzione è vuota! Usa <yellow>/maintenance add <player/uuid> <red>per aggiungere qualcuno!"
|
||||
playerNotFound: "<prefix><red>Nessun giocatore con questo username è mai entrato nel server."
|
||||
playerNotFoundUuid: "<prefix><red>Nessun player con quell'uuid è stato trovato."
|
||||
playerNotFoundUuid: "<prefix><red>Nessun giocatore con quell'uuid è stato trovato."
|
||||
playerNotOnline: "<prefix><red>Non c'è nessun giocatore online con quell'username."
|
||||
offlinePlayerFetchError: "<prefix><red>C'è stato un errore cercando il player offline. Riprova più tardi."
|
||||
offlinePlayerFetchError: "<prefix><red>C'è stato un errore cercando il giocatore offline. Riprova più tardi."
|
||||
invalidUuid: "<prefix><red>L'uuid presenta un formato invalido!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Sei stato inviato su un server d'attesa!"
|
||||
forceWaitingServer: "<prefix><red>Non puoi abbandonare il server d'attesa durante una manutenzione!"
|
||||
serverNotFound: "<prefix><red>Nessun server con questo nome è registrato sulla proxy!"
|
||||
serverNotFound: "<prefix><red>Nessun server con questo nome è registrato sul proxy server!"
|
||||
singleTimerAlreadyRunning: "<prefix><red>È già presente un timer pianificato per quel server!"
|
||||
singleTimerCancelled: "<prefix><red>Il timer attuale per il server <yellow>%SERVER% <red>è stato rimosso."
|
||||
singleTimerNotRunning: "<prefix><red>Non c'è nessun timer correntemente attivo per quel server."
|
||||
singleEndtimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà disabilitata tra <gold>%TIME%<gray>."
|
||||
singleEndtimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione per il server %SERVER% verrà disattivata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà disabilitata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>La modalità manutenzione per il server %SERVER% verrà attivata tra <gold>%TIME%<gray>."
|
||||
singleStarttimerStarted: "<prefix><green>Timer avviato: <gray>La modalità manutenzione per il server %SERVER% verrà attivata tra <gold>%TIME%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>Maintenance mode on server %SERVER% will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>La modalità manutenzione sul server %SERVER% sarà abilitata tra <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
singleScheduletimerStarted: "<prefix><green>Timer avviato: <gray>Modalità di manutenzione sul server %SERVER% sarà attivato in <gold>%TIME% <gray>e durerà per <gold>%DURATION%<gray>."
|
||||
singleMaintenanceKick: "<prefix><red>Il server %SERVER% è in manutenzione al momento! Ritenta più tardi!"
|
||||
singleMaintenanceKickComplete: "<red>Il server %SERVER% è in manutenzione!<br>Prova a rientrare per accedere ad un'altro server!"
|
||||
singleMaintenanceKickComplete: "<red>Il server %SERVER% è in manutenzione!<br>Prova a rientrare per accedere a un altro server!"
|
||||
singleMaintenanceActivated: "<prefix><gold>La modalità manutenzione è ora attiva sul server <yellow>%SERVER%<gold>."
|
||||
singleMaintenanceDeactivated: "<prefix><gold>La modalità manutenzione è ora disattivata sul server <yellow>%SERVER%<gold>."
|
||||
singleServerAlreadyEnabled: "<prefix><red>La modalità manutenzione è già attiva sul server <yellow>%SERVER%<red>!"
|
||||
singleServerAlreadyDisabled: "<prefix><red>La modalità manutenzione è già disattivata sul server <yellow>%SERVER%<red>!"
|
||||
singleServerMaintenanceList: "<prefix><gray>Servers sotto proxy che hanno la modalità manutenzione attiva:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nessun server sotto proxy ha la modalità manutenzione attiva."
|
||||
singleServerMaintenanceList: "<prefix><gray>Server collegati con manutenzione attiva:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Nessun server sotto proxy server ha la modalità manutenzione attiva."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "secondo"
|
||||
seconds: "secondi"
|
||||
minute: "minuto"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Non c'è alcuna pagina con quel numero!"
|
||||
helpNextPage: "<gray>Usa <aqua>/maintenance help %PAGE% <gray>per andare alla prossima pagina d'aiuto."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Se attivo, l'attuale timer verrà fermato)"
|
||||
helpEndtimer: ""
|
||||
helpStarttimer: "x"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Enables some debug logging)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <tempo di disattivazione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà disattivata)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <tempo di attivazione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà attivata)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <tempo di attivazione> <durata manutenzione> <gray>(Dopo il tempo specificato, es. 1h5m, la modalità manutenzione verrà attivata e durerà per il tempo indicato)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Attiva la registrazione di debug)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Copia alcune informazioni dal server, usato per segnalare problemi)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(Mostra questa fantastica pagina d'aiuto)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Elenca le attuali motds di manutenzione impostate. Se specifichi 'timer', verranno mostrati i motds dei timer)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Rimuove una motd di manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà rimosso)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Imposta il motd per la manutenzione. Se specifichi 'timer' come argomento, un messaggio specifico al timer verrà impostato)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Ricarica il file di configurazione, whitelist server e icona)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Abilita/Disabilita modalità manutenzione)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Scarica dall'esterno l'ultima versione del plugin nel server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Elenca tutti i giocatori nella whitelist per la manutenzione)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Aggiunge il giocatore alla whitelist di manutenzione, così possono entrare in un server durante la manutenzione)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Rimuovi il player dalla whitelist della manutenzione)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Rimuovi il giocatore dalla whitelist della manutenzione)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Se attivo, il timer attuale verrà fermato)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Abilita/disabilita la modalità di manutenzione)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Elenca tutti i server sotto proxy che hanno la modalità manutenzione attiva)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>このコマンドを実行する権限がありません。"
|
||||
kickmessage: "<red>メンテナンス中です。<br>しばらくたってから、もう一度お試しください"
|
||||
maintenanceActivated: "<prefix><green>メンテナンスを有効にしました。"
|
||||
maintenanceDeactivated: "<prefix><yellow>メンテナンスを解除しました。"
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>メンテナンスは既に有効です。"
|
||||
alreadyDisabled: "<prefix><red>メンテナンスは既に解除されています。"
|
||||
endtimerBroadcast: "<prefix><gray>メンテナンスモードは、<gold>%TIME%<gray>で無効になります。"
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>再読み込みが完了しました。"
|
||||
removedMotd: "<prefix><green>motd番号%INDEX%を削除しました。"
|
||||
removeMotdError: "<prefix><red>motdは1つしかないので、削除することはできません。"
|
||||
setMotd: "<prefix><greenINDEX%.の行 %LINE% を %MOTD% に設定します。"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>現在、%MOTDS%のMOTDを持っているので、1から%NEWAMOUNT%の間の数字を選ぶ必要があります。"
|
||||
setMotdLineError: "<prefix><red>第2引数には、行番号(1または2)を指定する必要があります。"
|
||||
updateDownloading: "<prefix><red><bold>アップデートをダウンロード中です..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><yellow>%SERVER%<red> のメンテナン
|
||||
singleServerMaintenanceList: "<prefix><gray>プロキシサーバーで、メンテナンスが有効になっているもの: "
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>メンテナンス中のプロキシサーバーはありません。"
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "秒"
|
||||
seconds: "秒"
|
||||
minute: "分"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>その番号のページがありません。"
|
||||
helpNextPage: "<gray>Use <aqua>/maintenance help %PAGE% <gray>で次のヘルプウィンドウに移動します。"
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(タイマーを実行していた場合、タイマーの実行を中止します。)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(指定された時間(例えば1時間5分)が経過すると、メンテナンス・モードは無効になる)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(指定された時間後、例えば1時間5分後にメンテナンス・モードが有効になる)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(指定された時間(例えば1時間5分)が経過すると、メンテナンスモードが有効になる)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(デバッグロギングを有効にします。)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(バグレポートに使用される、いくつかのサーバ情報をダンプします。)"
|
||||
helpHelp: "<gold>/maintenance help [page] <gray>(このようなヘルプページが表示されます。)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(現在設定されているメンテナンスMOTDを一覧表示します。'timer'を指定した場合は、タイマーの場合のMOTDを表示します。)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(メンテナンスの場合に使用されるMOTDを削除します。引数として'timer'を使用した場合にはタイマー固有のピングメッセージが表示されます。)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(メンテナンスの場合に使用されるMOTDを設定します。引数として'timer'を使用した場合にはタイマー固有のピングメッセージが表示されます。)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(設定ファイル、ホワイトリストファイル、サーバーアイコンを再読み込みします。)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(メンテナンスモードの有効/解除を設定します。)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(最新版のプラグインをサーバーにリモートでダウンロードします。)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(メンテナンスモードのホワイトリストに登録されているすべてのプレーヤーを表示します。)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(メンテナンスのホワイトリストにユーザーを追加し、メンテナンスが有効な状態でもサーバーに参加できるようにします。)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(メンテナンスのホワイトリストからプレーヤーを削除します。)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(もし、タイマーが実行中の場合、現在のタイマーを中止します。)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(メンテナンスモードの有効化/無効化を設定します。)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(現在メンテナンス中のプロキシサーバーをすべてリストアップします。)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>권한이 없습니다."
|
||||
kickmessage: "<red>서버가 현재 점검 중입니다!<br>나중에 다시 시도하세요!"
|
||||
maintenanceActivated: "<prefix><gold>유지 관리 모드가 활성화되었습니다."
|
||||
maintenanceDeactivated: "<prefix><gold>유지 관리 모드가 비활성화되었습니다."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>유지 관리가 이미 활성화되었습니다!"
|
||||
alreadyDisabled: "<prefix><red>유지보수가 이미 비활성화되었습니다!"
|
||||
endtimerBroadcast: "<prefix><gray>유지 관리 모드는<gold>%TIME%<gray>에 비활성화됩니다.."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>설정, 화이트리스트 플레이어, 언어 파일
|
||||
removedMotd: "<prefix><green>%INDEX%번째 motd를 삭제했습니다."
|
||||
removeMotdError: "<prefix><red>motd가 하나만 있으므로 제거할 수 없습니다!"
|
||||
setMotd: "<prefix><green>INDEX%의 %LINE% 줄을 %MOTD%로 설정합니다."
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>현재 %MOTDS% motd가 있으므로 1에서 %NEWAMOUNT% 사이의 숫자를 선택해야 합니다."
|
||||
setMotdLineError: "<prefix><red>두 번째 인수는 줄 번호(1 또는 2)여야 합니다!"
|
||||
updateDownloading: "<prefix><red><bold>업데이트 다운로드 중..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Maintenance is already disabled on se
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxied servers, that have maintenance enabled:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>There are no proxied servers that are under maintenance."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "second"
|
||||
seconds: "seconds"
|
||||
minute: "minute"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [page] <gray>(Shows this beautiful help windo
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Lists the currently set maintenance motds. If specifying 'timer', the timer motds are shown)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Removes a maintenance motd. If using 'timer' as an argument, a timerspecific pingmessage will be removed)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <message> <gray>(Sets a motd for maintenance mode. If using 'timer' as an argument, a timerspecific pingmessage will be set)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Reloads the config file, whitelist file and the server-icon)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Enables/disables maintenance mode)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Remotely downloads the newest version of the plugin onto your server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Shows all whitelisted players for the maintenance mode)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <name/uuid> <gray>(Adds the player to the maintenance whitelist, so they can join the server even though maintenance is enabled)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <name/uuid> <gray>(Removes the player from the maintenance whitelist)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(If running, the current timer will be aborted)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Enables/disables maintenance mode)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lists all proxied servers, that are currently under maintenance)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,14 +1,18 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Prace techniczne<dark_gray>] "
|
||||
noPermission: "<red>Nie posiadasz permisji na użycie tej komendy."
|
||||
kickmessage: "<red>Serwer jest w trakcie przerwy technicznej!<br>Spróbuj ponownie później!"
|
||||
maintenanceActivated: "<prefix><gold>Tryb konserwacji włączony."
|
||||
maintenanceDeactivated: "<prefix><gold>Tryb konserwacji wyłączony."
|
||||
alreadyEnabled: "<prefix><red>Przerwa techniczna już jest włącznona!"
|
||||
alreadyDisabled: "<prefix><red>Przerwa techniczna już jest wyłącznona!"
|
||||
maintenanceStatusOn: "<prefix><gold>Tryb konserwacji jest obecnie <green>włączony<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Tryb konserwacji jest obecnie <red>wyłączony<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Tryb konserwacji jest obecnie <green>włączony <grey>i zostanie wyłączony za <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Tryb konserwacji jest obecnie <red>wyłączony <grey>i zostanie włączony za <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Tryb konserwacji jest już włączony!"
|
||||
alreadyDisabled: "<prefix><red>Tryb konserwacji jest już wyłączony!"
|
||||
endtimerBroadcast: "<prefix><gray>Przerwa techniczna zostanie zakończona za <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Rozpoczęto timer: <gray>Tryb konserwacji zostanie wyłączony za <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>Przerwa techniczna zacznie się za <gold>%TIME%<gray>."
|
||||
@@ -18,7 +22,7 @@ scheduletimerStarted: "<prefix><green>Rozpoczęto timer: <gray>Przerwa techniczn
|
||||
timerAlreadyRunning: "<prefix><red>Timer został już zaplanowany!"
|
||||
timerNotRunning: "<prefix><red>Aktualnie nie ma żadnego działającego timera."
|
||||
timerCancelled: "<prefix><red>Bieżący timer został anulowany."
|
||||
timerTooLong: "<prefix><red>Liczba musi byc mniejsz niż 40320 (28 dni)!"
|
||||
timerTooLong: "<prefix><red>Podany czas musi być krótszy niż 28 dni!"
|
||||
timerMotdDisabled: "<prefix><red>Musisz ustawić 'enable-timerspecific-messages' w konfiguracji na 'true', jeśli chcesz używać motd z timerem."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Ponownie załadowano plik konfiguracji, białą listę,
|
||||
removedMotd: "<prefix><green>Usunięto motd numer %INDEX%."
|
||||
removeMotdError: "<prefix><red>Masz tylko jedno motd, którego nie możesz usunąć!"
|
||||
setMotd: "<prefix><green>Ustawiono wiersz %LINE% od %INDEX%. motd konserwacji na %MOTD%"
|
||||
setReason: "<prefix><green>Ustawiono powód konserwacji na: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Masz aktualnie %MOTDS% motd, więc musisz wybrać liczbę między 1 a %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Drugi argument musi być numerem lini (1 lub 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Pobieranie aktualizacji..."
|
||||
@@ -44,7 +49,7 @@ whitelistEmpty: "<prefix><red>Biała lista konserwacji jest pusta! Użyj <yellow
|
||||
playerNotFound: "<prefix><red>Ten gracz nigdy nie grał na serwerze."
|
||||
playerNotFoundUuid: "<prefix><red>Nie można znaleźć gracza z tym uuid."
|
||||
playerNotOnline: "<prefix><red>Nie ma gracza online z tym nickiem."
|
||||
offlinePlayerFetchError: ""
|
||||
offlinePlayerFetchError: "<prefix><red>Wystąpił błąd podczas pobierania gracza offline. Spróbuj ponownie później."
|
||||
invalidUuid: "<prefix><red>Nieprawidłowy format uuid!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<prefix><red>Zostałeś wysłany do poczekalni!"
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Tryb konserwacji jest już wyłączon
|
||||
singleServerMaintenanceList: "<prefix><gray>Serwery z włączonym trybem konserwacji:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Brak serwerów pod nadzorem."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>zaczyna się za <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>kończy się za <gold>%TIME%"
|
||||
second: "sekunda"
|
||||
seconds: "sekund"
|
||||
minute: "minuta"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Strona z tym numerem nie istnieje!"
|
||||
helpNextPage: "<gray>Użyj <aqua>/maintenance help %PAGE% <gray>aby przejść do następnej strony pomocy."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Jeśli aktywny, timer zostanie anulowany)"
|
||||
helpEndtimer: "<gold>/maintenance ender <disable in> <gray>(Po podanym czasie, np. 1 godzina 5 m, tryb konserwacji zostanie wyłączony)"
|
||||
helpStarttimer: "<gold>/maintenance ender <disable in> <gray>(Po podanym czasie, np. 1 godzina 5 m, tryb konserwacji zostanie wyłączony)."
|
||||
helpScheduleTimer: ""
|
||||
helpEndtimer: "<gold>/maintenance endtimer <czas> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie wyłączony)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <czas> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie włączony)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <czas do włączenia> <czas trwania> <gray>(Po podanym czasie, np. 1h5m, tryb konserwacji zostanie włączony)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Włacza logowanie dodatkowych informcji do debugowania)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Daje informacje o serwerze, używane do raportowania błędów)"
|
||||
helpHelp: "<gold>/maintenance help [strona] <gray>(Pokazuje tą piękną stronę pomocy)"
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Wyświetla aktualnie ustawione motd. Jeśli wstawiono 'timer', motd z timerem zostaną pokazane)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Usuwa motd konserwacji. Jeśli wstawiono 'timer', motd z timerem zostanie usunięte)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <wiadomość> <gray>(Ustawia motd konserwacji. Jeśli wstawiono 'timer', motd z timerem zostanie ustawione)"
|
||||
helpSetReason: "<gold>/maintenance setreason <powód/none> <gray>(Ustawia albo usuwa powód trybu konserwacji w wiadomościach. Wpisz \"none\" jako powód, aby wyczyścić)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Przeładowuje plik konfiguracji, białej listy i ikonę serwera)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Włącza/wyłącza tryb konserwacji)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Pokazuje status trybu konserwacji i wszystkie minutniki)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [tryb] <gray>(Włącza/Wyłącza tryb konserwacji, opcjonalnie z trybem podanym podczas włączania)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Pobiera najnowszą wersję plugina)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Pokazuje białą listę trybu konserwacji)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nazwa/uuid> <gray>(Dodaje gracza do listy konserwacji, aby mogli dołączyć do serwera w trakcie konserwacji)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nazwa/uuid> <gray>(Usuwa gracza z listy trybu konserwacji)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [serwer] <gray>(Jeśli aktywny, timer zostanie anulowany)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [serwer] <gray>(Włącza/wyłącza tryb konserwacji)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [serwer/global] [tryb] <gray>(Włącza/Wyłącza tryb konserwacji globalnie lub na podanym serwerze, opcjonalnie z trybem podanym podczas włączania)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Wyświetla wszystkie serwery w trybie konserwacji)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Tryb konserwacji włączony.**"
|
||||
webhookMaintenanceDeactivated: "**Tryb konserwacji wyłączony.**"
|
||||
webhookStarttimerStarted: "Tryb konserwacji zostanie włączony <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Tryb konserwacji zostanie wyłączony <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Zablokowano dołączenie: `%PLAYER%` próbował(a) dołączyć podczas konserwacji."
|
||||
webhookSingleMaintenanceActivated: "Tryb konserwacji włączony dla `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Tryb konserwacji wyłączony dla `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Tryb konserwacji zostanie włączony dla `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Tryb konserwacji zostanie wyłączony dla `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>Você não tem permissão para executar esse comando."
|
||||
kickmessage: "<red>O servidor está em manutenção!<br>Tente novamente mais tarde!"
|
||||
maintenanceActivated: "<prefix><gold>O modo de manutenção agora está ativado."
|
||||
maintenanceDeactivated: "<prefix><gold>O modo de manutenção agora está desativado."
|
||||
maintenanceStatusOn: "<prefix><gold>O modo de manutenção está atualmente <green>ativo<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>O modo de manutenção está atualmente <red>desativado<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>O modo de manutenção está atualmente <green>habilitado <grey>e será desabilitado em <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>O modo de manutenção está atualmente <red>desabilitado <grey>e será habilitado em <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>A manutenção já está ativada!"
|
||||
alreadyDisabled: "<prefix><red>A manutenção já está desativada!"
|
||||
endtimerBroadcast: "<prefix><gray>O modo de manutenção será desativado em <gold>%TIME%<gray>."
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Recarregou a configuração, lista de jogadores com perm
|
||||
removedMotd: "<prefix><green>Motd número %INDEX% removida."
|
||||
removeMotdError: "<prefix><red>Você possui apenas uma motd, portanto, não pode remover nenhuma!"
|
||||
setMotd: "<prefix><green>Definiu a linha %LINE% da motd de manutenção %INDEX% para %MOTD%"
|
||||
setReason: "<prefix><green>Definir motivo de manutenção para: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>No momento, você possui %MOTDS% motds, portanto, deve escolher um número entre 1 e %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>O segundo argumento deve ser o número da linha (1 ou 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Baixando atualização..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>A manutenção já está desativada n
|
||||
singleServerMaintenanceList: "<prefix><gray>Servidores proxy com manutenção ativada:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Não há servidores proxy em manutenção no momento."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>iniciando em <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>terminando em <gold>%TIME%"
|
||||
second: "segundo"
|
||||
seconds: "segundos"
|
||||
minute: "minuto"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Não há página com esse número!"
|
||||
helpNextPage: "<gray>Use <aqua>/maintenance help %PAGE% <gray>para ir para a próxima janela de ajuda."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Se estiver em execução, o temporizador atual será abortado)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <desabilitar em> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo manutenção será desabilitado)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <habilitar em> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo de manutenção será habilitado)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <habilitar em> <duração da manutenção> <gray>(Depois do tempo fornecido, exemplo: 1h5m, o modo de manutenção será habilitado)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Ativa alguns registros de depuração)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Exibe algumas informações do servidor, usadas para relatórios de bugs)"
|
||||
helpHelp: "<gold>/maintenance help [página] <gray>(Mostra esta bela janela de ajuda)"
|
||||
helpMotd: "<gold>/maintenance motd [temporizador] <gray>(Lista as motds de manutenção atualmente definidas. Se 'temporizador' for especificado, as motds de temporizador serão mostradas)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [temporizador] <índice> <gray>(Remove uma motd de manutenção. Se usar 'temporizador' como argumento, uma mensagem de ping específica do temporizador será removida)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [temporizador] <índice> <1/2> <mensagem> <gray>(Define uma motd para o modo de manutenção. Se usar 'temporizador' como argumento, uma mensagem de ping específica do temporizador será definida)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Define ou limpa o valor %REASON% comum)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Recarrega o arquivo de configuração, arquivo de lista branca e o ícone do servidor)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Ativa/desativa o modo de manutenção)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Mostra o estado atual da manutenção e qualquer timer em execução)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Ativa/desativa modo de manutenção com modo de exibição opcional quando ativado)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Baixa remotamente a versão mais recente do plugin para o seu servidor)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Mostra todos os jogadores na lista branca para o modo de manutenção)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <nome/uuid> <gray>(Adiciona o jogador à lista branca de manutenção, permitindo que eles entrem no servidor mesmo com a manutenção ativada)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <nome/uuid> <gray>(Remove o jogador da lista branca de manutenção)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [servidor] <gray>(Se estiver em execução, o temporizador atual será abortado)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [servidor] <gray>(Ativa/desativa o modo de manutenção)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Ativa/desativa modo de manutenção globalmente ou em um servidor especifico com um modo de exibição opcional quando ativado)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Lista todos os servidores proxy que estão atualmente em manutenção)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Modo de manutenção ativado.**"
|
||||
webhookMaintenanceDeactivated: "**Modo de manutenção desativado.**"
|
||||
webhookStarttimerStarted: "Manutenção será ativada em <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Manutenção será desativada em <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Entrada bloqueada: `%PLAYER%` tentou conectar durante a manutenção."
|
||||
webhookSingleMaintenanceActivated: "Manutenção será ativada em `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Manutenção será desativada em `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: ""
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,62 +1,67 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>У вас недостаточно прав."
|
||||
noPermission: "<red>У вас нет разрешения на выполнение этой команды."
|
||||
kickmessage: "<red>Сервер закрыт на технические работы!<br>Попробуйте позже!"
|
||||
maintenanceActivated: "<prefix><gold>Режим технических работ включен."
|
||||
maintenanceDeactivated: "<prefix><gold>Режим технических работ выключен."
|
||||
alreadyEnabled: "<prefix><red>Режим технических работ уже включен!"
|
||||
maintenanceStatusOn: "<prefix><gold>Режим обслуживания уже <green>включён<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Режим обслуживания уже <red>выключен<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Режим обслуживания уже <green>включён<grey> и будет выключен через - <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Режим обслуживания уже <red>Выключен<grey> и будет включен через - <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Режим технических работ уже включён!"
|
||||
alreadyDisabled: "<prefix><red>Режим технических работ не был включен!"
|
||||
endtimerBroadcast: "<prefix><gray>Сервер будет открыт через <gold>%TIME%<gray>."
|
||||
endtimerStarted: "<prefix><green>Таймер запущен: <gray>Сервер будет открыт через <gold>%TIME%<gray>."
|
||||
starttimerBroadcast: "<prefix><gray>Сервер будет закрыт на тех. работы через <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<green>Таймер успешно запущен! Сервер будет закрыт на технические работы через <white>%TIME%<green>!"
|
||||
scheduletimerBroadcast: "<prefix><gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Начат таймер: <gray>Тех. работы будут включены <gold>%TIME% <gray>и будут последние для <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<red>Таймер уже запущен!"
|
||||
timerNotRunning: "<red>Таймер не был запущен."
|
||||
timerCancelled: "<gray>Таймер был остановлен."
|
||||
timerTooLong: "<red>Число должно быть не больше чем <white>40320 <red>(<white>28 <red>дней)."
|
||||
timerMotdDisabled: "<red>Сообщения по таймеру выключены в настройках плагина."
|
||||
starttimerBroadcast: "<prefix><gray>Сервер будет закрыт на технические работы через <gold>%TIME%<gray>."
|
||||
starttimerStarted: "<prefix><green>Таймер запущен: <gray>Режим обслуживания будет включен через <gold>%TIME%<gray>."
|
||||
scheduletimerBroadcast: "<prefix><gray>Режим обслуживания будет включён через <gold>%TIME% <gray>и продлится <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Таймер запущен: <gray>Режим обслуживания будет включен через <gold>%TIME% <gray>и продлится <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<prefix><red>Таймер уже запланирован!"
|
||||
timerNotRunning: "<prefix><red>В данный момент нет активного таймера."
|
||||
timerCancelled: "<prefix><red>Таймер остановлен."
|
||||
timerTooLong: "<prefix><red>Длительность должна быть меньше 28 дней!"
|
||||
timerMotdDisabled: "<prefix><red>Вы должны установить 'enable-timerspecific-messages' в конфигурации как 'true', если вы хотите использовать/редактировать титульные строки таймера."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<red>Игрок <white>%PLAYER% <red>пытался зайти на сервер."
|
||||
motdList: "<gray>Список титульных строк в режиме технических работ:"
|
||||
motdListEmpty: "<red>Список пуст."
|
||||
reload: "<green>Плагин успешно перезагружен!"
|
||||
removedMotd: "<green>Титульная строка с индексом <white>%INDEX% <green>успешно удалена!"
|
||||
removeMotdError: "<red>Вы не можете удалить последние 2 титульные строки."
|
||||
setMotd: "<green>Титульная строка <white>%LINE% <green>с индексом <white>%INDEX% <green>успешно изменена: <white>%MOTD%"
|
||||
setMotdIndexError: "<red>Неверный индекс, допустимые значения: 1 - %NEWAMOUNT%."
|
||||
setMotdLineError: "<red>Второй аргумент должен быть номером строки (1 или 2)!"
|
||||
updateDownloading: "<green>Обновление загружается..."
|
||||
updateFailed: "<red>Обновление не удалось!"
|
||||
updateFinished: "<green>Обновление успешно пройдено! Перезагрузите сервер, чтобы избежать возможных проблем."
|
||||
whitelistedPlayers: "<gray>Белый лист в режиме технических работ:"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>попытался зайти на сервер."
|
||||
motdList: "<prefix><gray>Список титульных строк для режима обслуживания:"
|
||||
motdListEmpty: "<prefix><red>Список пуст."
|
||||
reload: "<prefix><green>Плагин успешно перезагружен!"
|
||||
removedMotd: "<prefix><green>Удалена титульная строка с индексом %INDEX%."
|
||||
removeMotdError: "<prefix><red>У вас должна оставаться хотя бы одна титульная строка!"
|
||||
setMotd: "<prefix><green>Титульная строка %LINE% с индексом %INDEX% успешно изменена на %MOTD%"
|
||||
setReason: "<prefix><green> Проводятся технические работы: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Неверный индекс, допустимые значения: 1 - %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Вторым аргументом должен быть номер строки (1 или 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Загрузка обновления..."
|
||||
updateFailed: "<prefix><dark_red><bold>Ошибка обновления!"
|
||||
updateFinished: "<prefix><green><bold>Обновление успешно установлено! Перезагрузите сервер, чтобы избежать возможных проблем."
|
||||
whitelistedPlayers: "<prefix><gold>Игроки допущенные к серверу во время технических работ:"
|
||||
whitelistedPlayersFormat: "<gray>- <white>%NAME% <gray>(<white>%UUID%<gray>)"
|
||||
whitelistAdded: "<green>Игрок <white>%PLAYER% <green>успешно добавлен в белый лист!"
|
||||
whitelistAlreadyAdded: "<red>Игрок <white>%PLAYER% <red>уже в белом листе!"
|
||||
whitelistRemoved: "<green>Игрок <white>%PLAYER% <green>успешно удалён из белого листа!"
|
||||
whitelistNotFound: "<red>Данный игрок не находится в белом листе!"
|
||||
whitelistEmpty: "<red>Белый лист пуст! Используйте /maintenance add [игрок|uuid] чтобы добавить кого-нибудь."
|
||||
playerNotFound: "<red>Игрок не найден!"
|
||||
playerNotFoundUuid: "<red>Игрок с таким UUID не найден!"
|
||||
playerNotOnline: "<red>Игрок должен быть онлайн!"
|
||||
offlinePlayerFetchError: "<prefix><red>Произошла ошибка при получении игрока в автономном режиме. Пожалуйста, повторите попытку позже."
|
||||
invalidUuid: "<red>Неверный формат UUID!"
|
||||
whitelistAdded: "<prefix><green>Игрок <aqua>%PLAYER% <green>успешно добавлен в вайтлист!"
|
||||
whitelistAlreadyAdded: "<prefix><aqua>Игрок <white>%PLAYER% <red>уже в вайтлисте!"
|
||||
whitelistRemoved: "<prefix><green>Игрок <aqua>%PLAYER% <green> удалён из вайтлиста!"
|
||||
whitelistNotFound: "<prefix><red>Данный игрок не находится в вайтлисте!"
|
||||
whitelistEmpty: "<prefix><red>Вайтлист пуст! Используйте <yellow>/maintenance add <player/uuid> <red>чтобы добавить кого-нибудь."
|
||||
playerNotFound: "<prefix><red>Игрок не найден!"
|
||||
playerNotFoundUuid: "<prefix><red>Игрок с таким UUID не найден!"
|
||||
playerNotOnline: "<prefix><red>Игрок должен быть онлайн!"
|
||||
offlinePlayerFetchError: "<prefix><red>Произошла ошибка при получении оффлайн игрока. Пожалуйста, повторите попытку позже."
|
||||
invalidUuid: "<prefix><red>Неверный формат UUID!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<red>Вы были перемещены в лобби!"
|
||||
forceWaitingServer: "<red>Вы не можете покинуть лобби во время технических работ!"
|
||||
serverNotFound: "<red>Сервер не найден!"
|
||||
singleTimerAlreadyRunning: "<red>Таймер сервера <white>%SERVER% <red>уже запущен!"
|
||||
singleTimerCancelled: "<gray>Таймер сервера <white>%SERVER% <gray>был остановлен."
|
||||
singleTimerNotRunning: "<red>Таймер сервера <white>%SERVER% <red>не был запущен."
|
||||
singleEndtimerBroadcast: "<green>Сервер <white>%SERVER% <green>будет открыт через <white>%TIME%<green>!"
|
||||
singleEndtimerStarted: "<prefix><green>Начат таймер: <gray>Тех. работы будут включены <gold>%TIME% <gray>и будут последние для <gold>%DURATION%<gray>."
|
||||
singleStarttimerBroadcast: "<red>Внимание! Сервер <white>%SERVER% <red>будет закрыт на технические работы через <white>%TIME%<red>!"
|
||||
singleStarttimerStarted: "<prefix><red>Внимание! <gray>Сервер <green>%SERVER%<gray> будет закрыт на технические работы через <gold>%TIME%<gray>."
|
||||
sentToWaitingServer: "<prefix><red>Вы были перемещены в лобби!"
|
||||
forceWaitingServer: "<prefix><red>Вы не можете покинуть лобби во время технических работ!"
|
||||
serverNotFound: "<prefix><red>Сервер с таким именем не зарегистрирован на прокси сервере!"
|
||||
singleTimerAlreadyRunning: "<prefix><red>Таймер для этого сервера уже запланирован!"
|
||||
singleTimerCancelled: "<prefix><red>Таймер сервера <yellow>%SERVER% <red>был остановлен."
|
||||
singleTimerNotRunning: "<prefix><red>Для этого сервера нет запущенных таймеров."
|
||||
singleEndtimerBroadcast: "<prefix><gray>Технические работы на сервере %SERVER% завершатся через <gold>%TIME%<gray>."
|
||||
singleEndtimerStarted: "<prefix><green>Таймер запущен: <gray>Режим обслуживания на сервере %SERVER% будет выключен спустя <gold>%TIME%<gray>."
|
||||
singleStarttimerBroadcast: "<prefix><gray>Технические работы на сервере %SERVER% начнутся через <gold>%TIME%<gray>."
|
||||
singleStarttimerStarted: "<prefix><green>Таймер запущен: <gray>Режим обслуживания на сервере %SERVER% будет включен через <gold>%TIME%<gray>."
|
||||
singleScheduletimerBroadcast: "<prefix><gray>Maintenance mode on server %SERVER% will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
singleScheduletimerStarted: "<prefix><green>Таймер начат: <gray>Тех. работы на сервере %SERVER% будут начаты в <gold>%TIME% <gray>и продлятся <gold>%DURATION%<gray>."
|
||||
singleMaintenanceKick: "<red>Данный сервер закрыт на технические работы! Попробуйте позже."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<red>Режим технических работ
|
||||
singleServerMaintenanceList: "<gray>Сервера на которых включен режим технических работ:"
|
||||
singleServerMaintenanceListEmpty: "<gray>Сервера на которых включен режим технических работ: <white>пусто"
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow> Запуститься через <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER%<yellow> Закончится через <gold>%TIME%"
|
||||
second: "секунду"
|
||||
seconds: "секунд"
|
||||
minute: "минуту"
|
||||
@@ -78,7 +85,7 @@ helpHeader: "<gray>========[ <white>%NAME% <gray>| <gold>%PAGE%<white>/<gold>%MA
|
||||
helpPageNotFound: "<red>Страница не найдена."
|
||||
helpNextPage: "<white>Используйте <gold>/maintenance help %PAGE% <white>чтобы перейти на следующую страницу."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>- <white>Остановить таймер включения/выключения режима технических работ."
|
||||
helpEndtimer: ""
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(Через данное время, например 1ч5мин, режим обслуживания выключится)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(По истечению заданного времени, например 1h5m, режим технических работ будет включен)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(По истечению заданного времени, например 1h5m, режим технических работ будет включен)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Enables some debug logging)"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [страница] <gray>- <white>Отобр
|
||||
helpMotd: "<gold>/maintenance motd <timer> <gray>- <white>Отобразить список титульных сообщений."
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd <timer> [индекс] <gray>- <white>Удалить титульное сообщение."
|
||||
helpSetMotd: "<gold>/maintenance setmotd <timer> [индекс] [1|2] [сообщение] <gray>- <white>Добавить новое титульное сообщение."
|
||||
helpSetReason: "<gold>/maintenance setreason <причина/ничего> <gray>(Установить или убрать %REASON% для отображения)"
|
||||
helpReload: "<gold>/maintenance reload <gray>- <white>Перезагрузить плагин."
|
||||
helpToggle: "<gold>/maintenance [on|off] <gray>- <white>Включить/выключить режим технических работ."
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Показывает текущее состояние технического обслуживания и все запущенные таймеры)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray> (Включает/выключает режим обслуживания с дополнительным режимом отображения при включении)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>- <white>Обновить плагин."
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>- <white>Отобразить всех игроков из белого списка."
|
||||
helpWhitelistAdd: "<gold>/maintenance add [ник|uuid] <gray>- <white>Добавить игрока в белый список."
|
||||
helpWhitelistRemove: "<gold>/maintenance remove [ник|uuid] <gray>- <white>Удалить игрока из белого списка."
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [сервер] <gray>- <white>Остановить таймер включения/выключения режима технических работ."
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [сервер] <disable in> <gray>(По истечению заданного времени, например 1h5m, режим технических работ будет выключен)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [сервер] <enable in> <gray>(По истечению заданного времени, например 1h5m, режим технических работ будет включен)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [сервер] <enable in> <maintenance duration> <gray>(По истечению заданного времени, например 1h5m, режим технических работ будет включен)"
|
||||
helpSingleToggle: "<gold>/maintenance [on|off] [сервер] <gray>- <white>Включить/выключить режим технических работ."
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray> (включает/отключает режим обслуживания глобально или на определенном сервере с дополнительным режимом отображения при включении)"
|
||||
helpStatus: "<gold>/maintenance status <gray>- <white>Список всех серверов закрытых на технические работы."
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Режим обслуживания включён.**"
|
||||
webhookMaintenanceDeactivated: "**Режим обслуживания выключен**"
|
||||
webhookStarttimerStarted: "Режим обслуживания будет включен через <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Режим обслуживания будет отключён через <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Заблокировано соединение: `%PLAYER%` пытался присоединиться во время обслуживания."
|
||||
webhookSingleMaintenanceActivated: "Режим обслуживания включен на `%SERVER% `."
|
||||
webhookSingleMaintenanceDeactivated: "Режим обслуживания отключен на `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Режим обслуживания будет включен на `%SERVER%` в <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Режим обслуживания будет выключен на `%SERVER%` в <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Underhållsarbete<dark_gray>] "
|
||||
noPermission: "<red>Du har inte rättigheterna att utfärda det kommandot."
|
||||
kickmessage: "<red>Servern är just nu under underhåll!<br>Försök igen senare!"
|
||||
maintenanceActivated: "<prefix><gold>Underhållsläge är aktiverat."
|
||||
maintenanceDeactivated: "<prefix><gold>Underhållsläge är avaktiverat."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Underhållsläge är redan aktiverat!"
|
||||
alreadyDisabled: "<prefix><red>Underhållsläge är redan avaktiverat!"
|
||||
endtimerBroadcast: "<prefix><gray>Underhållsläget kommer att vara avstängt om <gold>%TIME%<gray>."
|
||||
@@ -18,7 +22,7 @@ scheduletimerStarted: "<prefix><green>Startade timer: <gray>Underhållsläge kom
|
||||
timerAlreadyRunning: "<prefix><red>Det finns redan en timer schemalagd!"
|
||||
timerNotRunning: "<prefix><red>Ingen timer är aktiverad för tillfället."
|
||||
timerCancelled: "<prefix><red>Den nuvarande timern har blivit inaktiverad."
|
||||
timerTooLong: "<prefix><red>Talet måste vara mindre än 40320 (28 days)!"
|
||||
timerTooLong: "<prefix><red>Talet måste vara mindre än 40320 (28 dagar)!"
|
||||
timerMotdDisabled: "<prefix><red>Du måste sätta värdet för 'enable-timerspecific-messages' i konfigurationsfilen filen till 'true', om du vill använda/redigera tidsspecifika motds."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
@@ -29,6 +33,7 @@ reload: "<prefix><green>Laddade om konfigurationsfilen, vitlistade spelare, spr
|
||||
removedMotd: "<prefix><green>Tog bort motd nummer %INDEX%."
|
||||
removeMotdError: "<prefix><red>Du har bara en motd, så du kan inte ta bort några!"
|
||||
setMotd: "<prefix><green>Satte linjen %LINE% av %INDEX%. underhålls motd till %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Du har just nu %MOTDS% motds, så du måste välja ett nummer mellan 1 och %NEWAMOUNT%."
|
||||
setMotdLineError: "<prefix><red>Det andra argumentet måste vara linjenumret (1 or 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Laddar ner uppdatering..."
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix><red>Underhåll är redan avaktiverat på
|
||||
singleServerMaintenanceList: "<prefix><gray>Proxiade servrar, som är under underhåll:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Det finns inga proxiade servrar som har underhåll aktiverat."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "sekund"
|
||||
seconds: "sekunder"
|
||||
minute: "minut"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [sida] <gray>(Visar denna magiskt fina hjälp
|
||||
helpMotd: "<gold>/maintenance motd [timer] <gray>(Listar alla för närvarande aktiva underhålls motds. Om argumentet 'timer' specificeras, kommer alla timer motds visas)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [timer] <index> <gray>(Tar bort ett motd. Om 'timer' används som argument, kommer ett timerspecifikt pingmeddelande bli borttaget)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [timer] <index> <1/2> <meddelande> <gray>(Sätter ett specifikt motd. If using. Om argumentet 'timer' specificeras, kommer ett timerspecifikt pingmeddelande bli satt)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Laddar om konfigurationsfilen, vitlistan and server ikonen)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Aktiverar/avaktiverar underhållsläget)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Avlägset laddar ner senaste versionen av insticksprogrammet på din server)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Visar alla vitlistade spelare för underhållsläget)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <namn/uuid> <gray>(Lägger till en spelare på vitlistan för underhållsläget, så de kan logga in även om underhåll är aktiverat)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <namn/uuid> <gray>(Tar bort spelaren från vitlistan för underhållsläget)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [server] <gray>(Vid utfärdandet av detta kommando kommer den nuvarande timern bli avbruten)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server] <gray>(Aktiverar/avaktiverar underhållsläge)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Listar alla proxiade servrar som är i underhåll)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,12 +1,16 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<yellow><bold>Sunucu<bold> <dark_gray>▸ "
|
||||
noPermission: "<red>Bunun için iznin yok!"
|
||||
kickmessage: "<red>Sunucuda bakım çalışması vardır!"
|
||||
maintenanceActivated: "<prefix><gold>Bakım modu aktif."
|
||||
maintenanceDeactivated: "<prefix><gold>Bakım modu deaktif."
|
||||
noPermission: "<red>Bunun için iznin yok."
|
||||
kickmessage: "<red>Sunucuda bakım çalışması vardır!<br>Lütfen daha sonra tekrar deneyin!"
|
||||
maintenanceActivated: "<prefix><gold>Bakım modu aktifleştirildi."
|
||||
maintenanceDeactivated: "<prefix><gold>Bakım modu deaktifleştirildi."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<prefix><red>Bakım modu zaten aktif!"
|
||||
alreadyDisabled: "<prefix><red>Bakım modu zaten deaktif!"
|
||||
endtimerBroadcast: "<prefix><gray>Bakım modu <gold>%TIME%<gray> içerisinde devre dışı olacak."
|
||||
@@ -18,7 +22,7 @@ scheduletimerStarted: "<prefix><green>Başlatılan zamanlayıcı: <gray>Bakım m
|
||||
timerAlreadyRunning: "<prefix><red>Zaten planlanmış bir zamanlayıcı var!"
|
||||
timerNotRunning: "<prefix><red>Şu anda çalışan bir zamanlayıcı yok."
|
||||
timerCancelled: "<prefix><red>Geçerli zamanlayıcı devre dışı bırakıldı."
|
||||
timerTooLong: "<prefix><red>Belirtilen sayı 40320'den küçük olmalıdır (28 güne tekabül)!"
|
||||
timerTooLong: "<prefix><red>Belirtilen sayı 28 günden küçük olmalıdır!"
|
||||
timerMotdDisabled: "<prefix><red>Zamanlayıcıya özgü motd'ları kullanmak/düzenlemek istiyorsanız, konfigürasyonda 'enable-timerspecial-messages' kısmını 'true' olarak ayarlamalısınız."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
@@ -29,8 +33,9 @@ reload: "<prefix><green>Konfigürasyon dosyaları yeniden yüklendi."
|
||||
removedMotd: "<prefix><green>%INDEX% numaralı MOTD kaldırıldı."
|
||||
removeMotdError: "<prefix><red>Yalnızca bir MOTD'niz var, bu nedenle hiçbirini kaldıramazsınız!"
|
||||
setMotd: "<prefix><green>%LINE% satırını %INDEX% ayarlayın. Bakım MOTD'si %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>Şu anda %MOTDS% motd'unuz var, bu yüzden 1 ile %NEWAMOUNT% arasında bir sayı seçmeniz gerekiyor."
|
||||
setMotdLineError: "<prefix><red>2. argüman satır numarası (1 veya 2) olmalıdır.!"
|
||||
setMotdLineError: "<prefix><red>2. argüman satır numarası (1 veya 2) olmalıdır!"
|
||||
updateDownloading: "<prefix><red><bold>Güncelleme indiriliyor..."
|
||||
updateFailed: "<prefix><dark_red><bold>Güncelleme hataya uğradı!"
|
||||
updateFinished: "<prefix><green><bold>Güncelleme başarılı oldu! Işleyişle ilgili sorunları önlemek ve güncellemeyi tamamlamak için sunucuyu yeniden başlatmanız gerekir!"
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<prefix>%SERVER%<red> sunucusunda zaten bakım mod
|
||||
singleServerMaintenanceList: "<prefix><gray>Bakımı etkinleştirilmiş sunucular:"
|
||||
singleServerMaintenanceListEmpty: "<prefix><gray>Bakımda olan sunucu yok."
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "saniye"
|
||||
seconds: "saniye"
|
||||
minute: "dakika"
|
||||
@@ -78,27 +85,40 @@ helpHeader: "<dark_gray>========[ <yellow>%NAME% <dark_gray>| <yellow>%PAGE%/%MA
|
||||
helpPageNotFound: "<prefix><red>Bu numaraya sahip bir sayfa yok!"
|
||||
helpNextPage: "<aqua>/maintenance help %PAGE% <gray>yazarak bir sonraki yardım sayfasına geçebilirsiniz."
|
||||
helpAbortTimer: "<gold>/maintenance aborttimer <gray>(Eğer çalışıyorsa mevcut zamanlayıcı iptal edilecektir.)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpEndtimer: "<gold>/maintenance endtimer <disable in> <gray>(Belirtilen süreden sonra, Örnek: 1h5m, bakım modu deaktif olacaktır)"
|
||||
helpStarttimer: "<gold>/maintenance starttimer <enable in> <gray>(Belirtilen süreden sonra, Örnek: 1h5m, bakım modu aktif olacaktır)"
|
||||
helpScheduleTimer: "<gold>/maintenance scheduletimer <enable in> <maintenance duration> <gray>(Belirtilen süreden sonra, Örnek: 1h5m, bakım modu aktif olacaktır)"
|
||||
helpDebug: "<gold>/maintenance debug <gray>(Bazı hata ayıklama kaydını etkinleştirir)"
|
||||
helpDump: "<gold>/maintenance dump <gray>(Hata raporları için kullanılan bazı sunucu bilgilerini atar)"
|
||||
helpHelp: "<gold>/maintenance help [sayfa] <gray>(Bu güzel yardım penceresini gösterir)"
|
||||
helpMotd: "<gold>/maintenance motd [zamanlayıcı] <gray>(Halihazırda ayarlanmış bakım MOTD'lerini listeler. Zamanlayıcı belirtilirse, zamanlayıcı modları gösterilir)"
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd [zamanlayıcı] <dizin> <gray>(Bir bakım MOTD'sini kaldırır. Argüman olarak zamanlayıcı kullanılıyorsa, zamanlayıcıya özel bir MOTD mesajı kaldırılacaktır)"
|
||||
helpSetMotd: "<gold>/maintenance setmotd [zamanlayıcı] <dizin> <1/2> <mesaj> <gray>(Bakım modu için bir MOTD ayarlar. Argüman olarak zamanlayıcı kullanılıyorsa, zamanlayıcıya özel MOTD ping mesajı ayarlanır)"
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>(Konfigürasyon dosyasını, beyaz liste dosyasını ve sunucu simgesini yeniden yükler)"
|
||||
helpToggle: "<gold>/maintenance <on/off> <gray>(Bakım modunu etkinleştirir/devre dışı bırakır)"
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>(Eklentinin en yeni sürümünü sunucunuza uzaktan indirir)"
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>(Bakım modu için beyaz listedeki tüm oyuncuları gösterir)"
|
||||
helpWhitelistAdd: "<gold>/maintenance add <isim/uuid> <gray>(Oyuncuyu bakım beyaz listesine ekler, böylece bakım etkin olsa bile sunucuya katılabilir)"
|
||||
helpWhitelistRemove: "<gold>/maintenance remove <isim/uuid> <gray>(Oyuncuyu bakım beyaz listesinden kaldırır)"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [sunucu] <gray>(Çalışıyorsa, mevcut zamanlayıcı iptal edilecektir.)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [sunucu] <gray>(Bakım modunu etkinleştirir/devre dışı bırakır)"
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>(Şu anda bakımda olan tüm sunucuları listeler)"
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
@@ -1,51 +1,56 @@
|
||||
#Maintenance Plugin by kennytv
|
||||
#You can use https://webui.adventure.kyori.net/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.adventure.kyori.net/minimessage/format.html
|
||||
#You can use https://webui.advntr.dev/ to edit and preview the formatted text
|
||||
#For a full list of formats and fancy examples, see https://docs.papermc.io/adventure/minimessage/format/
|
||||
#If you want to contribute changes to the default messages, you can do so via https://crowdin.com/project/maintenance
|
||||
#Messages containing the placeholder "<prefix>" will have it replaced with the following string
|
||||
prefix: "<dark_gray>[<yellow>Maintenance<dark_gray>] "
|
||||
noPermission: "<red>У вас недостатньо прав!"
|
||||
kickmessage: "<red>Сервер зачинено на технічні роботи!"
|
||||
maintenanceActivated: "<green>Режим технічних робіт увімкнено!"
|
||||
maintenanceDeactivated: "<gray>Режим технічних робіт вимкнено!"
|
||||
alreadyEnabled: "<red>Режим технічних робіт вже увімкнено!"
|
||||
alreadyDisabled: "<red>Режим технічних робіт був включений."
|
||||
endtimerBroadcast: "<green>Сервер буде відкритий через<white>%TIME%<green>!"
|
||||
noPermission: "<red>У вас недостатньо прав для виконання цієї команди."
|
||||
kickmessage: "<red>Сервер перебуває на технічному обслуговуванні!<br>Спробуйте пізніше!"
|
||||
maintenanceActivated: "<green>Режим технічних робіт увімкнено."
|
||||
maintenanceDeactivated: "<gray>Режим технічних робіт вимкнено."
|
||||
maintenanceStatusOn: "<prefix><gold>Maintenance mode is currently <green>enabled<gold>."
|
||||
maintenanceStatusOff: "<prefix><gold>Maintenance mode is currently <red>disabled<gold>."
|
||||
maintenanceStatusOnWithEndTimer: "<prefix><gold>Maintenance mode is currently <green>enabled <grey>and will be disabled in <gold>%TIME%."
|
||||
maintenanceStatusOffWithStartTimer: "<prefix><gold>Maintenance mode is currently <red>disabled <grey>and will be enabled in <gold>%TIME%."
|
||||
alreadyEnabled: "<red>Режим технічних робіт вже увімкнений!"
|
||||
alreadyDisabled: "<red>Режим технічних робіт був вимкнений."
|
||||
endtimerBroadcast: "<green>Режим технічних робіт буде вимкнений через<gold>%TIME%<gray>."
|
||||
endtimerStarted: "<green>Таймер успішно запущено! Сервер буде відкритий через<white>%TIME%<green>!"
|
||||
starttimerBroadcast: "<green>Сервер буде закрито на технічні роботи через <white>%TIME%<green>!"
|
||||
starttimerStarted: "<green>Таймер успішно запущено! Сервер буде закрито на технічні роботи через <white>%TIME%<green>!"
|
||||
scheduletimerBroadcast: "<prefix><gray>Технічні роботи розпочнуться в<gold>%TIME% <gray>і триватимуть <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>Started timer: <gray>Maintenance mode will be enabled in <gold>%TIME% <gray>and will last for <gold>%DURATION%<gray>."
|
||||
scheduletimerStarted: "<prefix><green>стартований таймер: <gray>режим підтримки буде ввімкнуто в <gold>%TIME% <gray>і буде тривати <gold>%DURATION%<gray>."
|
||||
timerAlreadyRunning: "<red>Таймер вже запущено!"
|
||||
timerNotRunning: "<red>Таймер не було запущено."
|
||||
timerCancelled: "<gray>Таймер було зупинено."
|
||||
timerTooLong: "<red>Число має бути не більше ніж <white>40320 <red>(<white>28 <red>днів)."
|
||||
timerTooLong: "<red>Число має бути не більше ніж <white>40320 <red>(<white>28 <red>днів)!"
|
||||
timerMotdDisabled: "<red>Повідомлення про таймер вимкнено в налаштуваннях плагіна."
|
||||
motdTimer: "%HOURS%:%MINUTES%:%SECONDS%"
|
||||
motdTimerNotRunning: "-"
|
||||
joinNotification: "<red>Гравець <white>%PLAYER% <red>намагався зайти на сервер."
|
||||
motdList: "<gray>Лист титульних рядків у режимі технічних робіт:"
|
||||
motdListEmpty: "<red>Лист порожній."
|
||||
reload: "<green>Плагін успішно перезавантажено!"
|
||||
removedMotd: "<green>Титульний рядок з індексом <white>%INDEX% <green>успішно видалено!"
|
||||
removeMotdError: "<red>Ви не можете видалити останні 2 титульні рядки."
|
||||
setMotd: "<green>Титульний рядок <white>%LINE% <green>з індексом<white>%INDEX% <green>успішно змінено: <white>%MOTD%"
|
||||
setMotdIndexError: "<red>Неправильний індекс, допустимі значення: 1 - %NEWAMOUNT%."
|
||||
setMotdLineError: "<red>Другий аргумент має бути номером рядка (1 или 2)!"
|
||||
updateDownloading: "<green>Оновлення завантажується..."
|
||||
updateFailed: "<red>Оновлення не вдалось!"
|
||||
updateFinished: "<green>Оновлення успішно пройдено! Перезавантажте сервер, щоб уникнути можливих проблем."
|
||||
whitelistedPlayers: "<gray>Білий лист у режимі технічних робіт:"
|
||||
joinNotification: "<prefix><yellow>%PLAYER% <red>Намагався приєднатися до сервера."
|
||||
motdList: "<prefix><gray>Список motds для технічних робіт:"
|
||||
motdListEmpty: "<prefix><red>У вас немає жодного motds!"
|
||||
reload: "<prefix><green>Перезавантажено конфігурацію, білий список, мовні файли та іконку технічних робіт."
|
||||
removedMotd: "<prefix><green>Видалено motd номер %INDEX%."
|
||||
removeMotdError: "<prefix><red>У вас лише один motd, тому ви не можете його видалити!"
|
||||
setMotd: "<prefix><green>Set line %LINE% of the %INDEX%. maintenance motd to %MOTD%"
|
||||
setReason: "<prefix><green>Set maintenance reason to: <yellow>%REASON%"
|
||||
setMotdIndexError: "<prefix><red>У вас %MOTDS% motds, тому ви можете обрати число між 1 і %NEWAMOUNT%."
|
||||
setMotdLineError: "<red>Другий аргумент має бути числом (1 або 2)!"
|
||||
updateDownloading: "<prefix><red><bold>Оновлення завантажується..."
|
||||
updateFailed: "<prefix><dark_red><bold>Оновлення невдале!"
|
||||
updateFinished: "<green>Оновлення успішне! Перезавантажте сервер, щоб уникнути можливих проблем."
|
||||
whitelistedPlayers: "<gray>Білий список технічних робіт:й"
|
||||
whitelistedPlayersFormat: "<gray>- <white>%NAME% <gray>(<white>%UUID%<gray>)"
|
||||
whitelistAdded: "<green>Гравець <white>%PLAYER% <green>успішно доданий у білий лист!"
|
||||
whitelistAlreadyAdded: "<red>Гравець <white>%PLAYER% <red>вже у білому листі!"
|
||||
whitelistRemoved: "<green>Гравця <white>%PLAYER% <green>успішно видалено з білого листа!"
|
||||
whitelistNotFound: "<red>Цей гравець не знаходиться у білому листі!"
|
||||
whitelistEmpty: "<red>Білий лист порожній! Використовуйте /maintenance add [Гравець|uuid] щоб додати когось."
|
||||
playerNotFound: "<red>Гравець не знайден!"
|
||||
playerNotFoundUuid: "<red>Гравець з таким UUID не знайден!"
|
||||
playerNotOnline: "<red>Гравець повинен бути онлайн!"
|
||||
offlinePlayerFetchError: "<prefix><red>There was an error while fetching offline player. Please try again later."
|
||||
invalidUuid: "<red>Невірний формат UUID!"
|
||||
whitelistAdded: "<green>Гравець <white>%PLAYER% <green>успішно доданий у білий список технічних робіт!"
|
||||
whitelistAlreadyAdded: "<red>Гравець <white>%PLAYER% <red>вже у білому листі технічних робіт!"
|
||||
whitelistRemoved: "<green>Гравця <white>%PLAYER% <green>успішно видалено з білого листа технічних робіт!"
|
||||
whitelistNotFound: "<red>Цей гравець не знаходиться у білому листі технічних робіт!"
|
||||
whitelistEmpty: "<red>Білий список порожній! Використовуйте /maintenance add [Гравець|uuid] щоб додати когось!"
|
||||
playerNotFound: "<red>Жоден гравець з таким іменем раніше не грав на цьому сервері."
|
||||
playerNotFoundUuid: "<red>Гравець з таким UUID не знайдений!"
|
||||
playerNotOnline: "<red>Гравець повинен бути онлайн."
|
||||
offlinePlayerFetchError: "<prefix><red>Помилка при отриманні автономного гравця. Будь ласка, спробуйте ще раз."
|
||||
invalidUuid: "<red>Неправильний uuid формат!"
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
sentToWaitingServer: "<red>Ви були переміщені у лобі!"
|
||||
forceWaitingServer: "<red>Ви не можете залишити лобі під час технічних робіт!"
|
||||
@@ -68,6 +73,8 @@ singleServerAlreadyDisabled: "<red>Режим технічних робіт на
|
||||
singleServerMaintenanceList: "<gray>Сервера на яких включено режим технічних робіт:"
|
||||
singleServerMaintenanceListEmpty: "<gray>Сервера на яких включено режим технічних робіт:<white>порожньо"
|
||||
singleServerMaintenanceListEntry: "<dark_grey>- <aqua>%SERVER%"
|
||||
singleServerMaintenanceListEntryWithStartTimer: "<dark_grey>- <grey>%SERVER% <yellow>starting in <gold>%TIME%"
|
||||
singleServerMaintenanceListEntryWithEndTimer: "<dark_grey>- <aqua>%SERVER% <yellow>ending in <gold>%TIME%"
|
||||
second: "секунду"
|
||||
seconds: "секунд"
|
||||
minute: "хвилину"
|
||||
@@ -87,18 +94,31 @@ helpHelp: "<gold>/maintenance help [сторінка] <gray>- <white>Відоб
|
||||
helpMotd: "<gold>/maintenance motd <timer> <gray>- <white>Відобразити список титульних повідомлень."
|
||||
helpRemoveMotd: "<gold>/maintenance removemotd <timer> [індекс] <gray>- <white>Видалити титульне повідомлення."
|
||||
helpSetMotd: "<gold>/maintenance setmotd <timer> [індекс] [1|2] [сообщение] <gray>- <white>Додати нове титульне повідомлення."
|
||||
helpSetReason: "<gold>/maintenance setreason <reason/none> <gray>(Sets or clears the %REASON% placeholder value)"
|
||||
helpReload: "<gold>/maintenance reload <gray>- <white>Перезавантажити плагін."
|
||||
helpToggle: "<gold>/maintenance [on|off] <gray>- <white>Увімкнути/вимкнути режим технічних робіт."
|
||||
helpGlobalStatus: "<gold>/maintenance status <gray>(Shows the current maintenance status and any running timers)"
|
||||
helpToggle: "<gold>/maintenance <on/off> [mode] <gray>(Enables/disables maintenance mode with an optional display mode when enabling)"
|
||||
helpUpdate: "<gold>/maintenance update <gray>- <white>Оновити плагін."
|
||||
helpWhitelist: "<gold>/maintenance whitelist <gray>- <white>Відобразити всіх гравців із білого листа."
|
||||
helpWhitelistAdd: "<gold>/maintenance add [ник|uuid] <gray>- <white>Додати гравця до білого листа."
|
||||
helpWhitelistRemove: "<gold>/maintenance remove [ник|uuid] <gray>- <white>Видалити гравця із білого листа."
|
||||
#Messages for the Bungee/Velocity part, you can ignore them if you use the plugin on Paper/Sponge
|
||||
helpAbortSingleTimer: "<gold>/maintenance aborttimer [сервер] <gray>- <white>Зупинити таймер увімкнення/вимкнення режиму технічних робіт."
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance [on|off] [сервер] <gray>- <white>Увімкнути/вимкнути режим технічних робіт."
|
||||
helpSingleEndtimer: "<gold>/maintenance endtimer [server|global] <disable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be disabled)"
|
||||
helpSingleStarttimer: "<gold>/maintenance starttimer [server|global] [mode] <enable in> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleScheduleTimer: "<gold>/maintenance scheduletimer [server|global] [mode] <enable in> <maintenance duration> <gray>(After the given time, e.g. 1h5m, maintenance mode will be enabled)"
|
||||
helpSingleToggle: "<gold>/maintenance <on/off> [server|global] [mode] <gray>(Enables/disables maintenance mode globally or on a specific server with an optional display mode when enabling)"
|
||||
helpStatus: "<gold>/maintenance status <gray>- <white>Список всіх серверів, закритих на технічні роботи."
|
||||
#Discord webhook messages. These use Discord markdown, not MiniMessage.
|
||||
#For timer webhooks, %TIMESTAMP% is a Unix timestamp for use in Discord timestamp tags, e.g. <t:%TIMESTAMP%:R>.
|
||||
webhookMaintenanceActivated: "**Maintenance mode enabled.**"
|
||||
webhookMaintenanceDeactivated: "**Maintenance mode disabled.**"
|
||||
webhookStarttimerStarted: "Maintenance mode will be enabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookEndtimerStarted: "Maintenance mode will be disabled <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookJoinNotification: "Blocked join: `%PLAYER%` tried to join during maintenance."
|
||||
webhookSingleMaintenanceActivated: "Maintenance mode enabled on `%SERVER%`."
|
||||
webhookSingleMaintenanceDeactivated: "Maintenance mode disabled on `%SERVER%`."
|
||||
webhookSingleStarttimerStarted: "Maintenance mode will be enabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
webhookSingleEndtimerStarted: "Maintenance mode will be disabled on `%SERVER%` <t:%TIMESTAMP%:R> (`%TIME%`)."
|
||||
#Used for autoupdating the language file, do not change this value.
|
||||
language-version: 2
|
||||
language-version: 5
|
||||
Loaded 100 of 140 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user