├── .github ├── assets │ └── logo.png └── workflows │ └── build.yml ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitattributes ├── .editorconfig ├── gradle.properties ├── settings.gradle.kts ├── deepslateMC-server ├── minecraft-patches │ ├── sources │ │ └── net │ │ │ └── minecraft │ │ │ ├── network │ │ │ └── protocol │ │ │ │ └── common │ │ │ │ └── custom │ │ │ │ └── BrandPayload.java.patch │ │ │ ├── CrashReport.java.patch │ │ │ ├── server │ │ │ ├── commands │ │ │ │ └── ReloadCommand.java.patch │ │ │ ├── dedicated │ │ │ │ └── DedicatedServer.java.patch │ │ │ ├── players │ │ │ │ └── PlayerList.java.patch │ │ │ ├── network │ │ │ │ ├── ServerConfigurationPacketListenerImpl.java.patch │ │ │ │ └── ServerGamePacketListenerImpl.java.patch │ │ │ ├── Main.java.patch │ │ │ ├── gui │ │ │ │ └── MinecraftServerGui.java.patch │ │ │ └── MinecraftServer.java.patch │ │ │ ├── world │ │ │ └── level │ │ │ │ └── chunk │ │ │ │ └── storage │ │ │ │ └── RegionFileStorage.java.patch │ │ │ └── commands │ │ │ └── Commands.java.patch │ └── features │ │ ├── 0002-Global-EULA-file.patch │ │ └── 0001-Dont-show-spectator-players-in-tablist.patch ├── paper-patches │ └── files │ │ └── src │ │ └── main │ │ └── java │ │ ├── com │ │ └── destroystokyo │ │ │ └── paper │ │ │ ├── console │ │ │ └── PaperConsole.java.patch │ │ │ ├── PaperVersionFetcher.java.patch │ │ │ └── Metrics.java.patch │ │ ├── org │ │ ├── bukkit │ │ │ └── craftbukkit │ │ │ │ ├── CraftServer.java.patch │ │ │ │ ├── event │ │ │ │ └── CraftEventFactory.java.patch │ │ │ │ └── scheduler │ │ │ │ └── CraftScheduler.java.patch │ │ └── spigotmc │ │ │ └── WatchdogThread.java.patch │ │ └── io │ │ └── papermc │ │ └── paper │ │ ├── ServerBuildInfoImpl.java.patch │ │ └── connection │ │ └── HorriblePlayerLoginEventHack.java.patch ├── src │ └── main │ │ └── java │ │ └── de │ │ └── pascalpex │ │ └── deepslatemc │ │ ├── commands │ │ ├── HelpCommand.java │ │ ├── DiscordCommand.java │ │ ├── DeepslateCmdRegisterer.java │ │ ├── MaintenanceMode.java │ │ ├── ClearchatCommand.java │ │ ├── BuildworldCommand.java │ │ ├── SpawnCommand.java │ │ └── DeepslateCommand.java │ │ ├── util │ │ ├── ActionbarUtil.java │ │ ├── BossbarUtil.java │ │ ├── ServerLinkUtil.java │ │ └── TablistUtil.java │ │ └── files │ │ ├── MessagesEntry.java │ │ ├── ConfigEntry.java │ │ ├── MessagesFile.java │ │ └── Config.java └── build.gradle.kts.patch ├── deepslateMC-api ├── paper-patches │ └── files │ │ └── src │ │ └── main │ │ └── java │ │ └── io │ │ └── papermc │ │ └── paper │ │ └── ServerBuildInfo.java.patch └── build.gradle.kts.patch ├── .gitignore ├── LICENSE ├── README.md ├── gradlew.bat └── gradlew /.github/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pascalpex/DeepslateMC/HEAD/.github/assets/logo.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Pascalpex/DeepslateMC/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | 3 | *.sh text eol=lf 4 | gradlew text eol=lf 5 | *.bat text eol=crlf 6 | 7 | *.jar binary 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*.java] 2 | charset=utf-8 3 | end_of_line=lf 4 | insert_final_newline=true 5 | indent_style=space 6 | indent_size=4 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | group=de.pascalpex.deepslatemc 2 | version=1.21.11-R0.1-SNAPSHOT 3 | mcVersion=1.21.11 4 | apiVersion=1.21.11 5 | purpurRef=068b0d5a9e8b9946c2a5d98a51b03df7b08a41f4 6 | 7 | org.gradle.configuration-cache=true 8 | org.gradle.caching=true 9 | org.gradle.parallel=true 10 | org.gradle.vfs.watch=false -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | gradlePluginPortal() 4 | maven("https://repo.papermc.io/repository/maven-public/") 5 | } 6 | } 7 | 8 | plugins { 9 | id("org.gradle.toolchains.foojay-resolver-convention") version("1.0.0") 10 | } 11 | 12 | rootProject.name = "deepslateMC" 13 | 14 | include("deepslateMC-api", "deepslateMC-server") 15 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/network/protocol/common/custom/BrandPayload.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/network/protocol/common/custom/BrandPayload.java 2 | +++ b/net/minecraft/network/protocol/common/custom/BrandPayload.java 3 | @@ -12,7 +_,7 @@ 4 | } 5 | 6 | private void write(FriendlyByteBuf buffer) { 7 | - buffer.writeUtf(this.brand); 8 | + buffer.writeUtf(de.pascalpex.deepslatemc.files.Config.getF3name() + "§r"); // Deepslate - configurable F3 menu name 9 | } 10 | 11 | @Override 12 | -------------------------------------------------------------------------------- /deepslateMC-api/paper-patches/files/src/main/java/io/papermc/paper/ServerBuildInfo.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/io/papermc/paper/ServerBuildInfo.java 2 | +++ b/src/main/java/io/papermc/paper/ServerBuildInfo.java 3 | @@ -25,6 +_,14 @@ 4 | */ 5 | Key BRAND_PURPUR_ID = Key.key("purpurmc", "purpur"); 6 | // Purpur end 7 | + 8 | + // Deepslate start 9 | + /** 10 | + * The brand id for DeepslateMC. 11 | + */ 12 | + Key BRAND_DEEPSLATE_ID = Key.key("pascalpex", "deepslate"); 13 | + // Deepslate end 14 | + 15 | /** 16 | * Gets the {@code ServerBuildInfo}. 17 | * 18 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/com/destroystokyo/paper/console/PaperConsole.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/com/destroystokyo/paper/console/PaperConsole.java 2 | +++ b/src/main/java/com/destroystokyo/paper/console/PaperConsole.java 3 | @@ -20,7 +_,7 @@ 4 | @Override 5 | protected LineReader buildReader(LineReaderBuilder builder) { 6 | builder 7 | - .appName("Purpur") // Purpur - Rebrand 8 | + .appName("DeepslateMC") // Purpur - Rebrand // Deepslate 9 | .variable(LineReader.HISTORY_FILE, java.nio.file.Paths.get(".console_history")) 10 | .completer(new ConsoleCommandCompleter(this.server)) 11 | .option(LineReader.Option.COMPLETE_IN_WORD, true); 12 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/CrashReport.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/CrashReport.java 2 | +++ b/net/minecraft/CrashReport.java 3 | @@ -30,7 +_,7 @@ 4 | private boolean trackingStackTrace = true; 5 | private StackTraceElement[] uncategorizedStackTrace = new StackTraceElement[0]; 6 | private final SystemReport systemReport = new SystemReport(); 7 | - private List extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER! REPORT TO PURPUR INSTEAD!", ""); // Purpur - Rebrand 8 | + private List extraInfo = List.of("", "DO NOT REPORT THIS TO PAPER OR PURPUR! REPORT TO DEEPSLATEMC INSTEAD!", ""); // Purpur - Rebrand // Deepslate 9 | 10 | public CrashReport(String title, Throwable exception) { 11 | io.papermc.paper.util.StacktraceDeobfuscator.INSTANCE.deobfuscateThrowable(exception); // Paper 12 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/CraftServer.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java 2 | +++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java 3 | @@ -1041,6 +_,7 @@ 4 | io.papermc.paper.command.PaperCommands.registerCommands(this.console); // Paper 5 | this.spark.registerCommandBeforePlugins(this); // Paper - spark 6 | org.purpurmc.purpur.PurpurConfig.registerCommands(); // Purpur - Purpur config files 7 | + de.pascalpex.deepslatemc.commands.DeepslateCmdRegisterer.registerCommands(this.console); // Deepslate - register commands 8 | this.overrideAllCommandBlockCommands = this.commandsConfiguration.getStringList("command-block-overrides").contains("*"); 9 | this.ignoreVanillaPermissions = this.commandsConfiguration.getBoolean("ignore-vanilla-permissions"); 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle/ 2 | build/ 3 | 4 | # Eclipse stuff 5 | .classpath 6 | .project 7 | .settings/ 8 | 9 | # VSCode stuff 10 | .vscode/ 11 | 12 | # netbeans 13 | nbproject/ 14 | nbactions.xml 15 | 16 | # we use maven! 17 | build.xml 18 | 19 | # maven 20 | target/ 21 | dependency-reduced-pom.xml 22 | 23 | # vim 24 | .*.sw[a-p] 25 | 26 | # various other potential build files 27 | bin/ 28 | dist/ 29 | manifest.mf 30 | 31 | # Mac filesystem dust 32 | .DS_Store/ 33 | .DS_Store 34 | 35 | # intellij 36 | *.iml 37 | *.ipr 38 | *.iws 39 | .idea/ 40 | out/ 41 | 42 | # Linux temp files 43 | *~ 44 | 45 | # other stuff 46 | run/ 47 | 48 | deepslateMC-api/build.gradle.kts 49 | deepslateMC-server/build.gradle.kts 50 | deepslateMC-server/src/minecraft 51 | purpur-api 52 | purpur-server 53 | paper-api 54 | paper-server 55 | 56 | !gradle/wrapper/gradle-wrapper.jar 57 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/HelpCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.MessagesEntry; 4 | import de.pascalpex.deepslatemc.files.MessagesFile; 5 | import org.bukkit.command.Command; 6 | import org.bukkit.command.CommandSender; 7 | import org.jetbrains.annotations.NotNull; 8 | 9 | public class HelpCommand extends Command { 10 | 11 | public HelpCommand(String name) { 12 | super(name); 13 | this.description = "Shows the configured help page"; 14 | this.usageMessage = "/help"; 15 | } 16 | 17 | @Override 18 | public boolean execute(@NotNull CommandSender sender, String label, String @NotNull [] args) { 19 | if (label.equalsIgnoreCase("help")) { 20 | sender.sendMessage(MessagesFile.getMessage(MessagesEntry.HELP_MESSAGE)); 21 | } 22 | return true; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /deepslateMC-api/build.gradle.kts.patch: -------------------------------------------------------------------------------- 1 | --- a/purpur-api/build.gradle.kts 2 | +++ b/purpur-api/build.gradle.kts 3 | @@ -102,17 +_,21 @@ 4 | java { 5 | srcDir(generatedDir) 6 | srcDir(file("../paper-api/src/main/java")) 7 | + srcDir(file("../purpur-api/src/main/java")) // Deepslate - project setup 8 | } 9 | resources { 10 | srcDir(file("../paper-api/src/main/resources")) 11 | + srcDir(file("../purpur-api/src/main/resources")) // Deepslate - project setup 12 | } 13 | } 14 | test { 15 | java { 16 | srcDir(file("../paper-api/src/test/java")) 17 | + srcDir(file("../purpur-api/src/test/java")) // Deepslate - project setup 18 | } 19 | resources { 20 | srcDir(file("../paper-api/src/test/resources")) 21 | + srcDir(file("../purpur-api/src/test/resources")) // Deepslate - project setup 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build DeepslateMC 2 | on: [ push, pull_request ] 3 | jobs: 4 | build: 5 | runs-on: ubuntu-latest 6 | steps: 7 | - uses: actions/checkout@v6.0.1 8 | - name: Set up JDK 21 9 | uses: actions/setup-java@v5.1.0 10 | with: 11 | java-version: 21.0.9 12 | distribution: 'temurin' 13 | - name: Configure Git 14 | run: | 15 | git config --global user.email "actions@github.com" 16 | git config --global user.name "Github Actions" 17 | - name: Grant execute permission for gradlew 18 | run: chmod +x gradlew 19 | - name: Apply patches 20 | run: ./gradlew applyAllPatches 21 | - name: Generate Paperclip Jar 22 | run: ./gradlew createMojmapPaperclipJar 23 | - name: Upload Paperclip 24 | uses: actions/upload-artifact@v5.0.0 25 | with: 26 | name: DeepslateMC 27 | path: deepslateMC-server/build/libs/deepslateMC-paperclip-1.21.11-R0.1-SNAPSHOT-mojmap.jar 28 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/commands/ReloadCommand.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/commands/ReloadCommand.java 2 | +++ b/net/minecraft/server/commands/ReloadCommand.java 3 | @@ -44,6 +_,10 @@ 4 | Collection selectedIds = packRepository.getSelectedIds(); 5 | Collection collection = discoverNewPacks(packRepository, worldData, selectedIds); 6 | server.reloadResources(collection, io.papermc.paper.event.server.ServerResourcesReloadedEvent.Cause.PLUGIN); // Paper - Add ServerResourcesReloadedEvent 7 | + de.pascalpex.deepslatemc.util.TablistUtil.reloadTablist(); // Deepslate - reload tablist 8 | + de.pascalpex.deepslatemc.util.BossbarUtil.reloadBossbar(); // Deepslate - reload bossbar 9 | + de.pascalpex.deepslatemc.util.ActionbarUtil.reloadActionbar(); // Deepslate - reload actionbar 10 | + de.pascalpex.deepslatemc.util.ServerLinkUtil.loadLinks(); // Deepslate - reload server links 11 | } 12 | // CraftBukkit end 13 | 14 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java 2 | +++ b/src/main/java/org/bukkit/craftbukkit/event/CraftEventFactory.java 3 | @@ -651,6 +_,17 @@ 4 | if (cancelledItem) { 5 | event.setUseItemInHand(Result.DENY); 6 | } 7 | + // Deepslate start - Configurable knowledgebook click 8 | + if (de.pascalpex.deepslatemc.files.Config.getPreventKnowledgebookClick()) { 9 | + if (event.hasItem()) { 10 | + if (event.getAction() == Action.RIGHT_CLICK_AIR || event.getAction() == Action.RIGHT_CLICK_BLOCK) { 11 | + if (event.getItem().getType() == Material.KNOWLEDGE_BOOK) { 12 | + event.setCancelled(true); 13 | + } 14 | + } 15 | + } 16 | + } 17 | + // Deepslate end 18 | craftServer.getPluginManager().callEvent(event); 19 | 20 | // Purpur start - Ridables 21 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java 2 | +++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java 3 | @@ -491,7 +_,7 @@ 4 | this.parsePending(); 5 | } else { 6 | // this.debugTail = this.debugTail.setNext(new CraftAsyncDebugger(this.currentTick + CraftScheduler.RECENT_TICKS, task.getOwner(), task.getTaskClass())); // Paper 7 | - task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to Purpur"); // Paper // Purpur - Rebrand 8 | + task.getOwner().getLogger().log(Level.SEVERE, "Unexpected Async Task in the Sync Scheduler. Report this to DeepslateMC"); // Paper // Purpur - Rebrand // Deepslate 9 | // We don't need to parse pending 10 | // (async tasks must live with race-conditions if they attempt to cancel between these few lines of code) 11 | } 12 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/dedicated/DedicatedServer.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/dedicated/DedicatedServer.java 2 | +++ b/net/minecraft/server/dedicated/DedicatedServer.java 3 | @@ -281,6 +_,8 @@ 4 | org.spigotmc.WatchdogThread.doStart(org.spigotmc.SpigotConfig.timeoutTime, org.spigotmc.SpigotConfig.restartOnCrash); // Paper - start watchdog thread 5 | thread.start(); // Paper - Enhance console tab completions for brigadier commands; start console thread after MinecraftServer.console & PaperConfig are initialized 6 | io.papermc.paper.command.PaperCommands.registerCommands(this); // Paper - setup /paper command 7 | + de.pascalpex.deepslatemc.commands.DeepslateCmdRegisterer.registerCommands(this); // Deepslate - register commands 8 | + de.pascalpex.deepslatemc.util.ActionbarUtil.reloadActionbar(); // Deepslate - load actionbar 9 | this.server.spark.registerCommandBeforePlugins(this.server); // Paper - spark 10 | com.destroystokyo.paper.Metrics.PaperMetrics.startMetrics(); // Paper - start metrics 11 | // Purpur start - Purpur config files 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022-2025 Pascalpex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/DiscordCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.MessagesEntry; 4 | import de.pascalpex.deepslatemc.files.MessagesFile; 5 | import net.kyori.adventure.text.Component; 6 | import org.bukkit.command.Command; 7 | import org.bukkit.command.CommandSender; 8 | import org.jetbrains.annotations.NotNull; 9 | 10 | public class DiscordCommand extends Command { 11 | 12 | public DiscordCommand(String name) { 13 | super(name); 14 | this.description = "Discord link command"; 15 | this.usageMessage = "/discord"; 16 | } 17 | 18 | @Override 19 | public boolean execute(@NotNull CommandSender sender, String commandLabel, String @NotNull [] args) { 20 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 21 | if (commandLabel.equalsIgnoreCase("dc") || commandLabel.equalsIgnoreCase("discord")) { 22 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.DISCORD_MESSAGE))); 23 | } 24 | return true; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/util/ActionbarUtil.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.util; 2 | 3 | import net.kyori.adventure.text.Component; 4 | import de.pascalpex.deepslatemc.files.Config; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.entity.Player; 7 | import java.util.Timer; 8 | import java.util.TimerTask; 9 | 10 | public class ActionbarUtil { 11 | 12 | private static String title; 13 | private static final Timer timer = new Timer(); 14 | private static TimerTask task; 15 | 16 | public static void reloadActionbar() { 17 | if (task != null) { 18 | task.cancel(); 19 | } 20 | task = new TimerTask() { 21 | @Override 22 | public void run() { 23 | for (Player player : Bukkit.getOnlinePlayers()) { 24 | player.sendActionBar(Component.text(title)); 25 | } 26 | } 27 | }; 28 | if (Config.getActionbarEnabled()) { 29 | title = Config.getActionbarText().replace("&", "§"); 30 | timer.scheduleAtFixedRate(task, 500, 1500); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/players/PlayerList.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/players/PlayerList.java 2 | +++ b/net/minecraft/server/players/PlayerList.java 3 | @@ -238,6 +_,19 @@ 4 | player.containerMenu.transferTo(player.containerMenu, bukkitPlayer); 5 | 6 | org.bukkit.event.player.PlayerJoinEvent playerJoinEvent = new org.bukkit.event.player.PlayerJoinEvent(bukkitPlayer, io.papermc.paper.adventure.PaperAdventure.asAdventure(mutableComponent)); // Paper - Adventure 7 | + 8 | + de.pascalpex.deepslatemc.commands.SpawnCommand.playerJoin(bukkitPlayer); // Deepslate - Spawn functions 9 | + // Deepslate start - Tablist 10 | + if (de.pascalpex.deepslatemc.files.Config.getTablistEnabled()) { 11 | + de.pascalpex.deepslatemc.util.TablistUtil.setTablist(bukkitPlayer); 12 | + } 13 | + // Deepslate end 14 | + // Deepslate start - Bossbar 15 | + if (de.pascalpex.deepslatemc.files.Config.getBossbarEnabled()) { 16 | + de.pascalpex.deepslatemc.util.BossbarUtil.setBossbar(bukkitPlayer); 17 | + } 18 | + // Deepslate end 19 | + 20 | this.cserver.getPluginManager().callEvent(playerJoinEvent); 21 | 22 | if (!player.connection.isAcceptingMessages()) { 23 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java 2 | +++ b/src/main/java/com/destroystokyo/paper/PaperVersionFetcher.java 3 | @@ -36,7 +_,7 @@ 4 | private static final int DISTANCE_ERROR = -1; 5 | private static final int DISTANCE_UNKNOWN = -2; 6 | // Purpur start - Rebrand 7 | - private static final String DOWNLOAD_PAGE = "https://purpurmc.org/downloads"; 8 | + private static final String DOWNLOAD_PAGE = "https://pascalpex.de/deepslate/"; // Deepslate 9 | private static int distance = DISTANCE_UNKNOWN; public int distance() { return distance; } 10 | // Purpur end - Rebrand 11 | 12 | @@ -52,7 +_,7 @@ 13 | if (build.buildNumber().isEmpty() && build.gitCommit().isEmpty()) { 14 | updateMessage = text("You are running a development version without access to version information", color(0xFF5300)); 15 | } else { 16 | - updateMessage = getUpdateStatusMessage("PurpurMC/Purpur", build); // Purpur - Rebrand 17 | + updateMessage = getUpdateStatusMessage("Pascalpex/DeepslateMC", build); // Purpur - Rebrand // Deepslate 18 | } 19 | final @Nullable Component history = this.getHistory(); 20 | 21 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/world/level/chunk/storage/RegionFileStorage.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/world/level/chunk/storage/RegionFileStorage.java 2 | +++ b/net/minecraft/world/level/chunk/storage/RegionFileStorage.java 3 | @@ -309,7 +_,7 @@ 4 | 5 | // Paper start 6 | private static void printOversizedLog(String msg, Path file, int x, int z) { 7 | - org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PURPUR - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // Purpur - Rebrand 8 | + org.apache.logging.log4j.LogManager.getLogger().fatal(msg + " (" + file.toString().replaceAll(".+[\\\\/]", "") + " - " + x + "," + z + ") Go clean it up to remove this message. /minecraft:tp " + (x<<4)+" 128 "+(z<<4) + " - DO NOT REPORT THIS TO PURPUR OR DEEPSLATEMC - You may ask for help on Discord, but do not file an issue. These error messages can not be removed."); // Purpur - Rebrand // Deepslate 9 | } 10 | 11 | private static CompoundTag readOversizedChunk(RegionFile regionfile, ChunkPos chunkCoordinate) throws IOException { 12 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/util/BossbarUtil.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.util; 2 | 3 | import net.kyori.adventure.bossbar.BossBar; 4 | import net.kyori.adventure.text.Component; 5 | import de.pascalpex.deepslatemc.files.Config; 6 | import org.bukkit.Bukkit; 7 | import org.bukkit.entity.Player; 8 | 9 | public class BossbarUtil { 10 | 11 | private static BossBar bossbar; 12 | 13 | public static void setBossbar(Player player) { 14 | if (bossbar == null) { 15 | reloadBossbar(); 16 | return; 17 | } 18 | player.hideBossBar(bossbar); 19 | player.showBossBar(bossbar); 20 | } 21 | 22 | public static void reloadBossbar() { 23 | if (bossbar != null) { 24 | for (Player player : Bukkit.getOnlinePlayers()) { 25 | player.hideBossBar(bossbar); 26 | } 27 | } 28 | if (Config.getBossbarEnabled()) { 29 | bossbar = BossBar.bossBar(Component.text(Config.getBossbarText().replace("&", "§")).asComponent(), Config.getBossbarProgress(), BossBar.Color.valueOf(Config.getBossbarColor()), BossBar.Overlay.valueOf(Config.getBossbarStyle())); 30 | for (Player player : Bukkit.getOnlinePlayers()) { 31 | player.showBossBar(bossbar); 32 | } 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | # DeepslateMC 5 | ### A fork of [Leaf](https://github.com/Winds-Studio/Leaf) that adds neat functionalities 6 | ### Well, actually it is temporarily a [Purpur](https://github.com/PurpurMC/Purpur) fork 7 |
8 |
9 | 10 | ## Information 11 | This fork aims to add useful little functionalities to replace plugins that many servers use, like spawn commands, tablist decoration, a bossbar or the ability to clear the chat. 12 |
13 | All messages are customizable in a separate file. The default ones are in English and you can find translated ones [here](https://pascalpex.de/files/deepslate/translations/). 14 |
15 | You can find a full list of features, commands, permissions, config options and other information in the [wiki](https://github.com/Pascalpex/DeepslateMC/wiki). 16 | ## Building 17 | ``` 18 | ./gradlew applyPatches 19 | ./gradlew createMojmapPaperclipJar 20 | ``` 21 | ## Statistics 22 | [![bStats Graph](https://bstats.org/signatures/server-implementation/DeepslateMC.svg)](https://bstats.org/plugin/server-implementation/DeepslateMC) 23 | ## Support 24 | You can find support on our [Discord server](https://discord.gg/BGrhNnVczp) 25 | ## Download 26 | You can find the files on our [website](https://pascalpex.de/deepslate/) 27 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/util/ServerLinkUtil.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.util; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import net.kyori.adventure.text.Component; 5 | import net.kyori.adventure.text.minimessage.MiniMessage; 6 | import org.apache.logging.log4j.LogManager; 7 | 8 | import java.net.URI; 9 | import java.net.URISyntaxException; 10 | import java.util.HashMap; 11 | import java.util.Map; 12 | 13 | public class ServerLinkUtil { 14 | 15 | private static Map links = null; 16 | 17 | public static void loadLinks() { 18 | if (links == null) { 19 | links = new HashMap<>(); 20 | } else { 21 | links.clear(); 22 | } 23 | Config.getServerLinks().forEach((key, value) -> { 24 | if(key.isBlank() || value.isBlank()) { 25 | return; 26 | } 27 | try { 28 | links.put(MiniMessage.miniMessage().deserialize(key), new URI(value)); 29 | } catch (URISyntaxException e) { 30 | LogManager.getLogger(ServerLinkUtil.class.getSimpleName()).warn("Invalid URL in DeepslateMC server links: {}", value); 31 | } 32 | }); 33 | } 34 | 35 | public static Map getLinks() { 36 | if (links == null) { 37 | loadLinks(); 38 | } 39 | return links; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/DeepslateCmdRegisterer.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import net.minecraft.server.MinecraftServer; 4 | import org.bukkit.command.SimpleCommandMap; 5 | 6 | public class DeepslateCmdRegisterer { 7 | 8 | public static void registerCommands(final MinecraftServer server) { 9 | SimpleCommandMap commandMap = server.server.getCommandMap(); 10 | 11 | commandMap.register("deepslate", "Deepslate", new DeepslateCommand("deepslate")); 12 | commandMap.register("discord", "Deepslate", new DiscordCommand("discord")); 13 | commandMap.register("dc", "Deepslate", new DiscordCommand("dc")); 14 | commandMap.register("cc", "Deepslate", new ClearchatCommand("cc")); 15 | commandMap.register("clearchat", "Deepslate", new ClearchatCommand("clearchat")); 16 | commandMap.register("setbuildworld", "Deepslate", new BuildworldCommand("setbuildworld")); 17 | commandMap.register("buildworld", "Deepslate", new BuildworldCommand("buildworld")); 18 | commandMap.register("maintenance", "Deepslate", new MaintenanceMode("maintenance")); 19 | commandMap.register("help", "Deepslate", new HelpCommand("help")); 20 | commandMap.register("setspawn", "Deepslate", new SpawnCommand("setspawn")); 21 | commandMap.register("spawn", "Deepslate", new SpawnCommand("spawn")); 22 | commandMap.register("lobby", "Deepslate", new SpawnCommand("lobby")); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java 2 | +++ b/net/minecraft/server/network/ServerConfigurationPacketListenerImpl.java 3 | @@ -103,9 +_,13 @@ 4 | new io.papermc.paper.event.connection.configuration.PlayerConnectionInitialConfigureEvent(this.paperConnection).callEvent(); // Paper 5 | this.send(new ClientboundCustomPayloadPacket(new BrandPayload(this.server.getServerModName()))); 6 | ServerLinks serverLinks = this.server.serverLinks(); 7 | - if (!serverLinks.isEmpty()) { 8 | + if (!serverLinks.isEmpty() || !de.pascalpex.deepslatemc.util.ServerLinkUtil.getLinks().isEmpty()) { // Deepslate - server links 9 | // Paper start 10 | org.bukkit.craftbukkit.CraftServerLinks links = new org.bukkit.craftbukkit.CraftServerLinks(serverLinks); 11 | + // Deepslate start - server links 12 | + java.util.Map deepslateLinks = de.pascalpex.deepslatemc.util.ServerLinkUtil.getLinks(); 13 | + deepslateLinks.keySet().forEach(key -> links.addLink(key, deepslateLinks.get(key))); 14 | + // Deepslate end - server links 15 | new org.bukkit.event.player.PlayerLinksSendEvent(this.paperConnection, links).callEvent(); 16 | this.send(new ClientboundServerLinksPacket(links.getServerLinks().untrust())); 17 | // Paper end 18 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/Main.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/Main.java 2 | +++ b/net/minecraft/server/Main.java 3 | @@ -65,6 +_,17 @@ 4 | @SuppressForbidden(reason = "System.out needed before bootstrap") 5 | @DontObfuscate 6 | public static void main(final OptionSet optionSet) { // CraftBukkit - replaces main(String[] args) 7 | + // Deepslate start - Startup branding 8 | + System.out.println( 9 | + "\u001B[1;2m\u001B[1;31m\u001B[1;31m\u001B[1;31m _____ _ _ __ __ _____ \n" + 10 | + " | __ \\ | | | | | \\/ | / ____|\n" + 11 | + " | | | | ___ ___ _ __ ___ | | __ _ | |_ ___ | \\ / || | \n" + 12 | + " | | | | / _ \\ / _ \\| '_ \\ / __|| | / _` || __|/ _ \\| |\\/| || | \n" + 13 | + " | |__| || __/| __/| |_) |\\__ \\| || (_| || |_| __/| | | || |____ \n" + 14 | + " |_____/ \\___| \\___|| .__/ |___/|_| \\__,_| \\__|\\___||_| |_| \\_____|\n" + 15 | + " | | \n" + 16 | + " |_| \u001B[0m\u001B[1;31m\u001B[0m\u001B[1;31m\u001B[0m\u001B[0m\n"); 17 | + // Deepslate end - Startup branding 18 | io.papermc.paper.util.LogManagerShutdownThread.hook(); // Paper - Improved watchdog support 19 | SharedConstants.tryDetectVersion(); 20 | /* CraftBukkit start - Replace everything 21 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/MaintenanceMode.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import de.pascalpex.deepslatemc.files.MessagesEntry; 5 | import de.pascalpex.deepslatemc.files.MessagesFile; 6 | import net.kyori.adventure.text.Component; 7 | import org.bukkit.command.Command; 8 | import org.bukkit.command.CommandSender; 9 | import org.jetbrains.annotations.NotNull; 10 | 11 | public class MaintenanceMode extends Command { 12 | public MaintenanceMode(String name) { 13 | super(name); 14 | this.description = "Toggles the maintenance mode"; 15 | this.usageMessage = "/maintenance"; 16 | setPermission("deepslate.maintenance"); 17 | } 18 | 19 | public boolean execute(@NotNull CommandSender sender, @NotNull String label, String @NotNull [] args) { 20 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 21 | if (label.equalsIgnoreCase("maintenance") && sender.hasPermission("deepslate.maintenance")) { 22 | if (Config.getMaintenanceMode()) { 23 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.MAINTENANCE_OFF))); 24 | } else { 25 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.MAINTENANCE_ON))); 26 | } 27 | Config.toggleMaintenanceMode(); 28 | } else { 29 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 30 | } 31 | 32 | return true; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/util/TablistUtil.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.util; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import org.bukkit.Bukkit; 5 | import org.bukkit.entity.Player; 6 | 7 | public class TablistUtil { 8 | 9 | private static boolean initiated = false; 10 | private static String header = ""; 11 | private static String footer = ""; 12 | 13 | public static void setTablist(Player player) { 14 | if (!initiated) { 15 | reloadTablist(); 16 | } 17 | player.setPlayerListHeader(header); 18 | player.setPlayerListFooter(footer); 19 | } 20 | 21 | public static void reloadTablist() { 22 | if(!Config.getTablistEnabled()) { 23 | header = null; 24 | footer = null; 25 | initiated = true; 26 | for (Player player : Bukkit.getOnlinePlayers()) { 27 | setTablist(player); 28 | } 29 | return; 30 | } 31 | 32 | header = ""; 33 | footer = ""; 34 | for (String s : Config.getHeader()) { 35 | if (!header.isEmpty()) { 36 | header += "\n"; 37 | } 38 | header += s; 39 | } 40 | for (String s : Config.getFooter()) { 41 | if (!footer.isEmpty()) { 42 | footer += "\n"; 43 | } 44 | footer += s; 45 | } 46 | header = header.replace("&", "§"); 47 | footer = footer.replace("&", "§"); 48 | 49 | initiated = true; 50 | 51 | for (Player player : Bukkit.getOnlinePlayers()) { 52 | setTablist(player); 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java 2 | +++ b/src/main/java/io/papermc/paper/ServerBuildInfoImpl.java 3 | @@ -32,6 +_,7 @@ 4 | 5 | private static final String BRAND_PAPER_NAME = "Paper"; 6 | private static final String BRAND_PURPUR_NAME = "Purpur"; // Purpur - Rebrand 7 | + private static final String BRAND_DEEPSLATE_NAME = "DeepslateMC"; // Deepslate 8 | 9 | private static final String BUILD_DEV = "DEV"; 10 | 11 | @@ -43,9 +_,9 @@ 12 | this( 13 | getManifestAttribute(manifest, ATTRIBUTE_BRAND_ID) 14 | .map(Key::key) 15 | - .orElse(BRAND_PURPUR_ID), // Purpur - Rebrand 16 | + .orElse(BRAND_DEEPSLATE_ID), // Purpur - Rebrand // Deepslate 17 | getManifestAttribute(manifest, ATTRIBUTE_BRAND_NAME) 18 | - .orElse(BRAND_PURPUR_NAME), // Purpur - Rebrand 19 | + .orElse(BRAND_DEEPSLATE_NAME), // Purpur - Rebrand // Deepslate 20 | SharedConstants.getCurrentVersion().id(), 21 | SharedConstants.getCurrentVersion().name(), 22 | getManifestAttribute(manifest, ATTRIBUTE_BUILD_NUMBER) 23 | @@ -62,7 +_,7 @@ 24 | 25 | @Override 26 | public boolean isBrandCompatible(final @NotNull Key brandId) { 27 | - return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID); // Purpur - Fix pufferfish issues // Purpur - Rebrand 28 | + return brandId.equals(this.brandId) || brandId.equals(BRAND_PAPER_ID) || brandId.equals(BRAND_PURPUR_ID); // Purpur - Fix pufferfish issues // Purpur - Rebrand // Deepslate 29 | } 30 | 31 | @Override 32 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/ClearchatCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.MessagesEntry; 4 | import de.pascalpex.deepslatemc.files.MessagesFile; 5 | import net.kyori.adventure.text.Component; 6 | import net.kyori.adventure.text.TextReplacementConfig; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.command.Command; 9 | import org.bukkit.command.CommandSender; 10 | import org.jetbrains.annotations.NotNull; 11 | 12 | public class ClearchatCommand extends Command { 13 | public ClearchatCommand(String name) { 14 | super(name); 15 | this.description = "Clears the chat"; 16 | this.usageMessage = "/clearchat"; 17 | this.setPermission("deepslate.clearchat"); 18 | } 19 | 20 | @Override 21 | public boolean execute(@NotNull CommandSender sender, String commandLabel, String @NotNull [] args) { 22 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 23 | if (commandLabel.equalsIgnoreCase("cc") || commandLabel.equalsIgnoreCase("clearchat")) { 24 | if(sender.hasPermission("deepslate.clearchat")) { 25 | for (int x = 0; x < 150; x++){ 26 | Bukkit.broadcast(Component.empty()); 27 | } 28 | Component clearMessage = MessagesFile.getMessage(MessagesEntry.CLEARED_CHAT).replaceText(TextReplacementConfig.builder().match("%clearer%").replacement(sender.getName()).build()); 29 | Bukkit.broadcast(prefix.append(clearMessage)); 30 | } else { 31 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 32 | } 33 | } 34 | return true; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/files/MessagesEntry.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.files; 2 | 3 | import java.util.List; 4 | 5 | public enum MessagesEntry { 6 | PREFIX("prefix", "&0[&8DeepslateMC&0]"), 7 | WRONG_SYNTAX("wrongSyntax", "&cWrong usage, use: &b%usage%"), 8 | CONFIG_RELOADED("configReloaded", "&aConfig got reloaded successfully"), 9 | ONLY_FOR_PLAYERS("onlyForPlayers", "&cThis command can only be used by players"), 10 | DISCORD_MESSAGE("discordMessage", "&6The link to our Discord server: &b%link%"), 11 | NO_PERMISSIONS("noPermissions", "&cYou have no permission to do this"), 12 | CLEARED_CHAT("clearedChat", "&6The chat got cleared by &b%clearer%"), 13 | BUILDWORLD_SET("buildworldSet", "&aThe buildworld got set successfully"), 14 | BUILDWORLD_WELCOME("buildworldWelcome", "&aWelcome to the buildworld"), 15 | BUILDWORLD_NOT_SET("buildworldNotSet", "&cThe buildworld is not set"), 16 | MAINTENANCE_KICK("maintenanceKick", "&cThe server is currently in maintenance mode"), 17 | MAINTENANCE_ON("maintenanceOn", "&aYou turned on the maintenance mode"), 18 | MAINTENANCE_OFF("maintenanceOff", "&aYou turned off the maintenance mode"), 19 | HELP_MESSAGE("helpMessage", List.of("&6This is a custom help message.", "&6Configure it in the &bmessages.yml &6file inside the deepslate folder.")), 20 | SPAWN_SET("spawnSet", "&aThe spawn got set successfully"), 21 | SPAWN_NOT_SET("spawnNotSet", "&cThe spawn is not set"), 22 | SPAWN_TELEPORTED("spawnTeleport", "&aYou got teleported to the spawn"); 23 | 24 | final String key; 25 | final Object defaultValue; 26 | 27 | MessagesEntry(String key, Object defaultValue) { 28 | this.key = key; 29 | this.defaultValue = defaultValue; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/gui/MinecraftServerGui.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/gui/MinecraftServerGui.java 2 | +++ b/net/minecraft/server/gui/MinecraftServerGui.java 3 | @@ -51,7 +_,7 @@ 4 | } catch (Exception var3) { 5 | } 6 | 7 | - final JFrame jFrame = new JFrame("Purpur Minecraft server"); // Purpur - Improve GUI 8 | + final JFrame jFrame = new JFrame("DeepslateMC Minecraft server"); // Purpur - Improve GUI // Deepslate 9 | final MinecraftServerGui minecraftServerGui = new MinecraftServerGui(server); 10 | jFrame.setDefaultCloseOperation(2); 11 | jFrame.add(minecraftServerGui); 12 | @@ -59,7 +_,7 @@ 13 | jFrame.setLocationRelativeTo(null); 14 | jFrame.setVisible(true); 15 | // Paper start - Improve ServerGUI 16 | - jFrame.setName("Purpur Minecraft server"); // Purpur - Improve GUI 17 | + jFrame.setName("DeepslateMC Minecraft server"); // Purpur - Improve GUI // Deepslate 18 | try { 19 | jFrame.setIconImage(javax.imageio.ImageIO.read(java.util.Objects.requireNonNull(MinecraftServerGui.class.getClassLoader().getResourceAsStream("logo.png")))); 20 | } catch (java.io.IOException ignore) { 21 | @@ -69,7 +_,7 @@ 22 | @Override 23 | public void windowClosing(WindowEvent event) { 24 | if (!minecraftServerGui.isClosing.getAndSet(true)) { 25 | - jFrame.setTitle("Purpur Minecraft server - shutting down!"); // Purpur - Improve GUI 26 | + jFrame.setTitle("DeepslateMC Minecraft server - shutting down!"); // Purpur - Improve GUI // Deepslate 27 | server.halt(true); 28 | minecraftServerGui.runFinalizers(); 29 | } 30 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/network/ServerGamePacketListenerImpl.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/network/ServerGamePacketListenerImpl.java 2 | +++ b/net/minecraft/server/network/ServerGamePacketListenerImpl.java 3 | @@ -1582,7 +_,7 @@ 4 | io.papermc.paper.event.player.PlayerFailMoveEvent event = fireFailMove(io.papermc.paper.event.player.PlayerFailMoveEvent.FailReason.MOVED_TOO_QUICKLY, 5 | toX, toY, toZ, toYaw, toPitch, true); 6 | if (!event.isAllowed()) { 7 | - if (event.getLogWarning()) { 8 | + if (de.pascalpex.deepslatemc.files.Config.getMovedQuickly() && event.getLogWarning()) { // Deepslate 9 | LOGGER.warn("{} moved too quickly! {},{},{}", this.player.getPlainTextName(), d3, d4, d5); 10 | } 11 | this.teleport( 12 | @@ -1661,7 +_,7 @@ 13 | toX, toY, toZ, toYaw, toPitch, true); 14 | if (!event.isAllowed()) { 15 | movedWrongly = true; 16 | - if (event.getLogWarning()) 17 | + if (de.pascalpex.deepslatemc.files.Config.getMovedWrongly() && event.getLogWarning()) // Deepslate 18 | // Paper end 19 | LOGGER.warn("{} moved wrongly!, ({})", this.player.getPlainTextName(), verticalDelta); // Purpur - AFK API 20 | } // Paper 21 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/commands/Commands.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/commands/Commands.java 2 | +++ b/net/minecraft/commands/Commands.java 3 | @@ -193,6 +_,10 @@ 4 | } 5 | public Commands(Commands.CommandSelection selection, CommandBuildContext context, final boolean modern) { 6 | // Paper end - Brigadier API - modern minecraft overloads that do not use redirects but are copies instead 7 | + // Deepslate start 8 | + de.pascalpex.deepslatemc.files.Config.load(); 9 | + de.pascalpex.deepslatemc.files.MessagesFile.load(); 10 | + // Deepslate end 11 | AdvancementCommands.register(this.dispatcher); 12 | AttributeCommand.register(this.dispatcher, context); 13 | ExecuteCommand.register(this.dispatcher, context); 14 | @@ -217,7 +_,7 @@ 15 | GameModeCommand.register(this.dispatcher); 16 | GameRuleCommand.register(this.dispatcher, context); 17 | GiveCommand.register(this.dispatcher, context); 18 | - HelpCommand.register(this.dispatcher); 19 | + //HelpCommand.register(this.dispatcher); Deepslate - configurable help command 20 | ItemCommands.register(this.dispatcher, context); 21 | KickCommand.register(this.dispatcher); 22 | KillCommand.register(this.dispatcher); 23 | @@ -286,7 +_,9 @@ 24 | BanListCommands.register(this.dispatcher); 25 | BanPlayerCommands.register(this.dispatcher); 26 | DeOpCommands.register(this.dispatcher); 27 | - OpCommand.register(this.dispatcher); 28 | + if (de.pascalpex.deepslatemc.files.Config.getOpActive()) { // Deepslate - Toggleable op command 29 | + OpCommand.register(this.dispatcher); 30 | + } 31 | PardonCommand.register(this.dispatcher); 32 | PardonIpCommand.register(this.dispatcher); 33 | PerfCommand.register(this.dispatcher); 34 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/com/destroystokyo/paper/Metrics.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/com/destroystokyo/paper/Metrics.java 2 | +++ b/src/main/java/com/destroystokyo/paper/Metrics.java 3 | @@ -593,7 +_,7 @@ 4 | boolean logFailedRequests = config.getBoolean("logFailedRequests", false); 5 | // Only start Metrics, if it's enabled in the config 6 | if (config.getBoolean("enabled", true)) { 7 | - Metrics metrics = new Metrics("Purpur", serverUUID, logFailedRequests, Bukkit.getLogger()); // Purpur - Purpur config files 8 | + Metrics metrics = new Metrics("DeepslateMC", serverUUID, logFailedRequests, Bukkit.getLogger()); // Purpur - Purpur config files // Deepslate 9 | 10 | metrics.addCustomChart(new Metrics.SimplePie("minecraft_version", () -> { 11 | String minecraftVersion = Bukkit.getVersion(); 12 | @@ -603,7 +_,7 @@ 13 | 14 | metrics.addCustomChart(new Metrics.SingleLineChart("players", () -> Bukkit.getOnlinePlayers().size())); 15 | metrics.addCustomChart(new Metrics.SimplePie("online_mode", () -> Bukkit.getOnlineMode() ? "online" : (io.papermc.paper.configuration.GlobalConfiguration.get().proxies.isProxyOnlineMode() ? "bungee" : "offline"))); // Purpur - Purpur config files 16 | - metrics.addCustomChart(new Metrics.SimplePie("purpur_version", () -> (org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() != null) ? org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() : "unknown")); // Purpur - Purpur config files 17 | + metrics.addCustomChart(new Metrics.SimplePie("deepslatemc_version", () -> (org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() != null) ? org.bukkit.craftbukkit.Main.class.getPackage().getImplementationVersion() : "unknown")); // Purpur - Purpur config files // Deepslate 18 | 19 | metrics.addCustomChart(new Metrics.DrilldownPie("java_version", () -> { 20 | Map> map = new HashMap<>(); 21 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/files/ConfigEntry.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.files; 2 | 3 | import net.kyori.adventure.bossbar.BossBar; 4 | 5 | import java.util.List; 6 | 7 | enum ConfigEntry { 8 | DISCORD_LINK("discordLink", "https://discord.gg/BGrhNnVczp"), 9 | BUILDWORLD("buildworld", null), 10 | MAINTENANCE_MODE("maintenance", false), 11 | OP_COMMAND_ACTIVE("opCommandActive", true), 12 | SPAWN_ON_JOIN("spawnOnJoin", false), 13 | SPAWN_WORLD("spawn" + ".world", null), 14 | SPAWN_X("spawn" + ".X", null), 15 | SPAWN_Y("spawn" + ".Y", null), 16 | SPAWN_Z("spawn" + ".Z", null), 17 | SPAWN_PITCH("spawn" + ".pitch", null), 18 | SPAWN_YAW("spawn" + ".yaw", null), 19 | KNOWLEDGE_BOOK_CLICK("preventKnowledgebookClick", false), 20 | MOVED_WRONGLY_MESSAGES("messages" + ".movedWrongly", true), 21 | MOVED_QUICKLY_MESSAGES("messages" + ".movedQuickly", true), 22 | F3_NAME("f3name", "&b&lDeepslateMC"), 23 | TABLIST_ENABLED("tablist" + ".enabled", false), 24 | TABLIST_HEADER("tablist" + ".header", List.of("&4This is the", "&4default header")), 25 | TABLIST_FOOTER("tablist" + ".footer", List.of("&6This is the", "&6default footer")), 26 | PLAYERLIST_HOVER_ENABLED("playerlistHover" + ".enabled", false), 27 | PLAYERLIST_HOVER_LINES("playerlistHover" + ".lines", List.of("&6This is the", "&6default text")), 28 | BOSSBAR_ENABLED("bossbar" + ".enabled", false), 29 | BOSSBAR_COLOR("bossbar" + ".color", BossBar.Color.WHITE.name()), 30 | BOSSBAR_PROGRESS("bossbar" + ".progress", 1.0f), 31 | BOSSBAR_STYLE("bossbar" + ".style", BossBar.Overlay.PROGRESS.name()), 32 | BOSSBAR_TEXT("bossbar" + ".text", "&6Custom Bossbar"), 33 | ACTIONBAR_ENABLED("actionbar" + ".enabled", false), 34 | MINIMESSAGE_MOTD("miniMessageMotdSupport", false), 35 | ACTIONBAR_TEXT("actionbar" + ".text", "&6Custom Actionbar"), 36 | MINIMESSAGE_MESSAGES("miniMessageMessages", false), 37 | SPECTATOR_MODE_PACKETS("sendSpectatorModePackets", true), 38 | SERVER_LINKS("serverLinks", ""); 39 | 40 | final String key; 41 | final Object defaultValue; 42 | 43 | ConfigEntry(String key, Object defaultValue) { 44 | this.key = key; 45 | this.defaultValue = defaultValue; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/io/papermc/paper/connection/HorriblePlayerLoginEventHack.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/io/papermc/paper/connection/HorriblePlayerLoginEventHack.java 2 | +++ b/src/main/java/io/papermc/paper/connection/HorriblePlayerLoginEventHack.java 3 | @@ -46,12 +_,17 @@ 4 | } 5 | 6 | public static @Nullable Component execute(final Connection connection, MinecraftServer server, GameProfile profile, PlayerList.LoginResult result) { 7 | - if (PlayerLoginEvent.getHandlerList().getRegisteredListeners().length == 0) { 8 | + if (PlayerLoginEvent.getHandlerList().getRegisteredListeners().length == 0 && !de.pascalpex.deepslatemc.files.Config.getMaintenanceMode()) { // Deepslate - maintenance mode 9 | return result.message(); 10 | } 11 | 12 | if (!nagged) { 13 | Set plugins = new HashSet<>(); 14 | + // Deepslate start - Maintenance mode 15 | + if(de.pascalpex.deepslatemc.files.Config.getMaintenanceMode()) { 16 | + plugins.add("DeepslateMC"); // TODO: Find better solution 17 | + } 18 | + // Deepslate end 19 | for (final RegisteredListener listener : PlayerLoginEvent.getHandlerList().getRegisteredListeners()) { 20 | plugins.add(listener.getPlugin().getName()); 21 | } 22 | @@ -87,6 +_,16 @@ 23 | PlayerLoginEvent event = new PlayerLoginEvent(horribleBukkitPlayer, connection.hostname, ((java.net.InetSocketAddress) connection.getRemoteAddress()).getAddress(), ((java.net.InetSocketAddress) connection.channel.remoteAddress()).getAddress()); 24 | event.disallow(result.result(), PaperAdventure.asAdventure(result.message())); 25 | event.callEvent(); 26 | + 27 | + // Deepslate start - Maintenance mode 28 | + if(de.pascalpex.deepslatemc.files.Config.getMaintenanceMode()) { 29 | + if(!horribleBukkitPlayer.hasPermission("deepslate.maintenancebypass")) { 30 | + net.kyori.adventure.text.Component prefix = de.pascalpex.deepslatemc.files.MessagesFile.getMessage(de.pascalpex.deepslatemc.files.MessagesEntry.PREFIX); 31 | + net.kyori.adventure.text.Component kickMessage = de.pascalpex.deepslatemc.files.MessagesFile.getMessage(de.pascalpex.deepslatemc.files.MessagesEntry.MAINTENANCE_KICK); 32 | + event.disallow(org.bukkit.event.player.PlayerLoginEvent.Result.KICK_OTHER, prefix.appendSpace().append(kickMessage)); 33 | + } 34 | + } 35 | + // Deepslate end 36 | 37 | Component finalResult; 38 | if (event.getResult() == PlayerLoginEvent.Result.ALLOWED) { 39 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/BuildworldCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import de.pascalpex.deepslatemc.files.MessagesEntry; 5 | import de.pascalpex.deepslatemc.files.MessagesFile; 6 | import net.kyori.adventure.text.Component; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.World; 9 | import org.bukkit.command.Command; 10 | import org.bukkit.command.CommandSender; 11 | import org.bukkit.entity.Player; 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | public class BuildworldCommand extends Command { 15 | 16 | public BuildworldCommand(String name) { 17 | super(name); 18 | this.description = "Teleports builders to the buildworld"; 19 | this.usageMessage = "/buildworld"; 20 | this.setPermission("deepslate.buildworld"); 21 | } 22 | 23 | @Override 24 | public boolean execute(@NotNull CommandSender sender, @NotNull String label, String @NotNull [] args) { 25 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 26 | if (sender instanceof Player player) { 27 | if(label.equalsIgnoreCase("setbuildworld")) { 28 | if(player.hasPermission("deepslate.setbuildworld")) { 29 | World world = player.getLocation().getWorld(); 30 | Config.setBuildworld(world.getName()); 31 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.BUILDWORLD_SET))); 32 | } else { 33 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 34 | } 35 | } 36 | if(label.equalsIgnoreCase("buildworld")) { 37 | if(player.hasPermission("deepslate.buildworld")) { 38 | try { 39 | player.teleport(Bukkit.getWorld(Config.getBuildworld()).getSpawnLocation()); 40 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.BUILDWORLD_WELCOME))); 41 | } catch (IllegalArgumentException e) { 42 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.BUILDWORLD_NOT_SET))); 43 | } 44 | } else { 45 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 46 | } 47 | } 48 | } else { 49 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.ONLY_FOR_PLAYERS))); 50 | } 51 | return true; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/SpawnCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import de.pascalpex.deepslatemc.files.MessagesEntry; 5 | import de.pascalpex.deepslatemc.files.MessagesFile; 6 | import net.kyori.adventure.text.Component; 7 | import org.bukkit.Bukkit; 8 | import org.bukkit.command.Command; 9 | import org.bukkit.command.CommandSender; 10 | import org.bukkit.entity.Player; 11 | import org.jetbrains.annotations.NotNull; 12 | 13 | public class SpawnCommand extends Command { 14 | 15 | public SpawnCommand(String name) { 16 | super(name); 17 | this.description = "Teleports you to the spawn"; 18 | this.usageMessage = "/spawn"; 19 | this.setPermission("deepslate.spawn"); 20 | } 21 | 22 | public static void playerJoin(Player player) { 23 | if (Config.getSpawnOnJoin()) { 24 | try { 25 | player.teleport(Config.getSpawn()); 26 | } catch (Exception e) { 27 | Bukkit.getLogger().warning("The option spawnOnJoin in the deepslate.yml file is turned on but there is no spawn set!"); 28 | } 29 | } 30 | } 31 | 32 | @Override 33 | public boolean execute(@NotNull CommandSender sender, @NotNull String label, String @NotNull [] args) { 34 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 35 | if (sender instanceof Player player) { 36 | if (label.equalsIgnoreCase("setspawn")) { 37 | if (player.hasPermission("deepslate.setspawn")) { 38 | Config.setSpawn(player.getLocation()); 39 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.SPAWN_SET))); 40 | } else { 41 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 42 | } 43 | } 44 | if (label.equalsIgnoreCase("lobby") || label.equalsIgnoreCase("spawn")) { 45 | if (player.hasPermission("deepslate.spawn")) { 46 | try { 47 | player.teleport(Config.getSpawn()); 48 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.SPAWN_TELEPORTED))); 49 | } catch (IllegalArgumentException e) { 50 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.SPAWN_NOT_SET))); 51 | } 52 | } else { 53 | player.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.NO_PERMISSIONS))); 54 | } 55 | } 56 | } else { 57 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.ONLY_FOR_PLAYERS))); 58 | } 59 | return true; 60 | } 61 | 62 | } 63 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | @rem SPDX-License-Identifier: Apache-2.0 17 | @rem 18 | 19 | @if "%DEBUG%"=="" @echo off 20 | @rem ########################################################################## 21 | @rem 22 | @rem Gradle startup script for Windows 23 | @rem 24 | @rem ########################################################################## 25 | 26 | @rem Set local scope for the variables with windows NT shell 27 | if "%OS%"=="Windows_NT" setlocal 28 | 29 | set DIRNAME=%~dp0 30 | if "%DIRNAME%"=="" set DIRNAME=. 31 | @rem This is normally unused 32 | set APP_BASE_NAME=%~n0 33 | set APP_HOME=%DIRNAME% 34 | 35 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 36 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 37 | 38 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 39 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 40 | 41 | @rem Find java.exe 42 | if defined JAVA_HOME goto findJavaFromJavaHome 43 | 44 | set JAVA_EXE=java.exe 45 | %JAVA_EXE% -version >NUL 2>&1 46 | if %ERRORLEVEL% equ 0 goto execute 47 | 48 | echo. 1>&2 49 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 50 | echo. 1>&2 51 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 52 | echo location of your Java installation. 1>&2 53 | 54 | goto fail 55 | 56 | :findJavaFromJavaHome 57 | set JAVA_HOME=%JAVA_HOME:"=% 58 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 59 | 60 | if exist "%JAVA_EXE%" goto execute 61 | 62 | echo. 1>&2 63 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 64 | echo. 1>&2 65 | echo Please set the JAVA_HOME variable in your environment to match the 1>&2 66 | echo location of your Java installation. 1>&2 67 | 68 | goto fail 69 | 70 | :execute 71 | @rem Setup the command line 72 | 73 | 74 | 75 | @rem Execute Gradle 76 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* 77 | 78 | :end 79 | @rem End local scope for the variables with windows NT shell 80 | if %ERRORLEVEL% equ 0 goto mainEnd 81 | 82 | :fail 83 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 84 | rem the _cmd.exe /c_ return code! 85 | set EXIT_CODE=%ERRORLEVEL% 86 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 87 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 88 | exit /b %EXIT_CODE% 89 | 90 | :mainEnd 91 | if "%OS%"=="Windows_NT" endlocal 92 | 93 | :omega 94 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/features/0002-Global-EULA-file.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Martijn Muijsers 3 | Date: Mon, 26 Dec 2022 00:34:43 +0100 4 | Subject: [PATCH] Global EULA file 5 | 6 | License: MIT (https://opensource.org/licenses/MIT) 7 | Gale - https://galemc.org 8 | 9 | This patch is based on the following patch: 10 | "Global Eula file" 11 | By: tr7zw 12 | As part of: YAPFA (https://github.com/tr7zw/YAPFA) 13 | Licensed under: MIT (https://opensource.org/licenses/MIT) 14 | 15 | * YAPFA copyright * 16 | 17 | Copyright 2020 tr7zw 18 | 19 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 20 | 21 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 | 25 | diff --git a/net/minecraft/server/Eula.java b/net/minecraft/server/Eula.java 26 | index 1f0413214f54e9a47f53c623484d6882c85f54c9..2ffd2ee5846c35b0394230116334518ba95ed409 100644 27 | --- a/net/minecraft/server/Eula.java 28 | +++ b/net/minecraft/server/Eula.java 29 | @@ -17,13 +17,31 @@ public class Eula { 30 | 31 | public Eula(Path file) { 32 | this.file = file; 33 | - this.agreed = SharedConstants.IS_RUNNING_IN_IDE || this.readFile(); 34 | + this.agreed = SharedConstants.IS_RUNNING_IN_IDE || this.readGlobalFile() || this.readFile(); // Gale - YAPFA - global EULA file 35 | } 36 | 37 | private boolean readFile() { 38 | + // Gale start - YAPFA - global EULA file 39 | + return readFile(this.file); 40 | + } 41 | + 42 | + private boolean readGlobalFile() { 43 | + try { 44 | + Path globalFile = Path.of(System.getProperty("user.home"), "eula.txt"); 45 | + 46 | + if (globalFile.toFile().exists()) { 47 | + return readFile(globalFile); 48 | + } 49 | + } catch (Throwable ignored) {} 50 | + 51 | + return false; 52 | + } 53 | + 54 | + private boolean readFile(Path file) { 55 | + // Gale end - YAPFA - global EULA file 56 | try { 57 | boolean var3; 58 | - try (InputStream inputStream = Files.newInputStream(this.file)) { 59 | + try (InputStream inputStream = Files.newInputStream(file)) { // Gale - YAPFA - global EULA file 60 | Properties map = new Properties(); 61 | map.load(inputStream); 62 | var3 = Boolean.parseBoolean(map.getProperty("eula", "false")); 63 | @@ -31,8 +49,10 @@ public class Eula { 64 | 65 | return var3; 66 | } catch (Exception var6) { 67 | + if (file == this.file) { // Gale - YAPFA - global EULA file 68 | LOGGER.warn("Failed to load {}", this.file); 69 | this.saveDefaults(); 70 | + } // Gale - YAPFA - global EULA file 71 | return false; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /deepslateMC-server/build.gradle.kts.patch: -------------------------------------------------------------------------------- 1 | --- a/purpur-server/build.gradle.kts 2 | +++ b/purpur-server/build.gradle.kts 3 | @@ -32,7 +_,30 @@ 4 | outputDir = rootDirectory.dir("paper-server") 5 | } 6 | } 7 | - activeFork = purpur 8 | + // Deepslate start - project setup 9 | + val deepslateMC = forks.register("deepslateMC") { 10 | + forks = purpur 11 | + upstream.patchRepo("paperServer") { 12 | + upstreamRepo = purpur.patchedRepo("paperServer") 13 | + patchesDir = rootDirectory.dir("deepslateMC-server/paper-patches") 14 | + outputDir = rootDirectory.dir("paper-server") 15 | + } 16 | + upstream.patchDir("purpurServer") { 17 | + upstreamPath = "purpur-server" 18 | + excludes = setOf( 19 | + "src/minecraft", 20 | + "paper-patches", 21 | + "minecraft-patches", 22 | + "build.gradle.kts", 23 | + "build.gradle.kts.patch" 24 | + ) 25 | + patchesDir = rootDirectory.dir("deepslateMC-server/purpur-patches") 26 | + outputDir = rootDirectory.dir("purpur-server") 27 | + } 28 | + } 29 | + 30 | + activeFork = deepslateMC 31 | + // Deepslate end - project setup 32 | // Purpur end - Rebrand 33 | 34 | spigot { 35 | @@ -122,10 +_,14 @@ 36 | main { 37 | java { srcDir("../paper-server/src/main/java") } 38 | resources { srcDir("../paper-server/src/main/resources") } 39 | + java { srcDir("../purpur-server/src/main/java") } // Deepslate - project setup 40 | + resources { srcDir("../purpur-server/src/main/resources") } // Deepslate - project setup 41 | } 42 | test { 43 | java { srcDir("../paper-server/src/test/java") } 44 | resources { srcDir("../paper-server/src/test/resources") } 45 | + java { srcDir("../purpur-server/src/test/java") } // Deepslate - project setup 46 | + resources { srcDir("../purpur-server/src/test/resources") } // Deepslate - project setup 47 | } 48 | } 49 | val log4jPlugins = sourceSets.create("log4jPlugins") { 50 | @@ -154,7 +_,7 @@ 51 | } 52 | 53 | dependencies { 54 | - implementation(project(":purpur-api")) // Purpur 55 | + implementation(project(":deepslateMC-api")) // Purpur // Deepslate - project setup 56 | implementation("ca.spottedleaf:concurrentutil:0.0.7") 57 | implementation("org.jline:jline-terminal-ffm:3.27.1") // use ffm on java 22+ 58 | implementation("org.jline:jline-terminal-jni:3.27.1") // fall back to jni on java 21 59 | @@ -229,14 +_,14 @@ 60 | val gitBranch = git.exec(providers, "rev-parse", "--abbrev-ref", "HEAD").get().trim() 61 | attributes( 62 | "Main-Class" to "org.bukkit.craftbukkit.Main", 63 | - "Implementation-Title" to "Purpur", // Purpur 64 | + "Implementation-Title" to "DeepslateMC", // Purpur // Deepslate - Rebrand 65 | "Implementation-Version" to implementationVersion, 66 | "Implementation-Vendor" to date, 67 | - "Specification-Title" to "Purpur", // Purpur 68 | + "Specification-Title" to "DeepslateMC", // Purpur // Deepslate - Rebrand 69 | "Specification-Version" to project.version, 70 | - "Specification-Vendor" to "Purpur Team", // Purpur 71 | - "Brand-Id" to "purpurmc:purpur", // Purpur 72 | - "Brand-Name" to "Purpur", // Purpur 73 | + "Specification-Vendor" to "Pascalpex", // Purpur // Deepslate - Rebrand 74 | + "Brand-Id" to "pascalpex:deepslate", // Purpur // Deepslate - Rebrand 75 | + "Brand-Name" to "DeepslateMC", // Purpur // Deepslate - Rebrand 76 | "Build-Number" to (build ?: ""), 77 | "Build-Time" to buildTime.toString(), 78 | "Git-Branch" to gitBranch, 79 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/sources/net/minecraft/server/MinecraftServer.java.patch: -------------------------------------------------------------------------------- 1 | --- a/net/minecraft/server/MinecraftServer.java 2 | +++ b/net/minecraft/server/MinecraftServer.java 3 | @@ -1296,6 +_,7 @@ 4 | org.spigotmc.WatchdogThread.tick(); 5 | // Paper end 6 | org.spigotmc.WatchdogThread.hasStarted = true; // Paper 7 | + de.pascalpex.deepslatemc.files.Config.addSparkEntry(); // Deepslate - add deepslate.yml to spark 8 | // Paper start - Add onboarding message for initial server start 9 | if (io.papermc.paper.configuration.GlobalConfiguration.isFirstStart) { 10 | LOGGER.info("*************************************************************************************"); 11 | @@ -1769,6 +_,19 @@ 12 | private ServerStatus.Players buildPlayerStatus() { 13 | List players = this.playerList.getPlayers(); 14 | int maxPlayers = this.getMaxPlayers(); 15 | + 16 | + // Deepslate start - Custom playerlist hover text 17 | + if(de.pascalpex.deepslatemc.files.Config.getPlayerlistHoverEnabled()) { 18 | + List textList = de.pascalpex.deepslatemc.files.Config.getPlayerlistHoverLines(); 19 | + ObjectArrayList objectarraylist = new ObjectArrayList<>(textList.size()); 20 | + for(String line : textList) { 21 | + GameProfile profile = new GameProfile(UUID.randomUUID(), line.replace("&", "§")); 22 | + objectarraylist.add(new NameAndId(profile)); 23 | + } 24 | + return new ServerStatus.Players(maxPlayers, players.size(), objectarraylist); 25 | + } 26 | + // Deepslate end 27 | + 28 | if (this.hidesOnlinePlayers()) { 29 | return new ServerStatus.Players(maxPlayers, players.size(), List.of()); 30 | } else { 31 | @@ -2145,12 +_,29 @@ 32 | 33 | @Override 34 | public String getMotd() { 35 | - return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.motd); // Paper - Adventure 36 | + // Deepslate start - MiniMessage MOTD 37 | + if(de.pascalpex.deepslatemc.files.Config.getMinimessageMotd()) { 38 | + return net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().serialize(this.motd); 39 | + } else { 40 | + return net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().serialize(this.motd); // Paper - Adventure 41 | + } 42 | + // Deepslate end - MiniMessage MOTD 43 | } 44 | 45 | public void setMotd(String motd) { 46 | // Paper start - Adventure 47 | - this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOr(motd, net.kyori.adventure.text.Component.empty()); 48 | + // Deepslate start - MiniMessage MOTD 49 | + if(de.pascalpex.deepslatemc.files.Config.getMinimessageMotd()) { 50 | + try { 51 | + this.motd = net.kyori.adventure.text.minimessage.MiniMessage.miniMessage().deserializeOr(motd, net.kyori.adventure.text.Component.empty()); 52 | + } catch (net.kyori.adventure.text.minimessage.internal.parser.ParsingExceptionImpl e) { 53 | + LOGGER.error("You have enabled DeepslateMC's miniMessageMotdSupport but your motd contains legacy color codes. Will fallback to legacy colors."); 54 | + this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOr(motd, net.kyori.adventure.text.Component.empty()); 55 | + } 56 | + } else { 57 | + this.motd = net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer.legacySection().deserializeOr(motd, net.kyori.adventure.text.Component.empty()); 58 | + } 59 | + // Deepslate end - MiniMessage MOTD 60 | } 61 | 62 | public net.kyori.adventure.text.Component motd() { 63 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/commands/DeepslateCommand.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.commands; 2 | 3 | import de.pascalpex.deepslatemc.files.Config; 4 | import de.pascalpex.deepslatemc.files.MessagesEntry; 5 | import de.pascalpex.deepslatemc.files.MessagesFile; 6 | import de.pascalpex.deepslatemc.util.ActionbarUtil; 7 | import de.pascalpex.deepslatemc.util.BossbarUtil; 8 | import de.pascalpex.deepslatemc.util.ServerLinkUtil; 9 | import de.pascalpex.deepslatemc.util.TablistUtil; 10 | import net.kyori.adventure.text.Component; 11 | import net.kyori.adventure.text.format.NamedTextColor; 12 | import org.bukkit.Location; 13 | import org.bukkit.command.Command; 14 | import org.bukkit.command.CommandSender; 15 | import org.jetbrains.annotations.NotNull; 16 | 17 | import java.util.Collections; 18 | import java.util.List; 19 | import java.util.stream.Collectors; 20 | import java.util.stream.Stream; 21 | 22 | public class DeepslateCommand extends Command { 23 | 24 | public DeepslateCommand(String name) { 25 | super(name); 26 | this.description = "Deepslate command"; 27 | this.usageMessage = "/deepslate [reload | version]"; 28 | } 29 | 30 | @Override 31 | public @NotNull List tabComplete(@NotNull CommandSender sender, @NotNull String alias, String[] args, Location location) throws IllegalArgumentException { 32 | if (args.length == 1 && sender.hasPermission("deepslate.command")) { 33 | return Stream.of("reload", "version") 34 | .filter(arg -> arg.startsWith(args[0].toLowerCase())) 35 | .collect(Collectors.toList()); 36 | } 37 | return Collections.emptyList(); 38 | } 39 | 40 | @Override 41 | public boolean execute(@NotNull CommandSender sender, String commandLabel, String @NotNull [] args) { 42 | if (commandLabel.equalsIgnoreCase("deepslate")) { 43 | Component prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 44 | if (sender.hasPermission("deepslate.command")) { 45 | if (args.length == 0) { 46 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.WRONG_SYNTAX))); 47 | } 48 | if (args.length == 1) { 49 | if (args[0].equalsIgnoreCase("reload")) { 50 | MessagesFile.load(); 51 | Config.load(); 52 | TablistUtil.reloadTablist(); 53 | BossbarUtil.reloadBossbar(); 54 | ActionbarUtil.reloadActionbar(); 55 | ServerLinkUtil.loadLinks(); 56 | prefix = MessagesFile.getMessage(MessagesEntry.PREFIX).appendSpace(); 57 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.CONFIG_RELOADED))); 58 | } else { 59 | if (args[0].equalsIgnoreCase("version")) { 60 | String deepslateVersion = this.getClass().getPackage().getImplementationVersion().replace('"', ' ').replace(" ", ""); 61 | sender.sendMessage(prefix.append(Component.text("This server is running DeepslateMC from Pascalpex: " + deepslateVersion).color(NamedTextColor.GOLD))); 62 | } else { 63 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.WRONG_SYNTAX))); 64 | } 65 | } 66 | } 67 | if (args.length >= 2) { 68 | sender.sendMessage(prefix.append(MessagesFile.getMessage(MessagesEntry.WRONG_SYNTAX))); 69 | } 70 | } else { 71 | sender.sendMessage(prefix.append(Component.text("This server is running DeepslateMC from Pascalpex").color(NamedTextColor.GOLD))); 72 | } 73 | } 74 | return true; 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /deepslateMC-server/paper-patches/files/src/main/java/org/spigotmc/WatchdogThread.java.patch: -------------------------------------------------------------------------------- 1 | --- a/src/main/java/org/spigotmc/WatchdogThread.java 2 | +++ b/src/main/java/org/spigotmc/WatchdogThread.java 3 | @@ -75,14 +_,14 @@ 4 | this.lastEarlyWarning = currentTime; 5 | if (isLongTimeout) { 6 | logger.log(Level.SEVERE, "------------------------------"); 7 | - logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a Purpur bug."); // Paper // Purpur - Rebrand 8 | + logger.log(Level.SEVERE, "The server has stopped responding! This is (probably) not a DeepslateMC bug."); // Paper // Purpur - Rebrand // Depelsate 9 | logger.log(Level.SEVERE, "If you see a plugin in the Server thread dump below, then please report it to that author"); 10 | logger.log(Level.SEVERE, "\t *Especially* if it looks like HTTP or MySQL operations are occurring"); 11 | logger.log(Level.SEVERE, "If you see a world save or edit, then it means you did far more than your server can handle at once"); 12 | logger.log(Level.SEVERE, "\t If this is the case, consider increasing timeout-time in spigot.yml but note that this will replace the crash with LARGE lag spikes"); 13 | - logger.log(Level.SEVERE, "If you are unsure or still think this is a Purpur bug, please report this to https://github.com/PurpurMC/Purpur/issues"); // Purpur - Rebrand 14 | + logger.log(Level.SEVERE, "If you are unsure or still think this is a DeepslateMC bug, please report this to https://github.com/Pascalpex/DeepslateMC/issues"); // Purpur - Rebrand // Deepslate 15 | logger.log(Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports"); 16 | - logger.log(Level.SEVERE, "Purpur version: " + Bukkit.getServer().getVersion()); // Purpur - Rebrand 17 | + logger.log(Level.SEVERE, "DeepslateMC version: " + Bukkit.getServer().getVersion()); // Purpur - Rebrand // Deepslate 18 | 19 | if (net.minecraft.world.level.Level.lastPhysicsProblem != null) { 20 | logger.log(Level.SEVERE, "------------------------------"); 21 | @@ -102,12 +_,12 @@ 22 | } 23 | // Paper end 24 | } else { 25 | - logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PURPUR - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Purpur - Rebrand 26 | + logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO DEEPSLATEMC - THIS IS NOT A BUG OR A CRASH - " + Bukkit.getServer().getVersion() + " ---"); // Purpur - Rebrand // Deepslate 27 | logger.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); 28 | } 29 | // Paper end - Different message for short timeout 30 | logger.log(Level.SEVERE, "------------------------------"); 31 | - logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Purpur!):"); // Paper // Purpur - Rebrand 32 | + logger.log(Level.SEVERE, "Server thread dump (Look for plugins here before reporting to DeepslateMC!):"); // Paper // Purpur - Rebrand // Deepslate 33 | FeatureHooks.dumpAllChunkLoadInfo(MinecraftServer.getServer(), isLongTimeout); // Paper - log detailed tick information 34 | WatchdogThread.dumpThread(ManagementFactory.getThreadMXBean().getThreadInfo(MinecraftServer.getServer().serverThread.threadId(), Integer.MAX_VALUE), logger); 35 | logger.log(Level.SEVERE, "------------------------------"); 36 | @@ -120,7 +_,7 @@ 37 | WatchdogThread.dumpThread(thread, logger); 38 | } 39 | } else { 40 | - logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PURPUR - THIS IS NOT A BUG OR A CRASH ---"); // Purpur - Rebrand 41 | + logger.log(Level.SEVERE, "--- DO NOT REPORT THIS TO DEEPSLATEMC - THIS IS NOT A BUG OR A CRASH ---"); // Purpur - Rebrand // Deepslate 42 | } 43 | 44 | logger.log(Level.SEVERE, "------------------------------"); 45 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/files/MessagesFile.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.files; 2 | 3 | import net.kyori.adventure.text.Component; 4 | import net.kyori.adventure.text.JoinConfiguration; 5 | import net.kyori.adventure.text.event.ClickEvent; 6 | import net.kyori.adventure.text.minimessage.MiniMessage; 7 | import net.kyori.adventure.text.serializer.ComponentDecoder; 8 | import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; 9 | import org.apache.logging.log4j.LogManager; 10 | import org.apache.logging.log4j.Logger; 11 | import org.bukkit.configuration.InvalidConfigurationException; 12 | import org.bukkit.configuration.file.FileConfiguration; 13 | import org.bukkit.configuration.file.YamlConfiguration; 14 | 15 | import java.io.File; 16 | import java.io.IOException; 17 | import java.util.ArrayList; 18 | import java.util.List; 19 | 20 | import static de.pascalpex.deepslatemc.files.MessagesEntry.*; 21 | 22 | public class MessagesFile { 23 | 24 | public static final File configFile = new File("deepslate", "messages.yml"); 25 | public static final FileConfiguration config = YamlConfiguration.loadConfiguration(configFile); 26 | 27 | private static final Logger LOGGER = LogManager.getLogger(MessagesFile.class.getSimpleName()); 28 | private static final MiniMessage miniMessage = MiniMessage.miniMessage(); 29 | private static final LegacyComponentSerializer legacySerializer = LegacyComponentSerializer.legacyAmpersand(); 30 | 31 | private static final String COMMAND_USAGE = "/deepslate [reload | version]"; 32 | 33 | public static void load() { 34 | try { 35 | configFile.getParentFile().mkdirs(); 36 | if (!configFile.exists()) { 37 | configFile.createNewFile(); 38 | List header = new ArrayList<>(); 39 | header.add("This is the messages file of DeepslateMC"); 40 | header.add("You can find some pre-translated files here: https://pascalpex.de/files/deepslate/translations/"); 41 | config.options().setHeader(header); 42 | save(); 43 | } 44 | config.load(configFile); 45 | for(MessagesEntry messagesEntry : MessagesEntry.values()) { 46 | if(!config.contains(messagesEntry.key)) { 47 | config.set(messagesEntry.key, messagesEntry.defaultValue); 48 | } 49 | } 50 | save(); 51 | LOGGER.info("Loaded DeepslateMC messages file"); 52 | } catch (IOException | InvalidConfigurationException e) { 53 | LOGGER.error("Error loading DeepslateMC messages", e); 54 | } 55 | } 56 | 57 | public static void save() { 58 | try { 59 | config.save(configFile); 60 | } catch (IOException e) { 61 | LOGGER.error("Error saving DeepslateMC messages", e); 62 | } 63 | } 64 | 65 | public static Component getMessage(MessagesEntry key) { 66 | return switch (key) { 67 | case HELP_MESSAGE -> getHelpMessage(); 68 | case DISCORD_MESSAGE -> getDiscordMessage(); 69 | case WRONG_SYNTAX -> getWrongSyntaxMessage(); 70 | default -> processColors(config.getString(key.key)); 71 | }; 72 | } 73 | 74 | private static Component processColors(String message) { 75 | ComponentDecoder decoder = Config.getMinimessageMessages() ? miniMessage : legacySerializer; 76 | return decoder.deserialize(message); 77 | } 78 | 79 | private static Component getDiscordMessage() { 80 | String message = config.getString(DISCORD_MESSAGE.key); 81 | message = message.replace("%link%", Config.getDiscordLink()); 82 | return processColors(message).clickEvent(ClickEvent.openUrl(Config.getDiscordLink())); 83 | } 84 | 85 | private static Component getWrongSyntaxMessage() { 86 | String message = config.getString(WRONG_SYNTAX.key); 87 | message = message.replace("%usage%", COMMAND_USAGE); 88 | return processColors(message); 89 | } 90 | 91 | private static Component getHelpMessage() { 92 | List messages = config.getList(HELP_MESSAGE.key).stream().map(Object::toString).toList(); 93 | List components = messages.stream() 94 | .map(MessagesFile::processColors) 95 | .toList(); 96 | 97 | return Component.join(JoinConfiguration.separator(Component.newline()), components); 98 | } 99 | 100 | 101 | } 102 | -------------------------------------------------------------------------------- /deepslateMC-server/minecraft-patches/features/0001-Dont-show-spectator-players-in-tablist.patch: -------------------------------------------------------------------------------- 1 | From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 2 | From: Pascalpex 3 | Date: Tue, 27 May 2025 16:04:17 +0200 4 | Subject: [PATCH] Dont show spectator players in tablist 5 | 6 | 7 | diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java 8 | index 2e3b6da733387c95c0add1f7a42508023f0b74ff..f0abe276540d1ca7e6d43e9c365437a029a27870 100644 9 | --- a/net/minecraft/server/level/ServerPlayerGameMode.java 10 | +++ b/net/minecraft/server/level/ServerPlayerGameMode.java 11 | @@ -84,10 +84,16 @@ public class ServerPlayerGameMode { 12 | } 13 | 14 | this.player.onUpdateAbilities(); 15 | - this.level 16 | - .getServer() 17 | - .getPlayerList() 18 | - .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit 19 | + // Deepslate start - Don't send spectator mode packets to other players 20 | + if(de.pascalpex.deepslatemc.files.Config.getSendSpectatorModePackets() || gameModeForPlayer != GameType.SPECTATOR) { 21 | + this.level 22 | + .getServer() 23 | + .getPlayerList() 24 | + .broadcastAll(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player), this.player); // CraftBukkit 25 | + } else { 26 | + this.player.connection.send(new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE, this.player)); 27 | + } 28 | + // Deepslate end - Don't send spectator mode packets to other players 29 | this.level.updateSleepingPlayerList(); 30 | if (gameModeForPlayer == GameType.CREATIVE) { 31 | this.player.resetCurrentImpulseContext(); 32 | diff --git a/net/minecraft/server/players/PlayerList.java b/net/minecraft/server/players/PlayerList.java 33 | index 34d8495507f1607af805ba17f7d17cb7a0e6dcc8..6767cdbda355bb861f2743fec34b2b833e638a35 100644 34 | --- a/net/minecraft/server/players/PlayerList.java 35 | +++ b/net/minecraft/server/players/PlayerList.java 36 | @@ -268,6 +268,25 @@ public abstract class PlayerList { 37 | // CraftBukkit start - sendAll above replaced with this loop 38 | ClientboundPlayerInfoUpdatePacket packet = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(List.of(player)); // Paper - Add Listing API for Player 39 | 40 | + // Deepslate start - Don't send spectator mode packets to other players 41 | + ClientboundPlayerInfoUpdatePacket modifiedPacket = null; 42 | + if (!de.pascalpex.deepslatemc.files.Config.getSendSpectatorModePackets()) { 43 | + ClientboundPlayerInfoUpdatePacket.Entry entry = packet.entries().getFirst(); 44 | + ClientboundPlayerInfoUpdatePacket.Entry entryWithoutSpectator = new ClientboundPlayerInfoUpdatePacket.Entry( 45 | + entry.profileId(), 46 | + entry.profile(), 47 | + entry.listed(), 48 | + entry.latency(), 49 | + entry.gameMode() == net.minecraft.world.level.GameType.SPECTATOR ? net.minecraft.world.level.GameType.SURVIVAL : entry.gameMode(), 50 | + entry.displayName(), 51 | + entry.showHat(), 52 | + entry.listOrder(), 53 | + entry.chatSession()); 54 | + 55 | + modifiedPacket = new ClientboundPlayerInfoUpdatePacket(packet.actions(), List.of(entryWithoutSpectator)); 56 | + } 57 | + // Deepslate end - Don't send spectator mode packets to other players 58 | + 59 | final List onlinePlayers = Lists.newArrayListWithExpectedSize(this.players.size() - 1); // Paper - Use single player info update packet on join 60 | for (int i = 0; i < this.players.size(); ++i) { 61 | ServerPlayer entityplayer1 = (ServerPlayer) this.players.get(i); 62 | @@ -276,7 +295,13 @@ public abstract class PlayerList { 63 | // Paper start - Add Listing API for Player 64 | if (entityplayer1.getBukkitEntity().isListed(bukkitPlayer)) { 65 | // Paper end - Add Listing API for Player 66 | - entityplayer1.connection.send(packet); 67 | + // Deepslate start - Don't send spectator mode packets to other players 68 | + if (de.pascalpex.deepslatemc.files.Config.getSendSpectatorModePackets() || entityplayer1 == player) { 69 | + entityplayer1.connection.send(packet); 70 | + } else { 71 | + entityplayer1.connection.send(modifiedPacket); 72 | + } 73 | + // Deepslate end - Don't send spectator mode packets to other players 74 | // Paper start - Add Listing API for Player 75 | } else { 76 | entityplayer1.connection.send(ClientboundPlayerInfoUpdatePacket.createSinglePlayerInitializing(player, false)); 77 | @@ -292,7 +317,27 @@ public abstract class PlayerList { 78 | } 79 | // Paper start - Use single player info update packet on join 80 | if (!onlinePlayers.isEmpty()) { 81 | - player.connection.send(ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player)); // Paper - Add Listing API for Player 82 | + // Deepslate start - Don't send spectator mode packets to other players 83 | + ClientboundPlayerInfoUpdatePacket updatePacket = ClientboundPlayerInfoUpdatePacket.createPlayerInitializing(onlinePlayers, player); 84 | + if (!de.pascalpex.deepslatemc.files.Config.getSendSpectatorModePackets()) { 85 | + List newEntries = new java.util.ArrayList<>(); 86 | + for (ClientboundPlayerInfoUpdatePacket.Entry entry : updatePacket.entries()) { 87 | + ClientboundPlayerInfoUpdatePacket.Entry newEntry = new ClientboundPlayerInfoUpdatePacket.Entry( 88 | + entry.profileId(), 89 | + entry.profile(), 90 | + entry.listed(), 91 | + entry.latency(), 92 | + entry.gameMode() == net.minecraft.world.level.GameType.SPECTATOR ? net.minecraft.world.level.GameType.SURVIVAL : entry.gameMode(), 93 | + entry.displayName(), 94 | + entry.showHat(), 95 | + entry.listOrder(), 96 | + entry.chatSession()); 97 | + newEntries.add(newEntry); 98 | + } 99 | + updatePacket = new ClientboundPlayerInfoUpdatePacket(updatePacket.actions(), newEntries); 100 | + } 101 | + player.connection.send(updatePacket); // Paper - Add Listing API for Player 102 | + // Deepslate end - Don't send spectator mode packets to other players 103 | } 104 | // Paper end - Use single player info update packet on join 105 | player.sentListPacket = true; 106 | -------------------------------------------------------------------------------- /deepslateMC-server/src/main/java/de/pascalpex/deepslatemc/files/Config.java: -------------------------------------------------------------------------------- 1 | package de.pascalpex.deepslatemc.files; 2 | 3 | import org.apache.logging.log4j.LogManager; 4 | import org.apache.logging.log4j.Logger; 5 | import org.bukkit.Bukkit; 6 | import org.bukkit.Location; 7 | import org.bukkit.World; 8 | import org.bukkit.configuration.InvalidConfigurationException; 9 | import org.bukkit.configuration.file.FileConfiguration; 10 | import org.bukkit.configuration.file.YamlConfiguration; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.util.ArrayList; 15 | import java.util.Arrays; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | import static de.pascalpex.deepslatemc.files.ConfigEntry.*; 21 | 22 | public class Config { 23 | 24 | public static final File configFile = new File("deepslate", "deepslate.yml"); 25 | public static final FileConfiguration config = YamlConfiguration.loadConfiguration(configFile); 26 | 27 | private static final Logger LOGGER = LogManager.getLogger(Config.class.getSimpleName()); 28 | private static final String SPARK_EXTRA_PROPERTY = "spark.serverconfigs.extra"; 29 | 30 | public static void load() { 31 | try { 32 | configFile.getParentFile().mkdirs(); 33 | if (!configFile.exists()) { 34 | configFile.createNewFile(); 35 | List header = new ArrayList<>(); 36 | header.add("This is the main configuration file of DeepslateMC"); 37 | header.add("You can find an explanation of all options here: https://github.com/Pascalpex/DeepslateMC/wiki"); 38 | header.add("You can get support on our Discord server: https://discord.gg/BGrhNnVczp"); 39 | config.options().setHeader(header); 40 | save(); 41 | } 42 | config.load(configFile); 43 | for(ConfigEntry configEntry : ConfigEntry.values()) { 44 | if(configEntry.defaultValue == null) { 45 | continue; 46 | } 47 | if(!config.contains(configEntry.key)) { 48 | if(configEntry == SERVER_LINKS) { 49 | config.set(SERVER_LINKS.key + ".My first link", ""); 50 | continue; 51 | } 52 | config.set(configEntry.key, configEntry.defaultValue); 53 | } 54 | } 55 | save(); 56 | LOGGER.info("Loaded DeepslateMC config file"); 57 | } catch (IOException | InvalidConfigurationException e) { 58 | LOGGER.error("Error loading DeepslateMC config", e); 59 | } 60 | } 61 | 62 | public static void save() { 63 | try { 64 | config.save(configFile); 65 | } catch (IOException e) { 66 | LOGGER.error("Error saving DeepslateMC config", e); 67 | } 68 | } 69 | 70 | public static void addSparkEntry() { 71 | List additionalConfigs = new ArrayList<>(List.of( 72 | configFile.getPath() 73 | )); 74 | 75 | String existingConfigs = System.getProperty(SPARK_EXTRA_PROPERTY); 76 | if (existingConfigs != null) { 77 | additionalConfigs.addAll(Arrays.asList(existingConfigs.split(","))); 78 | } 79 | 80 | System.setProperty(SPARK_EXTRA_PROPERTY, String.join(",", additionalConfigs)); 81 | } 82 | 83 | public static boolean getOpActive() { 84 | return config.getBoolean(OP_COMMAND_ACTIVE.key); 85 | } 86 | public static String getDiscordLink() { 87 | return config.getString(DISCORD_LINK.key); 88 | } 89 | public static String getBuildworld() { 90 | return config.getString(BUILDWORLD.key); 91 | } 92 | public static void setBuildworld(String worldName) { 93 | config.set(BUILDWORLD.key, worldName); 94 | save(); 95 | } 96 | public static boolean getMaintenanceMode() { 97 | return config.getBoolean(MAINTENANCE_MODE.key); 98 | } 99 | public static void toggleMaintenanceMode() { 100 | config.set(MAINTENANCE_MODE.key, !getMaintenanceMode()); 101 | save(); 102 | } 103 | public static boolean getSpawnOnJoin() { 104 | return config.getBoolean(SPAWN_ON_JOIN.key); 105 | } 106 | public static void setSpawn(Location loc) { 107 | config.set(SPAWN_WORLD.key, loc.getWorld().getName()); 108 | config.set(SPAWN_X.key, loc.getX()); 109 | config.set(SPAWN_Y.key, loc.getY()); 110 | config.set(SPAWN_Z.key, loc.getZ()); 111 | config.set(SPAWN_PITCH.key, (double) loc.getPitch()); 112 | config.set(SPAWN_YAW.key, (double) loc.getYaw()); 113 | save(); 114 | } 115 | public static Location getSpawn() { 116 | World world = Bukkit.getWorld(config.getString(SPAWN_WORLD.key)); 117 | double x = config.getDouble(SPAWN_X.key); 118 | double y = config.getDouble(SPAWN_Y.key); 119 | double z = config.getDouble(SPAWN_Z.key); 120 | float pitch = (float) config.getDouble(SPAWN_PITCH.key); 121 | float yaw = (float) config.getDouble(SPAWN_YAW.key); 122 | return new Location(world, x, y, z, yaw, pitch); 123 | } 124 | public static boolean getPreventKnowledgebookClick() { 125 | return config.getBoolean(KNOWLEDGE_BOOK_CLICK.key); 126 | } 127 | public static boolean getMovedQuickly() { 128 | return config.getBoolean(MOVED_QUICKLY_MESSAGES.key); 129 | } 130 | public static boolean getMovedWrongly() { 131 | return config.getBoolean(MOVED_WRONGLY_MESSAGES.key); 132 | } 133 | public static String getF3name() { 134 | return config.getString(F3_NAME.key).replace("&", "§"); 135 | } 136 | public static boolean getTablistEnabled() { 137 | return config.getBoolean(TABLIST_ENABLED.key); 138 | } 139 | public static List getHeader() { 140 | return config.getList(TABLIST_HEADER.key).stream().map(Object::toString).toList(); 141 | } 142 | public static List getFooter() { 143 | return config.getList(TABLIST_FOOTER.key).stream().map(Object::toString).toList(); 144 | } 145 | public static boolean getPlayerlistHoverEnabled() { 146 | return config.getBoolean(PLAYERLIST_HOVER_ENABLED.key); 147 | } 148 | public static List getPlayerlistHoverLines() { 149 | return config.getList(PLAYERLIST_HOVER_LINES.key).stream().map(Object::toString).toList(); 150 | } 151 | public static boolean getBossbarEnabled() { 152 | return config.getBoolean(BOSSBAR_ENABLED.key); 153 | } 154 | public static String getBossbarColor() { 155 | return config.getString(BOSSBAR_COLOR.key); 156 | } 157 | public static String getBossbarText() { 158 | return config.getString(BOSSBAR_TEXT.key); 159 | } 160 | public static String getBossbarStyle() { 161 | return config.getString(BOSSBAR_STYLE.key); 162 | } 163 | public static float getBossbarProgress() { 164 | return (float) config.getDouble(BOSSBAR_PROGRESS.key); 165 | } 166 | public static boolean getActionbarEnabled() { 167 | return config.getBoolean(ACTIONBAR_ENABLED.key); 168 | } 169 | public static String getActionbarText() { 170 | return config.getString(ACTIONBAR_TEXT.key); 171 | } 172 | public static boolean getMinimessageMotd() { 173 | return config.getBoolean(MINIMESSAGE_MOTD.key); 174 | } 175 | public static boolean getMinimessageMessages() { 176 | return config.getBoolean(MINIMESSAGE_MESSAGES.key); 177 | } 178 | public static boolean getSendSpectatorModePackets() { 179 | return config.getBoolean(SPECTATOR_MODE_PACKETS.key); 180 | } 181 | public static Map getServerLinks() { 182 | Map serverLinks = new HashMap<>(); 183 | config.getConfigurationSection(SERVER_LINKS.key).getKeys(false).forEach(key -> serverLinks.put(key, config.getString(SERVER_LINKS.key + "." + key))); 184 | return serverLinks; 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | # SPDX-License-Identifier: Apache-2.0 19 | # 20 | 21 | ############################################################################## 22 | # 23 | # Gradle start up script for POSIX generated by Gradle. 24 | # 25 | # Important for running: 26 | # 27 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 28 | # noncompliant, but you have some other compliant shell such as ksh or 29 | # bash, then to run this script, type that shell name before the whole 30 | # command line, like: 31 | # 32 | # ksh Gradle 33 | # 34 | # Busybox and similar reduced shells will NOT work, because this script 35 | # requires all of these POSIX shell features: 36 | # * functions; 37 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 38 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 39 | # * compound commands having a testable exit status, especially «case»; 40 | # * various built-in commands including «command», «set», and «ulimit». 41 | # 42 | # Important for patching: 43 | # 44 | # (2) This script targets any POSIX shell, so it avoids extensions provided 45 | # by Bash, Ksh, etc; in particular arrays are avoided. 46 | # 47 | # The "traditional" practice of packing multiple parameters into a 48 | # space-separated string is a well documented source of bugs and security 49 | # problems, so this is (mostly) avoided, by progressively accumulating 50 | # options in "$@", and eventually passing that to Java. 51 | # 52 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 53 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 54 | # see the in-line comments for details. 55 | # 56 | # There are tweaks for specific operating systems such as AIX, CygWin, 57 | # Darwin, MinGW, and NonStop. 58 | # 59 | # (3) This script is generated from the Groovy template 60 | # https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 61 | # within the Gradle project. 62 | # 63 | # You can find Gradle at https://github.com/gradle/gradle/. 64 | # 65 | ############################################################################## 66 | 67 | # Attempt to set APP_HOME 68 | 69 | # Resolve links: $0 may be a link 70 | app_path=$0 71 | 72 | # Need this for daisy-chained symlinks. 73 | while 74 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 75 | [ -h "$app_path" ] 76 | do 77 | ls=$( ls -ld "$app_path" ) 78 | link=${ls#*' -> '} 79 | case $link in #( 80 | /*) app_path=$link ;; #( 81 | *) app_path=$APP_HOME$link ;; 82 | esac 83 | done 84 | 85 | # This is normally unused 86 | # shellcheck disable=SC2034 87 | APP_BASE_NAME=${0##*/} 88 | # Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) 89 | APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | 118 | 119 | # Determine the Java command to use to start the JVM. 120 | if [ -n "$JAVA_HOME" ] ; then 121 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 122 | # IBM's JDK on AIX uses strange locations for the executables 123 | JAVACMD=$JAVA_HOME/jre/sh/java 124 | else 125 | JAVACMD=$JAVA_HOME/bin/java 126 | fi 127 | if [ ! -x "$JAVACMD" ] ; then 128 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 129 | 130 | Please set the JAVA_HOME variable in your environment to match the 131 | location of your Java installation." 132 | fi 133 | else 134 | JAVACMD=java 135 | if ! command -v java >/dev/null 2>&1 136 | then 137 | die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 138 | 139 | Please set the JAVA_HOME variable in your environment to match the 140 | location of your Java installation." 141 | fi 142 | fi 143 | 144 | # Increase the maximum file descriptors if we can. 145 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 146 | case $MAX_FD in #( 147 | max*) 148 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 149 | # shellcheck disable=SC2039,SC3045 150 | MAX_FD=$( ulimit -H -n ) || 151 | warn "Could not query maximum file descriptor limit" 152 | esac 153 | case $MAX_FD in #( 154 | '' | soft) :;; #( 155 | *) 156 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 157 | # shellcheck disable=SC2039,SC3045 158 | ulimit -n "$MAX_FD" || 159 | warn "Could not set maximum file descriptor limit to $MAX_FD" 160 | esac 161 | fi 162 | 163 | # Collect all arguments for the java command, stacking in reverse order: 164 | # * args from the command line 165 | # * the main class name 166 | # * -classpath 167 | # * -D...appname settings 168 | # * --module-path (only if needed) 169 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 170 | 171 | # For Cygwin or MSYS, switch paths to Windows format before running java 172 | if "$cygwin" || "$msys" ; then 173 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 174 | 175 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 176 | 177 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 178 | for arg do 179 | if 180 | case $arg in #( 181 | -*) false ;; # don't mess with options #( 182 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 183 | [ -e "$t" ] ;; #( 184 | *) false ;; 185 | esac 186 | then 187 | arg=$( cygpath --path --ignore --mixed "$arg" ) 188 | fi 189 | # Roll the args list around exactly as many times as the number of 190 | # args, so each arg winds up back in the position where it started, but 191 | # possibly modified. 192 | # 193 | # NB: a `for` loop captures its iteration list before it begins, so 194 | # changing the positional parameters here affects neither the number of 195 | # iterations, nor the values presented in `arg`. 196 | shift # remove old arg 197 | set -- "$@" "$arg" # push replacement arg 198 | done 199 | fi 200 | 201 | 202 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 203 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 204 | 205 | # Collect all arguments for the java command: 206 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, 207 | # and any embedded shellness will be escaped. 208 | # * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be 209 | # treated as '${Hostname}' itself on the command line. 210 | 211 | set -- \ 212 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 213 | -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ 214 | "$@" 215 | 216 | # Stop when "xargs" is not available. 217 | if ! command -v xargs >/dev/null 2>&1 218 | then 219 | die "xargs is not available" 220 | fi 221 | 222 | # Use "xargs" to parse quoted args. 223 | # 224 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 225 | # 226 | # In Bash we could simply go: 227 | # 228 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 229 | # set -- "${ARGS[@]}" "$@" 230 | # 231 | # but POSIX shell has neither arrays nor command substitution, so instead we 232 | # post-process each arg (as a line of input to sed) to backslash-escape any 233 | # character that might be a shell metacharacter, then use eval to reverse 234 | # that process (while maintaining the separation between arguments), and wrap 235 | # the whole thing up as a single "set" statement. 236 | # 237 | # This will of course break if any of these variables contains a newline or 238 | # an unmatched quote. 239 | # 240 | 241 | eval "set -- $( 242 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 243 | xargs -n1 | 244 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 245 | tr '\n' ' ' 246 | )" '"$@"' 247 | 248 | exec "$JAVACMD" "$@" 249 | --------------------------------------------------------------------------------