Got old Windows datapack and monsters do not load on Linux? [on Linux
Downloaded map with
Find all bugged names and fixes for them.
Code suggests existing file path with same lowercase file path as in
Online version: OTS.ME - Monsters & Spawn files checker (https://ots.me/monsters-fixer/)
It generates reports like this:

Sorry for ugly variables and 20
PHP code:
achad.xml != Achad.xml]Downloaded map with
spawns.xml, but some monster are not in your datapack?Find all bugged names and fixes for them.
Code suggests existing file path with same lowercase file path as in
monsters.xml. If there is none, it searches in all folders for file with same lowercase name.Online version: OTS.ME - Monsters & Spawn files checker (https://ots.me/monsters-fixer/)
It generates reports like this:

Sorry for ugly variables and 20
for/if. I made it few years ago to fix one datapack. I did not plan to release it, but there are still people that try to mix datapacks and get million errors on server startup.PHP code:
PHP:
<?php
function colorChanges($orginalString, $changedString)
{
$original = str_split($orginalString);
$changed = str_split($changedString);
$offset = 1;
$ret = '';
while($offset <= count($original) && $offset <= count($changed)) {
$o = $original[count($original)-$offset];
$c = $changed[count($changed)-$offset];
if($o == $c)
$ret = $o . $ret;
else
$ret = '<span class="diff">' . $c . '</span>' . $ret;
$offset++;
}
if (count($original) < count($changed)) {
while($offset <= count($changed)) {
$c = $changed[count($changed)-$offset];
$ret = '<span class="diff">' . $c . '</span>' . $ret;
$offset++;
}
}
return $ret;
}
$monstersErrorsList = array();
$spawnsErrorsList = array();
if(isset($_FILES['monsters_file']['tmp_name']))
{
try {
$monstersPaths = array();
$monstersZIP = new ZipArchive();
if($monstersZIP->open($_FILES['monsters_file']['tmp_name']))
{
// create list of .xml file paths in .zip
for($i = 0; $i < $monstersZIP->numFiles; $i++) {
$monsterFilePath = $monstersZIP->getNameIndex($i);
if(substr($monsterFilePath, -4, 4) == '.xml'){
$monstersPaths[$monsterFilePath] = $monsterFilePath;
}
}
// remove 'monster/' from file paths
$removeMonsterDir = true;
foreach($monstersPaths as $monsterPath)
{
if(substr($monsterPath, 0, 8) != 'monster/') {
$removeMonsterDir = false;
break;
}
}
if($removeMonsterDir)
{
$monstersFilePath = 'monster/monsters.xml';
foreach($monstersPaths as $monsterPath)
{
unset($monstersPaths[$monsterPath]);
$newMonsterPath = substr($monsterPath, 8, strlen($monsterPath) -8);
$monstersPaths[$newMonsterPath] = $newMonsterPath;
}
} else {
$monstersFilePath = 'monsters.xml';
}
ksort($monstersPaths);
$monstersPathsLowercase = [];
$monstersFilesLowercase = [];
foreach($monstersPaths as $value) {
$lowercasePath = strtolower($value);
$lowercaseFileName = array_reverse(explode('/', str_replace('\\', '/', strtolower($value))))[0];
$monstersPathsLowercase[$lowercasePath] = [
'path' => $value,
'lowercasePath' => $lowercasePath,
'lowercaseFileName' => $lowercaseFileName,
];
$monstersFilesLowercase[$lowercaseFileName] = [
'path' => $value,
'lowercasePath' => $lowercasePath,
'lowercaseFileName' => $lowercaseFileName,
];
}
}
else {
throw new RuntimeException('Failed to open monsters .zip file');
}
$monstersXMLfileContent = $monstersZIP->getFromName($monstersFilePath);
$monstersXML = new DOMDocument();
$monstersXML->loadXML($monstersXMLfileContent);
$monstersList = array();
$monstersElements = $monstersXML->getElementsByTagName('monster');
for($m = 0; $m < $monstersElements->length; $m++)
{
if($monstersElements->item($m)->hasAttributes() && $monstersElements->item($m)->attributes->getNamedItem('name') && $monstersElements->item($m)->attributes->getNamedItem('file'))
$monstersList[$monstersElements->item($m)->attributes->getNamedItem('name')->nodeValue] = $monstersElements->item($m)->attributes->getNamedItem('file')->nodeValue;
}
$i = 0;
$monsterPathId = array_values($monstersPaths);
foreach($monstersList as $name => $file)
{
if(!isset($monstersPaths[$file]))
{
$fileName = array_reverse(explode('/', str_replace('\\', '/', strtolower($file))))[0];
if(isset($monstersPathsLowercase[strtolower($file)])) { // same lowercase path
$result = [
'name' => $name,
'now' => colorChanges($monstersPathsLowercase[strtolower($file)]['path'], $file),
'proposition' => colorChanges($file, $monstersPathsLowercase[strtolower($file)]['path'])
];
} elseif(isset($monstersFilesLowercase[$fileName])) { // same lowercase file name
$result = [
'name' => $name,
'now' => colorChanges($monstersFilesLowercase[$fileName]['path'], $file),
'proposition' => colorChanges($file, $monstersFilesLowercase[$fileName]['path'])
];
} else {
$result = [
'name' => $name,
'now' => $file,
'proposition' => 'NONE :('
];
}
$monstersErrorsList[] = $result;
}
$i++;
}
if(!empty($_FILES['spawns_file']['tmp_name']))
{
$spawnsXML = new DOMDocument();
$spawnsXML->load($_FILES['spawns_file']['tmp_name']);
$spawnMonstersList = array();
$spawnsMonsters = $spawnsXML->getElementsByTagName('monster');
for($s = 0; $s < $spawnsMonsters->length; $s++) {
if($spawnsMonsters->item($s)->hasAttributes() && $spawnsMonsters->item($s)->attributes->getNamedItem('name')) {
$monsterName = $spawnsMonsters->item($s)->attributes->getNamedItem('name')->nodeValue;
$spawnMonstersList[] = $monsterName;
}
}
foreach($spawnMonstersList as $spawnMonsterName)
if(!isset($monstersList[$spawnMonsterName])) {
$result = [
'name' => $name,
'now' => $name,
'proposition' => 'NONE :('
];
// try to find monster in monster.xml with same lowercase name
foreach($monstersList as $name => $file) {
if (strtolower($name) == strtolower($spawnMonsterName)) {
$result = [
'name' => $name,
'now' => colorChanges($spawnMonsterName, $name),
'proposition' => colorChanges($name, $spawnMonsterName)
];
break;
}
}
$spawnsErrorsList[] = $result;
}
}
} catch(Exception $e) {
echo '<div style="font-size: 20px;color: red">Errors while loading files: ' . $e->getMessage() . '</div>';
} catch(ValueError $e) {
echo '<div style="font-size: 20px;color: red">Errors while loading ZIP archive. Probably you uploaded wrong file.</div>';
}
}
echo '<html><head><title>OTS.ME - Monsters & Spawn files checker</title></head><body>';
echo '<style>
table {
text-align: left;
border-collapse: collapse;
}
table td, table th {
border: 1px solid #AAAAAA;
padding: 5px 4px;
font-size: 16px;
}
.diff {
font-size: 18px;
color: blue;
}
</style>';
echo '<h3>ZIP your <i>data/monster</i> directory and upload to check <i>monster.xml</i> and file names compatibility</h3>';
echo '<h3>You can also upload your <i>data/world/spawns.xml</i> to check, if all monsters from map are in <i>monster.xml</i></h3>';
echo '<form action="index.php" method="post" enctype="multipart/form-data">
Monsters ZIP file: <input type="file" name="monsters_file" /> [monster.zip]<br />
Spawns file: <input type="file" name="spawns_file" /> [..-spawn.xml]<br />
<input type="submit" value="Send & verify" />
</form>';
echo '<div style="font-size: 20px;color: red">Wrong paths to monsters in monsters.xml:</div>';
echo '<table style="font-size:16px"><tr><th>Name</th><th>Now</th><th>Proposition</th></tr>';
foreach($monstersErrorsList as $errorData) {
echo '<tr><td>' . $errorData['name'] . '</td><td>' . $errorData['now'] . '</td><td>' . $errorData['proposition'] . '</td></tr>';
}
echo '</table>';
echo '<div style="font-size: 20px;color: red">Monsters from spawns file that can\'t be loaded:</div>';
echo '<table><tr><th>Name</th><th>Now</th><th>Proposition</th></tr>';
foreach($spawnsErrorsList as $errorData) {
echo '<tr><td>' . $errorData['name'] . '</td><td>' . $errorData['now'] . '</td><td>' . $errorData['proposition'] . '</td></tr>';
echo '</table>';
}[/php]