Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -112,5 +112,10 @@
"event-listener-missing-class-problem": "The plugin '{{plugin-name}}' could not register the event listener '{{listener}}', because the class '{{missing-class}}' it references does not exist.",
"client-only-mod-problem": "The mod '{{mod-name}}' cannot run on a server. It is either a client-only mod or uses client-only code.",
"circular-plugin-dependency-problem": "Circular plugin dependencies detected: {{cycle}}.",
"restricted-plugin-name-problem": "A plugin has a name that is not allowed."
"restricted-plugin-name-problem": "A plugin has a name that is not allowed.",
"paper-newer-config-file-problem": "The Paper config file '{{file-path}}' was created by a newer Paper version (config version {{config-version}}, this server supports up to {{supported-version}}). Settings in it might not work.",
"paper-newer-world-config-problem": "The Paper config file of the world '{{world-name}}' was created by a newer Paper version (config version {{config-version}}, this server supports up to {{supported-version}}). Settings in it might not work.",
"paper-config-reset-solution": "Back up and delete the file '{{file-path}}'. Paper creates it again with default settings.",
"paper-world-config-reset-solution": "Back up and delete the file 'paper-world.yml' of the world '{{world-name}}'. Paper creates it again with default settings.",
"paper-install-newer-version-solution": "Install the newer Paper version that created this config file."
}
2 changes: 2 additions & 0 deletions src/Analyser/PaperAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Aternos\Codex\Minecraft\Analysis\Problem\Paper\EventListenerMissingClassProblem;
use Aternos\Codex\Minecraft\Analysis\Problem\Paper\CircularPluginDependencyProblem;
use Aternos\Codex\Minecraft\Analysis\Problem\Paper\RestrictedPluginNameProblem;
use Aternos\Codex\Minecraft\Analysis\Problem\Paper\NewerConfigVersionProblem;

class PaperAnalyser extends BukkitAnalyser
{
Expand All @@ -34,5 +35,6 @@ public function __construct()
$this->addPossibleInsightClass(EventListenerMissingClassProblem::class);
$this->addPossibleInsightClass(CircularPluginDependencyProblem::class);
$this->addPossibleInsightClass(RestrictedPluginNameProblem::class);
$this->addPossibleInsightClass(NewerConfigVersionProblem::class);
}
}
136 changes: 136 additions & 0 deletions src/Analysis/Problem/Paper/NewerConfigVersionProblem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
<?php

namespace Aternos\Codex\Minecraft\Analysis\Problem\Paper;

use Aternos\Codex\Analysis\InsightInterface;
use Aternos\Codex\Minecraft\Analysis\Solution\Paper\PaperConfigResetSolution;
use Aternos\Codex\Minecraft\Analysis\Solution\Paper\PaperInstallNewerVersionSolution;
use Aternos\Codex\Minecraft\Analysis\Solution\Paper\PaperWorldConfigResetSolution;
use Aternos\Codex\Minecraft\Translator\Translator;

