Спасибо за ответ. По началу я таким же способом и хотел парситьПримерно так:
1) Для начала определяешь полную структуру файла. То есть из каких характеристик состоит каждый скилл.
2) Для каждой характеристики задаешь метод, который парсит значение. Например, [s_power_strike11] - считываем как строку или что-то другое, как душе угодно. Или enemy - парсим как значение enum`а.
3) Помимо сплита по \t (допустим String[] tabSplitted) еще сплитить потом каждый элемент по '=' (допустим String[] element). Ну и потом в зависимости от element[0] соответственно парсим значение из element[1] для каждого tabSplitted.
Возможно это проще сделать с помощью регулярных выражений, но я особо ими не пользовался, поэтому не знаю.
Вот из-за того, что количество параметров периодически меняется, и нужно сплитить по =. А в структуре задаем обязательные и необязательные для считывания поля (с дефолтным значением). Например:Спасибо за ответ. По началу я таким же способом и хотел парситьпотом понял, что скиллы имеют разное количество параметров: от 7 до 37. соответственно привязываться по номеру элемента уже нельзя. Здесь нужно как-то сопоставить имя параметра и переменную.
п.с. с регулярными та же фигня
public class Skill {
@Required
private String _name;
@Required
private int _id;
...
private RideState _rideState = RideState.NONE;
...
}
Map<String, Skill> (где идентификатор - skill_name) или Map<Integer, Skill> loadedSkills;
Files.lines(Paths.get(SKILLDATA_FILENAME)).forEach((el) -> {
String[] splittedLine = el.split("\t");
if (splittedLine == null || splittedLine.length() <= 2)
throw new DataParseException(...);
Skill newSkill = new Skill();
for (int i = 1; i < el.length() - 1; i++) {
if (splittedLine[i].trim().isEmpty())
throw new DataParseException(...);
String[] skillParameter = splittedLine[i].split("=");
switch (skillParameter[0]) {
case "skill_name":
newSkill.parseName(skillParameter[1]) или newSkill.setId(SkillParser.parseName(skillParameter[1])), тут как удобней
break;
...
default:
log.warn(...); // что-то, что не можем прочитать
}
}
if (newSkill.isValid())
loadedSkills.put(newSkill.getName() или newSkill.getId(), newSkill);
else
log.warn(...);
});
Почва в виде вспомогательных классов уже подготовлена. Вопрос пока стоит лишь в том, как оптимальнее заполнить этими данными наш объектВпрочем, если нужно считывать все файлы, то оптимальней будет создать какой-то PtsDataReader, который парсит имена и значения параметров. Судя по строке из skilldata в топике, можно такие типы данных как:
- строка или параметр из *pch - [текст]
- число
- enum - A1, enemy, single, возможно и @ride_none, но не уверен, что значит этот @
- объект - {{i_p_attack_over_hit;25;0}}
- массив - ? (по идее он должен где-то всплыть и возможно будет что-то вроде [1;2;3]
ну и т.д.
Вернитесь к изначальному варианту, только вспомните про чудесный "startsWith", может быть более опытные программисты посчитаю и не правильным, но на практике это самый быстрый и простой способ, работает быстрей чем вариант у JTS(не знаю что в этих сорсах, сравнивалось много лет назад в паке который делал камелион).Спасибо за ответ. По началу я таким же способом и хотел парситьпотом понял, что скиллы имеют разное количество параметров: от 7 до 37. соответственно привязываться по номеру элемента уже нельзя. Здесь нужно как-то сопоставить имя параметра и переменную.
п.с. с регулярными та же фигня
Думаю очевидно, что каждый парсер требует индивидуального подхода при совершенно любой его реализации, скилы парсятся таким образом, можно еще через Field парсить, нпсдат парсится в сто раз проще скилов...скилы и нпспос самые громоздкие...если бы я этот код разбил на три десятка нелепых классов, тогда вы наверно бы точно заценили и поставили класс/лайк/сердечкоСмотрю я на ваш код и аж стало интересно как вы npcdata будете парсить, где для некоторых токенов = нет
Повезло ПТС, особенно с учетом того, что он сто лет парсит эту датку, смею предположить что он просто find field по строке, но это сомнительное решение...И да, говорю сразу: птс принимает не \t, а например 5 пробелов. В итоге ваши парсеры нахер сломаются
Целых 0.0001 секунды при старте сервера мало, что дадут.Повезло ПТС, особенно с учетом того, что он сто лет парсит эту датку, смею предположить что он просто find field по строке, но это сомнительное решение...
да даже 30 секунд на старте сервера игрокам погоды не сделают.Целых 0.0001 секунды при старте сервера мало, что дадут.
Насколько я помню, он просто идет по строке.
ну, такое...если 30 секунд грузить скиллы, 10 минут нпс, 5 минут геодату, то старта сервера придется ждать часда даже 30 секунд на старте сервера игрокам погоды не сделают.
Круто, быстрее зато каждый файл нести ахинею, и описывать каждое поле для каждого файла. Логика достойная. Но да ладно, судя по всему кто то гонится за быстрым стартом сервера, тогда вопрос почему все поля типа int, имеют примитив Integer.parseInt(val)? Ведь мы гонимся за оптимизацией, и быстрой загрузкой сервера, ведь большинство параметров значения типа "уровня" 0-127, есть конечно же и больше. Хм... Может стоит использовать valueOf? Ведь он умеет ложить значения -128 127 в кэш, не копируя каждый раз.Вернитесь к изначальному варианту, только вспомните про чудесный "startsWith", может быть более опытные программисты посчитаю и не правильным, но на практике это самый быстрый и простой способ, работает быстрей чем вариант у JTS(не знаю что в этих сорсах, сравнивалось много лет назад в паке который делал камелион).
ПТС с НПС за 29 секунд? мммм) что-то новенькое. Как добились успеха?)Запускаем весь сервер + нпц сервер за 10-30 секунд
Ой, давай не будем про ахинею, хоть палец в жопу, хоть куда, нужно описывать каждый файл персонально, только в случае с решением камаэля, нужно еще сделать 100 классов, а потом с их помощью описывать "не ахинею"...Никто, ни за чем не гонится, это было просто к слову сказано...Конкретно на скрине, левел в int ибо в конечном итоге он всеравно будет преобразован в него, данные которые помещаются в byte/short и не переходят в int, сидят в byte/short...Использование кеша здесь мало того что беспощадно бестолковое, так еще и код писался 8 лет назад, когда я понятия не имел о многих вещах...Круто, быстрее зато каждый файл нести ахинею, и описывать каждое поле для каждого файла. Логика достойная. Но да ладно, судя по всему кто то гонится за быстрым стартом сервера, тогда вопрос почему все поля типа int, имеют примитив Integer.parseInt(val)? Ведь мы гонимся за оптимизацией, и быстрой загрузкой сервера, ведь большинство параметров значения типа "уровня" 0-127, есть конечно же и больше. Хм... Может стоит использовать valueOf? Ведь он умеет ложить значения -128 127 в кэш, не копируя каждый раз.
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?