Commit 7925d1cd authored by Melledy's avatar Melledy
Browse files

Initial commit

parents
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.World;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PropValueOuterClass.PropValue;
import emu.grasscutter.net.proto.WorldDataNotifyOuterClass.WorldDataNotify;
public class PacketWorldDataNotify extends GenshinPacket {
public PacketWorldDataNotify(World world) {
super(PacketOpcodes.WorldDataNotify);
int worldLevel = world.getWorldLevel();
int isMp = world.isMultiplayer() ? 1 : 0;
WorldDataNotify proto = WorldDataNotify.newBuilder()
.putWorldPropMap(1, PropValue.newBuilder().setType(1).setIval(worldLevel).setVal(worldLevel).build())
.putWorldPropMap(2, PropValue.newBuilder().setType(2).setIval(isMp).setVal(isMp).build())
.build();
this.setData(proto);
}
}
package emu.grasscutter.server.packet.send;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PlayerDieTypeOuterClass.PlayerDieType;
import emu.grasscutter.net.proto.WorldPlayerDieNotifyOuterClass.WorldPlayerDieNotify;
public class PacketWorldPlayerDieNotify extends GenshinPacket {
public PacketWorldPlayerDieNotify(PlayerDieType playerDieType, int killerId) {
super(PacketOpcodes.WorldPlayerDieNotify);
WorldPlayerDieNotify proto = WorldPlayerDieNotify.newBuilder()
.setDieType(playerDieType)
.setMonsterId(killerId)
.build();
this.setData(proto);
}
}
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.WorldPlayerInfoNotifyOuterClass.WorldPlayerInfoNotify;
public class PacketWorldPlayerInfoNotify extends GenshinPacket {
public PacketWorldPlayerInfoNotify(World world) {
super(PacketOpcodes.WorldPlayerInfoNotify);
WorldPlayerInfoNotify.Builder proto = WorldPlayerInfoNotify.newBuilder();
for (int i = 0; i < world.getPlayers().size(); i++) {
GenshinPlayer p = world.getPlayers().get(i);
proto.addPlayerInfoList(p.getOnlinePlayerInfo());
proto.addPlayerUidList(p.getId());
}
this.setData(proto.build());
}
}
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.WorldPlayerLocationNotifyOuterClass.WorldPlayerLocationNotify;
public class PacketWorldPlayerLocationNotify extends GenshinPacket {
public PacketWorldPlayerLocationNotify(World world) {
super(PacketOpcodes.WorldPlayerLocationNotify);
WorldPlayerLocationNotify.Builder proto = WorldPlayerLocationNotify.newBuilder();
for (GenshinPlayer p : world.getPlayers()) {
proto.addPlayerLocList(p.getPlayerLocationInfo());
}
this.setData(proto);
}
}
package emu.grasscutter.server.packet.send;
import emu.grasscutter.game.GenshinPlayer;
import emu.grasscutter.game.World;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.PlayerRTTInfoOuterClass.PlayerRTTInfo;
import emu.grasscutter.net.proto.WorldPlayerRTTNotifyOuterClass.WorldPlayerRTTNotify;
public class PacketWorldPlayerRTTNotify extends GenshinPacket {
public PacketWorldPlayerRTTNotify(World world) {
super(PacketOpcodes.WorldPlayerRTTNotify);
WorldPlayerRTTNotify.Builder proto = WorldPlayerRTTNotify.newBuilder();
for (GenshinPlayer player : world.getPlayers()) {
proto.addPlayerRttList(
PlayerRTTInfo.newBuilder()
.setUid(player.getId())
.setRtt(10) // TODO - put player ping here
);
}
this.setData(proto);
}
}
package emu.grasscutter.tools;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import emu.grasscutter.game.props.OpenState;
import emu.grasscutter.net.proto.GetGachaInfoRspOuterClass.GetGachaInfoRsp;
import emu.grasscutter.net.proto.GetShopRspOuterClass.GetShopRsp;
import emu.grasscutter.net.proto.OpenStateUpdateNotifyOuterClass.OpenStateUpdateNotify;
import emu.grasscutter.utils.FileUtils;
public class Dumpers {
public static void extractBanner(byte[] data) throws Exception {
GetGachaInfoRsp proto = GetGachaInfoRsp.parseFrom(data);
System.out.println(proto);
}
public static void extractShop(byte[] data) throws Exception {
GetShopRsp proto = GetShopRsp.parseFrom(data);
System.out.println(proto);
}
public static void dumpOpenStates(byte[] data) throws Exception {
OpenStateUpdateNotify proto = OpenStateUpdateNotify.parseFrom(data);
List<Integer> list = new ArrayList<>(proto.getOpenStateMap().keySet());
Collections.sort(list);
for (int key : list) {
System.out.println(OpenState.getTypeByValue(key) + " : " + key);
}
}
}
package emu.grasscutter.tools;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.GenshinConstants;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.ResourceLoader;
import emu.grasscutter.data.def.AvatarData;
import emu.grasscutter.data.def.ItemData;
import emu.grasscutter.data.def.MonsterData;
public class Tools {
@SuppressWarnings("deprecation")
public static void createGmHandbook() throws Exception {
ResourceLoader.loadResources();
Map<Long, String> map;
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().RESOURCE_FOLDER + "TextMapEN.json")) {
map = Grasscutter.getGsonFactory().fromJson(fileReader, new TypeToken<Map<Long, String>>() {}.getType());
}
List<Integer> list;
String fileName = "./GM Handbook.txt";
try (FileWriter fileWriter = new FileWriter(fileName); PrintWriter writer = new PrintWriter(fileWriter)) {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
LocalDateTime now = LocalDateTime.now();
writer.println("// Genshin Impact " + GenshinConstants.VERSION + " GM Handbook");
writer.println("// Created " + dtf.format(now) + System.lineSeparator() + System.lineSeparator());
list = GenshinData.getAvatarDataMap().keySet().stream().collect(Collectors.toList());
Collections.sort(list);
writer.println("// Avatars");
for (Integer id : list) {
AvatarData data = GenshinData.getAvatarDataMap().get(id);
writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
}
writer.println();
list = GenshinData.getItemDataMap().keySet().stream().collect(Collectors.toList());
Collections.sort(list);
writer.println("// Items");
for (Integer id : list) {
ItemData data = GenshinData.getItemDataMap().get(id);
writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
}
writer.println();
writer.println("// Monsters");
list = GenshinData.getMonsterDataMap().keySet().stream().collect(Collectors.toList());
Collections.sort(list);
for (Integer id : list) {
MonsterData data = GenshinData.getMonsterDataMap().get(id);
writer.println(data.getId() + " : " + map.get(data.getNameTextMapHash()));
}
}
Grasscutter.getLogger().info("GM Handbook generated!");
}
}
package emu.grasscutter.utils;
import java.security.SecureRandom;
import java.util.Base64;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.net.proto.GetPlayerTokenRspOuterClass.GetPlayerTokenRsp;
import emu.grasscutter.net.proto.QueryCurrRegionHttpRspOuterClass.QueryCurrRegionHttpRsp;
public class Crypto {
private static SecureRandom secureRandom = new SecureRandom();
public static final long ENCRYPT_SEED = Long.parseUnsignedLong("11468049314633205968");
public static byte[] ENCRYPT_SEED_BUFFER = new byte[0];
public static byte[] DISPATCH_KEY;
public static byte[] ENCRYPT_KEY;
public static void loadKeys() {
DISPATCH_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "dispatchKey.bin");
ENCRYPT_KEY = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKey.bin");
ENCRYPT_SEED_BUFFER = FileUtils.read(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin");
}
public static void xor(byte[] packet, byte[] key) {
try {
for (int i = 0; i < packet.length; i++) {
packet[i] ^= key[i % key.length];
}
} catch (Exception e) {
Grasscutter.getLogger().error("Crypto error.", e);
}
}
public static void extractSecretKeyBuffer(byte[] data) {
try {
GetPlayerTokenRsp p = GetPlayerTokenRsp.parseFrom(data);
FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "secretKeyBuffer.bin", p.getSecretKeyBuffer().toByteArray());
Grasscutter.getLogger().info("Secret Key: " + p.getSecretKey());
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void extractDispatchSeed(String data) {
try {
QueryCurrRegionHttpRsp p = QueryCurrRegionHttpRsp.parseFrom(Base64.getDecoder().decode(data));
FileUtils.write(Grasscutter.getConfig().KEY_FOLDER + "dispatchSeed.bin", p.getRegionInfo().getSecretKey().toByteArray());
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] createSessionKey(int length) {
byte[] bytes = new byte[length];
secureRandom.nextBytes(bytes);
return bytes;
}
}
package emu.grasscutter.utils;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileUtils {
public static void write(String dest, byte[] bytes) {
Path path = Paths.get(dest);
try {
Files.write(path, bytes);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static byte[] read(String dest) {
return read(Paths.get(dest));
}
public static byte[] read(Path path) {
try {
return Files.readAllBytes(path);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return new byte[0];
}
public static byte[] read(File file) {
return read(file.getPath());
}
public static String getFilenameWithoutPath(String fileName) {
if (fileName.indexOf(".") > 0) {
return fileName.substring(0, fileName.lastIndexOf("."));
} else {
return fileName;
}
}
}
package emu.grasscutter.utils;
import java.io.Serializable;
import emu.grasscutter.net.proto.VectorOuterClass.Vector;
public class Position implements Serializable {
private static final long serialVersionUID = -2001232313615923575L;
private float x;
private float y;
private float z;
public Position() {
}
public Position(float x, float y) {
set(x, y);
}
public Position(float x, float y, float z) {
set(x, y, z);
}
public Position(String p) {
String[] split = p.split(",");
if (split.length >= 2) {
this.x = Float.parseFloat(split[0]);
this.y = Float.parseFloat(split[1]);
}
if (split.length >= 3) {
this.z = Float.parseFloat(split[2]);
}
}
public Position(Vector vector) {
this.set(vector);
}
public Position(Position pos) {
this.set(pos);
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getZ() {
return z;
}
public void setZ(float z) {
this.z = z;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
public Position set(float x, float y) {
this.x = x;
this.y = y;
return this;
}
// Deep copy
public Position set(Position pos) {
return this.set(pos.getX(), pos.getY(), pos.getZ());
}
public Position set(Vector pos) {
return this.set(pos.getX(), pos.getY(), pos.getZ());
}
public Position set(float x, float y, float z) {
this.x = x;
this.y = y;
this.z = z;
return this;
}
public Position add(Position add) {
this.x += add.getX();
this.y += add.getY();
this.z += add.getZ();
return this;
}
public Position addX(float d) {
this.x += d;
return this;
}
public Position addY(float d) {
this.y += d;
return this;
}
public Position addZ(float d) {
this.z += d;
return this;
}
public Position subtract(Position sub) {
this.x -= sub.getX();
this.y -= sub.getY();
this.z -= sub.getZ();
return this;
}
/** In radians
* */
public Position translate(float dist, float angle) {
this.x += dist * Math.sin(angle);
this.y += dist * Math.cos(angle);
return this;
}
public boolean equal2d(Position other) {
return getX() == other.getX() && getY() == other.getY();
}
public Position translateWithDegrees(float dist, float angle) {
angle = (float) Math.toRadians(angle);
this.x += dist * Math.sin(angle);
this.y += -dist * Math.cos(angle);
return this;
}
@Override
public Position clone() {
return new Position(x, y, z);
}
@Override
public String toString() {
return "(" + this.getX() + ", " + this.getY() + ", " + this.getZ() + ")";
}
public Vector toProto() {
return Vector.newBuilder()
.setX(this.getX())
.setY(this.getY())
.setZ(this.getZ())
.build();
}
}
package emu.grasscutter.utils;
import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.net.proto.PropValueOuterClass.PropValue;
public class ProtoHelper {
public static PropValue newPropValue(PlayerProperty key, int value) {
return PropValue.newBuilder().setType(key.getId()).setIval(value).setVal(value).build();
}
}
package emu.grasscutter.utils;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Random;
import emu.grasscutter.Grasscutter;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import io.netty.buffer.Unpooled;
public class Utils {
public static final Random random = new Random();
public static int randomRange(int min, int max) {
return random.nextInt(max - min + 1) + min;
}
public static float randomFloatRange(float min, float max) {
return random.nextFloat() * (max - min) + min;
}
public static int getCurrentSeconds() {
return (int) (System.currentTimeMillis() / 1000.0);
}
public static String lowerCaseFirstChar(String s) {
StringBuilder sb = new StringBuilder(s);
sb.setCharAt(0, Character.toLowerCase(sb.charAt(0)));
return sb.toString();
}
public static String toString(InputStream inputStream) throws IOException {
BufferedInputStream bis = new BufferedInputStream(inputStream);
ByteArrayOutputStream buf = new ByteArrayOutputStream();
for (int result = bis.read(); result != -1; result = bis.read()) {
buf.write((byte) result);
}
return buf.toString();
}
public static void logByteArray(byte[] array) {
ByteBuf b = Unpooled.wrappedBuffer(array);
Grasscutter.getLogger().info("\n" + ByteBufUtil.prettyHexDump(b));
b.release();
}
private static final char[] HEX_ARRAY = "0123456789abcdef".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = HEX_ARRAY[v >>> 4];
hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
}
return new String(hexChars);
}
public static String bytesToHex(ByteBuf buf) {
return bytesToHex(byteBufToArray(buf));
}
public static byte[] byteBufToArray(ByteBuf buf) {
byte[] bytes = new byte[buf.capacity()];
buf.getBytes(0, bytes);
return bytes;
}
public static int abilityHash(String str) {
int v7 = 0;
int v8 = 0;
while (v8 < str.length()) {
v7 = str.charAt(v8++) + 131 * v7;
}
return v7;
}
}
package emu.grasscutter.utils;
import java.util.NavigableMap;
import java.util.TreeMap;
import java.util.concurrent.ThreadLocalRandom;
public class WeightedList<E> {
private final NavigableMap<Double, E> map = new TreeMap<Double, E>();
private double total = 0;
public WeightedList() {
}
public WeightedList<E> add(double weight, E result) {
if (weight <= 0) return this;
total += weight;
map.put(total, result);
return this;
}
public E next() {
double value = ThreadLocalRandom.current().nextDouble() * total;
return map.higherEntry(value).getValue();
}
public int size() {
return map.size();
}
}
\ No newline at end of file
<Configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%d{HH:mm:ss}] [%level] %msg%n</pattern>
</encoder>
</appender>
<logger name="org.reflections" level="OFF"/>
<root level="INFO">
<appender-ref ref="STDOUT" />
</root>
</Configuration>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment