L2ClientDat decoder.
This commit is contained in:
238
L2ClientDat/java/com/l2jmobius/data/GameDataName.java
Normal file
238
L2ClientDat/java/com/l2jmobius/data/GameDataName.java
Normal file
@ -0,0 +1,238 @@
|
||||
/*
|
||||
* This file is part of the L2J Mobius project.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package com.l2jmobius.data;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.file.Files;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.l2jmobius.L2ClientDat;
|
||||
import com.l2jmobius.clientcryptor.DatFile;
|
||||
import com.l2jmobius.clientcryptor.crypt.DatCrypter;
|
||||
import com.l2jmobius.config.ConfigDebug;
|
||||
import com.l2jmobius.util.ByteReader;
|
||||
import com.l2jmobius.util.ByteWriter;
|
||||
import com.l2jmobius.util.Util;
|
||||
import com.l2jmobius.xml.ParamNode;
|
||||
|
||||
public class GameDataName
|
||||
{
|
||||
private static final byte[] endFileBytes = new byte[]
|
||||
{
|
||||
12,
|
||||
83,
|
||||
97,
|
||||
102,
|
||||
101,
|
||||
80,
|
||||
97,
|
||||
99,
|
||||
107,
|
||||
97,
|
||||
103,
|
||||
101,
|
||||
0
|
||||
};
|
||||
private final Map<Integer, String> names = new HashMap<>();
|
||||
private final Map<String, Integer> nameHash = new HashMap<>();
|
||||
private final Map<String, Integer> nameLowHash = new HashMap<>();
|
||||
|
||||
private void load(File currentFile, DatCrypter decCrypter) throws Exception
|
||||
{
|
||||
names.clear();
|
||||
nameHash.clear();
|
||||
nameLowHash.clear();
|
||||
if (decCrypter.isEncrypt())
|
||||
{
|
||||
File file = new File(currentFile.getParent(), "L2GameDataName.txt");
|
||||
if (file.exists())
|
||||
{
|
||||
List<String> list = Files.readAllLines(file.toPath());
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
String str = list.get(i);
|
||||
Map<String, String> map = Util.stringToMap(str);
|
||||
String name = map.get("name");
|
||||
name = name.substring(1, name.length() - 1);
|
||||
names.put(i, name);
|
||||
nameHash.put(name, i);
|
||||
nameLowHash.put(name.toLowerCase(), i);
|
||||
}
|
||||
L2ClientDat.addLogConsole("GameDataName: Load " + names.size() + " count.", true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
File file = new File(currentFile.getParent(), "L2GameDataName.dat");
|
||||
FileInputStream fis = new FileInputStream(file);
|
||||
if (fis.available() < 28)
|
||||
{
|
||||
L2ClientDat.addLogConsole(file.getName() + " The file is too small.", true);
|
||||
fis.close();
|
||||
return;
|
||||
}
|
||||
byte[] head = new byte[28];
|
||||
fis.read(head);
|
||||
fis.close();
|
||||
String header = new String(head, "UTF-16LE");
|
||||
if (!header.startsWith("Lineage2Ver"))
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: File " + file.getName() + " not encrypted. Skip decrypt.", true);
|
||||
return;
|
||||
}
|
||||
if (Integer.valueOf(header.substring(11)).intValue() != decCrypter.getCode())
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: File " + file.getName() + " encrypted code: " + header + ". Skip decrypt.", true);
|
||||
return;
|
||||
}
|
||||
L2ClientDat.addLogConsole("Unpacking [" + file.getName() + "]", true);
|
||||
DatFile dat = new DatFile(file.getAbsolutePath());
|
||||
dat.decrypt(decCrypter);
|
||||
ByteBuffer buff = dat.getBuff();
|
||||
int size = ByteReader.readUInt(buff);
|
||||
for (int i = 0; i < size; ++i)
|
||||
{
|
||||
String name = ByteReader.readUtfString(buff, false);
|
||||
if (name.contains("[") || name.contains("]"))
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: Error index: " + i + " string: " + name, true);
|
||||
}
|
||||
names.put(i, name);
|
||||
nameHash.put(name, i);
|
||||
nameLowHash.put(name.toLowerCase(), i);
|
||||
}
|
||||
L2ClientDat.addLogConsole("GameDataName: Load " + names.size() + " count.", true);
|
||||
}
|
||||
}
|
||||
|
||||
public String getString(File currentFile, DatCrypter crypter, int index) throws Exception
|
||||
{
|
||||
String val;
|
||||
if (names.isEmpty())
|
||||
{
|
||||
load(currentFile, crypter);
|
||||
}
|
||||
if (!names.containsKey(index))
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: Not found index: " + index, true);
|
||||
}
|
||||
if ((val = names.getOrDefault(index, String.valueOf(index))).isEmpty())
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: String name Empty!!! file: " + currentFile.getName(), true);
|
||||
}
|
||||
return "[" + val + "]";
|
||||
}
|
||||
|
||||
public synchronized int getId(File currentFile, DatCrypter crypter, ParamNode node, String str) throws Exception
|
||||
{
|
||||
String low;
|
||||
if (!str.startsWith("[") || !str.endsWith("]"))
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: String name not brackets!!! file: " + currentFile.getName() + " str: " + str + " node: " + node, true);
|
||||
}
|
||||
if ((str = str.substring(1, str.length() - 1)).isEmpty())
|
||||
{
|
||||
L2ClientDat.addLogConsole("GameDataName: String name Empty!!! file: " + currentFile.getName() + " node: " + node, true);
|
||||
return -1;
|
||||
}
|
||||
if (nameLowHash.isEmpty())
|
||||
{
|
||||
load(currentFile, crypter);
|
||||
}
|
||||
if (nameLowHash.containsKey(low = str.toLowerCase()))
|
||||
{
|
||||
return nameLowHash.get(low);
|
||||
}
|
||||
int newIndex = nameLowHash.size();
|
||||
nameLowHash.put(low, newIndex);
|
||||
nameHash.put(str, nameHash.size());
|
||||
return newIndex;
|
||||
}
|
||||
|
||||
public void checkAndUpdate(String currentDir, DatCrypter crypter) throws Exception
|
||||
{
|
||||
if (!nameHash.isEmpty())
|
||||
{
|
||||
HashSet<String> setList = new HashSet<>();
|
||||
TreeMap<Integer, String> sortedMap = new TreeMap<>();
|
||||
for (String key : nameHash.keySet())
|
||||
{
|
||||
sortedMap.put(nameHash.get(key), key);
|
||||
if (setList.add(key.toLowerCase()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
L2ClientDat.addLogConsole("GameDataName: name " + key + " conflicted.", true);
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
baos.write((byte[]) ByteWriter.writeInt(sortedMap.size()).array());
|
||||
for (String key : sortedMap.values())
|
||||
{
|
||||
baos.write((byte[]) ByteWriter.writeUtfString(key, false).array());
|
||||
}
|
||||
byte[] bytes = baos.toByteArray();
|
||||
byte[] resultBytes = new byte[bytes.length + endFileBytes.length];
|
||||
System.arraycopy(bytes, 0, resultBytes, 0, bytes.length);
|
||||
System.arraycopy(endFileBytes, 0, resultBytes, bytes.length, endFileBytes.length);
|
||||
String file = currentDir + "/L2GameDataName.dat";
|
||||
if (ConfigDebug.ENCRYPT)
|
||||
{
|
||||
DatFile.encrypt(resultBytes, file, crypter);
|
||||
}
|
||||
else
|
||||
{
|
||||
FileOutputStream os = new FileOutputStream(file, false);
|
||||
os.write(resultBytes);
|
||||
os.close();
|
||||
}
|
||||
L2ClientDat.addLogConsole("GameDataName: packed " + sortedMap.size() + " count.", true);
|
||||
names.clear();
|
||||
nameHash.clear();
|
||||
nameLowHash.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void clear()
|
||||
{
|
||||
names.clear();
|
||||
nameHash.clear();
|
||||
nameLowHash.clear();
|
||||
}
|
||||
|
||||
public static GameDataName getInstance()
|
||||
{
|
||||
return SingletonHolder._instance;
|
||||
}
|
||||
|
||||
private static class SingletonHolder
|
||||
{
|
||||
static final GameDataName _instance = new GameDataName();
|
||||
|
||||
private SingletonHolder()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user