Скрипт для раскукоживания SkillName-* в IO+

Gaikotsu

яжпрограммист
Легенда
Победитель в номинации 2023
Победитель в номинации 2022
Победитель в номинации 2021
Участник Новогоднего Фонда 2021
Эксперт
Знаток
Просветитель
Магистр реакций
Знаток письма
Куратор Данных
Медаль Благодарности
Старожил II степени
Старожил I степени
Победитель в номинации 2020
Победитель в номинации 2019
Клиент разработчик
Преподаватель
За веру и верность форуму
Победитель в номинации 2018
Медаль за активность на Форуме
За заслуги перед форумом
Web разработчик
Разработчик
За знание датапака
За знание ядра
Сообщения
1 519
Розыгрыши
0
Решения
24
Репутация
6 004
Реакции
2 579
Баллы
2 188
Все в курсе думаю, что начиная с IO и далее, данные в файле SkillName-*.dat корейцы начали хранить особым способом, для сокращения объемов файла.
Примерно вот так:
Код:
skill_begin    skill_id=1    skill_level=1    skill_sublevel=0    prev_skill_id=0    prev_skill_level=-1    prev_skill_sublevel=-1    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно $s1 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[517]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=2    skill_sublevel=0    prev_skill_id=1    prev_skill_level=1    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[]    desc_param=[549]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=3    skill_sublevel=0    prev_skill_id=1    prev_skill_level=2    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[]    desc_param=[583]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=4    skill_sublevel=0    prev_skill_id=1    prev_skill_level=3    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[]    desc_param=[619]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=5    skill_sublevel=0    prev_skill_id=1    prev_skill_level=4    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[]    desc_param=[656]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
т.е. если описание для разных уровней скилла по сути почти одинаковое и меняется лишь какое-то значение/значения в нем - это описание пишется только для одного уровня, а при загрузке файла клиентом просто идет копирование этой строки в другие уровни, с подстановкой нужных значений в эту строку.

Ну и собственно говоря, чисто для работы с данными из файла, типа сверок клиентских описаний на соответствие с тем что в сервере прописано, такой формат не очень удобен и не очень читаем.

Я вот для своих нужд набросал на скорую руку буквально за 10-15 минут простенький php-скрипт, который все эти описания в файле раскукоживает до более читабельного вида - вот до такого например:
Код:
skill_begin    skill_id=1    skill_level=1    skill_sublevel=0    prev_skill_id=0    prev_skill_level=-1    prev_skill_sublevel=-1    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно 517 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=2    skill_sublevel=0    prev_skill_id=1    prev_skill_level=1    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно 549 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=3    skill_sublevel=0    prev_skill_id=1    prev_skill_level=2    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно 583 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=4    skill_sublevel=0    prev_skill_id=1    prev_skill_level=3    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно 619 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
skill_begin    skill_id=1    skill_level=5    skill_sublevel=0    prev_skill_id=1    prev_skill_level=4    prev_skill_sublevel=0    name=[Тройное Рассечение]    desc=[Атакует и наносит дополнительно 656 ед. урона. Требуются парные мечи. Игнорирует защиту щитом. Возможен сверхудар. Возможен крит. удар.]    desc_param=[]    enchant_name=[]    enchant_name_param=[]    enchant_desc=[]    enchant_desc_param=[]    skill_end
Ну и собственно сам скрипт - может кому пригодится тоже:
PHP:
<?
$files = array(
	"../SkillName-ru.txt",
	"../SkillName-e.txt",
	);

function getKV($s)
{
	$t = explode("=", $s);

	if (strlen($t[1]) > 0)
	{
		if ($t[1][0] == "[")
			$t[1] = substr($t[1], 1, -1);
	}

	return $t;
}

function formatStr($s, $p)
{
	$p = explode(";", $p);

	for ($x = 1; $x <= count($p); $x++)
		$s = str_replace("\$s{$x}", $p[$x - 1], $s);

	return $s;
}