/**
* A Paper configuration file has a higher config version than the server supports,
* usually because the server was downgraded to an older Paper version.
* Paper still starts, but settings from the newer version might be ignored or misread.
*
* The path of a world config file is not reported, because it depends on the Paper version:
* up to 1.21 it is in the world folder ('world_nether/paper-world.yml'),
* since 26.1 it is in the dimension folder ('world/dimensions/minecraft/the_nether/paper-world.yml').
*/
class NewerConfigVersionProblem extends PaperProblem
{
/**
* The start shared by all variants of the message, capturing both config versions.
*
* Example: Loading a newer configuration than is supported (999 > 31)! You may have to backup & delete
*/
protected const string NEWER_CONFIG_PREFIX = 'Loading a newer configuration than is supported \((?<config_version>\d+) > (?<supported_version>\d+)\)! You may have to backup & delete ';

protected const string GLOBAL_CONFIG_PATH = "config/paper-global.yml";
protected const string WORLD_DEFAULTS_CONFIG_PATH = "config/paper-world-defaults.yml";

protected int $configVersion;
protected int $supportedVersion;
protected ?string $filePath = null;
protected ?string $worldName = null;

/**
* @inheritDoc
*/
public function getMessage(): string
{
$placeholders = [
"config-version" => $this->configVersion,
"supported-version" => $this->supportedVersion
];

if ($this->worldName !== null) {
return Translator::getInstance()->getTranslation("paper-newer-world-config-problem",
["world-name" => $this->worldName, ...$placeholders]);
}

return Translator::getInstance()->getTranslation("paper-newer-config-file-problem",
["file-path" => $this->filePath, ...$placeholders]);
}

/**
* Global config, world defaults config and the config of a single world.
* Newer Paper versions name the world by its key ('minecraft:the_nether'), older ones by its name ('world_nether').
*
* Example: Loading a newer configuration than is supported (999 > 31)! You may have to backup & delete your global config file to start the server.
* Example: Loading a newer configuration than is supported (999 > 31)! You may have to backup & delete the world defaults config file to start the server.
* Example: Loading a newer configuration than is supported (999 > 31)! You may have to backup & delete the minecraft:the_nether config file to start the server.
* Example: Loading a newer configuration than is supported (999 > 31)! You may have to backup & delete the world_nether config file to start the server.
*
* @inheritDoc
*/
public static function getPatterns(): array
{
return [
'/' . static::NEWER_CONFIG_PREFIX . 'your global config file to start the server\./',
'/' . static::NEWER_CONFIG_PREFIX . 'the world defaults config file to start the server\./',
'/' . static::NEWER_CONFIG_PREFIX . 'the (?<world>\S+) config file to start the server\./'
];
}

/**
* @inheritDoc
*/
public function setMatches(array $matches, mixed $patternKey): void
{
$this->configVersion = (int)$matches["config_version"];
$this->supportedVersion = (int)$matches["supported_version"];

if ($patternKey === 2) {
$this->worldName = $matches["world"];
$this->addSolution(new PaperWorldConfigResetSolution($this->worldName));
} else {
$this->filePath = $patternKey === 0 ? static::GLOBAL_CONFIG_PATH : static::WORLD_DEFAULTS_CONFIG_PATH;
$this->addSolution(new PaperConfigResetSolution($this->filePath));
}

$this->addSolution(new PaperInstallNewerVersionSolution());
}

/**
* @return int
*/
public function getConfigVersion(): int
{
return $this->configVersion;
}

/**
* @return int
*/
public function getSupportedVersion(): int
{
return $this->supportedVersion;
}

/**
* @return string|null The path of the global or world defaults config, null for the config of a single world
*/
public function getFilePath(): ?string
{
return $this->filePath;
}

/**
* @return string|null The name or key of the world, null for the global or world defaults config
*/
public function getWorldName(): ?string
{
return $this->worldName;
}

/**
* @inheritDoc
*/
public function isEqual(InsightInterface $insight): bool
{
return $insight instanceof static
&& $this->getFilePath() === $insight->getFilePath()
&& $this->getWorldName() === $insight->getWorldName();
}
}
37 changes: 37 additions & 0 deletions src/Analysis/Solution/Paper/PaperConfigResetSolution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Aternos\Codex\Minecraft\Analysis\Solution\Paper;

use Aternos\Codex\Minecraft\Translator\Translator;

/**
* Back up and delete a Paper config file, so that Paper creates it again with default settings.
* Deliberately not automatable, because deleting the file loses all settings in it.
*/
class PaperConfigResetSolution extends PaperSolution
{
/**
* @param string $filePath The path of the config file, relative to the server root
*/
public function __construct(protected string $filePath)
{
}

/**
* @inheritDoc
*/
public function getMessage(): string
{
return Translator::getInstance()->getTranslation("paper-config-reset-solution", [
"file-path" => $this->filePath
]);
}

/**
* @return string
*/
public function getFilePath(): string
{
return $this->filePath;
}
}
19 changes: 19 additions & 0 deletions src/Analysis/Solution/Paper/PaperInstallNewerVersionSolution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<?php

namespace Aternos\Codex\Minecraft\Analysis\Solution\Paper;

use Aternos\Codex\Minecraft\Translator\Translator;

/**
* Install the newer Paper version that a config file was created with.
*/
class PaperInstallNewerVersionSolution extends PaperSolution
{
/**
* @inheritDoc
*/
public function getMessage(): string
{
return Translator::getInstance()->getTranslation("paper-install-newer-version-solution");
}
}
37 changes: 37 additions & 0 deletions src/Analysis/Solution/Paper/PaperWorldConfigResetSolution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

namespace Aternos\Codex\Minecraft\Analysis\Solution\Paper;

use Aternos\Codex\Minecraft\Translator\Translator;

/**
* Back up and delete the 'paper-world.yml' of a single world, so that Paper creates it again with default settings.
* Names the world instead of a path, because the location of the file depends on the Paper version.
*/
class PaperWorldConfigResetSolution extends PaperSolution
{
/**
* @param string $worldName The name or key of the world, like 'world_nether' or 'minecraft:the_nether'
*/
public function __construct(protected string $worldName)
{
}

/**
* @inheritDoc
*/
public function getMessage(): string
{
return Translator::getInstance()->getTranslation("paper-world-config-reset-solution", [
"world-name" => $this->worldName
]);
}

/**
* @return string
*/
public function getWorldName(): string
{
return $this->worldName;
}
}
Loading
Loading