Форум администраторов игровых серверов

Форум администраторов игровых серверов (https://forum.zone-game.info/TT.php)
-   Игровой клиент (https://forum.zone-game.info/forumdisplay.php?f=54)
-   -   client files editor (https://forum.zone-game.info/showthread.php?t=29927)

acmi 06.07.2013 01:21

client files editor
 
В общем, как я писал ранее, я сел за написание утилиты для редактирования файлов клиента Lineage 2.
Итак, уже есть чем поделиться(правда конвертирование пока только в одну сторону).

На данный момент реализованы 2 ключевых класса для чтения.
L2FileInputStream
Как можно догадаться по названию, этот класс предоставляет возможность читать данные из файлов клиента. Он служит заменой утилите l2encdec, на лету снимает крипт и распаковывает.
L2DataInputStream
Этот класс реализует интерфейс DataInput, предоставляя методы для чтения базовых классов. Также он умеет считывать объекты по классу через рефлекшн.

Структура файлов описывается классами
Поэтому мы сразу получаем богатый набор инструментов для работы с ними(ORM, OXM, итд).

Пример использования(Клиент Lindvior NA)
PHP код:

import ee.l2.clientstuff.files.*;
import ee.l2.clientstuff.files.dat.*;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.FileInputStream;

public class 
Test2 {
    @
XmlRootElement
    
@DatFile(value "ActionName"localizable true)
    @
SafePackage
    
public static class ActionNameDat{
        public 
ActionName[] actionName;
    }

    public static class 
ActionName{
        @
IntConst(1)
        public 
int tag;
        public 
int id;
        public 
int type;
        public 
int category;
        @
Length(lengthType LengthType.COMPACT)
        public 
int[] unkIds;
        public 
String name;
        public 
String icon;
        public 
String icon2;
        public 
String desc;
        public 
boolean unkBool;
        @
Unicode
        
public String cmd;
    }

    public static 
void main(String[] argsthrows Exception{
        Class<
ActionNameDatdatClass ActionNameDat.class;
        
String datName DatNameUtil.getFileName(datClass);

        
ActionNameDat dat = new L2DatInputStream(
                new 
L2FileInputStream(
                        new 
FileInputStream("D:\\Lineage II\\System\\"datName),
                        
datName
                
)
        ).
readObject(datClass);

        
JAXBContext context JAXBContext.newInstance(ActionNameDat.class);
        
Marshaller marshaller context.createMarshaller();
        
marshaller.setProperty("jaxb.formatted.output"true);
        
marshaller.marshal(datSystem.out);
    }


Результат:
 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<actionNameDat>
    <actionName>
        <tag>1</tag>
        <id>5000</id>
        <type>-1</type>
        <category>5</category>
        <unkIds>1538</unkIds>
        <name>Hand of Warmth</name>
        <icon>BranchSys.icon.br_rudolf_hand_i00</icon>
        <icon2>none</icon2>
        <desc>Can express affection to Rudolph. Affection Level rises by 25%. Warning: Can be used only when a Rudolph requests expression of affection, and cannot be used while transformed!</desc>
        <unkBool>false</unkBool>
        <cmd>usepetskill</cmd>
    </actionName>
    ...
</actionNameDat>
 
Code: XML
Как видите, всего лишь описав формат дат-файла в виде класса, мы получили возможность его экспорта в xml. По-моему это круто:)
Можно как в l2jc1 генерировать датапак на основе файлов клиента.

Числа и строки
Типы из DDF:
CNTR - INT, записанный в компактном виде. В классах описывается как переменная с типом int или Integer, с добавлением аннотации @Compact.
ASCF/UNICODE - Строки, в классах описываются типом String. Если это UNICODE, то добавляется аннотация @Unicode.

Для проверки данных определены 2 аннотации IntConst/StrConst. Если определенные значения не совпадают со считанными, то выбрасывается исключение(мб и найдется применение).

Массивы
Поддерживаются только одномерные массивы.
Длина массива по умолчанию считывается как int. Если длина массива константа, и ее не нужно считывать, то добавляется аннотация @Length(<значение>). Если длина массива определяется CNTR, то добавляется аннотация @Length(lengthType = LengthType.COMPACT).


Планы на ближайшее будущее:
  • Замена xml более читабельным форматом
  • Описать датки
  • Автоматическая компиляция классов даток из более примитивных исходников DONE
  • Запись обратно в файл DONE
  • unreal packages

Проект на гитхабе/src
Жду ваших замечаний/пожеланий.

Если хотите поучаствовать - пишите.

Mifesto 06.07.2013 01:24

Re: client files editor
 
Спасибо, забрал в архив.

acmi 06.07.2013 01:25

Re: client files editor
 
Рано пока в архив:) Это только начало...

Mifesto 06.07.2013 01:28

Re: client files editor
 
я уже увидел, но все же декрипт есть а остальное думаю не составит труда написать.

VISTALL 06.07.2013 11:53

Re: client files editor
 
Давайте подумаем - Вы суете в классы, это неудобно - в плане того что прийдется перекомпиливать.


а так посмотрите в мою сторону https://github.com/VISTALL/l2ce

acmi 06.07.2013 12:34

Re: client files editor
 
Я реализовал простенький компилятор, который ищет классы в заданной папке + добавляет необходимые импорты и аннотации.

Например пишем исходный файл episodion/SetItemGrp.java с таким содержанием:
PHP код:

@DatFile(value "SetItemGrp"localizable true)
@
SafePackage
class SetItemGrpDat{
    
SetItemGrp[] setItemGrp;
}
class 
SetItemGrp{
    
int setId;
    
ItemVariable[] items;
    
String[] itemBonus;
    
ItemVariable[] shileds;
    
String[] shieldBonus;
    @
IntConst(0)
    
int unk1;
    @
IntConst(0)
    
int unk2;
    
EnchantBonus[] enchantBonus;
}
class 
ItemVariable {
    
int[] itemId;
}
class 
EnchantBonus{
    
int level;
    
String bonus;


Вызов компилятора и генерация xml:
PHP код:

File srcFolder = new File("dat");
File outFolder = new File("classes");

new 
SimpleCompiler(outFolder).compile(srcFolder);

ClassLoader cl = new URLClassLoader(new URL[]{
        new 
File("classes").toURI().toURL()
});
Class 
clazz cl.loadClass("episodion.SetItemGrpDat");

Object dat = new L2DatInputStream(
        new 
L2FileInputStream(
                new 
FileInputStream("G:\\Lineage II Kr\\system\\"DatNameUtil.getFileName(clazz"k"))
        )
).
readObject(clazz);

JAXBContext context JAXBContext.newInstance(clazz);
Marshaller marshaller context.createMarshaller();
marshaller.setProperty("jaxb.formatted.output"true);
marshaller.marshal(datSystem.out); 

 
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<setItemGrpDat>
    <setItemGrp>
        <setId>0</setId>
        <items>
            <itemId>23</itemId>
        </items>
        <items>
            <itemId>2386</itemId>
        </items>
        <items>
            <itemId>43</itemId>
        </items>
        <itemBonus>&#49464;&#53944; &#54952;&#44284; &#50630;&#51020;</itemBonus>
        <itemBonus>&#47932;&#47532;&#48169;&#50612;&#47141; 2% &#51613;&#44032;, &#52572;&#45824;HP 41 &#51613;&#44032;.</itemBonus>
        <unk1>0</unk1>
        <unk2>0</unk2>
    </setItemGrp>
    ...
</setItemGrpDat>
 
Code: XML

Описывать формат такими простыми классами не намного сложнее ddf.
Cразу получаем маппинг в xml и кучу других плюшек.

VISTALL 06.07.2013 12:59

Re: client files editor
 
Ну я б не сказал бы что проще.


Нужна IDE что б менять. Вручную - можно сделать кучу ошибок(если Notepad++).


А что за разномерные масивы?

типо таких

http://pastebin.com/xr3cJTc1

acmi 06.07.2013 13:17

Re: client files editor
 
Если ошибетесь, то получите вывод стандартного java-компилятора
PHP код:

class Schema24hzDat {
    
String schema


Код:

Error on line 11 in /lindvior/Schema24hzDat.java:11: error: ';' expected
String schema
            ^


Поддержки многомерных массивов не делал из-за различного представления длины(int или compact int).
PHP код:

InnerArray[] arr1;
...
class 
InnerArray{
    @
Length(lengthType LengthType.COMPACT)
    
int[] arr2;


Такую структуру не опишешь как
PHP код:

int[][] arr


VISTALL 06.07.2013 13:23

Re: client files editor
 
Извини моя ошибка, я про вложеные масивы в масивы

PHP код:

                 <node name="setid_2" reader="UINT" />
                        <for 
name="setid_2">
                                <
node name="seteffect_2_sub" reader="UINT" />
                                <for 
name="seteffect_2_sub">
                                        <
node name="seteffect_2_sub2" reader="UINT" />
                                </for>
                        </for> 

типо такого


Тоисть что б проверить валидность нужно всегда запускать, лишнии движения. Плюс будет туча классов, когда файл большой

acmi 06.07.2013 13:39

Re: client files editor
 
В данном случае будет что-то типо такого:
PHP код:

class itemname{
    ...
    
name_class[] name_class;
    ...
    
setid_2[] setid_2;
    ...
}
class 
name_class{
    
int[] name_class_sub;    
}
class 
setid_2{
    
int[] seteffect_2_sub;    


Подобные структуры можно описать отдельным классом и повторно использовать.
PHP код:

class itemname{
    ...
    
IntArr[] name_class;
    ...
    
IntArr[] setid_2;
    ...
}
class 
IntArr{
    
int[] arr;    




Текущее время: 13:56. Часовой пояс GMT +3.

Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot