Commit 01b190bc authored by Magix's avatar Magix Committed by GitHub
Browse files

UPGRADE TO 1.1.0 POG

Merge `development` into `stable`
parents 6b81b888 1beddf16
package emu.grasscutter.game.shop;
import com.google.gson.reflect.TypeToken;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.common.ItemParamData;
import emu.grasscutter.data.def.ShopGoodsData;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.utils.Utils;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
public class ShopManager {
private final GameServer server;
public Int2ObjectMap<List<ShopInfo>> getShopData() {
return shopData;
}
public List<ShopChestTable> getShopChestData() {
return shopChestData;
}
public List<ShopChestBatchUseTable> getShopChestBatchUseData() {
return shopChestBatchUseData;
}
private final Int2ObjectMap<List<ShopInfo>> shopData;
private final List<ShopChestTable> shopChestData;
private final List<ShopChestBatchUseTable> shopChestBatchUseData;
public ShopManager(GameServer server) {
this.server = server;
this.shopData = new Int2ObjectOpenHashMap<>();
this.shopChestData = new ArrayList<>();
this.shopChestBatchUseData = new ArrayList<>();
this.load();
}
private static final int REFRESH_HOUR = 4; // In GMT+8 server
private static final String TIME_ZONE = "Asia/Shanghai"; // GMT+8 Timezone
public static int getShopNextRefreshTime(ShopInfo shopInfo) {
return switch (shopInfo.getShopRefreshType()) {
case SHOP_REFRESH_DAILY -> Utils.getNextTimestampOfThisHour(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam());
case SHOP_REFRESH_WEEKLY -> Utils.getNextTimestampOfThisHourInNextWeek(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam());
case SHOP_REFRESH_MONTHLY -> Utils.getNextTimestampOfThisHourInNextMonth(REFRESH_HOUR, TIME_ZONE, shopInfo.getShopRefreshParam());
default -> 0;
};
}
private void loadShop() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "Shop.json")) {
getShopData().clear();
List<ShopTable> banners = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopTable.class).getType());
if(banners.size() > 0) {
for (ShopTable shopTable : banners) {
for (ShopInfo cost : shopTable.getItems()) {
if (cost.getCostItemList() != null) {
Iterator<ItemParamData> iterator = cost.getCostItemList().iterator();
while (iterator.hasNext()) {
ItemParamData ipd = iterator.next();
if (ipd.getId() == 201) {
cost.setHcoin(cost.getHcoin() + ipd.getCount());
iterator.remove();
}
if (ipd.getId() == 203) {
cost.setMcoin(cost.getMcoin() + ipd.getCount());
iterator.remove();
}
}
}
}
getShopData().put(shopTable.getShopId(), shopTable.getItems());
}
Grasscutter.getLogger().info("Shop data successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load shop data. Shop data size is 0.");
}
if (Grasscutter.getConfig().getGameServerOptions().EnableOfficialShop) {
GameData.getShopGoodsDataEntries().forEach((k, v) -> {
if (!getShopData().containsKey(k.intValue()))
getShopData().put(k.intValue(), new ArrayList<>());
for (ShopGoodsData sgd : v) {
var shopInfo = new ShopInfo(sgd);
getShopData().get(k.intValue()).add(shopInfo);
}
});
}
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load shop data.", e);
}
}
private void loadShopChest() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChest.json")) {
getShopChestData().clear();
List<ShopChestTable> shopChestTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestTable.class).getType());
if (shopChestTableList.size() > 0) {
getShopChestData().addAll(shopChestTableList);
Grasscutter.getLogger().info("ShopChest data successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load ShopChest data. ShopChest data size is 0.");
}
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load ShopChest data.", e);
}
}
private void loadShopChestBatchUse() {
try (FileReader fileReader = new FileReader(Grasscutter.getConfig().DATA_FOLDER + "ShopChestBatchUse.json")) {
getShopChestBatchUseData().clear();
List<ShopChestBatchUseTable> shopChestBatchUseTableList = Grasscutter.getGsonFactory().fromJson(fileReader, TypeToken.getParameterized(Collection.class, ShopChestBatchUseTable.class).getType());
if (shopChestBatchUseTableList.size() > 0) {
getShopChestBatchUseData().addAll(shopChestBatchUseTableList);
Grasscutter.getLogger().info("ShopChestBatchUse data successfully loaded.");
} else {
Grasscutter.getLogger().error("Unable to load ShopChestBatchUse data. ShopChestBatchUse data size is 0.");
}
} catch (Exception e) {
Grasscutter.getLogger().error("Unable to load ShopChestBatchUse data.", e);
}
}
public synchronized void load() {
loadShop();
loadShopChest();
loadShopChestBatchUse();
}
public GameServer getServer() {
......
package emu.grasscutter.game.shop;
import java.util.ArrayList;
import java.util.List;
public class ShopTable {
private int shopId;
private List<ShopInfo> items = new ArrayList<>();
public int getShopId() {
return shopId;
}
public void setShopId(int shopId) {
this.shopId = shopId;
}
public List<ShopInfo> getItems() {
return items;
}
public void setItems(List<ShopInfo> items) {
this.items = items;
}
}
package emu.grasscutter.game.tower;
import dev.morphia.annotations.Entity;
import dev.morphia.annotations.Transient;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.TowerLevelData;
import emu.grasscutter.game.dungeons.DungeonSettleListener;
import emu.grasscutter.game.dungeons.TowerDungeonSettleListener;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.packet.send.PacketTowerCurLevelRecordChangeNotify;
import emu.grasscutter.server.packet.send.PacketTowerEnterLevelRsp;
import java.util.List;
@Entity
public class TowerManager {
@Transient private Player player;
public TowerManager(Player player) {
this.player = player;
}
public void setPlayer(Player player) {
this.player = player;
}
private int currentFloorId;
private int currentLevel;
@Transient
private int currentLevelId;
@Transient
private int entryScene;
public int getCurrentFloorId() {
return currentFloorId;
}
private static final List<DungeonSettleListener> towerDungeonSettleListener = List.of(new TowerDungeonSettleListener());
public void teamSelect(int floor, List<List<Long>> towerTeams) {
var floorData = GameData.getTowerFloorDataMap().get(floor);
this.currentFloorId = floorData.getFloorId();
this.currentLevel = 0;
this.currentLevelId = GameData.getTowerLevelDataMap().values().stream()
.filter(x -> x.getLevelId() == floorData.getLevelId() && x.getLevelIndex() == 1)
.findFirst()
.map(TowerLevelData::getID)
.orElse(0);
if (entryScene == 0){
entryScene = player.getSceneId();
}
player.getTeamManager().setupTemporaryTeam(towerTeams);
}
public void enterLevel(int enterPointId) {
var levelData = GameData.getTowerLevelDataMap().get(currentLevelId + currentLevel);
this.currentLevel++;
var id = levelData.getDungeonId();
notifyCurLevelRecordChange();
// use team user choose
player.getTeamManager().useTemporaryTeam(0);
player.getServer().getDungeonManager().handoffDungeon(player, id,
towerDungeonSettleListener);
// make sure user can exit dungeon correctly
player.getScene().setPrevScene(entryScene);
player.getScene().setPrevScenePoint(enterPointId);
player.getSession().send(new PacketTowerEnterLevelRsp(currentFloorId, currentLevel));
}
public void notifyCurLevelRecordChange(){
player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel));
}
public void notifyCurLevelRecordChangeWhenDone(){
player.getSession().send(new PacketTowerCurLevelRecordChangeNotify(currentFloorId, currentLevel + 1));
}
public boolean hasNextLevel(){
return this.currentLevel < 3;
}
public int getNextFloorId() {
if(hasNextLevel()){
return 0;
}
this.currentFloorId++;
return this.currentFloorId;
}
public void clearEntry() {
this.entryScene = 0;
}
}
package emu.grasscutter.game;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
package emu.grasscutter.game.world;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.GameDepot;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.data.def.MonsterData;
import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityClientGadget;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.GenshinEntity;
import emu.grasscutter.data.def.WorldLevelData;
import emu.grasscutter.game.dungeons.DungeonChallenge;
import emu.grasscutter.game.dungeons.DungeonSettleListener;
import emu.grasscutter.game.entity.*;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.TeamInfo;
import emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.game.props.SceneType;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.game.world.SpawnDataEntry.SpawnGroupEntry;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.SceneScriptManager;
import emu.grasscutter.scripts.data.SceneBlock;
import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.server.packet.send.PacketAvatarSkillInfoNotify;
import emu.grasscutter.server.packet.send.PacketDungeonChallengeFinishNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketSceneEntityAppearNotify;
import emu.grasscutter.server.packet.send.PacketSceneEntityDisappearNotify;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.danilopianini.util.SpatialIndex;
import java.util.*;
public class GenshinScene {
public class Scene {
private final World world;
private final SceneData sceneData;
private final List<GenshinPlayer> players;
private final Int2ObjectMap<GenshinEntity> entities;
private final List<Player> players;
private final Int2ObjectMap<GameEntity> entities;
private final Set<SpawnDataEntry> spawnedEntities;
private final Set<SpawnDataEntry> deadSpawnedEntities;
private final Set<SceneBlock> loadedBlocks;
private boolean dontDestroyWhenEmpty;
private int autoCloseTime;
private int time;
private ClimateType climate;
private int weather;
public GenshinScene(World world, SceneData sceneData) {
private SceneScriptManager scriptManager;
private DungeonChallenge challenge;
private List<DungeonSettleListener> dungeonSettleListeners;
private DungeonData dungeonData;
private int prevScene; // Id of the previous scene
private int prevScenePoint;
public Scene(World world, SceneData sceneData) {
this.world = world;
this.sceneData = sceneData;
this.players = Collections.synchronizedList(new ArrayList<>());
this.entities = new Int2ObjectOpenHashMap<>();
this.entities = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
this.time = 8 * 60;
this.climate = ClimateType.CLIMATE_SUNNY;
this.prevScene = 3;
this.spawnedEntities = new HashSet<>();
this.deadSpawnedEntities = new HashSet<>();
this.loadedBlocks = new HashSet<>();
this.scriptManager = new SceneScriptManager(this);
}
public int getId() {
......@@ -62,7 +90,7 @@ public class GenshinScene {
return getSceneData().getSceneType();
}
public List<GenshinPlayer> getPlayers() {
public List<Player> getPlayers() {
return players;
}
......@@ -70,14 +98,28 @@ public class GenshinScene {
return this.getPlayers().size();
}
public Int2ObjectMap<GenshinEntity> getEntities() {
public Int2ObjectMap<GameEntity> getEntities() {
return entities;
}
public GenshinEntity getEntityById(int id) {
public GameEntity getEntityById(int id) {
return this.entities.get(id);
}
/**
* @return the autoCloseTime
*/
public int getAutoCloseTime() {
return autoCloseTime;
}
/**
* @param autoCloseTime the autoCloseTime to set
*/
public void setAutoCloseTime(int autoCloseTime) {
this.autoCloseTime = autoCloseTime;
}
public int getTime() {
return time;
}
......@@ -102,11 +144,81 @@ public class GenshinScene {
this.weather = weather;
}
public boolean isInScene(GenshinEntity entity) {
public int getPrevScene() {
return prevScene;
}
public void setPrevScene(int prevScene) {
this.prevScene = prevScene;
}
public int getPrevScenePoint() {
return prevScenePoint;
}
public void setPrevScenePoint(int prevPoint) {
this.prevScenePoint = prevPoint;
}
public boolean dontDestroyWhenEmpty() {
return dontDestroyWhenEmpty;
}
public void setDontDestroyWhenEmpty(boolean dontDestroyWhenEmpty) {
this.dontDestroyWhenEmpty = dontDestroyWhenEmpty;
}
public Set<SceneBlock> getLoadedBlocks() {
return loadedBlocks;
}
public Set<SpawnDataEntry> getSpawnedEntities() {
return spawnedEntities;
}
public Set<SpawnDataEntry> getDeadSpawnedEntities() {
return deadSpawnedEntities;
}
public SceneScriptManager getScriptManager() {
return scriptManager;
}
public DungeonData getDungeonData() {
return dungeonData;
}
public void setDungeonData(DungeonData dungeonData) {
if (dungeonData == null || this.dungeonData != null || this.getSceneType() != SceneType.SCENE_DUNGEON || dungeonData.getSceneId() != this.getId()) {
return;
}
this.dungeonData = dungeonData;
}
public DungeonChallenge getChallenge() {
return challenge;
}
public void setChallenge(DungeonChallenge challenge) {
this.challenge = challenge;
}
public void addDungeonSettleObserver(DungeonSettleListener dungeonSettleListener){
if(dungeonSettleListeners == null){
dungeonSettleListeners = new ArrayList<>();
}
dungeonSettleListeners.add(dungeonSettleListener);
}
public List<DungeonSettleListener> getDungeonSettleObservers() {
return dungeonSettleListeners;
}
public boolean isInScene(GameEntity entity) {
return this.entities.containsKey(entity.getId());
}
public void addPlayer(GenshinPlayer player) {
public synchronized void addPlayer(Player player) {
// Check if player already in
if (getPlayers().contains(player)) {
return;
......@@ -125,7 +237,12 @@ public class GenshinScene {
this.setupPlayerAvatars(player);
}
public void removePlayer(GenshinPlayer player) {
public synchronized void removePlayer(Player player) {
// Remove from challenge if leaving
if (this.getChallenge() != null && this.getChallenge().inProgress()) {
player.sendPacket(new PacketDungeonChallengeFinishNotify(this.getChallenge()));
}
// Remove player from scene
getPlayers().remove(player);
player.setScene(null);
......@@ -134,17 +251,17 @@ public class GenshinScene {
this.removePlayerAvatars(player);
// Remove player gadgets
for (EntityGadget gadget : player.getTeamManager().getGadgets()) {
for (EntityBaseGadget gadget : player.getTeamManager().getGadgets()) {
this.removeEntity(gadget);
}
// Deregister scene if not in use
if (this.getEntities().size() <= 0) {
if (this.getPlayerCount() <= 0 && !this.dontDestroyWhenEmpty()) {
this.getWorld().deregisterScene(this);
}
}
private void setupPlayerAvatars(GenshinPlayer player) {
private void setupPlayerAvatars(Player player) {
// Clear entities from old team
player.getTeamManager().getActiveTeam().clear();
......@@ -161,15 +278,15 @@ public class GenshinScene {
}
}
private void removePlayerAvatars(GenshinPlayer player) {
private void removePlayerAvatars(Player player) {
Iterator<EntityAvatar> it = player.getTeamManager().getActiveTeam().iterator();
while (it.hasNext()) {
this.removeEntity(it.next(), VisionType.VisionRemove);
this.removeEntity(it.next(), VisionType.VISION_REMOVE);
it.remove();
}
}
public void spawnPlayer(GenshinPlayer player) {
public void spawnPlayer(Player player) {
if (this.isInScene(player.getTeamManager().getCurrentAvatarEntity())) {
return;
}
......@@ -179,35 +296,47 @@ public class GenshinScene {
}
this.addEntity(player.getTeamManager().getCurrentAvatarEntity());
// Notify the client of any extra skill charges
for (EntityAvatar entity : player.getTeamManager().getActiveTeam()) {
if (entity.getAvatar().getSkillExtraChargeMap().size() > 0) {
player.sendPacket(new PacketAvatarSkillInfoNotify(entity.getAvatar()));
}
}
}
private void addEntityDirectly(GenshinEntity entity) {
private void addEntityDirectly(GameEntity entity) {
getEntities().put(entity.getId(), entity);
}
public synchronized void addEntity(GenshinEntity entity) {
public synchronized void addEntity(GameEntity entity) {
this.addEntityDirectly(entity);
this.broadcastPacket(new PacketSceneEntityAppearNotify(entity));
}
public synchronized void addEntityToSingleClient(Player player, GameEntity entity) {
this.addEntityDirectly(entity);
player.sendPacket(new PacketSceneEntityAppearNotify(entity));
}
public synchronized void addEntities(Collection<GenshinEntity> entities) {
for (GenshinEntity entity : entities) {
public synchronized void addEntities(Collection<GameEntity> entities) {
for (GameEntity entity : entities) {
this.addEntityDirectly(entity);
}
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionBorn));
this.broadcastPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_BORN));
}
private GenshinEntity removeEntityDirectly(GenshinEntity entity) {
private GameEntity removeEntityDirectly(GameEntity entity) {
return getEntities().remove(entity.getId());
}
public void removeEntity(GenshinEntity entity) {
this.removeEntity(entity, VisionType.VisionDie);
public void removeEntity(GameEntity entity) {
this.removeEntity(entity, VisionType.VISION_DIE);
}
public synchronized void removeEntity(GenshinEntity entity, VisionType visionType) {
GenshinEntity removed = this.removeEntityDirectly(entity);
public synchronized void removeEntity(GameEntity entity, VisionType visionType) {
GameEntity removed = this.removeEntityDirectly(entity);
if (removed != null) {
this.broadcastPacket(new PacketSceneEntityDisappearNotify(removed, visionType));
}
......@@ -216,27 +345,27 @@ public class GenshinScene {
public synchronized void replaceEntity(EntityAvatar oldEntity, EntityAvatar newEntity) {
this.removeEntityDirectly(oldEntity);
this.addEntityDirectly(newEntity);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VisionReplace));
this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VisionReplace, oldEntity.getId()));
this.broadcastPacket(new PacketSceneEntityDisappearNotify(oldEntity, VisionType.VISION_REPLACE));
this.broadcastPacket(new PacketSceneEntityAppearNotify(newEntity, VisionType.VISION_REPLACE, oldEntity.getId()));
}
public void showOtherEntities(GenshinPlayer player) {
List<GenshinEntity> entities = new LinkedList<>();
GenshinEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity();
public void showOtherEntities(Player player) {
List<GameEntity> entities = new LinkedList<>();
GameEntity currentEntity = player.getTeamManager().getCurrentAvatarEntity();
for (GenshinEntity entity : this.getEntities().values()) {
for (GameEntity entity : this.getEntities().values()) {
if (entity == currentEntity) {
continue;
}
entities.add(entity);
}
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VisionMeet));
player.sendPacket(new PacketSceneEntityAppearNotify(entities, VisionType.VISION_MEET));
}
public void handleAttack(AttackResult result) {
//GenshinEntity attacker = getEntityById(result.getAttackerId());
GenshinEntity target = getEntityById(result.getDefenseId());
//GameEntity attacker = getEntityById(result.getAttackerId());
GameEntity target = getEntityById(result.getDefenseId());
if (target == null) {
return;
......@@ -249,6 +378,11 @@ public class GenshinScene {
}
}
// Sanity check
if (target.getFightProperties() == null) {
return;
}
// Lose hp
target.addFightProperty(FightProperty.FIGHT_PROP_CUR_HP, -result.getDamage());
......@@ -268,15 +402,181 @@ public class GenshinScene {
}
}
public void killEntity(GenshinEntity target, int attackerId) {
public void killEntity(GameEntity target, int attackerId) {
// Packet
this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD));
// Reward drop
if (target instanceof EntityMonster && this.getSceneType() != SceneType.SCENE_DUNGEON) {
getWorld().getServer().getDropManager().callDrop((EntityMonster) target);
}
this.removeEntity(target);
// Death event
target.onDeath(attackerId);
}
public void onTick() {
if (this.getScriptManager().isInit()) {
this.checkBlocks();
} else {
// TEMPORARY
this.checkSpawns();
}
// Triggers
this.getScriptManager().onTick();
}
// TODO - Test
public void checkSpawns() {
SpatialIndex<SpawnGroupEntry> list = GameDepot.getSpawnListById(this.getId());
Set<SpawnDataEntry> visible = new HashSet<>();
for (Player player : this.getPlayers()) {
int RANGE = 100;
Collection<SpawnGroupEntry> entries = list.query(
new double[] {player.getPos().getX() - RANGE, player.getPos().getZ() - RANGE},
new double[] {player.getPos().getX() + RANGE, player.getPos().getZ() + RANGE}
);
for (SpawnGroupEntry entry : entries) {
for (SpawnDataEntry spawnData : entry.getSpawns()) {
visible.add(spawnData);
}
}
}
// World level
WorldLevelData worldLevelData = GameData.getWorldLevelDataMap().get(getWorld().getWorldLevel());
int worldLevelOverride = 0;
if (worldLevelData != null) {
worldLevelOverride = worldLevelData.getMonsterLevel();
}
// Todo
List<GameEntity> toAdd = new LinkedList<>();
List<GameEntity> toRemove = new LinkedList<>();
for (SpawnDataEntry entry : visible) {
if (!this.getSpawnedEntities().contains(entry) && !this.getDeadSpawnedEntities().contains(entry)) {
// Spawn entity
MonsterData data = GameData.getMonsterDataMap().get(entry.getMonsterId());
if (data == null) {
continue;
}
EntityMonster entity = new EntityMonster(this, data, entry.getPos(), worldLevelOverride > 0 ? worldLevelOverride : entry.getLevel());
entity.getRotation().set(entry.getRot());
entity.setGroupId(entry.getGroup().getGroupId());
entity.setPoseId(entry.getPoseId());
entity.setConfigId(entry.getConfigId());
entity.setSpawnEntry(entry);
toAdd.add(entity);
// Add to spawned list
this.getSpawnedEntities().add(entry);
}
}
for (GameEntity entity : this.getEntities().values()) {
if (entity.getSpawnEntry() != null && !visible.contains(entity.getSpawnEntry())) {
toRemove.add(entity);
}
}
if (toAdd.size() > 0) {
toAdd.stream().forEach(this::addEntityDirectly);
this.broadcastPacket(new PacketSceneEntityAppearNotify(toAdd, VisionType.VISION_BORN));
}
if (toRemove.size() > 0) {
toRemove.stream().forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE));
}
}
public void checkBlocks() {
Set<SceneBlock> visible = new HashSet<>();
for (Player player : this.getPlayers()) {
for (SceneBlock block : getScriptManager().getBlocks()) {
if (!block.contains(player.getPos())) {
continue;
}
visible.add(block);
}
}
Iterator<SceneBlock> it = this.getLoadedBlocks().iterator();
while (it.hasNext()) {
SceneBlock block = it.next();
if (!visible.contains(block)) {
it.remove();
onUnloadBlock(block);
}
}
for (SceneBlock block : visible) {
if (!this.getLoadedBlocks().contains(block)) {
this.onLoadBlock(block);
this.getLoadedBlocks().add(block);
}
}
}
// TODO optimize
public void onLoadBlock(SceneBlock block) {
for (SceneGroup group : block.groups) {
// We load the script files for the groups here
if (!group.isLoaded()) {
this.getScriptManager().loadGroupFromScript(group);
}
group.triggers.forEach(getScriptManager()::registerTrigger);
group.regions.forEach(getScriptManager()::registerRegion);
}
// Spawn gadgets AFTER triggers are added
// TODO
for (SceneGroup group : block.groups) {
if (group.init_config == null) {
continue;
}
int suite = group.init_config.suite;
if (suite == 0) {
continue;
}
do {
this.getScriptManager().spawnGadgetsInGroup(group, suite);
suite++;
} while (suite < group.init_config.end_suite);
}
}
public void onUnloadBlock(SceneBlock block) {
List<GameEntity> toRemove = this.getEntities().values().stream().filter(e -> e.getBlockId() == block.id).toList();
if (toRemove.size() > 0) {
toRemove.stream().forEach(this::removeEntityDirectly);
this.broadcastPacket(new PacketSceneEntityDisappearNotify(toRemove, VisionType.VISION_REMOVE));
}
for (SceneGroup group : block.groups) {
group.triggers.forEach(getScriptManager()::deregisterTrigger);
group.regions.forEach(getScriptManager()::deregisterRegion);
}
}
// Gadgets
public void onPlayerCreateGadget(EntityClientGadget gadget) {
......@@ -295,7 +595,7 @@ public class GenshinScene {
}
public void onPlayerDestroyGadget(int entityId) {
GenshinEntity entity = getEntities().get(entityId);
GameEntity entity = getEntities().get(entityId);
if (entity == null || !(entity instanceof EntityClientGadget)) {
return;
......@@ -313,25 +613,25 @@ public class GenshinScene {
return;
}
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VisionDie));
this.broadcastPacketToOthers(gadget.getOwner(), new PacketSceneEntityDisappearNotify(gadget, VisionType.VISION_DIE));
}
// Broadcasting
public void broadcastPacket(GenshinPacket packet) {
public void broadcastPacket(BasePacket packet) {
// Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) {
for (Player player : this.getPlayers()) {
player.getSession().send(packet);
}
}
public void broadcastPacketToOthers(GenshinPlayer excludedPlayer, GenshinPacket packet) {
public void broadcastPacketToOthers(Player excludedPlayer, BasePacket packet) {
// Optimization
if (this.getPlayerCount() == 1 && this.getPlayers().get(0) == excludedPlayer) {
return;
}
// Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) {
for (Player player : this.getPlayers()) {
if (player == excludedPlayer) {
continue;
}
......
package emu.grasscutter.game.world;
import java.util.ArrayList;
import java.util.List;
import emu.grasscutter.utils.Position;
public class SpawnDataEntry {
private transient SpawnGroupEntry group;
private int monsterId;
private int configId;
private int level;
private int poseId;
private Position pos;
private Position rot;
public SpawnGroupEntry getGroup() {
return group;
}
public void setGroup(SpawnGroupEntry group) {
this.group = group;
}
public int getMonsterId() {
return monsterId;
}
public int getConfigId() {
return configId;
}
public int getLevel() {
return level;
}
public int getPoseId() {
return poseId;
}
public Position getPos() {
return pos;
}
public Position getRot() {
return rot;
}
public static class SpawnGroupEntry {
private int sceneId;
private int groupId;
private int blockId;
private Position pos;
private List<SpawnDataEntry> spawns;
public int getSceneId() {
return sceneId;
}
public int getGroupId() {
return groupId;
}
public int getBlockId() {
return blockId;
}
public void setBlockId(int blockId) {
this.blockId = blockId;
}
public Position getPos() {
return pos;
}
public List<SpawnDataEntry> getSpawns() {
return spawns;
}
}
}
package emu.grasscutter.game;
package emu.grasscutter.game.world;
import java.util.ArrayList;
import java.util.Collection;
......@@ -8,22 +8,26 @@ import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
import emu.grasscutter.game.entity.GenshinEntity;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.player.Player.SceneLoadState;
import emu.grasscutter.game.props.ClimateType;
import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.EntityIdType;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.game.props.LifeState;
import emu.grasscutter.data.GenshinData;
import emu.grasscutter.data.GameData;
import emu.grasscutter.data.def.DungeonData;
import emu.grasscutter.data.def.SceneData;
import emu.grasscutter.game.GenshinPlayer.SceneLoadState;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.entity.EntityClientGadget;
import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.net.packet.GenshinPacket;
import emu.grasscutter.game.entity.EntityBaseGadget;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.data.SceneConfig;
import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.packet.send.PacketDelTeamEntityNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
......@@ -37,12 +41,14 @@ import emu.grasscutter.server.packet.send.PacketWorldPlayerInfoNotify;
import emu.grasscutter.server.packet.send.PacketWorldPlayerRTTNotify;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class World implements Iterable<GenshinPlayer> {
private final GenshinPlayer owner;
private final List<GenshinPlayer> players;
private final Int2ObjectMap<GenshinScene> scenes;
public class World implements Iterable<Player> {
private final GameServer server;
private final Player owner;
private final List<Player> players;
private final Int2ObjectMap<Scene> scenes;
private int levelEntityId;
private int nextEntityId = 0;
......@@ -51,24 +57,31 @@ public class World implements Iterable<GenshinPlayer> {
private boolean isMultiplayer;
public World(GenshinPlayer player) {
public World(Player player) {
this(player, false);
}
public World(GenshinPlayer player, boolean isMultiplayer) {
public World(Player player, boolean isMultiplayer) {
this.owner = player;
this.server = player.getServer();
this.players = Collections.synchronizedList(new ArrayList<>());
this.scenes = new Int2ObjectOpenHashMap<>();
this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
this.levelEntityId = getNextEntityId(EntityIdType.MPLEVEL);
this.worldLevel = player.getWorldLevel();
this.isMultiplayer = isMultiplayer;
this.owner.getServer().registerWorld(this);
}
public GenshinPlayer getHost() {
public Player getHost() {
return owner;
}
public GameServer getServer() {
return server;
}
public int getLevelEntityId() {
return levelEntityId;
}
......@@ -92,25 +105,25 @@ public class World implements Iterable<GenshinPlayer> {
this.worldLevel = worldLevel;
}
public List<GenshinPlayer> getPlayers() {
public List<Player> getPlayers() {
return players;
}
public Int2ObjectMap<GenshinScene> getScenes() {
public Int2ObjectMap<Scene> getScenes() {
return this.scenes;
}
public GenshinScene getSceneById(int sceneId) {
public Scene getSceneById(int sceneId) {
// Get scene normally
GenshinScene scene = getScenes().get(sceneId);
Scene scene = getScenes().get(sceneId);
if (scene != null) {
return scene;
}
// Create scene from scene data if it doesnt exist
SceneData sceneData = GenshinData.getSceneDataMap().get(sceneId);
SceneData sceneData = GameData.getSceneDataMap().get(sceneId);
if (sceneData != null) {
scene = new GenshinScene(this, sceneData);
scene = new Scene(this, sceneData);
this.registerScene(scene);
return scene;
}
......@@ -130,7 +143,7 @@ public class World implements Iterable<GenshinPlayer> {
return (idType.getId() << 24) + ++this.nextEntityId;
}
public synchronized void addPlayer(GenshinPlayer player) {
public synchronized void addPlayer(Player player) {
// Check if player already in
if (getPlayers().contains(player)) {
return;
......@@ -156,7 +169,7 @@ public class World implements Iterable<GenshinPlayer> {
}
// Add to scene
GenshinScene scene = this.getSceneById(player.getSceneId());
Scene scene = this.getSceneById(player.getSceneId());
scene.addPlayer(player);
// Info packet for other players
......@@ -165,7 +178,7 @@ public class World implements Iterable<GenshinPlayer> {
}
}
public synchronized void removePlayer(GenshinPlayer player) {
public synchronized void removePlayer(Player player) {
// Remove team entities
player.sendPacket(
new PacketDelTeamEntityNotify(
......@@ -179,7 +192,7 @@ public class World implements Iterable<GenshinPlayer> {
player.setWorld(null);
// Remove from scene
GenshinScene scene = this.getSceneById(player.getSceneId());
Scene scene = this.getSceneById(player.getSceneId());
scene.removePlayer(player);
// Info packet for other players
......@@ -189,51 +202,95 @@ public class World implements Iterable<GenshinPlayer> {
// Disband world if host leaves
if (getHost() == player) {
List<GenshinPlayer> kicked = new ArrayList<>(this.getPlayers());
for (GenshinPlayer victim : kicked) {
List<Player> kicked = new ArrayList<>(this.getPlayers());
for (Player victim : kicked) {
World world = new World(victim);
world.addPlayer(victim);
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.EnterSelf, EnterReason.TeamKick, victim.getSceneId(), victim.getPos()));
victim.sendPacket(new PacketPlayerEnterSceneNotify(victim, EnterType.ENTER_SELF, EnterReason.TeamKick, victim.getSceneId(), victim.getPos()));
}
}
}
public void registerScene(GenshinScene scene) {
public void registerScene(Scene scene) {
this.getScenes().put(scene.getId(), scene);
}
public void deregisterScene(GenshinScene scene) {
public void deregisterScene(Scene scene) {
this.getScenes().remove(scene.getId());
}
public boolean transferPlayerToScene(GenshinPlayer player, int sceneId, Position pos) {
if (GenshinData.getSceneDataMap().get(sceneId) == null) {
public boolean transferPlayerToScene(Player player, int sceneId, Position pos) {
return transferPlayerToScene(player, sceneId, null, pos);
}
public boolean transferPlayerToScene(Player player, int sceneId, DungeonData data) {
return transferPlayerToScene(player, sceneId, data, null);
}
public boolean transferPlayerToScene(Player player, int sceneId, DungeonData dungeonData, Position pos) {
if (GameData.getSceneDataMap().get(sceneId) == null) {
return false;
}
Integer oldSceneId = null;
Scene oldScene = null;
if (player.getScene() != null) {
oldSceneId = player.getScene().getId();
player.getScene().removePlayer(player);
oldScene = player.getScene();
// Dont deregister scenes if the player is going to tp back into them
if (oldScene.getId() == sceneId) {
oldScene.setDontDestroyWhenEmpty(true);
}
oldScene.removePlayer(player);
}
Scene newScene = this.getSceneById(sceneId);
newScene.setDungeonData(dungeonData);
newScene.addPlayer(player);
// Dungeon
SceneConfig config = newScene.getScriptManager().getConfig();
if (pos == null && config != null) {
if (config.born_pos != null) {
pos = newScene.getScriptManager().getConfig().born_pos;
}
if (config.born_rot != null) {
player.getRotation().set(config.born_rot);
}
}
// Set player position
if (pos == null) {
pos = player.getPos();
}
GenshinScene scene = this.getSceneById(sceneId);
scene.addPlayer(player);
player.getPos().set(pos);
if (oldScene != null) {
newScene.setPrevScene(oldScene.getId());
oldScene.setDontDestroyWhenEmpty(false);
}
// Get enter types
EnterType enterType = EnterType.ENTER_JUMP;
EnterReason enterReason = EnterReason.TransPoint;
// Teleport packet
if (oldSceneId.equals(sceneId)) {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterGoto, EnterReason.TransPoint, sceneId, pos));
} else {
player.sendPacket(new PacketPlayerEnterSceneNotify(player, EnterType.EnterJump, EnterReason.TransPoint, sceneId, pos));
if (dungeonData != null) {
enterType = EnterType.ENTER_DUNGEON;
enterReason = EnterReason.DungeonEnter;
} else if (oldScene == newScene) {
enterType = EnterType.ENTER_GOTO;
}
// Teleport packet
player.sendPacket(new PacketPlayerEnterSceneNotify(player, enterType, enterReason, sceneId, pos));
return true;
}
private void updatePlayerInfos(GenshinPlayer paramPlayer) {
for (GenshinPlayer player : getPlayers()) {
private void updatePlayerInfos(Player paramPlayer) {
for (Player player : getPlayers()) {
// Dont send packets if player is loading in and filter out joining player
if (!player.hasSentAvatarDataNotify() || player.getSceneLoadState().getValue() < SceneLoadState.INIT.getValue() || player == paramPlayer) {
continue;
......@@ -256,19 +313,25 @@ public class World implements Iterable<GenshinPlayer> {
}
}
public void broadcastPacket(GenshinPacket packet) {
public void broadcastPacket(BasePacket packet) {
// Send to all players - might have to check if player has been sent data packets
for (GenshinPlayer player : this.getPlayers()) {
for (Player player : this.getPlayers()) {
player.getSession().send(packet);
}
}
public void onTick() {
for (Scene scene : this.getScenes().values()) {
scene.onTick();
}
}
public void close() {
}
@Override
public Iterator<GenshinPlayer> iterator() {
public Iterator<Player> iterator() {
return getPlayers().iterator();
}
}
......@@ -7,7 +7,7 @@ import com.google.protobuf.GeneratedMessageV3;
import emu.grasscutter.net.proto.PacketHeadOuterClass.PacketHead;
import emu.grasscutter.utils.Crypto;
public class GenshinPacket {
public class BasePacket {
private static final int const1 = 17767; // 0x4567
private static final int const2 = -30293; // 0x89ab
......@@ -21,16 +21,16 @@ public class GenshinPacket {
private boolean useDispatchKey;
public boolean shouldEncrypt = true;
public GenshinPacket(int opcode) {
public BasePacket(int opcode) {
this.opcode = opcode;
}
public GenshinPacket(int opcode, int clientSequence) {
public BasePacket(int opcode, int clientSequence) {
this.opcode = opcode;
this.buildHeader(clientSequence);
}
public GenshinPacket(int opcode, boolean buildHeader) {
public BasePacket(int opcode, boolean buildHeader) {
this.opcode = opcode;
this.shouldBuildHeader = buildHeader;
}
......@@ -80,7 +80,7 @@ public class GenshinPacket {
this.data = proto.build().toByteArray();
}
public GenshinPacket buildHeader(int clientSequence) {
public BasePacket buildHeader(int clientSequence) {
if (this.getHeader() != null && clientSequence == 0) {
return this;
}
......
package emu.grasscutter.net.packet;
import java.util.Arrays;
import java.util.List;
public class PacketOpcodes {
// Empty
public static final int NONE = 0;
......@@ -15,17 +18,23 @@ public class PacketOpcodes {
public static final int AchievementUpdateNotify = 1146;
public static final int ActivityCoinInfoNotify = 2056;
public static final int ActivityCondStateChangeNotify = 2162;
public static final int ActivityDisableTransferPointInteractionNotify = 8295;
public static final int ActivityInfoNotify = 2023;
public static final int ActivityPlayOpenAnimNotify = 2164;
public static final int ActivitySaleChangeNotify = 2043;
public static final int ActivityScheduleInfoNotify = 2187;
public static final int ActivityScheduleInfoNotify = 2180;
public static final int ActivityScheduleInfoNotify_1 = 2187;
public static final int ActivitySelectAvatarCardReq = 2153;
public static final int ActivitySelectAvatarCardRsp = 2069;
public static final int ActivityTakeAllScoreRewardReq = 8708;
public static final int ActivityTakeAllScoreRewardRsp = 8836;
public static final int ActivityTakeScoreRewardReq = 8767;
public static final int ActivityTakeScoreRewardRsp = 8445;
public static final int ActivityTakeWatcherRewardBatchReq = 2027;
public static final int ActivityTakeWatcherRewardBatchRsp = 2036;
public static final int ActivityTakeWatcherRewardReq = 2074;
public static final int ActivityTakeWatcherRewardRsp = 2180;
public static final int ActivityTakeWatcherRewardRsp_1 = 2187;
public static final int ActivityUpdateWatcherNotify = 2101;
public static final int AddBlacklistReq = 4067;
public static final int AddBlacklistRsp = 4020;
......@@ -61,6 +70,8 @@ public class PacketOpcodes {
public static final int AvatarBuffDelNotify = 320;
public static final int AvatarCardChangeReq = 667;
public static final int AvatarCardChangeRsp = 620;
public static final int AvatarChangeAnimHashReq = 1630;
public static final int AvatarChangeAnimHashRsp = 1747;
public static final int AvatarChangeCostumeNotify = 1748;
public static final int AvatarChangeCostumeReq = 1650;
public static final int AvatarChangeCostumeRsp = 1632;
......@@ -140,6 +151,8 @@ public class PacketOpcodes {
public static final int BlessingRedeemRewardRsp = 2039;
public static final int BlessingScanReq = 2186;
public static final int BlessingScanRsp = 2007;
public static final int BlitzRushParkourRestartReq = 8212;
public static final int BlitzRushParkourRestartRsp = 8962;
public static final int BlossomBriefInfoNotify = 2710;
public static final int BlossomChestCreateNotify = 2793;
public static final int BlossomChestInfoNotify = 845;
......@@ -147,6 +160,8 @@ public class PacketOpcodes {
public static final int BonusActivityInfoRsp = 2588;
public static final int BonusActivityUpdateNotify = 2591;
public static final int BossChestActivateNotify = 844;
public static final int BounceConjuringSettleNotify = 8339;
public static final int BuoyantCombatSettleNotify = 9000;
public static final int BuyBattlePassLevelReq = 2639;
public static final int BuyBattlePassLevelRsp = 2621;
public static final int BuyGoodsReq = 710;
......@@ -155,12 +170,12 @@ public class PacketOpcodes {
public static final int BuyResinRsp = 647;
public static final int CalcWeaponUpgradeReturnItemsReq = 643;
public static final int CalcWeaponUpgradeReturnItemsRsp = 686;
public static final int CanUseSkillNotify = 1055;
public static final int CancelCityReputationRequestReq = 2834;
public static final int CancelCityReputationRequestRsp = 2879;
public static final int CancelCoopTaskReq = 1989;
public static final int CancelCoopTaskRsp = 1971;
public static final int CancelFinishParentQuestNotify = 492;
public static final int CanUseSkillNotify = 1055;
public static final int CardProductRewardNotify = 4148;
public static final int ChallengeDataNotify = 983;
public static final int ChallengeRecordNotify = 909;
......@@ -171,27 +186,64 @@ public class PacketOpcodes {
public static final int ChangeMailStarNotify = 1497;
public static final int ChangeMpTeamAvatarReq = 1794;
public static final int ChangeMpTeamAvatarRsp = 1629;
public static final int ChangeServerGlobalValueNotify = 65;
public static final int ChangeTeamNameReq = 1793;
public static final int ChangeTeamNameRsp = 1707;
public static final int ChangeWorldToSingleModeNotify = 3293;
public static final int ChangeWorldToSingleModeReq = 3174;
public static final int ChangeWorldToSingleModeRsp = 3308;
public static final int ChannelerSlabStageActiveChallengeIndexNotify = 8578;
public static final int ChannelerSlabStageOneoffDungeonNotify = 8137;
public static final int ChannellerSlabCheckEnterLoopDungeonReq = 8684;
public static final int ChannellerSlabCheckEnterLoopDungeonRsp = 8376;
public static final int ChannellerSlabEnterLoopDungeonReq = 8090;
public static final int ChannellerSlabEnterLoopDungeonRsp = 8120;
public static final int ChannellerSlabLoopDungeonChallengeInfoNotify = 8263;
public static final int ChannellerSlabLoopDungeonSelectConditionReq = 8741;
public static final int ChannellerSlabLoopDungeonSelectConditionRsp = 8341;
public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardReq = 8914;
public static final int ChannellerSlabLoopDungeonTakeFirstPassRewardRsp = 8503;
public static final int ChannellerSlabLoopDungeonTakeScoreRewardReq = 8012;
public static final int ChannellerSlabLoopDungeonTakeScoreRewardRsp = 8123;
public static final int ChannellerSlabOneOffDungeonInfoNotify = 8795;
public static final int ChannellerSlabOneOffDungeonInfoReq = 8772;
public static final int ChannellerSlabOneOffDungeonInfoRsp = 8715;
public static final int ChannellerSlabSaveAssistInfoReq = 8518;
public static final int ChannellerSlabSaveAssistInfoRsp = 8773;
public static final int ChannellerSlabTakeoffBuffReq = 8407;
public static final int ChannellerSlabTakeoffBuffRsp = 8260;
public static final int ChannellerSlabWearBuffReq = 8850;
public static final int ChannellerSlabWearBuffRsp = 8203;
public static final int ChapterStateNotify = 455;
public static final int ChatChannelDataNotify = 5047;
public static final int ChatChannelUpdateNotify = 5041;
public static final int ChatHistoryNotify = 3265;
public static final int CheckAddItemExceedLimitNotify = 639;
public static final int CheckSegmentCRCNotify = 56;
public static final int CheckSegmentCRCReq = 83;
public static final int ChessEscapedMonstersNotify = 5394;
public static final int ChessLeftMonstersNotify = 5378;
public static final int ChessManualRefreshCardsReq = 5325;
public static final int ChessManualRefreshCardsRsp = 5349;
public static final int ChessPickCardNotify = 5377;
public static final int ChessPickCardReq = 5343;
public static final int ChessPickCardRsp = 5386;
public static final int ChessPlayerInfoNotify = 5385;
public static final int ChessSelectedCardsNotify = 5339;
public static final int ChooseCurAvatarTeamReq = 1713;
public static final int ChooseCurAvatarTeamRsp = 1608;
public static final int CityReputationDataNotify = 2855;
public static final int CityReputationLevelupNotify = 2837;
public static final int ClientAIStateNotify = 1128;
public static final int ClearRoguelikeCurseNotify = 8997;
public static final int ClientAbilitiesInitFinishCombineNotify = 1144;
public static final int ClientAbilityChangeNotify = 1191;
public static final int ClientAbilityInitBeginNotify = 1110;
public static final int ClientAbilityInitFinishNotify = 1115;
public static final int ClientAIStateNotify = 1128;
public static final int ClientBulletCreateNotify = 89;
public static final int ClientCollectorDataNotify = 4262;
public static final int ClientHashDebugNotify = 3163;
public static final int ClientLoadingCostumeVerificationNotify = 3133;
public static final int ClientLockGameTimeNotify = 194;
public static final int ClientNewMailNotify = 1434;
public static final int ClientPauseNotify = 278;
......@@ -202,6 +254,7 @@ public class PacketOpcodes {
public static final int ClientTransmitRsp = 292;
public static final int ClientTriggerEventNotify = 197;
public static final int CloseCommonTipsNotify = 3187;
public static final int ClosedItemNotify = 694;
public static final int CodexDataFullNotify = 4204;
public static final int CodexDataUpdateNotify = 4205;
public static final int CombatInvocationsNotify = 347;
......@@ -209,7 +262,9 @@ public class PacketOpcodes {
public static final int CombineFormulaDataNotify = 685;
public static final int CombineReq = 663;
public static final int CombineRsp = 608;
public static final int CommonPlayerTipsNotify = 8928;
public static final int CompoundDataNotify = 181;
public static final int CompoundUnlockNotify = 199;
public static final int CookDataNotify = 164;
public static final int CookGradeDataNotify = 166;
public static final int CookRecipeDataNotify = 101;
......@@ -223,27 +278,38 @@ public class PacketOpcodes {
public static final int CreateMassiveEntityNotify = 336;
public static final int CreateMassiveEntityReq = 323;
public static final int CreateMassiveEntityRsp = 313;
public static final int CreateVehicleReq = 809;
public static final int CreateVehicleRsp = 865;
public static final int CutSceneBeginNotify = 241;
public static final int CutSceneEndNotify = 214;
public static final int CutSceneFinishNotify = 248;
public static final int DailyTaskDataNotify = 124;
public static final int DailyTaskFilterCityReq = 159;
public static final int DailyTaskFilterCityRsp = 150;
public static final int DailyTaskProgressNotify = 161;
public static final int DailyTaskScoreRewardNotify = 138;
public static final int DailyTaskUnlockedCitiesNotify = 119;
public static final int DataResVersionNotify = 136;
public static final int DealAddFriendReq = 4044;
public static final int DealAddFriendRsp = 4045;
public static final int DeleteFriendNotify = 4083;
public static final int DeleteFriendReq = 4079;
public static final int DeleteFriendRsp = 4091;
public static final int DelMailReq = 1493;
public static final int DelMailRsp = 1444;
public static final int DelScenePlayTeamEntityNotify = 3117;
public static final int DelTeamEntityNotify = 330;
public static final int DeleteFriendNotify = 4083;
public static final int DeleteFriendReq = 4079;
public static final int DeleteFriendRsp = 4091;
public static final int DestroyMassiveEntityNotify = 324;
public static final int DestroyMaterialReq = 670;
public static final int DestroyMaterialRsp = 654;
public static final int DigActivityChangeGadgetStateReq = 8283;
public static final int DigActivityChangeGadgetStateRsp = 8609;
public static final int DigActivityMarkPointChangeNotify = 8143;
public static final int DisableRoguelikeTrapNotify = 8029;
public static final int DoGachaReq = 1510;
public static final int DoGachaRsp = 1515;
public static final int DoRoguelikeDungeonCardGachaReq = 8897;
public static final int DoRoguelikeDungeonCardGachaRsp = 8973;
public static final int DoSetPlayerBornDataNotify = 174;
public static final int DraftGuestReplyInviteNotify = 5445;
public static final int DraftGuestReplyInviteReq = 5493;
......@@ -283,6 +349,8 @@ public class PacketOpcodes {
public static final int DungeonCandidateTeamRefuseNotify = 967;
public static final int DungeonCandidateTeamReplyInviteReq = 927;
public static final int DungeonCandidateTeamReplyInviteRsp = 902;
public static final int DungeonCandidateTeamSetChangingAvatarReq = 954;
public static final int DungeonCandidateTeamSetChangingAvatarRsp = 935;
public static final int DungeonCandidateTeamSetReadyReq = 952;
public static final int DungeonCandidateTeamSetReadyRsp = 992;
public static final int DungeonChallengeBeginNotify = 974;
......@@ -308,6 +376,7 @@ public class PacketOpcodes {
public static final int DungeonRestartReq = 932;
public static final int DungeonRestartResultNotify = 970;
public static final int DungeonRestartRsp = 951;
public static final int DungeonReviseLevelNotify = 957;
public static final int DungeonSettleNotify = 934;
public static final int DungeonShowReminderNotify = 988;
public static final int DungeonSlipRevivePointActivateReq = 924;
......@@ -316,11 +385,19 @@ public class PacketOpcodes {
public static final int DungeonWayPointActivateRsp = 975;
public static final int DungeonWayPointNotify = 944;
public static final int EchoNotify = 62;
public static final int EchoShellTakeRewardReq = 8801;
public static final int EchoShellTakeRewardRsp = 8888;
public static final int EchoShellUpdateNotify = 8730;
public static final int EffigyChallengeInfoNotify = 2159;
public static final int EffigyChallengeResultNotify = 2024;
public static final int EndCameraSceneLookNotify = 238;
public static final int EnterChessDungeonReq = 8336;
public static final int EnterChessDungeonRsp = 8581;
public static final int EnterFishingReq = 5835;
public static final int EnterFishingRsp = 5825;
public static final int EnterMechanicusDungeonReq = 3979;
public static final int EnterMechanicusDungeonRsp = 3991;
public static final int EnterRoguelikeDungeonNotify = 8330;
public static final int EnterSceneDoneReq = 268;
public static final int EnterSceneDoneRsp = 290;
public static final int EnterScenePeerNotify = 282;
......@@ -345,12 +422,16 @@ public class PacketOpcodes {
public static final int EntityMoveRoomNotify = 3135;
public static final int EntityPropNotify = 1260;
public static final int EntityTagChangeNotify = 3262;
public static final int EquipRoguelikeRuneReq = 8579;
public static final int EquipRoguelikeRuneRsp = 8412;
public static final int EvtAiSyncCombatThreatInfoNotify = 351;
public static final int EvtAiSyncSkillCdNotify = 317;
public static final int EvtAnimatorParameterNotify = 333;
public static final int EvtAnimatorStateChangedNotify = 379;
public static final int EvtAvatarEnterFocusNotify = 389;
public static final int EvtAvatarExitFocusNotify = 309;
public static final int EvtAvatarLockChairReq = 354;
public static final int EvtAvatarLockChairRsp = 335;
public static final int EvtAvatarSitDownNotify = 392;
public static final int EvtAvatarStandUpNotify = 358;
public static final int EvtAvatarUpdateFocusNotify = 365;
......@@ -370,10 +451,13 @@ public class PacketOpcodes {
public static final int EvtFaceToEntityNotify = 344;
public static final int EvtRushMoveNotify = 391;
public static final int EvtSetAttackTargetNotify = 334;
public static final int ExclusiveRuleNotify = 169;
public static final int ExecuteGadgetLuaReq = 231;
public static final int ExecuteGadgetLuaRsp = 240;
public static final int ExecuteGroupTriggerReq = 284;
public static final int ExecuteGroupTriggerRsp = 212;
public static final int ExitFishingReq = 5812;
public static final int ExitFishingRsp = 5839;
public static final int ExitSceneWeatherAreaNotify = 223;
public static final int ExitTransPointRegionNotify = 246;
public static final int ExpeditionChallengeEnterRegionNotify = 2095;
......@@ -384,11 +468,27 @@ public class PacketOpcodes {
public static final int ExpeditionStartRsp = 2148;
public static final int ExpeditionTakeRewardReq = 2053;
public static final int ExpeditionTakeRewardRsp = 2181;
public static final int FindHilichurlAcceptQuestNotify = 8292;
public static final int FindHilichurlFinishSecondQuestNotify = 8799;
public static final int FinishDeliveryNotify = 2126;
public static final int FinishMainCoopReq = 1963;
public static final int FinishMainCoopRsp = 1951;
public static final int FinishedParentQuestNotify = 415;
public static final int FinishedParentQuestUpdateNotify = 437;
public static final int FinishMainCoopReq = 1963;
public static final int FinishMainCoopRsp = 1951;
public static final int FishAttractNotify = 5821;
public static final int FishBaitGoneNotify = 5846;
public static final int FishBattleBeginReq = 5815;
public static final int FishBattleBeginRsp = 5827;
public static final int FishBattleEndReq = 5837;
public static final int FishBattleEndRsp = 5806;
public static final int FishBiteReq = 5843;
public static final int FishBiteRsp = 5826;
public static final int FishCastRodReq = 5813;
public static final int FishCastRodRsp = 5801;
public static final int FishChosenNotify = 5817;
public static final int FishEscapeNotify = 5836;
public static final int FishingGallerySettleNotify = 8870;
public static final int FishPoolDataNotify = 5850;
public static final int FleurFairBalloonSettleNotify = 2192;
public static final int FleurFairBuffEnergyNotify = 5392;
public static final int FleurFairFallSettleNotify = 2015;
......@@ -421,6 +521,7 @@ public class PacketOpcodes {
public static final int FoundationNotify = 874;
public static final int FoundationReq = 855;
public static final int FoundationRsp = 846;
public static final int FriendInfoChangeNotify = 4085;
public static final int FunitureMakeMakeInfoChangeNotify = 4523;
public static final int FurnitureCurModuleArrangeCountNotify = 4770;
public static final int FurnitureMakeBeHelpedNotify = 4825;
......@@ -433,11 +534,14 @@ public class PacketOpcodes {
public static final int FurnitureMakeRsp = 4819;
public static final int FurnitureMakeStartReq = 4518;
public static final int FurnitureMakeStartRsp = 4521;
public static final int GMShowNavMeshReq = 2384;
public static final int GMShowNavMeshRsp = 2312;
public static final int GMShowObstacleReq = 2332;
public static final int GMShowObstacleRsp = 2351;
public static final int GachaOpenWishNotify = 1544;
public static final int GachaSimpleInfoNotify = 1545;
public static final int GachaWishReq = 1537;
public static final int GachaWishRsp = 1593;
public static final int GadgetAutoPickDropInfoNotify = 888;
public static final int GadgetChainLevelChangeNotify = 826;
public static final int GadgetChainLevelUpdateNotify = 883;
public static final int GadgetCustomTreeInfoNotify = 873;
public static final int GadgetGeneralRewardInfoNotify = 897;
public static final int GadgetInteractReq = 860;
public static final int GadgetInteractRsp = 833;
......@@ -449,6 +553,7 @@ public class PacketOpcodes {
public static final int GadgetTalkChangeNotify = 856;
public static final int GalleryBalloonScoreNotify = 5510;
public static final int GalleryBalloonShootNotify = 5533;
public static final int GalleryBounceConjuringHitNotify = 5555;
public static final int GalleryBrokenFloorFallNotify = 5591;
public static final int GalleryBulletHitNotify = 5579;
public static final int GalleryFallCatchNotify = 5537;
......@@ -457,6 +562,7 @@ public class PacketOpcodes {
public static final int GalleryPreStartNotify = 5534;
public static final int GalleryStartNotify = 5560;
public static final int GalleryStopNotify = 5515;
public static final int GallerySumoKillMonsterNotify = 5546;
public static final int GetActivityInfoReq = 2011;
public static final int GetActivityInfoRsp = 2170;
public static final int GetActivityScheduleReq = 2663;
......@@ -466,6 +572,7 @@ public class PacketOpcodes {
public static final int GetAllActivatedBargainDataReq = 480;
public static final int GetAllActivatedBargainDataRsp = 464;
public static final int GetAllH5ActivityInfoReq = 5675;
public static final int GetAllH5ActivityInfoRsp = 5685;
public static final int GetAllMailReq = 1479;
public static final int GetAllMailRsp = 1491;
public static final int GetAllSceneGalleryInfoReq = 5544;
......@@ -474,10 +581,10 @@ public class PacketOpcodes {
public static final int GetAllUnlockNameCardRsp = 4003;
public static final int GetAreaExplorePointReq = 227;
public static final int GetAreaExplorePointRsp = 202;
public static final int GetAuthSalesmanInfoReq = 2082;
public static final int GetAuthSalesmanInfoRsp = 2173;
public static final int GetAuthkeyReq = 1445;
public static final int GetAuthkeyRsp = 1475;
public static final int GetAuthSalesmanInfoReq = 2082;
public static final int GetAuthSalesmanInfoRsp = 2173;
public static final int GetBargainDataReq = 467;
public static final int GetBargainDataRsp = 420;
public static final int GetBattlePassProductReq = 2643;
......@@ -486,6 +593,8 @@ public class PacketOpcodes {
public static final int GetBlossomBriefInfoListRsp = 2733;
public static final int GetBonusActivityRewardReq = 2528;
public static final int GetBonusActivityRewardRsp = 2555;
public static final int GetChatEmojiCollectionReq = 4057;
public static final int GetChatEmojiCollectionRsp = 4043;
public static final int GetCityHuntingOfferReq = 4456;
public static final int GetCityHuntingOfferRsp = 4747;
public static final int GetCityReputationInfoReq = 2860;
......@@ -515,6 +624,8 @@ public class PacketOpcodes {
public static final int GetInvestigationMonsterRsp = 1921;
public static final int GetMailItemReq = 1415;
public static final int GetMailItemRsp = 1437;
public static final int GetMapAreaReq = 3269;
public static final int GetMapAreaRsp = 3366;
public static final int GetMapMarkTipsReq = 3307;
public static final int GetMapMarkTipsRsp = 3040;
public static final int GetMechanicusInfoReq = 3960;
......@@ -527,6 +638,7 @@ public class PacketOpcodes {
public static final int GetOnlinePlayerListRsp = 75;
public static final int GetOpActivityInfoReq = 5160;
public static final int GetOpActivityInfoRsp = 5133;
public static final int GetPlayerAskFriendListReq = 4054;
public static final int GetPlayerAskFriendListRsp = 4035;
public static final int GetPlayerBlacklistReq = 4002;
public static final int GetPlayerBlacklistRsp = 4052;
......@@ -560,33 +672,61 @@ public class PacketOpcodes {
public static final int GetScenePerformanceRsp = 3319;
public static final int GetScenePointReq = 288;
public static final int GetScenePointRsp = 228;
public static final int GetShopReq = 760;
public static final int GetShopRsp = 733;
public static final int GetShopmallDataReq = 737;
public static final int GetShopmallDataRsp = 793;
public static final int GetShopReq = 760;
public static final int GetShopRsp = 733;
public static final int GetSignInRewardReq = 2537;
public static final int GetSignInRewardRsp = 2593;
public static final int GetWidgetSlotReq = 4258;
public static final int GetWidgetSlotRsp = 4294;
public static final int GetWorldMpInfoReq = 3439;
public static final int GetWorldMpInfoRsp = 3424;
public static final int GiveUpRoguelikeDungeonCardReq = 8425;
public static final int GiveUpRoguelikeDungeonCardRsp = 8976;
public static final int GivingRecordChangeNotify = 172;
public static final int GivingRecordNotify = 153;
public static final int GMShowNavMeshReq = 2384;
public static final int GMShowNavMeshRsp = 2312;
public static final int GMShowObstacleReq = 2332;
public static final int GMShowObstacleRsp = 2351;
public static final int GmTalkNotify = 3;
public static final int GmTalkReq = 33;
public static final int GmTalkRsp = 10;
public static final int GrantRewardNotify = 680;
public static final int GroupLinkAllNotify = 5785;
public static final int GroupLinkChangeNotify = 5775;
public static final int GroupLinkDeleteNotify = 5795;
public static final int GroupSuiteNotify = 3368;
public static final int GroupUnloadNotify = 3019;
public static final int GuestBeginEnterSceneNotify = 3033;
public static final int GuestPostEnterSceneNotify = 3198;
public static final int H5ActivityIdsNotify = 5695;
public static final int HideAndSeekPlayerReadyNotify = 5330;
public static final int HideAndSeekPlayerSetAvatarNotify = 5347;
public static final int HideAndSeekSelectAvatarReq = 5313;
public static final int HideAndSeekSelectAvatarRsp = 5336;
public static final int HideAndSeekSelectSkillReq = 8689;
public static final int HideAndSeekSelectSkillRsp = 8948;
public static final int HideAndSeekSetReadyReq = 5324;
public static final int HideAndSeekSetReadyRsp = 5361;
public static final int HideAndSeekSettleNotify = 5338;
public static final int HitClientTrivialNotify = 250;
public static final int HitTreeNotify = 3432;
public static final int HomeAvatarAllFinishRewardNotify = 4612;
public static final int HomeAvatarCostumeChangeNotify = 4888;
public static final int HomeAvatarRewardEventGetReq = 4568;
public static final int HomeAvatarRewardEventGetRsp = 4453;
public static final int HomeAvatarRewardEventNotify = 4801;
public static final int HomeAvatarSummonAllEventNotify = 4575;
public static final int HomeAvatarSummonEventReq = 4871;
public static final int HomeAvatarSummonEventRsp = 4895;
public static final int HomeAvatarSummonFinishReq = 4654;
public static final int HomeAvatarSummonFinishRsp = 4503;
public static final int HomeAvatarTalkFinishInfoNotify = 4800;
public static final int HomeAvatarTalkReq = 4610;
public static final int HomeAvatarTalkRsp = 4507;
public static final int HomeAvtarAllFinishRewardNotify = 4546;
public static final int HomeBasicInfoNotify = 4869;
public static final int HomeBlockNotify = 4784;
public static final int HomeChangeEditModeReq = 4483;
......@@ -596,9 +736,15 @@ public class PacketOpcodes {
public static final int HomeChooseModuleReq = 4567;
public static final int HomeChooseModuleRsp = 4633;
public static final int HomeComfortInfoNotify = 4649;
public static final int HomeCustomFurnitureInfoNotify = 4636;
public static final int HomeEditCustomFurnitureReq = 4621;
public static final int HomeEditCustomFurnitureRsp = 4804;
public static final int HomeFishFarmingInfoNotify = 4893;
public static final int HomeGetArrangementInfoReq = 4480;
public static final int HomeGetArrangementInfoRsp = 4781;
public static final int HomeGetBasicInfoReq = 4839;
public static final int HomeGetFishFarmingInfoReq = 4848;
public static final int HomeGetFishFarmingInfoRsp = 4451;
public static final int HomeGetOnlineStatusReq = 4673;
public static final int HomeGetOnlineStatusRsp = 4626;
public static final int HomeKickPlayerReq = 4547;
......@@ -611,15 +757,34 @@ public class PacketOpcodes {
public static final int HomeLimitedShopInfoNotify = 4679;
public static final int HomeLimitedShopInfoReq = 4715;
public static final int HomeLimitedShopInfoRsp = 4808;
public static final int HomeMarkPointNotify = 4764;
public static final int HomeModuleSeenReq = 4642;
public static final int HomeModuleSeenRsp = 4688;
public static final int HomeModuleUnlockNotify = 4778;
public static final int HomePlantFieldNotify = 4529;
public static final int HomePlantInfoNotify = 4832;
public static final int HomePlantInfoReq = 4771;
public static final int HomePlantInfoRsp = 4806;
public static final int HomePlantSeedReq = 4730;
public static final int HomePlantSeedRsp = 4857;
public static final int HomePlantWeedReq = 4760;
public static final int HomePlantWeedRsp = 4463;
public static final int HomePriorCheckNotify = 4601;
public static final int HomeResourceNotify = 4513;
public static final int HomeResourceTakeFetterExpReq = 4884;
public static final int HomeResourceTakeFetterExpRsp = 4608;
public static final int HomeResourceTakeHomeCoinReq = 4812;
public static final int HomeResourceTakeHomeCoinRsp = 4481;
public static final int HomeSceneInitFinishReq = 4520;
public static final int HomeSceneInitFinishRsp = 4605;
public static final int HomeSceneJumpReq = 4862;
public static final int HomeSceneJumpRsp = 4663;
public static final int HomeTransferReq = 4656;
public static final int HomeTransferRsp = 4669;
public static final int HomeUpdateArrangementInfoReq = 4632;
public static final int HomeUpdateArrangementInfoRsp = 4820;
public static final int HomeUpdateFishFarmingInfoReq = 4810;
public static final int HomeUpdateFishFarmingInfoRsp = 4500;
public static final int HostPlayerNotify = 310;
public static final int HuntingFailNotify = 4345;
public static final int HuntingGiveUpReq = 4313;
......@@ -643,6 +808,7 @@ public class PacketOpcodes {
public static final int InteractDailyDungeonInfoNotify = 947;
public static final int InterruptGalleryReq = 5597;
public static final int InterruptGalleryRsp = 5588;
public static final int InvestigationMonsterUpdateNotify = 1918;
public static final int ItemAddHintNotify = 637;
public static final int ItemCdGroupTimeNotify = 666;
public static final int ItemExceedLimitNotify = 639;
......@@ -655,17 +821,32 @@ public class PacketOpcodes {
public static final int KeepAliveNotify = 60;
public static final int LeaveSceneReq = 233;
public static final int LeaveSceneRsp = 210;
public static final int LeaveWorldNotify = 3203;
public static final int LevelupCityReq = 253;
public static final int LevelupCityRsp = 272;
public static final int LifeStateChangeNotify = 1233;
public static final int LiveEndNotify = 801;
public static final int LiveStartNotify = 820;
public static final int LoadActivityTerrainNotify = 2152;
public static final int LuaEnvironmentEffectNotify = 3175;
public static final int LuaSetOptionNotify = 353;
public static final int LunaRiteAreaFinishNotify = 8822;
public static final int LunaRiteGroupBundleRegisterNotify = 8956;
public static final int LunaRiteHintPointRemoveNotify = 8544;
public static final int LunaRiteHintPointReq = 8173;
public static final int LunaRiteHintPointRsp = 8129;
public static final int LunaRiteSacrificeReq = 8364;
public static final int LunaRiteSacrificeRsp = 8328;
public static final int LunaRiteTakeSacrificeRewardReq = 8987;
public static final int LunaRiteTakeSacrificeRewardRsp = 8352;
public static final int MailChangeNotify = 1433;
public static final int MainCoopUpdateNotify = 1975;
public static final int MapAreaChangeNotify = 3055;
public static final int MarkEntityInMinMapNotify = 230;
public static final int MarkMapReq = 3053;
public static final int MarkMapRsp = 3139;
public static final int MarkNewNotify = 1291;
public static final int MarkTargetInvestigationMonsterNotify = 1924;
public static final int MassiveEntityElementOpBatchNotify = 384;
public static final int MassiveEntityStateChangedNotify = 361;
public static final int MaterialDeleteReturnNotify = 632;
......@@ -692,6 +873,11 @@ public class PacketOpcodes {
public static final int MiracleRingDropResultNotify = 5201;
public static final int MiracleRingTakeRewardReq = 5248;
public static final int MiracleRingTakeRewardRsp = 5213;
public static final int MistTrialDunegonFailNotify = 8337;
public static final int MistTrialGetChallengeMissionReq = 8250;
public static final int MistTrialGetChallengeMissionRsp = 8894;
public static final int MistTrialSelectAvatarAndEnterDungeonReq = 8186;
public static final int MistTrialSelectAvatarAndEnterDungeonRsp = 8522;
public static final int MonsterAIConfigHashNotify = 3024;
public static final int MonsterAlertChangeNotify = 380;
public static final int MonsterForceAlertNotify = 364;
......@@ -713,12 +899,19 @@ public class PacketOpcodes {
public static final int MultistagePlayFinishStageReq = 5333;
public static final int MultistagePlayFinishStageRsp = 5328;
public static final int MultistagePlayInfoNotify = 5360;
public static final int MultistagePlaySettleNotify = 5318;
public static final int MultistagePlayStageEndNotify = 5321;
public static final int MusicGameSettleReq = 8851;
public static final int MusicGameSettleRsp = 8028;
public static final int MusicGameStartReq = 8760;
public static final int MusicGameStartRsp = 8922;
public static final int NavMeshStatsNotify = 2353;
public static final int NormalUidOpNotify = 5735;
public static final int NpcTalkReq = 560;
public static final int NpcTalkRsp = 533;
public static final int ObstacleModifyNotify = 2310;
public static final int OfferingInteractReq = 2916;
public static final int OfferingInteractRsp = 2912;
public static final int OneoffGatherPointDetectorDataNotify = 4289;
public static final int OpActivityDataNotify = 5110;
public static final int OpActivityStateNotify = 2560;
......@@ -728,17 +921,39 @@ public class PacketOpcodes {
public static final int OpenStateUpdateNotify = 109;
public static final int OrderDisplayNotify = 4101;
public static final int OrderFinishNotify = 4145;
public static final int PSPlayerApplyEnterMpReq = 1837;
public static final int PSPlayerApplyEnterMpRsp = 1806;
public static final int OtherPlayerEnterHomeNotify = 4591;
public static final int PacketHead = 13371337;
public static final int PathfindingEnterSceneReq = 2337;
public static final int PathfindingEnterSceneRsp = 2393;
public static final int PathfindingPingNotify = 2315;
public static final int PersonalLineAllDataReq = 408;
public static final int PersonalLineAllDataRsp = 417;
public static final int PersonalLineNewUnlockNotify = 423;
public static final int PersonalSceneJumpReq = 286;
public static final int PersonalSceneJumpRsp = 277;
public static final int PingReq = 37;
public static final int PingRsp = 93;
public static final int PlantFlowerAcceptAllGiveFlowerReq = 8775;
public static final int PlantFlowerAcceptAllGiveFlowerRsp = 8174;
public static final int PlantFlowerAcceptGiveFlowerReq = 8525;
public static final int PlantFlowerAcceptGiveFlowerRsp = 8957;
public static final int PlantFlowerEditFlowerCombinationReq = 8347;
public static final int PlantFlowerEditFlowerCombinationRsp = 8625;
public static final int PlantFlowerGetCanGiveFriendFlowerReq = 8617;
public static final int PlantFlowerGetCanGiveFriendFlowerRsp = 8091;
public static final int PlantFlowerGetFriendFlowerWishListReq = 8893;
public static final int PlantFlowerGetFriendFlowerWishListRsp = 8476;
public static final int PlantFlowerGetRecvFlowerListReq = 8459;
public static final int PlantFlowerGetRecvFlowerListRsp = 8597;
public static final int PlantFlowerGetSeedInfoReq = 8535;
public static final int PlantFlowerGetSeedInfoRsp = 8584;
public static final int PlantFlowerGiveFriendFlowerReq = 8934;
public static final int PlantFlowerGiveFriendFlowerRsp = 8456;
public static final int PlantFlowerHaveRecvFlowerNotify = 8711;
public static final int PlantFlowerSetFlowerWishReq = 8601;
public static final int PlantFlowerSetFlowerWishRsp = 8550;
public static final int PlantFlowerTakeSeedRewardReq = 8317;
public static final int PlantFlowerTakeSeedRewardRsp = 8152;
public static final int PlatformChangeRouteNotify = 257;
public static final int PlatformStartRouteNotify = 254;
public static final int PlatformStopRouteNotify = 235;
......@@ -774,6 +989,7 @@ public class PacketOpcodes {
public static final int PlayerEnterSceneInfoNotify = 294;
public static final int PlayerEnterSceneNotify = 260;
public static final int PlayerEyePointStateNotify = 3461;
public static final int PlayerFishingDataNotify = 5831;
public static final int PlayerForceExitReq = 125;
public static final int PlayerForceExitRsp = 149;
public static final int PlayerGameTimeNotify = 179;
......@@ -824,6 +1040,7 @@ public class PacketOpcodes {
public static final int PlayerStartMatchRsp = 4175;
public static final int PlayerStoreNotify = 660;
public static final int PlayerTimeNotify = 152;
public static final int PlayerWorldSceneInfoListNotify = 3386;
public static final int PostEnterSceneReq = 3390;
public static final int PostEnterSceneRsp = 3213;
public static final int PrivateChatNotify = 4960;
......@@ -831,10 +1048,17 @@ public class PacketOpcodes {
public static final int PrivateChatRsp = 4983;
public static final int PrivateChatSetSequenceReq = 4965;
public static final int PrivateChatSetSequenceRsp = 4987;
public static final int ProfilePictureChangeNotify = 4053;
public static final int ProjectorOptionReq = 880;
public static final int ProjectorOptionRsp = 864;
public static final int ProudSkillChangeNotify = 1079;
public static final int ProudSkillExtraLevelNotify = 1028;
public static final int ProudSkillUpgradeReq = 1075;
public static final int ProudSkillUpgradeRsp = 1034;
public static final int PSNBlackListNotify = 4070;
public static final int PSNFriendListNotify = 4072;
public static final int PSPlayerApplyEnterMpReq = 1837;
public static final int PSPlayerApplyEnterMpRsp = 1806;
public static final int PullPrivateChatReq = 5043;
public static final int PullPrivateChatRsp = 4994;
public static final int PullRecentChatReq = 4995;
......@@ -860,6 +1084,7 @@ public class PacketOpcodes {
public static final int QuestProgressUpdateNotify = 446;
public static final int QuestTransmitReq = 473;
public static final int QuestTransmitRsp = 463;
public static final int QuestUpdateQuestTimeVarNotify = 458;
public static final int QuestUpdateQuestVarNotify = 483;
public static final int QuestUpdateQuestVarReq = 474;
public static final int QuestUpdateQuestVarRsp = 456;
......@@ -876,8 +1101,12 @@ public class PacketOpcodes {
public static final int RedeemLegendaryKeyRsp = 427;
public static final int RefreshBackgroundAvatarReq = 1744;
public static final int RefreshBackgroundAvatarRsp = 1719;
public static final int RefreshRoguelikeDungeonCardReq = 8433;
public static final int RefreshRoguelikeDungeonCardRsp = 8678;
public static final int RegionSearchChangeRegionNotify = 5625;
public static final int RegionSearchNotify = 5635;
public static final int ReliquaryDecomposeReq = 606;
public static final int ReliquaryDecomposeRsp = 659;
public static final int ReliquaryPromoteReq = 665;
public static final int ReliquaryPromoteRsp = 603;
public static final int ReliquaryUpgradeReq = 689;
......@@ -885,9 +1114,14 @@ public class PacketOpcodes {
public static final int RemoveBlacklistReq = 4080;
public static final int RemoveBlacklistRsp = 4064;
public static final int RemoveRandTaskInfoNotify = 132;
public static final int ReportFightAntiCheatNotify = 357;
public static final int ReportTrackingIOInfoNotify = 4117;
public static final int RequestLiveInfoReq = 803;
public static final int RequestLiveInfoRsp = 867;
public static final int ResinCardDataUpdateNotify = 4126;
public static final int ResinChangeNotify = 623;
public static final int RestartEffigyChallengeReq = 2061;
public static final int RestartEffigyChallengeRsp = 2112;
public static final int ReunionActivateNotify = 5081;
public static final int ReunionBriefInfoReq = 5085;
public static final int ReunionBriefInfoRsp = 5075;
......@@ -895,6 +1129,28 @@ public class PacketOpcodes {
public static final int ReunionPrivilegeChangeNotify = 5100;
public static final int ReunionSettleNotify = 5096;
public static final int RobotPushPlayerDataNotify = 88;
public static final int RogueCellUpdateNotify = 8074;
public static final int RogueDungeonPlayerCellChangeNotify = 8784;
public static final int RogueHealAvatarsReq = 8959;
public static final int RogueHealAvatarsRsp = 8473;
public static final int RoguelikeCardGachaNotify = 8079;
public static final int RoguelikeEffectDataNotify = 8529;
public static final int RoguelikeEffectViewReq = 8396;
public static final int RoguelikeEffectViewRsp = 8040;
public static final int RoguelikeGiveUpReq = 8716;
public static final int RoguelikeGiveUpRsp = 8728;
public static final int RoguelikeMistClearNotify = 8471;
public static final int RoguelikeRefreshCardCostUpdateNotify = 8304;
public static final int RoguelikeResourceBonusPropUpdateNotify = 8312;
public static final int RoguelikeRuneRecordUpdateNotify = 8985;
public static final int RoguelikeSelectAvatarAndEnterDungeonReq = 8697;
public static final int RoguelikeSelectAvatarAndEnterDungeonRsp = 8377;
public static final int RoguelikeTakeStageFirstPassRewardReq = 8667;
public static final int RoguelikeTakeStageFirstPassRewardRsp = 8101;
public static final int RogueResumeDungeonReq = 8496;
public static final int RogueResumeDungeonRsp = 8759;
public static final int RogueSwitchAvatarReq = 8856;
public static final int RogueSwitchAvatarRsp = 8141;
public static final int SalesmanDeliverItemReq = 2103;
public static final int SalesmanDeliverItemRsp = 2198;
public static final int SalesmanTakeRewardReq = 2091;
......@@ -925,6 +1181,7 @@ public class PacketOpcodes {
public static final int SceneEntityMoveNotify = 291;
public static final int SceneEntityMoveReq = 245;
public static final int SceneEntityMoveRsp = 275;
public static final int SceneEntityUpdateNotify = 3423;
public static final int SceneForceLockNotify = 266;
public static final int SceneForceUnlockNotify = 201;
public static final int SceneGalleryInfoNotify = 5528;
......@@ -938,6 +1195,9 @@ public class PacketOpcodes {
public static final int ScenePlayBattleInterruptNotify = 4441;
public static final int ScenePlayBattleResultNotify = 4447;
public static final int ScenePlayBattleUidOpNotify = 4438;
public static final int ScenePlayerInfoNotify = 236;
public static final int ScenePlayerLocationNotify = 297;
public static final int ScenePlayerSoundNotify = 243;
public static final int ScenePlayGuestReplyInviteReq = 4394;
public static final int ScenePlayGuestReplyInviteRsp = 4395;
public static final int ScenePlayGuestReplyNotify = 4425;
......@@ -949,9 +1209,6 @@ public class PacketOpcodes {
public static final int ScenePlayOwnerInviteNotify = 4443;
public static final int ScenePlayOwnerStartInviteReq = 4365;
public static final int ScenePlayOwnerStartInviteRsp = 4387;
public static final int ScenePlayerInfoNotify = 236;
public static final int ScenePlayerLocationNotify = 297;
public static final int ScenePlayerSoundNotify = 243;
public static final int ScenePointUnlockNotify = 274;
public static final int SceneRouteChangeNotify = 270;
public static final int SceneTeamUpdateNotify = 1696;
......@@ -981,6 +1238,8 @@ public class PacketOpcodes {
public static final int SelectAsterMidDifficultyRsp = 2003;
public static final int SelectEffigyChallengeConditionReq = 2143;
public static final int SelectEffigyChallengeConditionRsp = 2072;
public static final int SelectRoguelikeDungeonCardReq = 8964;
public static final int SelectRoguelikeDungeonCardRsp = 8572;
public static final int SelectWorktopOptionReq = 837;
public static final int SelectWorktopOptionRsp = 893;
public static final int ServerAnnounceNotify = 2199;
......@@ -990,10 +1249,13 @@ public class PacketOpcodes {
public static final int ServerDisconnectClientNotify = 186;
public static final int ServerGlobalValueChangeNotify = 1188;
public static final int ServerLogNotify = 79;
public static final int ServerMessageNotify = 5725;
public static final int ServerTimeNotify = 34;
public static final int ServerUpdateGlobalValueNotify = 1197;
public static final int SetBattlePassViewedReq = 2637;
public static final int SetBattlePassViewedRsp = 2606;
public static final int SetChatEmojiCollectionReq = 4086;
public static final int SetChatEmojiCollectionRsp = 4077;
public static final int SetCoopChapterViewedReq = 1980;
public static final int SetCoopChapterViewedRsp = 1988;
public static final int SetCurExpeditionChallengeIdReq = 2017;
......@@ -1005,6 +1267,11 @@ public class PacketOpcodes {
public static final int SetFriendEnterHomeOptionRsp = 4724;
public static final int SetFriendRemarkNameReq = 4023;
public static final int SetFriendRemarkNameRsp = 4013;
public static final int SetH5ActivityRedDotTimestampReq = 5698;
public static final int SetH5ActivityRedDotTimestampRsp = 5663;
public static final int SetIsAutoUnlockSpecificEquipReq = 687;
public static final int SetIsAutoUnlockSpecificEquipRsp = 604;
public static final int SetLimitOptimizationNotify = 8189;
public static final int SetNameCardReq = 4089;
public static final int SetNameCardRsp = 4009;
public static final int SetOpenStateReq = 162;
......@@ -1029,6 +1296,8 @@ public class PacketOpcodes {
public static final int SetUpLunchBoxWidgetRsp = 4293;
public static final int SetWidgetSlotReq = 4266;
public static final int SetWidgetSlotRsp = 4279;
public static final int ShowClientGuideNotify = 3190;
public static final int ShowClientTutorialNotify = 3374;
public static final int ShowCommonTipsNotify = 3277;
public static final int ShowMessageNotify = 15;
public static final int ShowTemplateReminderNotify = 3164;
......@@ -1039,13 +1308,38 @@ public class PacketOpcodes {
public static final int SpringUseRsp = 1727;
public static final int StartArenaChallengeLevelReq = 2022;
public static final int StartArenaChallengeLevelRsp = 2033;
public static final int StartBuoyantCombatGalleryReq = 8313;
public static final int StartBuoyantCombatGalleryRsp = 8754;
public static final int StartCoopPointReq = 1956;
public static final int StartCoopPointRsp = 1962;
public static final int StartEffigyChallengeReq = 2123;
public static final int StartEffigyChallengeRsp = 2166;
public static final int StartFishingReq = 5845;
public static final int StartFishingRsp = 5848;
public static final int StartRogueEliteCellChallengeReq = 8620;
public static final int StartRogueEliteCellChallengeRsp = 8198;
public static final int StartRogueNormalCellChallengeReq = 8748;
public static final int StartRogueNormalCellChallengeRsp = 8630;
public static final int StoreItemChangeNotify = 610;
public static final int StoreItemDelNotify = 615;
public static final int StoreWeightLimitNotify = 633;
public static final int SummerTimeFloatSignalPositionNotify = 8389;
public static final int SummerTimeFloatSignalUpdateNotify = 8763;
public static final int SummerTimeSprintBoatRestartReq = 8682;
public static final int SummerTimeSprintBoatRestartRsp = 8562;
public static final int SummerTimeSprintBoatSettleNotify = 8150;
public static final int SumoDungeonSettleNotify = 8946;
public static final int SumoEnterDungeonNotify = 8540;
public static final int SumoLeaveDungeonNotify = 8460;
public static final int SumoRestartDungeonReq = 8602;
public static final int SumoRestartDungeonRsp = 8498;
public static final int SumoSaveTeamReq = 8874;
public static final int SumoSaveTeamRsp = 8287;
public static final int SumoSelectTeamAndEnterDungeonReq = 8605;
public static final int SumoSelectTeamAndEnterDungeonRsp = 8998;
public static final int SumoSetNoSwitchPunishTimeNotify = 8804;
public static final int SumoSwitchTeamReq = 8718;
public static final int SumoSwitchTeamRsp = 8356;
public static final int SyncScenePlayTeamEntityNotify = 3296;
public static final int SyncTeamEntityNotify = 338;
public static final int TakeAchievementGoalRewardReq = 2695;
......@@ -1086,6 +1380,8 @@ public class PacketOpcodes {
public static final int TakeInvestigationTargetRewardRsp = 1929;
public static final int TakeMaterialDeleteReturnReq = 651;
public static final int TakeMaterialDeleteReturnRsp = 684;
public static final int TakeoffEquipReq = 655;
public static final int TakeoffEquipRsp = 646;
public static final int TakeOfferingLevelRewardReq = 2921;
public static final int TakeOfferingLevelRewardRsp = 2910;
public static final int TakePlayerLevelRewardReq = 151;
......@@ -1102,8 +1398,6 @@ public class PacketOpcodes {
public static final int TakeReunionSignInRewardRsp = 5086;
public static final int TakeReunionWatcherRewardReq = 5065;
public static final int TakeReunionWatcherRewardRsp = 5077;
public static final int TakeoffEquipReq = 655;
public static final int TakeoffEquipRsp = 646;
public static final int TaskVarNotify = 178;
public static final int TeamResonanceChangeNotify = 1046;
public static final int TowerAllDataReq = 2445;
......@@ -1131,12 +1425,17 @@ public class PacketOpcodes {
public static final int TreasureMapCurrencyNotify = 2127;
public static final int TreasureMapDetectorDataNotify = 4272;
public static final int TreasureMapGuideTaskDoneNotify = 2200;
public static final int TreasureMapHostInfoNotify = 8960;
public static final int TreasureMapMpChallengeNotify = 2177;
public static final int TreasureMapPreTaskDoneNotify = 2188;
public static final int TreasureMapRegionActiveNotify = 2141;
public static final int TreasureMapRegionInfoNotify = 2120;
public static final int TrialAvatarFirstPassDungeonNotify = 2093;
public static final int TrialAvatarInDungeonIndexNotify = 2138;
public static final int TriggerCreateGadgetToEquipPartNotify = 373;
public static final int TriggerRoguelikeCurseNotify = 8878;
public static final int TriggerRoguelikeRuneReq = 8607;
public static final int TriggerRoguelikeRuneRsp = 8246;
public static final int TryEnterHomeReq = 4622;
public static final int TryEnterHomeRsp = 4731;
public static final int UnfreezeGroupLimitNotify = 3401;
......@@ -1145,23 +1444,28 @@ public class PacketOpcodes {
public static final int UnlockAvatarTalentRsp = 1033;
public static final int UnlockCoopChapterReq = 1965;
public static final int UnlockCoopChapterRsp = 1977;
public static final int UnlockedFurnitureFormulaDataNotify = 4700;
public static final int UnlockedFurnitureSuiteDataNotify = 4788;
public static final int UnlockNameCardNotify = 4001;
public static final int UnlockPersonalLineReq = 402;
public static final int UnlockPersonalLineRsp = 452;
public static final int UnlockTransPointReq = 3421;
public static final int UnlockTransPointRsp = 3073;
public static final int UnlockedFurnitureFormulaDataNotify = 4700;
public static final int UnlockedFurnitureSuiteDataNotify = 4788;
public static final int UnmarkEntityInMinMapNotify = 247;
public static final int UpdateAbilityCreatedMovingPlatformNotify = 828;
public static final int UpdatePS4BlockListReq = 4081;
public static final int UpdatePS4BlockListRsp = 4027;
public static final int UpdatePS4FriendListNotify = 4056;
public static final int UpdatePlayerShowAvatarListReq = 4036;
public static final int UpdatePlayerShowAvatarListRsp = 4024;
public static final int UpdatePlayerShowNameCardListReq = 4030;
public static final int UpdatePlayerShowNameCardListRsp = 4047;
public static final int UpdatePS4BlockListReq = 4081;
public static final int UpdatePS4BlockListRsp = 4027;
public static final int UpdatePS4FriendListNotify = 4056;
public static final int UpdatePS4FriendListReq = 4025;
public static final int UpdatePS4FriendListRsp = 4049;
public static final int UpdateRedPointNotify = 9;
public static final int UpdateReunionWatcherNotify = 5087;
public static final int UpgradeRoguelikeShikigamiReq = 8575;
public static final int UpgradeRoguelikeShikigamiRsp = 8440;
public static final int UseItemReq = 645;
public static final int UseItemRsp = 675;
public static final int UseMiracleRingReq = 5235;
......@@ -1170,6 +1474,11 @@ public class PacketOpcodes {
public static final int UseWidgetCreateGadgetRsp = 4290;
public static final int UseWidgetRetractGadgetReq = 4255;
public static final int UseWidgetRetractGadgetRsp = 4297;
public static final int VehicleInteractReq = 862;
public static final int VehicleInteractRsp = 889;
public static final int VehicleSpawnReq = 809;
public static final int VehicleSpawnRsp = 865;
public static final int VehicleStaminaNotify = 866;
public static final int ViewCodexReq = 4210;
public static final int ViewCodexRsp = 4209;
public static final int WatcherAllDataNotify = 2260;
......@@ -1185,13 +1494,17 @@ public class PacketOpcodes {
public static final int WeaponUpgradeRsp = 683;
public static final int WearEquipReq = 688;
public static final int WearEquipRsp = 628;
public static final int WidgetActiveChangeNotify = 4273;
public static final int WidgetCoolDownNotify = 4277;
public static final int WidgetDoBagReq = 4269;
public static final int WidgetDoBagRsp = 4270;
public static final int WidgetGadgetAllDataNotify = 4260;
public static final int WidgetGadgetDataNotify = 4268;
public static final int WidgetGadgetDestroyNotify = 4282;
public static final int WidgetReportReq = 4287;
public static final int WidgetReportRsp = 4256;
public static final int WidgetSlotChangeNotify = 4299;
public static final int WidgetUseAttachAbilityGroupChangeNotify = 4257;
public static final int WindSeedClientNotify = 1134;
public static final int WorktopOptionNotify = 815;
public static final int WorldAllRoutineTypeNotify = 3525;
......@@ -1202,11 +1515,60 @@ public class PacketOpcodes {
public static final int WorldPlayerDieNotify = 211;
public static final int WorldPlayerInfoNotify = 3088;
public static final int WorldPlayerLocationNotify = 224;
public static final int WorldPlayerRTTNotify = 26;
public static final int WorldPlayerReviveReq = 216;
public static final int WorldPlayerReviveRsp = 222;
public static final int WorldPlayerRTTNotify = 26;
public static final int WorldRoutineChangeNotify = 3548;
public static final int WorldRoutineTypeCloseNotify = 3513;
public static final int WorldRoutineTypeRefreshNotify = 3545;
}
\ No newline at end of file
// Unknown
public static final int UNKNOWN = 2013;
public static final int UNKNOWN_1 = 2042;
public static final int UNKNOWN_2 = 343;
public static final int UNKNOWN_3 = 4259;
public static final int UNKNOWN_4 = 4261;
public static final int UNKNOWN_5 = 4306;
public static final int UNKNOWN_6 = 4315;
public static final int UNKNOWN_7 = 4317;
public static final int UNKNOWN_8 = 4326;
public static final int UNKNOWN_9 = 4327;
public static final int UNKNOWN_10 = 4336;
public static final int UNKNOWN_11 = 4337;
public static final int UNKNOWN_12 = 4343;
public static final int UNKNOWN_13 = 5932;
public static final int UNKNOWN_14 = 5959;
public static final int UNKNOWN_15 = 67;
public static final int UNKNOWN_16 = 8010;
public static final int UNKNOWN_17 = 8024;
public static final int UNKNOWN_18 = 8050;
public static final int UNKNOWN_19 = 8077;
public static final int UNKNOWN_20 = 8083;
public static final int UNKNOWN_21 = 8114;
public static final int UNKNOWN_22 = 8154;
public static final int UNKNOWN_23 = 8157;
public static final int UNKNOWN_24 = 8188;
public static final int UNKNOWN_25 = 8190;
public static final int UNKNOWN_26 = 8210;
public static final int UNKNOWN_27 = 8385;
public static final int UNKNOWN_28 = 8405;
public static final int UNKNOWN_29 = 8420;
public static final int UNKNOWN_30 = 8421;
public static final int UNKNOWN_31 = 8429;
public static final int UNKNOWN_32 = 8437;
public static final int UNKNOWN_33 = 8439;
public static final int UNKNOWN_34 = 8461;
public static final int UNKNOWN_35 = 8502;
public static final int UNKNOWN_36 = 8559;
public static final int UNKNOWN_37 = 8580;
public static final int UNKNOWN_38 = 8604;
public static final int UNKNOWN_39 = 8710;
public static final int UNKNOWN_40 = 8761;
public static final int UNKNOWN_41 = 8787;
public static final int UNKNOWN_42 = 8830;
public static final int UNKNOWN_43 = 8877;
public static final int UNKNOWN_44 = 8983;
public static final int UNKNOWN_45 = 943;
public static final List<Integer> BANNED_PACKETS = Arrays.asList(PacketOpcodes.WindSeedClientNotify, PacketOpcodes.PlayerLuaShellNotify);
}
package emu.grasscutter.net.packet;
public class Retcode {
public static final int SUCCESS = 0;
public static final int FAIL = 1;
}
......@@ -8,7 +8,7 @@ import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public abstract class MihoyoKcpChannel extends ChannelInboundHandlerAdapter {
public abstract class KcpChannel extends ChannelInboundHandlerAdapter {
private UkcpChannel kcpChannel;
private ChannelHandlerContext ctx;
private boolean isActive;
......
......@@ -10,9 +10,9 @@ import io.netty.channel.ChannelMetadata;
import io.netty.channel.ChannelOutboundBuffer;
import io.netty.channel.nio.AbstractNioMessageChannel;
public class MihoyoKcpHandshaker extends AbstractNioMessageChannel {
public class KcpHandshaker extends AbstractNioMessageChannel {
protected MihoyoKcpHandshaker(Channel parent, SelectableChannel ch, int readInterestOp) {
protected KcpHandshaker(Channel parent, SelectableChannel ch, int readInterestOp) {
super(parent, ch, readInterestOp);
}
......
......@@ -13,14 +13,14 @@ import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
@SuppressWarnings("rawtypes")
public class MihoyoKcpServer extends Thread {
public class KcpServer extends Thread {
private EventLoopGroup group;
private UkcpServerBootstrap bootstrap;
private ChannelInitializer serverInitializer;
private InetSocketAddress address;
public MihoyoKcpServer(InetSocketAddress address) {
public KcpServer(InetSocketAddress address) {
this.address = address;
this.setName("Netty Server Thread");
}
......@@ -40,7 +40,7 @@ public class MihoyoKcpServer extends Thread {
@Override
public void run() {
if (getServerInitializer() == null) {
this.setServerInitializer(new MihoyoKcpServerInitializer());
this.setServerInitializer(new KcpServerInitializer());
}
try {
......@@ -64,9 +64,8 @@ public class MihoyoKcpServer extends Thread {
// Wait until the server socket is closed.
f.channel().closeFuture().sync();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception exception) {
Grasscutter.getLogger().error("Unable to start game server.", exception);
} finally {
// Close
finish();
......
......@@ -5,7 +5,7 @@ import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
@SuppressWarnings("unused")
public class MihoyoKcpServerInitializer extends ChannelInitializer<UkcpChannel> {
public class KcpServerInitializer extends ChannelInitializer<UkcpChannel> {
@Override
protected void initChannel(UkcpChannel ch) throws Exception {
......
package emu.grasscutter.plugin;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.plugin.api.ServerHook;
import emu.grasscutter.server.game.GameServer;
import java.io.File;
import java.io.InputStream;
import java.net.URLClassLoader;
/**
* The base class for all plugins to extend.
*/
public abstract class Plugin {
private final ServerHook server = ServerHook.getInstance();
private PluginIdentifier identifier;
private URLClassLoader classLoader;
private File dataFolder;
/**
* This method is reflected into.
*
* Set plugin variables.
* @param identifier The plugin's identifier.
*/
private void initializePlugin(PluginIdentifier identifier, URLClassLoader classLoader) {
if(this.identifier != null) {
Grasscutter.getLogger().warn(this.identifier.name + " had a reinitialization attempt.");
return;
}
this.identifier = identifier;
this.classLoader = classLoader;
this.dataFolder = new File(Grasscutter.getConfig().PLUGINS_FOLDER, identifier.name);
if(!this.dataFolder.exists() && !this.dataFolder.mkdirs()) {
Grasscutter.getLogger().warn("Failed to create plugin data folder for " + this.identifier.name);
return;
}
}
/**
* The plugin's identifier instance.
* @return An instance of {@link PluginIdentifier}.
*/
public final PluginIdentifier getIdentifier(){
return this.identifier;
}
/**
* Get the plugin's name.
*/
public final String getName() {
return this.identifier.name;
}
/**
* Get the plugin's description.
*/
public final String getDescription() {
return this.identifier.description;
}
/**
* Get the plugin's version.
*/
public final String getVersion() {
return this.identifier.version;
}
/**
* Returns the server that initialized the plugin.
* @return A server instance.
*/
public final GameServer getServer() {
return this.server.getGameServer();
}
/**
* Returns an input stream for a resource in the JAR file.
* @param resourceName The name of the resource.
* @return An input stream.
*/
public final InputStream getResource(String resourceName) {
return this.classLoader.getResourceAsStream(resourceName);
}
/**
* Returns a directory where plugins can store data files.
* @return A directory on the file system.
*/
public final File getDataFolder() {
return this.dataFolder;
}
/**
* Returns the server hook.
* @return A server hook singleton.
*/
public final ServerHook getHandle() {
return this.server;
}
/* Called when the plugin is first loaded. */
public void onLoad() { }
/* Called after (most of) the server enables. */
public void onEnable() { }
/* Called before the server disables. */
public void onDisable() { }
}
package emu.grasscutter.plugin;
/**
* The data contained in the plugin's `plugin.json` file.
*/
public final class PluginConfig {
public String name, description, version;
public String mainClass;
public String[] authors;
/**
* Attempts to validate this config instance.
* @return True if the config is valid, false otherwise.
*/
public boolean validate() {
return name != null && description != null && mainClass != null;
}
}
package emu.grasscutter.plugin;
// TODO: Potentially replace with Lombok?
public final class PluginIdentifier {
public final String name, description, version;
public final String[] authors;
public PluginIdentifier(
String name, String description, String version,
String[] authors
) {
this.name = name;
this.description = description;
this.version = version;
this.authors = authors;
}
/**
* Converts a {@link PluginConfig} into a {@link PluginIdentifier}.
*/
public static PluginIdentifier fromPluginConfig(PluginConfig config) {
if(!config.validate())
throw new IllegalArgumentException("A valid plugin config is required to convert into a plugin identifier.");
return new PluginIdentifier(
config.name, config.description, config.version,
config.authors
);
}
}
package emu.grasscutter.plugin;
import emu.grasscutter.Grasscutter;
import emu.grasscutter.server.event.Event;
import emu.grasscutter.server.event.EventHandler;
import emu.grasscutter.server.event.HandlerPriority;
import emu.grasscutter.utils.Utils;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
/**
* Manages the server's plugins and the event system.
*/
public final class PluginManager {
private final Map<String, Plugin> plugins = new HashMap<>();
private final List<EventHandler<? extends Event>> listeners = new LinkedList<>();
public PluginManager() {
this.loadPlugins(); // Load all plugins from the plugins directory.
}
/**
* Loads plugins from the config-specified directory.
*/
private void loadPlugins() {
String directory = Grasscutter.getConfig().PLUGINS_FOLDER;
File pluginsDir = new File(Utils.toFilePath(directory));
if(!pluginsDir.exists() && !pluginsDir.mkdirs()) {
Grasscutter.getLogger().error("Failed to create plugins directory: " + pluginsDir.getAbsolutePath());
return;
}
File[] files = pluginsDir.listFiles();
if(files == null) {
// The directory is empty, there aren't any plugins to load.
return;
}
List<File> plugins = Arrays.stream(files)
.filter(file -> file.getName().endsWith(".jar"))
.toList();
URL[] pluginNames = new URL[plugins.size()];
plugins.forEach(plugin -> {
try {
pluginNames[plugins.indexOf(plugin)] = plugin.toURI().toURL();
} catch (MalformedURLException exception) {
Grasscutter.getLogger().warn("Unable to load plugin.", exception);
}
});
URLClassLoader classLoader = new URLClassLoader(pluginNames);
plugins.forEach(plugin -> {
try {
URL url = plugin.toURI().toURL();
try (URLClassLoader loader = new URLClassLoader(new URL[]{url})) {
URL configFile = loader.findResource("plugin.json"); // Find the plugin.json file for each plugin.
InputStreamReader fileReader = new InputStreamReader(configFile.openStream());
PluginConfig pluginConfig = Grasscutter.getGsonFactory().fromJson(fileReader, PluginConfig.class);
if(!pluginConfig.validate()) {
Utils.logObject(pluginConfig);
Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " has an invalid config file.");
return;
}
JarFile jarFile = new JarFile(plugin);
Enumeration<JarEntry> entries = jarFile.entries();
while(entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
if(entry.isDirectory() || !entry.getName().endsWith(".class") || entry.getName().contains("module-info")) continue;
String className = entry.getName().replace(".class", "").replace("/", ".");
classLoader.loadClass(className); // Use the same class loader for ALL plugins.
}
Class<?> pluginClass = classLoader.loadClass(pluginConfig.mainClass);
Plugin pluginInstance = (Plugin) pluginClass.getDeclaredConstructor().newInstance();
this.loadPlugin(pluginInstance, PluginIdentifier.fromPluginConfig(pluginConfig), loader);
fileReader.close(); // Close the file reader.
} catch (ClassNotFoundException ignored) {
Grasscutter.getLogger().warn("Plugin " + plugin.getName() + " has an invalid main class.");
}
} catch (Exception exception) {
Grasscutter.getLogger().error("Failed to load plugin: " + plugin.getName(), exception);
}
});
}
/**
* Load the specified plugin.
* @param plugin The plugin instance.
*/
private void loadPlugin(Plugin plugin, PluginIdentifier identifier, URLClassLoader classLoader) {
Grasscutter.getLogger().info("Loading plugin: " + identifier.name);
// Add the plugin's identifier.
try {
Class<Plugin> pluginClass = Plugin.class;
Method method = pluginClass.getDeclaredMethod("initializePlugin", PluginIdentifier.class, URLClassLoader.class);
method.setAccessible(true); method.invoke(plugin, identifier, classLoader); method.setAccessible(false);
} catch (Exception ignored) {
Grasscutter.getLogger().warn("Failed to add plugin identifier: " + identifier.name);
}
// Add the plugin to the list of loaded plugins.
this.plugins.put(identifier.name, plugin);
// Call the plugin's onLoad method.
plugin.onLoad();
}
/**
* Enables all registered plugins.
*/
public void enablePlugins() {
this.plugins.forEach((name, plugin) -> {
Grasscutter.getLogger().info("Enabling plugin: " + name);
plugin.onEnable();
});
}
/**
* Disables all registered plugins.
*/
public void disablePlugins() {
this.plugins.forEach((name, plugin) -> {
Grasscutter.getLogger().info("Disabling plugin: " + name);
plugin.onDisable();
});
}
/**
* Registers a plugin's event listener.
* @param listener The event listener.
*/
public void registerListener(EventHandler<? extends Event> listener) {
this.listeners.add(listener);
}
/**
* Invoke the provided event on all registered event listeners.
* @param event The event to invoke.
*/
public void invokeEvent(Event event) {
EnumSet.allOf(HandlerPriority.class)
.forEach(priority -> this.checkAndFilter(event, priority));
}
/**
* Check an event to handlers for the priority.
* @param event The event being called.
* @param priority The priority to call for.
*/
private void checkAndFilter(Event event, HandlerPriority priority) {
this.listeners.stream()
.filter(handler -> handler.handles().isInstance(event))
.filter(handler -> handler.getPriority() == priority)
.toList().forEach(handler -> this.invokeHandler(event, handler));
}
public Plugin getPlugin(String name) {
return this.plugins.get(name);
}
/**
* Performs logic checks then invokes the provided event handler.
* @param event The event passed through to the handler.
* @param handler The handler to invoke.
*/
@SuppressWarnings("unchecked")
private <T extends Event> void invokeHandler(Event event, EventHandler<T> handler) {
if(!event.isCanceled() ||
(event.isCanceled() && handler.ignoresCanceled())
) handler.getCallback().consume((T) event);
}
}
package emu.grasscutter.plugin.api;
public enum Item {
/* TODO: Use handbook to generate an Item enum. */
}
package emu.grasscutter.plugin.api;
import emu.grasscutter.game.avatar.Avatar;
import emu.grasscutter.game.entity.EntityAvatar;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.game.props.EnterReason;
import emu.grasscutter.game.props.FightProperty;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.server.packet.send.PacketAvatarFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketAvatarLifeStateChangeNotify;
import emu.grasscutter.server.packet.send.PacketPlayerEnterSceneNotify;
import emu.grasscutter.utils.Position;
/**
* Hooks into the {@link Player} class, adding convenient ways to do certain things.
*/
public final class PlayerHook {
private final Player player;
/**
* Hooks into the player.
* @param player The player to hook into.
*/
public PlayerHook(Player player) {
this.player = player;
}
/**
* Kicks a player from the server.
* TODO: Refactor to kick using a packet.
*/
public void kick() {
this.player.getSession().close();
}
/**
* Sends a player to another scene.
* @param sceneId The scene to send the player to.
*/
public void changeScenes(int sceneId) {
this.player.getWorld().transferPlayerToScene(this.player, sceneId, this.player.getPos());
}
/**
* Broadcasts an avatar property notify to all world players.
* @param property The property that was updated.
*/
public void updateFightProperty(FightProperty property) {
this.broadcastPacketToWorld(new PacketAvatarFightPropUpdateNotify(this.getCurrentAvatar(), property));
}
/**
* Broadcasts the packet sent to all world players.
* @param packet The packet to send.
*/
public void broadcastPacketToWorld(BasePacket packet) {
this.player.getWorld().broadcastPacket(packet);
}
/**
* Set the currently equipped avatar's health.
* @param health The health to set the avatar to.
*/
public void setHealth(float health) {
this.getCurrentAvatarEntity().setFightProperty(FightProperty.FIGHT_PROP_CUR_HP, health);
this.updateFightProperty(FightProperty.FIGHT_PROP_CUR_HP);
}
/**
* Revives the specified avatar.
* @param avatar The avatar to revive.
*/
public void reviveAvatar(Avatar avatar) {
this.broadcastPacketToWorld(new PacketAvatarLifeStateChangeNotify(avatar));
}
/**
* Teleports a player to a position.
* This will **not** transfer the player to another scene.
* @param position The position to teleport the player to.
*/
public void teleport(Position position) {
this.player.getPos().set(position);
this.player.sendPacket(new PacketPlayerEnterSceneNotify(this.player,
EnterType.ENTER_JUMP, EnterReason.TransPoint,
this.player.getSceneId(), position
));
}
/**
* Gets the currently selected avatar's max health.
* @return The max health as a float.
*/
public float getMaxHealth() {
return this.getCurrentAvatarEntity().getFightProperty(FightProperty.FIGHT_PROP_MAX_HP);
}
/**
* Gets the currently selected avatar in entity form.
* @return The avatar as an {@link EntityAvatar}.
*/
public EntityAvatar getCurrentAvatarEntity() {
return this.player.getTeamManager().getCurrentAvatarEntity();
}
/**
* Gets the currently selected avatar.
* @return The avatar as an {@link Avatar}.
*/
public Avatar getCurrentAvatar() {
return this.getCurrentAvatarEntity().getAvatar();
}
}
\ No newline at end of file
package emu.grasscutter.plugin.api;
import emu.grasscutter.command.Command;
import emu.grasscutter.command.CommandHandler;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.dispatch.DispatchServer;
import emu.grasscutter.server.game.GameServer;
import java.util.LinkedList;
import java.util.List;
/**
* Hooks into the {@link GameServer} class, adding convenient ways to do certain things.
*/
public final class ServerHook {
private static ServerHook instance;
private final GameServer gameServer;
private final DispatchServer dispatchServer;
/**
* Gets the server hook instance.
* @return A {@link ServerHook} singleton.
*/
public static ServerHook getInstance() {
return instance;
}
/**
* Hooks into a server.
* @param gameServer The game server to hook into.
* @param dispatchServer The dispatch server to hook into.
*/
public ServerHook(GameServer gameServer, DispatchServer dispatchServer) {
this.gameServer = gameServer;
this.dispatchServer = dispatchServer;
instance = this;
}
/**
* @return The game server.
*/
public GameServer getGameServer() {
return this.gameServer;
}
/**
* @return The dispatch server.
*/
public DispatchServer getDispatchServer() {
return this.dispatchServer;
}
/**
* Gets all online players.
* @return Players connected to the server.
*/
public List<Player> getOnlinePlayers() {
return new LinkedList<>(this.gameServer.getPlayers().values());
}
/**
* Registers a command to the {@link emu.grasscutter.command.CommandMap}.
* @param handler The command handler.
*/
public void registerCommand(CommandHandler handler) {
Class<? extends CommandHandler> clazz = handler.getClass();
if(!clazz.isAnnotationPresent(Command.class))
throw new IllegalArgumentException("Command handler must be annotated with @Command.");
Command commandData = clazz.getAnnotation(Command.class);
this.gameServer.getCommandMap().registerCommand(commandData.label(), handler);
}
}
\ 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