foreach ($files as $file)
{
	echo "load file [{$file}]...\n";
	$temp = explode("\n", file_get_contents($file));

	echo "prepare data [pass #1]...\n";
	$t0 = array();

	foreach ($temp as $t)
	{
		$t1 = explode("\t", $t);
		$t3 = array();

		for ($x = 1; $x < count($t1) - 1; $x++)
		{
			$t2 = getKV($t1[$x]);
			$t3[$t2[0]] = trim($t2[1]);
		}

		$t0[$t3["skill_id"]."_".$t3["skill_level"]."_".$t3["skill_sublevel"]] = $t3;
	}

	$temp = $t0;
	unset($t0);

	echo "prepare data [pass #2]...\n";

	foreach ($temp as $k => $v)
	{
		$psId = (int) $v["prev_skill_id"];
		$psLevel = (int) $v["prev_skill_level"];
		$psSubLevel = (int) $v["prev_skill_sublevel"];

		if ($psId != 0 && $psLevel != -1 && $psSubLevel != -1)
		{
			$uid = "{$psId}_{$psLevel}_{$psSubLevel}";

			if ($v["desc"] == "")
				$temp[$k]["desc"] = $temp[$uid]["desc"];

			if ($v["enchant_name"] == "")
				$temp[$k]["enchant_name"] = $temp[$uid]["enchant_name"];

			if ($v["enchant_desc"] == "")
				$temp[$k]["enchant_desc"] = $temp[$uid]["enchant_desc"];
		}
	}

	echo "prepare data [pass #3]...\n";

	foreach ($temp as $k => $v)
	{
		if ($v["desc_param"] != "")
		{
			$temp[$k]["desc"] = formatStr($v["desc"], $v["desc_param"]);
			$temp[$k]["desc_param"] = "";
		}

		if ($v["enchant_name_param"] != "")
		{
			$temp[$k]["enchant_name"] = formatStr($v["enchant_name"], $v["enchant_name_param"]);
			$temp[$k]["enchant_name_param"] = "";
		}

		if ($v["enchant_desc_param"] != "")
		{
			$temp[$k]["enchant_desc"] = formatStr($v["enchant_desc"], $v["enchant_desc_param"]);
			$temp[$k]["enchant_desc_param"] = "";
		}
	}

	$_file = "_".basename($file);
	echo "save file [{$_file}]...\n";

	$fh = fopen($_file, "w+");
	$t0 = array();

	foreach ($temp as $t)
	{
		$s = "skill_begin\t";
		$s .= "skill_id={$t['skill_id']}\tskill_level={$t['skill_level']}\tskill_sublevel={$t['skill_sublevel']}\t";
		$s .= "prev_skill_id={$t['prev_skill_id']}\tprev_skill_level={$t['prev_skill_level']}\tprev_skill_sublevel={$t['prev_skill_sublevel']}\t";
		$s .= "name=[{$t['name']}]\tdesc=[{$t['desc']}]\tdesc_param=[{$t['desc_param']}]\t";
		$s .= "enchant_name=[{$t['enchant_name']}]\tenchant_name_param=[{$t['enchant_name_param']}]\t";
		$s .= "enchant_desc=[{$t['enchant_desc']}]\tenchant_desc_param=[{$t['enchant_desc_param']}]\t";
		$s .= "skill_end";
		$t0[] = $s;

		if (count($t0) > 999)
		{
			fwrite($fh, implode("\n", $t0)."\n");
			$t0 = array();
		}
	}

	if (count($t0) > 0)
	{
		fwrite($fh, implode("\n", $t0));
		$t0 = array();
	}

	fclose($fh);
}
?>
 

    kick

    Баллов: 25
    Спасибо за вклад в развитие форума

    ArtToKill

    Баллов: 43
    Спасибо за вклад в развитие форума

    6yka

    Баллов: 32
    Спасибо за вклад в развитие форума

Исправление небольшой ошибки, замените в скрипте функцию formatStr на такую
PHP:
function formatStr($s, $p)
{
	$p = explode(";", $p);

	for ($x = count($p); $x > 0; $x--)
		$s = str_replace("\$s{$x}", $p[$x - 1], $s);

	return $s;
}
это исправит ошибку форматирования строк, в которых имеется больше 9 подставляемых параметров.
 
