Commit be507310 authored by Magix's avatar Magix Committed by GitHub
Browse files

Merge branch 'development' into api

parents 28025a81 a62520f9
...@@ -21,7 +21,6 @@ import emu.grasscutter.game.inventory.Inventory; ...@@ -21,7 +21,6 @@ import emu.grasscutter.game.inventory.Inventory;
import emu.grasscutter.game.mail.Mail; import emu.grasscutter.game.mail.Mail;
import emu.grasscutter.game.props.ActionReason; import emu.grasscutter.game.props.ActionReason;
import emu.grasscutter.game.props.PlayerProperty; import emu.grasscutter.game.props.PlayerProperty;
import emu.grasscutter.game.shop.ShopInfo;
import emu.grasscutter.game.shop.ShopLimit; import emu.grasscutter.game.shop.ShopLimit;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.game.world.World; import emu.grasscutter.game.world.World;
...@@ -34,10 +33,12 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo; ...@@ -34,10 +33,12 @@ import emu.grasscutter.net.proto.OnlinePlayerInfoOuterClass.OnlinePlayerInfo;
import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass; import emu.grasscutter.net.proto.PlayerApplyEnterMpResultNotifyOuterClass;
import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo; import emu.grasscutter.net.proto.PlayerLocationInfoOuterClass.PlayerLocationInfo;
import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass; import emu.grasscutter.net.proto.PlayerWorldLocationInfoOuterClass;
import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass;
import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture; import emu.grasscutter.net.proto.ProfilePictureOuterClass.ProfilePicture;
import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail; import emu.grasscutter.net.proto.SocialDetailOuterClass.SocialDetail;
import emu.grasscutter.net.proto.SocialShowAvatarInfoOuterClass; import emu.grasscutter.net.proto.SocialShowAvatarInfoOuterClass;
import emu.grasscutter.server.event.game.PlayerQuitEvent; import emu.grasscutter.server.event.player.PlayerJoinEvent;
import emu.grasscutter.server.event.player.PlayerQuitEvent;
import emu.grasscutter.server.event.player.PlayerReceiveMailEvent; import emu.grasscutter.server.event.player.PlayerReceiveMailEvent;
import emu.grasscutter.server.game.GameServer; import emu.grasscutter.server.game.GameServer;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
...@@ -828,7 +829,7 @@ public class Player { ...@@ -828,7 +829,7 @@ public class Player {
.setProfilePicture(ProfilePicture.newBuilder().setAvatarId(this.getHeadImage())); .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(this.getHeadImage()));
if (this.getWorld() != null) { if (this.getWorld() != null) {
onlineInfo.setCurPlayerNumInWorld(this.getWorld().getPlayers().indexOf(this) + 1); onlineInfo.setCurPlayerNumInWorld(getWorld().getPlayerCount());
} else { } else {
onlineInfo.setCurPlayerNumInWorld(1); onlineInfo.setCurPlayerNumInWorld(1);
} }
...@@ -904,6 +905,35 @@ public class Player { ...@@ -904,6 +905,35 @@ public class Player {
.setFinishAchievementNum(0); .setFinishAchievementNum(0);
return social; return social;
} }
public List<ShowAvatarInfoOuterClass.ShowAvatarInfo> getShowAvatarInfoList() {
List<ShowAvatarInfoOuterClass.ShowAvatarInfo> showAvatarInfoList = new ArrayList<>();
Player player;
boolean shouldRecalc;
if (this.isOnline()) {
player = this;
shouldRecalc = false;
} else {
player = DatabaseHelper.getPlayerById(id);
player.getAvatars().loadFromDatabase();
player.getInventory().loadFromDatabase();
shouldRecalc = true;
}
List<Integer> showAvatarList = player.getShowAvatarList();
AvatarStorage avatars = player.getAvatars();
if (showAvatarList != null) {
for (int avatarId : showAvatarList) {
Avatar avatar = avatars.getAvatarById(avatarId);
if (shouldRecalc) {
avatar.recalcStats();
}
showAvatarInfoList.add(avatar.toShowAvatarInfoProto());
}
}
return showAvatarInfoList;
}
public PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo getWorldPlayerLocationInfo() { public PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo getWorldPlayerLocationInfo() {
return PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo.newBuilder() return PlayerWorldLocationInfoOuterClass.PlayerWorldLocationInfo.newBuilder()
...@@ -1014,6 +1044,11 @@ public class Player { ...@@ -1014,6 +1044,11 @@ public class Player {
// First notify packets sent // First notify packets sent
this.setHasSentAvatarDataNotify(true); this.setHasSentAvatarDataNotify(true);
// Call join event.
PlayerJoinEvent event = new PlayerJoinEvent(this); event.call();
if(event.isCanceled()) // If event is not cancelled, continue.
session.close();
} }
public void onLogout() { public void onLogout() {
......
...@@ -375,8 +375,8 @@ public class Scene { ...@@ -375,8 +375,8 @@ public class Scene {
this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD)); this.broadcastPacket(new PacketLifeStateChangeNotify(attackerId, target, LifeState.LIFE_DEAD));
// Reward drop // Reward drop
if (target instanceof EntityMonster) { if (target instanceof EntityMonster && this.getSceneType() != SceneType.SCENE_DUNGEON) {
Grasscutter.getGameServer().getDropManager().callDrop((EntityMonster) target); getWorld().getServer().getDropManager().callDrop((EntityMonster) target);
} }
this.removeEntity(target); this.removeEntity(target);
...@@ -508,6 +508,7 @@ public class Scene { ...@@ -508,6 +508,7 @@ public class Scene {
} }
group.triggers.forEach(getScriptManager()::registerTrigger); group.triggers.forEach(getScriptManager()::registerTrigger);
group.regions.forEach(getScriptManager()::registerRegion);
} }
// Spawn gadgets AFTER triggers are added // Spawn gadgets AFTER triggers are added
...@@ -526,6 +527,7 @@ public class Scene { ...@@ -526,6 +527,7 @@ public class Scene {
for (SceneGroup group : block.groups) { for (SceneGroup group : block.groups) {
group.triggers.forEach(getScriptManager()::deregisterTrigger); group.triggers.forEach(getScriptManager()::deregisterTrigger);
group.regions.forEach(getScriptManager()::deregisterRegion);
} }
} }
......
...@@ -27,6 +27,7 @@ import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult; ...@@ -27,6 +27,7 @@ import emu.grasscutter.net.proto.AttackResultOuterClass.AttackResult;
import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType; import emu.grasscutter.net.proto.EnterTypeOuterClass.EnterType;
import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType; import emu.grasscutter.net.proto.VisionTypeOuterClass.VisionType;
import emu.grasscutter.scripts.data.SceneConfig; 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.PacketDelTeamEntityNotify;
import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify; import emu.grasscutter.server.packet.send.PacketEntityFightPropUpdateNotify;
import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify; import emu.grasscutter.server.packet.send.PacketLifeStateChangeNotify;
...@@ -44,6 +45,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMaps; ...@@ -44,6 +45,7 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMaps;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class World implements Iterable<Player> { public class World implements Iterable<Player> {
private final GameServer server;
private final Player owner; private final Player owner;
private final List<Player> players; private final List<Player> players;
private final Int2ObjectMap<Scene> scenes; private final Int2ObjectMap<Scene> scenes;
...@@ -61,6 +63,7 @@ public class World implements Iterable<Player> { ...@@ -61,6 +63,7 @@ public class World implements Iterable<Player> {
public World(Player player, boolean isMultiplayer) { public World(Player player, boolean isMultiplayer) {
this.owner = player; this.owner = player;
this.server = player.getServer();
this.players = Collections.synchronizedList(new ArrayList<>()); this.players = Collections.synchronizedList(new ArrayList<>());
this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>()); this.scenes = Int2ObjectMaps.synchronize(new Int2ObjectOpenHashMap<>());
...@@ -75,6 +78,10 @@ public class World implements Iterable<Player> { ...@@ -75,6 +78,10 @@ public class World implements Iterable<Player> {
return owner; return owner;
} }
public GameServer getServer() {
return server;
}
public int getLevelEntityId() { public int getLevelEntityId() {
return levelEntityId; return levelEntityId;
} }
......
package emu.grasscutter.scripts; package emu.grasscutter.scripts;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
...@@ -23,6 +24,7 @@ import emu.grasscutter.data.def.WorldLevelData; ...@@ -23,6 +24,7 @@ import emu.grasscutter.data.def.WorldLevelData;
import emu.grasscutter.game.entity.EntityGadget; import emu.grasscutter.game.entity.EntityGadget;
import emu.grasscutter.game.entity.EntityMonster; import emu.grasscutter.game.entity.EntityMonster;
import emu.grasscutter.game.entity.GameEntity; import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.game.world.Scene; import emu.grasscutter.game.world.Scene;
import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.constants.ScriptGadgetState; import emu.grasscutter.scripts.constants.ScriptGadgetState;
...@@ -33,6 +35,7 @@ import emu.grasscutter.scripts.data.SceneGadget; ...@@ -33,6 +35,7 @@ import emu.grasscutter.scripts.data.SceneGadget;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.SceneInitConfig; import emu.grasscutter.scripts.data.SceneInitConfig;
import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.SceneMonster;
import emu.grasscutter.scripts.data.SceneRegion;
import emu.grasscutter.scripts.data.SceneSuite; import emu.grasscutter.scripts.data.SceneSuite;
import emu.grasscutter.scripts.data.SceneTrigger; import emu.grasscutter.scripts.data.SceneTrigger;
import emu.grasscutter.scripts.data.SceneVar; import emu.grasscutter.scripts.data.SceneVar;
...@@ -49,14 +52,17 @@ public class SceneScriptManager { ...@@ -49,14 +52,17 @@ public class SceneScriptManager {
private Bindings bindings; private Bindings bindings;
private SceneConfig config; private SceneConfig config;
private List<SceneBlock> blocks; private List<SceneBlock> blocks;
private Int2ObjectOpenHashMap<Set<SceneTrigger>> triggers;
private boolean isInit; private boolean isInit;
private final Int2ObjectOpenHashMap<Set<SceneTrigger>> triggers;
private final Int2ObjectOpenHashMap<SceneRegion> regions;
public SceneScriptManager(Scene scene) { public SceneScriptManager(Scene scene) {
this.scene = scene; this.scene = scene;
this.scriptLib = new ScriptLib(this); this.scriptLib = new ScriptLib(this);
this.scriptLibLua = CoerceJavaToLua.coerce(this.scriptLib); this.scriptLibLua = CoerceJavaToLua.coerce(this.scriptLib);
this.triggers = new Int2ObjectOpenHashMap<>(); this.triggers = new Int2ObjectOpenHashMap<>();
this.regions = new Int2ObjectOpenHashMap<>();
this.variables = new HashMap<>(); this.variables = new HashMap<>();
// TEMPORARY // TEMPORARY
...@@ -108,6 +114,18 @@ public class SceneScriptManager { ...@@ -108,6 +114,18 @@ public class SceneScriptManager {
getTriggersByEvent(trigger.event).remove(trigger); getTriggersByEvent(trigger.event).remove(trigger);
} }
public SceneRegion getRegionById(int id) {
return regions.get(id);
}
public void registerRegion(SceneRegion region) {
regions.put(region.config_id, region);
}
public void deregisterRegion(SceneRegion region) {
regions.remove(region.config_id);
}
// TODO optimize // TODO optimize
public SceneGroup getGroupById(int groupId) { public SceneGroup getGroupById(int groupId) {
for (SceneBlock block : this.getScene().getLoadedBlocks()) { for (SceneBlock block : this.getScene().getLoadedBlocks()) {
...@@ -134,11 +152,8 @@ public class SceneScriptManager { ...@@ -134,11 +152,8 @@ public class SceneScriptManager {
bindings = ScriptLoader.getEngine().createBindings(); bindings = ScriptLoader.getEngine().createBindings();
// Set variables // Set variables
bindings.put("EventType", new EventType()); // TODO - make static class to avoid instantiating a new class every scene
bindings.put("GadgetState", new ScriptGadgetState());
bindings.put("RegionShape", new ScriptRegionShape());
bindings.put("ScriptLib", getScriptLib()); bindings.put("ScriptLib", getScriptLib());
// Eval script // Eval script
try { try {
cs.eval(getBindings()); cs.eval(getBindings());
...@@ -211,6 +226,7 @@ public class SceneScriptManager { ...@@ -211,6 +226,7 @@ public class SceneScriptManager {
group.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, bindings.get("gadgets")); group.gadgets = ScriptLoader.getSerializer().toList(SceneGadget.class, bindings.get("gadgets"));
group.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, bindings.get("triggers")); group.triggers = ScriptLoader.getSerializer().toList(SceneTrigger.class, bindings.get("triggers"));
group.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites")); group.suites = ScriptLoader.getSerializer().toList(SceneSuite.class, bindings.get("suites"));
group.regions = ScriptLoader.getSerializer().toList(SceneRegion.class, bindings.get("regions"));
group.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, bindings.get("init_config")); group.init_config = ScriptLoader.getSerializer().toObject(SceneInitConfig.class, bindings.get("init_config"));
// Add variables to suite // Add variables to suite
...@@ -235,11 +251,27 @@ public class SceneScriptManager { ...@@ -235,11 +251,27 @@ public class SceneScriptManager {
} }
public void onTick() { public void onTick() {
checkTriggers(); checkRegions();
} }
public void checkTriggers() { public void checkRegions() {
if (this.regions.size() == 0) {
return;
}
for (SceneRegion region : this.regions.values()) {
getScene().getEntities().values()
.stream()
.filter(e -> e.getEntityType() <= 2 && region.contains(e.getPosition()))
.forEach(region::addEntity);
if (region.hasNewEntities()) {
// This is not how it works, source_eid should be region entity id, but we dont have an entity for regions yet
callEvent(EventType.EVENT_ENTER_REGION, new ScriptArgs(region.config_id).setSourceEntityId(region.config_id));
region.resetNewEntities();
}
}
} }
public void spawnGadgetsInGroup(SceneGroup group) { public void spawnGadgetsInGroup(SceneGroup group) {
......
...@@ -17,6 +17,7 @@ import emu.grasscutter.game.entity.GameEntity; ...@@ -17,6 +17,7 @@ import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.scripts.constants.EventType; import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.data.SceneGroup; import emu.grasscutter.scripts.data.SceneGroup;
import emu.grasscutter.scripts.data.SceneMonster; import emu.grasscutter.scripts.data.SceneMonster;
import emu.grasscutter.scripts.data.SceneRegion;
import emu.grasscutter.scripts.data.ScriptArgs; import emu.grasscutter.scripts.data.ScriptArgs;
import emu.grasscutter.server.packet.send.PacketGadgetStateNotify; import emu.grasscutter.server.packet.send.PacketGadgetStateNotify;
import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify; import emu.grasscutter.server.packet.send.PacketWorktopOptionNotify;
...@@ -184,6 +185,19 @@ public class ScriptLib { ...@@ -184,6 +185,19 @@ public class ScriptLib {
return 0; return 0;
} }
public int GetRegionEntityCount(LuaTable table) {
int regionId = table.get("region_eid").toint();
int entityType = table.get("entity_type").toint();
SceneRegion region = this.getSceneScriptManager().getRegionById(regionId);
if (region == null) {
return 0;
}
return (int) region.getEntities().intStream().filter(e -> e >> 24 == entityType).count();
}
public void PrintContextLog(String msg) { public void PrintContextLog(String msg) {
Grasscutter.getLogger().info("[LUA] " + msg); Grasscutter.getLogger().info("[LUA] " + msg);
} }
......
...@@ -4,6 +4,7 @@ import java.io.File; ...@@ -4,6 +4,7 @@ import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
...@@ -13,7 +14,17 @@ import javax.script.ScriptEngine; ...@@ -13,7 +14,17 @@ import javax.script.ScriptEngine;
import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager; import javax.script.ScriptEngineManager;
import org.luaj.vm2.LuaTable;
import org.luaj.vm2.LuaValue;
import org.luaj.vm2.lib.OneArgFunction;
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
import org.luaj.vm2.script.LuajContext;
import emu.grasscutter.Grasscutter; import emu.grasscutter.Grasscutter;
import emu.grasscutter.game.props.EntityType;
import emu.grasscutter.scripts.constants.EventType;
import emu.grasscutter.scripts.constants.ScriptGadgetState;
import emu.grasscutter.scripts.constants.ScriptRegionShape;
import emu.grasscutter.scripts.serializer.LuaSerializer; import emu.grasscutter.scripts.serializer.LuaSerializer;
import emu.grasscutter.scripts.serializer.Serializer; import emu.grasscutter.scripts.serializer.Serializer;
...@@ -31,11 +42,31 @@ public class ScriptLoader { ...@@ -31,11 +42,31 @@ public class ScriptLoader {
throw new Exception("Script loader already initialized"); throw new Exception("Script loader already initialized");
} }
// Create script engine
sm = new ScriptEngineManager(); sm = new ScriptEngineManager();
engine = sm.getEngineByName("luaj"); engine = sm.getEngineByName("luaj");
factory = getEngine().getFactory(); factory = getEngine().getFactory();
// Lua stuff
fileType = "lua"; fileType = "lua";
serializer = new LuaSerializer(); serializer = new LuaSerializer();
// Set engine to replace require as a temporary fix to missing scripts
LuajContext ctx = (LuajContext) engine.getContext();
ctx.globals.set("require", new OneArgFunction() {
@Override
public LuaValue call(LuaValue arg0) {
return LuaValue.ZERO;
}
});
LuaTable table = new LuaTable();
Arrays.stream(EntityType.values()).forEach(e -> table.set(e.name().toUpperCase(), e.getValue()));
ctx.globals.set("EntityType", table);
ctx.globals.set("EventType", CoerceJavaToLua.coerce(new EventType())); // TODO - make static class to avoid instantiating a new class every scene
ctx.globals.set("GadgetState", CoerceJavaToLua.coerce(new ScriptGadgetState()));
ctx.globals.set("RegionShape", CoerceJavaToLua.coerce(new ScriptRegionShape()));
} }
public static ScriptEngine getEngine() { public static ScriptEngine getEngine() {
......
...@@ -14,6 +14,7 @@ public class SceneGroup { ...@@ -14,6 +14,7 @@ public class SceneGroup {
public List<SceneMonster> monsters; public List<SceneMonster> monsters;
public List<SceneGadget> gadgets; public List<SceneGadget> gadgets;
public List<SceneTrigger> triggers; public List<SceneTrigger> triggers;
public List<SceneRegion> regions;
public List<SceneSuite> suites; public List<SceneSuite> suites;
public SceneInitConfig init_config; public SceneInitConfig init_config;
......
package emu.grasscutter.scripts.data;
import emu.grasscutter.game.entity.GameEntity;
import emu.grasscutter.scripts.constants.ScriptRegionShape;
import emu.grasscutter.utils.Position;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet;
public class SceneRegion {
public int config_id;
public int shape;
public Position pos;
public Position size;
private boolean hasNewEntities;
private final IntSet entities; // Ids of entities inside this region
public SceneRegion() {
this.entities = new IntOpenHashSet();
}
public IntSet getEntities() {
return entities;
}
public void addEntity(GameEntity entity) {
if (this.getEntities().contains(entity.getId())) {
return;
}
this.getEntities().add(entity.getId());
this.hasNewEntities = true;
}
public void removeEntity(GameEntity entity) {
this.getEntities().remove(entity.getId());
}
public boolean contains(Position p) {
switch (shape) {
case ScriptRegionShape.CUBIC:
return (Math.abs(pos.getX() - p.getX()) <= size.getX()) &&
(Math.abs(pos.getZ() - p.getZ()) <= size.getZ());
case ScriptRegionShape.SPHERE:
return false;
}
return false;
}
public boolean hasNewEntities() {
return hasNewEntities;
}
public void resetNewEntities() {
hasNewEntities = false;
}
}
...@@ -4,6 +4,7 @@ public class ScriptArgs { ...@@ -4,6 +4,7 @@ public class ScriptArgs {
public int param1; public int param1;
public int param2; public int param2;
public int param3; public int param3;
public int source_eid; // Source entity
public ScriptArgs() { public ScriptArgs() {
...@@ -44,4 +45,13 @@ public class ScriptArgs { ...@@ -44,4 +45,13 @@ public class ScriptArgs {
this.param3 = param3; this.param3 = param3;
return this; return this;
} }
public int getSourceEntityId() {
return source_eid;
}
public ScriptArgs setSourceEntityId(int source_eid) {
this.source_eid = source_eid;
return this;
}
} }
...@@ -455,8 +455,7 @@ public final class DispatchServer { ...@@ -455,8 +455,7 @@ public final class DispatchServer {
// hk4e-sdk-os-static.hoyoverse.com // hk4e-sdk-os-static.hoyoverse.com
httpServer.get("/hk4e_global/combo/granter/api/getConfig", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}")); httpServer.get("/hk4e_global/combo/granter/api/getConfig", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"protocol\":true,\"qr_enabled\":false,\"log_level\":\"INFO\",\"announce_url\":\"https://webstatic-sea.hoyoverse.com/hk4e/announcement/index.html?sdk_presentation_style=fullscreen\\u0026sdk_screen_transparent=true\\u0026game_biz=hk4e_global\\u0026auth_appid=announcement\\u0026game=hk4e#/\",\"push_alias_type\":2,\"disable_ysdk_guard\":false,\"enable_announce_pic_popup\":true}}"));
// hk4e-sdk-os-static.hoyoverse.com // hk4e-sdk-os-static.hoyoverse.com
httpServer.get("/hk4e_global/mdk/shield/api/loadConfig", new DispatchHttpJsonHandler( "{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}")); httpServer.get("/hk4e_global/mdk/shield/api/loadConfig", new DispatchHttpJsonHandler("{\"retcode\":0,\"message\":\"OK\",\"data\":{\"id\":6,\"game_key\":\"hk4e_global\",\"client\":\"PC\",\"identity\":\"I_IDENTITY\",\"guest\":false,\"ignore_versions\":\"\",\"scene\":\"S_NORMAL\",\"name\":\"原神海外\",\"disable_regist\":false,\"enable_email_captcha\":false,\"thirdparty\":[\"fb\",\"tw\"],\"disable_mmt\":false,\"server_guest\":false,\"thirdparty_ignore\":{\"tw\":\"\",\"fb\":\"\"},\"enable_ps_bind_account\":false,\"thirdparty_login_configs\":{\"tw\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800},\"fb\":{\"token_type\":\"TK_GAME_TOKEN\",\"game_token_expires_in\":604800}}}}"));
// Test api? // Test api?
// abtest-api-data-sg.hoyoverse.com // abtest-api-data-sg.hoyoverse.com
httpServer.post("/data_abtest_api/config/experiment/list", new DispatchHttpJsonHandler("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}")); httpServer.post("/data_abtest_api/config/experiment/list", new DispatchHttpJsonHandler("{\"retcode\":0,\"success\":true,\"message\":\"\",\"data\":[{\"code\":1000,\"type\":2,\"config_id\":\"14\",\"period_id\":\"6036_99\",\"version\":\"1\",\"configs\":{\"cardType\":\"old\"}}]}"));
......
package emu.grasscutter.server.event.game;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.event.types.GameEvent;
import emu.grasscutter.server.game.GameSession;
public final class PlayerCreationEvent extends GameEvent {
private final GameSession session;
private Class<? extends Player> playerClass;
public PlayerCreationEvent(GameSession session, Class<? extends Player> playerClass) {
this.session = session;
this.playerClass = playerClass;
}
public GameSession getSession() {
return this.session;
}
public void setPlayerClass(Class<? extends Player> playerClass) {
this.playerClass = playerClass;
}
public Class<? extends Player> getPlayerClass() {
return this.playerClass;
}
}
package emu.grasscutter.server.event.game; package emu.grasscutter.server.event.player;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.event.Cancellable; import emu.grasscutter.server.event.Cancellable;
import emu.grasscutter.server.event.types.GameEvent; import emu.grasscutter.server.event.types.PlayerEvent;
public final class PlayerJoinEvent extends GameEvent implements Cancellable { public final class PlayerJoinEvent extends PlayerEvent implements Cancellable {
private final Player player;
public PlayerJoinEvent(Player player) { public PlayerJoinEvent(Player player) {
this.player = player; super(player);
}
public Player getPlayer() {
return this.player;
} }
} }
package emu.grasscutter.server.event.game; package emu.grasscutter.server.event.player;
import emu.grasscutter.game.player.Player; import emu.grasscutter.game.player.Player;
import emu.grasscutter.server.event.types.GameEvent; import emu.grasscutter.server.event.types.GameEvent;
import emu.grasscutter.server.event.types.PlayerEvent;
public final class PlayerQuitEvent extends GameEvent { public final class PlayerQuitEvent extends PlayerEvent {
private final Player player;
public PlayerQuitEvent(Player player) { public PlayerQuitEvent(Player player) {
this.player = player; super(player);
}
public Player getPlayer() {
return this.player;
} }
} }
package emu.grasscutter.server.packet.recv;
import emu.grasscutter.game.player.Player;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetFriendShowAvatarInfoReqOuterClass.GetFriendShowAvatarInfoReq;
import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.packet.send.PacketGetFriendShowAvatarInfoRsp;
@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoReq)
public class HandlerGetFriendShowAvatarInfoReq extends PacketHandler {
@Override
public void handle(GameSession session, byte[] header, byte[] payload) throws Exception {
GetFriendShowAvatarInfoReq req = GetFriendShowAvatarInfoReq.parseFrom(payload);
int targetUid = req.getUid();
Player targetPlayer = session.getServer().getPlayerByUid(targetUid, true);
if (targetPlayer.isShowAvatars()) {
session.send(new PacketGetFriendShowAvatarInfoRsp(targetUid, targetPlayer.getShowAvatarInfoList()));
}
}
}
...@@ -13,10 +13,12 @@ import emu.grasscutter.net.packet.Opcodes; ...@@ -13,10 +13,12 @@ import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.SetPlayerBornDataReqOuterClass.SetPlayerBornDataReq; import emu.grasscutter.net.proto.SetPlayerBornDataReqOuterClass.SetPlayerBornDataReq;
import emu.grasscutter.net.packet.PacketHandler; import emu.grasscutter.net.packet.PacketHandler;
import emu.grasscutter.server.event.game.PlayerJoinEvent; import emu.grasscutter.server.event.game.PlayerCreationEvent;
import emu.grasscutter.server.game.GameSession; import emu.grasscutter.server.game.GameSession;
import emu.grasscutter.server.game.GameSession.SessionState; import emu.grasscutter.server.game.GameSession.SessionState;
import java.util.Arrays;
@Opcodes(PacketOpcodes.SetPlayerBornDataReq) @Opcodes(PacketOpcodes.SetPlayerBornDataReq)
public class HandlerSetPlayerBornDataReq extends PacketHandler { public class HandlerSetPlayerBornDataReq extends PacketHandler {
...@@ -40,8 +42,10 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler { ...@@ -40,8 +42,10 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
nickname = "Traveler"; nickname = "Traveler";
} }
// Create character // Call creation event.
Player player = new Player(session); PlayerCreationEvent event = new PlayerCreationEvent(session, Player.class); event.call();
// Create player instance from event.
Player player = event.getPlayerClass().getDeclaredConstructor(GameSession.class).newInstance(session);
player.setNickname(nickname); player.setNickname(nickname);
try { try {
...@@ -83,19 +87,12 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler { ...@@ -83,19 +87,12 @@ public class HandlerSetPlayerBornDataReq extends PacketHandler {
mailBuilder.mail.mailContent.title = String.format("W%sl%som%s to %s%s%s%s%s%s%s%s%s%s%s!", DatabaseHelper.AWJVN, u, DatabaseHelper.AWJVN, d, e, z, GameData.EJWOA, GameData.EJWOA, u, PacketOpcodes.ONLWE, s, s, DatabaseHelper.AWJVN, e); mailBuilder.mail.mailContent.title = String.format("W%sl%som%s to %s%s%s%s%s%s%s%s%s%s%s!", DatabaseHelper.AWJVN, u, DatabaseHelper.AWJVN, d, e, z, GameData.EJWOA, GameData.EJWOA, u, PacketOpcodes.ONLWE, s, s, DatabaseHelper.AWJVN, e);
mailBuilder.mail.mailContent.sender = String.format("L%swnmow%s%s @ Gi%sH%sb", z, DatabaseHelper.AWJVN, e, s, PacketOpcodes.ONLWE); mailBuilder.mail.mailContent.sender = String.format("L%swnmow%s%s @ Gi%sH%sb", z, DatabaseHelper.AWJVN, e, s, PacketOpcodes.ONLWE);
mailBuilder.mail.mailContent.content = Grasscutter.getConfig().GameServer.WelcomeMailContent; mailBuilder.mail.mailContent.content = Grasscutter.getConfig().GameServer.WelcomeMailContent;
for (int itemId : Grasscutter.getConfig().GameServer.WelcomeMailItems) { mailBuilder.mail.itemList.addAll(Arrays.asList(Grasscutter.getConfig().GameServer.WelcomeMailItems));
mailBuilder.mail.itemList.add(new Mail.MailItem(itemId, 1, 1));
}
mailBuilder.mail.importance = 1; mailBuilder.mail.importance = 1;
player.sendMail(mailBuilder.mail); player.sendMail(mailBuilder.mail);
} catch (Exception e) { } catch (Exception e) {
Grasscutter.getLogger().error("Error creating player object: ", e); Grasscutter.getLogger().error("Error creating player object: ", e);
session.close(); session.close();
} }
// Call join event.
PlayerJoinEvent event = new PlayerJoinEvent(player); event.call();
if(event.isCanceled()) // If event is not cancelled, continue.
session.close();
} }
} }
...@@ -17,11 +17,13 @@ public class PacketDungeonEntryInfoRsp extends BasePacket { ...@@ -17,11 +17,13 @@ public class PacketDungeonEntryInfoRsp extends BasePacket {
DungeonEntryInfoRsp.Builder proto = DungeonEntryInfoRsp.newBuilder() DungeonEntryInfoRsp.Builder proto = DungeonEntryInfoRsp.newBuilder()
.setPointId(pointData.getId()); .setPointId(pointData.getId());
for (int dungeonId : pointData.getDungeonIds()) { if (pointData.getDungeonIds() != null) {
DungeonEntryInfo info = DungeonEntryInfo.newBuilder().setDungeonId(dungeonId).build(); for (int dungeonId : pointData.getDungeonIds()) {
proto.addDungeonEntryList(info); DungeonEntryInfo info = DungeonEntryInfo.newBuilder().setDungeonId(dungeonId).build();
proto.addDungeonEntryList(info);
}
} }
this.setData(proto); this.setData(proto);
} }
......
package emu.grasscutter.server.packet.send;
import java.util.List;
import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.Opcodes;
import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetFriendShowAvatarInfoRspOuterClass.GetFriendShowAvatarInfoRsp;
import emu.grasscutter.net.proto.ShowAvatarInfoOuterClass.ShowAvatarInfo;
@Opcodes(PacketOpcodes.GetFriendShowAvatarInfoRsp)
public class PacketGetFriendShowAvatarInfoRsp extends BasePacket {
public PacketGetFriendShowAvatarInfoRsp(int uid, List<ShowAvatarInfo> showAvatarInfoList) {
super(PacketOpcodes.GetFriendShowAvatarInfoRsp);
GetFriendShowAvatarInfoRsp.Builder p = GetFriendShowAvatarInfoRsp.newBuilder()
.setUid(uid)
.addAllShowAvatarInfoList(showAvatarInfoList);
this.setData(p.build());
}
}
...@@ -18,36 +18,19 @@ import java.util.Objects; ...@@ -18,36 +18,19 @@ import java.util.Objects;
public class PacketGetOnlinePlayerListRsp extends BasePacket { public class PacketGetOnlinePlayerListRsp extends BasePacket {
public PacketGetOnlinePlayerListRsp(Player session){ public PacketGetOnlinePlayerListRsp(Player session){
super(PacketOpcodes.GetOnlinePlayerListRsp); super(PacketOpcodes.GetOnlinePlayerListRsp);
Map<Integer, Player> playersMap = Grasscutter.getGameServer().getPlayers();
List<Player> players = Grasscutter.getGameServer().getPlayers().values().stream().limit(50).toList();
GetOnlinePlayerListRsp.Builder proto = GetOnlinePlayerListRsp.newBuilder(); GetOnlinePlayerListRsp.Builder proto = GetOnlinePlayerListRsp.newBuilder();
if(playersMap.size() != 0){
List<OnlinePlayerInfo> playerInfoList = new ArrayList<>(); if (players.size() != 0) {
for(Player player : players) {
for(Player player:playersMap.values()){ if (player.getUid() == session.getUid()) continue;
ProfilePicture.Builder picture = ProfilePicture.newBuilder();
OnlinePlayerInfo.Builder playerInfo = OnlinePlayerInfo.newBuilder(); proto.addPlayerInfoList(player.getOnlinePlayerInfo());
if(player.getUid() == session.getUid())continue;
picture.setAvatarId(player.getProfile().getAvatarId())
.build();
System.out.println(player.getHeadImage());
playerInfo.setUid(player.getUid())
.setNickname(player.getNickname())
.setPlayerLevel(player.getLevel())
.setMpSettingType(MpSettingTypeOuterClass.MpSettingType.MP_SETTING_ENTER_AFTER_APPLY)
.setCurPlayerNumInWorld(player.getWorld().getPlayerCount())
.setWorldLevel(player.getWorldLevel())
.setNameCardId(player.getNameCardId())
.setProfilePicture(picture);
if(!Objects.equals(player.getSignature(), "")){
playerInfo.setSignature(player.getSignature());
}
playerInfoList.add(playerInfo.build());
}
for (OnlinePlayerInfo onlinePlayerInfo : playerInfoList) {
proto.addPlayerInfoList(onlinePlayerInfo).build();
} }
} }
this.setData(proto); this.setData(proto);
} }
} }
...@@ -18,9 +18,9 @@ public class PacketGetPlayerFriendListRsp extends BasePacket { ...@@ -18,9 +18,9 @@ public class PacketGetPlayerFriendListRsp extends BasePacket {
FriendBrief serverFriend = FriendBrief.newBuilder() FriendBrief serverFriend = FriendBrief.newBuilder()
.setUid(GameConstants.SERVER_CONSOLE_UID) .setUid(GameConstants.SERVER_CONSOLE_UID)
.setNickname("Server") .setNickname(GameConstants.SERVER_AVATAR_NAME)
.setLevel(1) .setLevel(1)
.setProfilePicture(ProfilePicture.newBuilder().setAvatarId(GameConstants.MAIN_CHARACTER_FEMALE)) .setProfilePicture(ProfilePicture.newBuilder().setAvatarId(GameConstants.SERVER_AVATAR_ID))
.setWorldLevel(0) .setWorldLevel(0)
.setSignature("") .setSignature("")
.setLastActiveTime((int) (System.currentTimeMillis() / 1000f)) .setLastActiveTime((int) (System.currentTimeMillis() / 1000f))
......
package emu.grasscutter.server.packet.send; package emu.grasscutter.server.packet.send;
import emu.grasscutter.data.GameData;
import emu.grasscutter.net.packet.BasePacket; import emu.grasscutter.net.packet.BasePacket;
import emu.grasscutter.net.packet.PacketOpcodes; import emu.grasscutter.net.packet.PacketOpcodes;
import emu.grasscutter.net.proto.GetScenePointRspOuterClass.GetScenePointRsp; import emu.grasscutter.net.proto.GetScenePointRspOuterClass.GetScenePointRsp;
...@@ -12,8 +13,12 @@ public class PacketGetScenePointRsp extends BasePacket { ...@@ -12,8 +13,12 @@ public class PacketGetScenePointRsp extends BasePacket {
GetScenePointRsp.Builder p = GetScenePointRsp.newBuilder() GetScenePointRsp.Builder p = GetScenePointRsp.newBuilder()
.setSceneId(sceneId); .setSceneId(sceneId);
for (int i = 1; i < 1000; i++) { if (GameData.getScenePointIdList().size() == 0) {
p.addUnlockedPointList(i); for (int i = 1; i < 1000; i++) {
p.addUnlockedPointList(i);
}
} else {
p.addAllUnlockedPointList(GameData.getScenePointIdList());
} }
for (int i = 1; i < 9; i++) { for (int i = 1; i < 9; i++) {
......
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