Обновленная версия для более новых хроник, в которых в скилнейме уже нет полей prev_skill_id/prev_skill_level/prev_skill_sublevel, по которым в предыдущей версии шло определение того, откуда взять строки описаний и т.д.
PHP:
<?php
$files =
[
    "../SkillName-ru.txt",
    "../en/SkillName-eu.txt",
    "../classic/SkillName_Classic-ru.txt",
    "../en/classic/SkillName_Classic-eu.txt",
    "../classic/SkillName_ClassicAden-ru.txt",
    "../en/classic/SkillName_ClassicAden-eu.txt",
];

function getKV($s)
{
    $t = explode("=", $s);

    if (strlen($t[1]) > 0)
    {
        if ($t[1][0] == "[")
            $t[1] = substr($t[1], 1, -1);

        $t[1] = str_replace("%%", "%", $t[1]);
    }

    return $t;
}

function formatStr($s, $p)
{
    $p = explode(";", $p);

    for ($x = count($p); $x > 0; $x--)
        $s = str_replace("\$s{$x}", $p[$x - 1], $s);

    return $s;
}

foreach ($files as $file)
{
    echo "load file [{$file}]...\n";
    $temp = explode("\n", file_get_contents($file));

    echo "prepare data [pass #1]...\n";
    $t0 = [];

    foreach ($temp as $t)
    {
        $t1 = explode("\t", trim($t));
        $t3 = [];

        for ($x = 1; $x < count($t1) - 1; $x++)
        {
            $t2 = getKV($t1[$x]);
            $t3[$t2[0]] = trim($t2[1]);
        }

        $t0[$t3["skill_id"]."_".$t3["skill_level"]."_".$t3["skill_sublevel"]] = $t3;
    }

    $temp = $t0;
    unset($t0);

    echo "prepare data [pass #2]...\n";

    $prev = null;

    foreach ($temp as $k => &$v)
    {
        if ($v["skill_level"] == 1)
        {
            $prev = $v;
            continue;
        }

        if ($v["desc"] == "")
            $v["desc"] = $prev["desc"];

        if ($v["enchant_name"] == "")
            $v["enchant_name"] = $prev["enchant_name"];

        if ($v["enchant_desc"] == "")
            $v["enchant_desc"] = $prev["enchant_desc"];

        $prev = $v;
    }

    echo "prepare data [pass #3]...\n";

    foreach ($temp as $k => $v)
    {
        if ($v["desc_param"] != "")
        {
            $temp[$k]["desc"] = formatStr($v["desc"], $v["desc_param"]);
            $temp[$k]["desc_param"] = "";
        }

        if ($v["enchant_name_param"] != "")
        {
            $temp[$k]["enchant_name"] = formatStr($v["enchant_name"], $v["enchant_name_param"]);
            $temp[$k]["enchant_name_param"] = "";
        }

        if ($v["enchant_desc_param"] != "")
        {
            $temp[$k]["enchant_desc"] = formatStr($v["enchant_desc"], $v["enchant_desc_param"]);
            $temp[$k]["enchant_desc_param"] = "";
        }
    }

    $_file = "_".basename($file);
    echo "save file [{$_file}]...\n";

    $fh = fopen($_file, "w+");
    $t0 = array();

    foreach ($temp as $t)
    {
        $s = "skill_begin\t";
        $s .= "skill_id={$t['skill_id']}\tskill_level={$t['skill_level']}\tskill_sublevel={$t['skill_sublevel']}\t";
        $s .= "name=[{$t['name']}]\tdesc=[{$t['desc']}]\tdesc_param=[{$t['desc_param']}]\t";
        $s .= "enchant_name=[{$t['enchant_name']}]\tenchant_name_param=[{$t['enchant_name_param']}]\t";
        $s .= "enchant_desc=[{$t['enchant_desc']}]\tenchant_desc_param=[{$t['enchant_desc_param']}]\t";
        $s .= "skill_end";
        $t0[] = $s;

        if (count($t0) > 999)
        {
            fwrite($fh, implode("\n", $t0)."\n");
            $t0 = array();
        }
    }

    if (count($t0) > 0)
    {
        fwrite($fh, implode("\n", $t0));
        $t0 = array();
    }

    fclose($fh);
}
?>
 
Назад
Сверху Снизу