mirror of
https://github.com/Melledy/Nebula.git
synced 2026-09-20 01:29:54 +02:00
Initial Commit
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
package emu.nebula.server;
|
||||
|
||||
import org.eclipse.jetty.server.HttpConfiguration;
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory;
|
||||
import org.eclipse.jetty.server.SecureRequestCustomizer;
|
||||
import org.eclipse.jetty.server.ServerConnector;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
import emu.nebula.Config.HttpServerConfig;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.Nebula.ServerType;
|
||||
import emu.nebula.server.routes.*;
|
||||
import io.javalin.Javalin;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class HttpServer {
|
||||
private final Javalin app;
|
||||
private ServerType type;
|
||||
private boolean started;
|
||||
|
||||
public HttpServer(ServerType type) {
|
||||
this.app = Javalin.create();
|
||||
this.type = type;
|
||||
|
||||
this.addRoutes();
|
||||
}
|
||||
|
||||
public HttpServerConfig getServerConfig() {
|
||||
return Nebula.getConfig().getHttpServer();
|
||||
}
|
||||
|
||||
private HttpConnectionFactory getHttpFactory() {
|
||||
HttpConfiguration httpsConfig = new HttpConfiguration();
|
||||
SecureRequestCustomizer src = new SecureRequestCustomizer();
|
||||
src.setSniHostCheck(false);
|
||||
httpsConfig.addCustomizer(src);
|
||||
return new HttpConnectionFactory(httpsConfig);
|
||||
}
|
||||
|
||||
private SslContextFactory.Server getSSLContextFactory() {
|
||||
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
|
||||
sslContextFactory.setKeyStorePath(Nebula.getConfig().getKeystore().getPath());
|
||||
sslContextFactory.setKeyStorePassword(Nebula.getConfig().getKeystore().getPassword());
|
||||
sslContextFactory.setSniRequired(false);
|
||||
sslContextFactory.setRenegotiationAllowed(false);
|
||||
return sslContextFactory;
|
||||
}
|
||||
|
||||
// Start server
|
||||
|
||||
public void start() {
|
||||
if (this.started) return;
|
||||
this.started = true;
|
||||
|
||||
// Http server
|
||||
if (getServerConfig().isUseSSL()) {
|
||||
ServerConnector sslConnector = new ServerConnector(getApp().jettyServer().server(), getSSLContextFactory(), getHttpFactory());
|
||||
sslConnector.setHost(getServerConfig().getBindAddress());
|
||||
sslConnector.setPort(getServerConfig().getBindPort());
|
||||
getApp().jettyServer().server().addConnector(sslConnector);
|
||||
|
||||
getApp().start();
|
||||
} else {
|
||||
getApp().start(getServerConfig().getBindAddress(), getServerConfig().getBindPort());
|
||||
}
|
||||
|
||||
// Done
|
||||
Nebula.getLogger().info("Http Server started on " + getServerConfig().getBindPort());
|
||||
}
|
||||
|
||||
// Server endpoints
|
||||
|
||||
private void addRoutes() {
|
||||
// Add routes
|
||||
if (this.getType().runLogin()) {
|
||||
this.addLoginServerRoutes();
|
||||
}
|
||||
|
||||
if (this.getType().runGame()) {
|
||||
this.addGameServerRoutes();
|
||||
}
|
||||
|
||||
// Exception handler
|
||||
getApp().exception(Exception.class, (e, _) -> {
|
||||
e.printStackTrace();
|
||||
});
|
||||
|
||||
// Fallback handler
|
||||
getApp().error(404, this::notFoundHandler);
|
||||
}
|
||||
|
||||
private void addLoginServerRoutes() {
|
||||
// https://en-sdk-api.yostarplat.com/
|
||||
getApp().post("/common/config", new CommonConfigHandler(this));
|
||||
getApp().post("/common/version", new HttpJsonResponse("{\"Code\":200,\"Data\":{\"Agreement\":[{\"Version\":\"0.1\",\"Type\":\"user_agreement\",\"Title\":\"用户协议\",\"Content\":\"\",\"Lang\":\"en\"},{\"Version\":\"0.1\",\"Type\":\"privacy_agreement\",\"Title\":\"隐私政策\",\"Content\":\"\",\"Lang\":\"en\"}],\"ErrorCode\":\"4.4\"},\"Msg\":\"OK\"}"));
|
||||
|
||||
getApp().post("/user/detail", new UserLoginHandler());
|
||||
getApp().post("/user/set", new UserSetDataHandler());
|
||||
getApp().post("/user/login", new UserLoginHandler());
|
||||
getApp().post("/user/quick-login", new UserLoginHandler());
|
||||
|
||||
getApp().post("/yostar/get-auth", new GetAuthHandler());
|
||||
getApp().post("/yostar/send-code", new HttpJsonResponse("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}")); // Dummy handler
|
||||
|
||||
// https://nova-static.stellasora.global/
|
||||
getApp().get("/meta/serverlist.html", new MetaServerlistHandler(this));
|
||||
getApp().get("/meta/win.html", new MetaWinHandler());
|
||||
}
|
||||
|
||||
private void addGameServerRoutes() {
|
||||
getApp().post("/agent-zone-1/", new AgentZoneHandler());
|
||||
}
|
||||
|
||||
private void notFoundHandler(Context ctx) {
|
||||
ctx.status(404);
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{}");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.none)
|
||||
public class Handler extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Template
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Public.Achievements;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.achievement_info_req)
|
||||
public class HandlerAchievementInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = Achievements.newInstance();
|
||||
|
||||
return this.encodeMsg(NetMsgId.achievement_info_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.ActivityDetail.ActivityMsg;
|
||||
import emu.nebula.proto.ActivityDetail.ActivityResp;
|
||||
import emu.nebula.proto.Public.ActivityTrial;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.activity_detail_req)
|
||||
public class HandlerActivityDetailReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = ActivityResp.newInstance();
|
||||
|
||||
var activity = ActivityMsg.newInstance()
|
||||
.setId(700101)
|
||||
.setTrial(ActivityTrial.newInstance());
|
||||
|
||||
rsp.addList(activity);
|
||||
|
||||
return this.encodeMsg(NetMsgId.activity_detail_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.agent_apply_req)
|
||||
public class HandlerAgentApplyReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.agent_apply_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.battle_pass_info_req)
|
||||
public class HandlerBattlePassInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.battle_pass_info_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Public.UI32;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.char_advance_req)
|
||||
public class HandlerCharAdvanceReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = UI32.parseFrom(message);
|
||||
|
||||
// Get character
|
||||
var character = session.getPlayer().getCharacters().getCharacterById(req.getValue());
|
||||
|
||||
if (character == null) {
|
||||
return this.encodeMsg(NetMsgId.char_advance_failed_ack);
|
||||
}
|
||||
|
||||
// Advance character
|
||||
var change = character.advance();
|
||||
|
||||
if (change == null) {
|
||||
return this.encodeMsg(NetMsgId.char_advance_failed_ack);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.char_advance_succeed_ack, change.toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.CharSkillUpgrade.CharSkillUpgradeReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.char_skill_upgrade_req)
|
||||
public class HandlerCharSkillUpgradeReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = CharSkillUpgradeReq.parseFrom(message);
|
||||
|
||||
// Get character
|
||||
var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId());
|
||||
|
||||
if (character == null) {
|
||||
return this.encodeMsg(NetMsgId.char_skill_upgrade_failed_ack);
|
||||
}
|
||||
|
||||
// Advance character
|
||||
int index = req.getIndex() - 1; // Lua indexes start at 1
|
||||
var change = character.upgradeSkill(index);
|
||||
|
||||
if (change == null) {
|
||||
return this.encodeMsg(NetMsgId.char_skill_upgrade_failed_ack);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.char_skill_upgrade_succeed_ack, change.toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.CharUpgrade.CharUpgradeReq;
|
||||
import emu.nebula.proto.CharUpgrade.CharUpgradeResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.char_upgrade_req)
|
||||
public class HandlerCharUpgradeReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = CharUpgradeReq.parseFrom(message);
|
||||
|
||||
// Get character
|
||||
var character = session.getPlayer().getCharacters().getCharacterById(req.getCharId());
|
||||
|
||||
if (character == null) {
|
||||
return this.encodeMsg(NetMsgId.char_upgrade_failed_ack);
|
||||
}
|
||||
|
||||
// Upgrade character
|
||||
var params = ItemParamMap.fromTemplates(req.getItems());
|
||||
var change = character.upgrade(params);
|
||||
|
||||
if (change == null) {
|
||||
return this.encodeMsg(NetMsgId.char_upgrade_failed_ack);
|
||||
}
|
||||
|
||||
// Create response
|
||||
var rsp = CharUpgradeResp.newInstance()
|
||||
.setChange(change.toProto())
|
||||
.setLevel(character.getLevel())
|
||||
.setExp(character.getExp());
|
||||
|
||||
return this.encodeMsg(NetMsgId.char_upgrade_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.client_event_report_req)
|
||||
public class HandlerClientEventReportReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.client_event_report_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.DiscPromote.DiscPromoteReq;
|
||||
import emu.nebula.proto.DiscPromote.DiscPromoteResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.disc_promote_req)
|
||||
public class HandlerDiscPromoteReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = DiscPromoteReq.parseFrom(message);
|
||||
|
||||
// Get character
|
||||
var disc = session.getPlayer().getCharacters().getDiscById(req.getId());
|
||||
|
||||
if (disc == null) {
|
||||
return this.encodeMsg(NetMsgId.disc_promote_failed_ack);
|
||||
}
|
||||
|
||||
// Advance character
|
||||
var change = disc.promote();
|
||||
|
||||
if (change == null) {
|
||||
return this.encodeMsg(NetMsgId.disc_promote_failed_ack);
|
||||
}
|
||||
|
||||
// Build request
|
||||
var rsp = DiscPromoteResp.newInstance()
|
||||
.setPhase(disc.getPhase())
|
||||
.setChange(change.toProto());
|
||||
|
||||
return this.encodeMsg(NetMsgId.disc_promote_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.disc_read_reward_receive_req)
|
||||
public class HandlerDiscReadRewardReceiveReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.disc_read_reward_receive_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.DiscStrengthen.DiscStrengthenReq;
|
||||
import emu.nebula.proto.DiscStrengthen.DiscStrengthenResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.inventory.ItemParamMap;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.disc_strengthen_req)
|
||||
public class HandlerDiscStrengthenReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = DiscStrengthenReq.parseFrom(message);
|
||||
|
||||
// Get character
|
||||
var disc = session.getPlayer().getCharacters().getDiscById(req.getId());
|
||||
|
||||
if (disc == null) {
|
||||
return this.encodeMsg(NetMsgId.disc_strengthen_failed_ack);
|
||||
}
|
||||
|
||||
// Upgrade character
|
||||
var params = ItemParamMap.fromItemInfos(req.getItems());
|
||||
var change = disc.upgrade(params);
|
||||
|
||||
if (change == null) {
|
||||
return this.encodeMsg(NetMsgId.disc_strengthen_failed_ack);
|
||||
}
|
||||
|
||||
// Create response
|
||||
var rsp = DiscStrengthenResp.newInstance()
|
||||
.setChange(change.toProto())
|
||||
.setLevel(disc.getLevel())
|
||||
.setExp(disc.getExp());
|
||||
|
||||
return this.encodeMsg(NetMsgId.disc_strengthen_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.FriendListGet.FriendListGetResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.friend_list_get_req)
|
||||
public class HandlerFriendListGetReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = FriendListGetResp.newInstance();
|
||||
|
||||
return this.encodeMsg(NetMsgId.friend_list_get_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.GachaInformation.GachaInformationResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.gacha_information_req)
|
||||
public class HandlerGachaInformationReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = GachaInformationResp.newInstance();
|
||||
|
||||
// TODO
|
||||
|
||||
return this.encodeMsg(NetMsgId.gacha_information_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.GachaInformation.GachaInformationResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.gacha_newbie_info_req)
|
||||
public class HandlerGachaNewbieInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = GachaInformationResp.newInstance();
|
||||
|
||||
return this.encodeMsg(NetMsgId.gacha_newbie_info_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.GachaNewbieObtain.GachaNewbieObtainReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.gacha_newbie_obtain_req)
|
||||
public class HandlerGachaNewbieObtainReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
@SuppressWarnings("unused")
|
||||
var req = GachaNewbieObtainReq.parseFrom(message);
|
||||
|
||||
// TODO
|
||||
return this.encodeMsg(NetMsgId.gacha_newbie_obtain_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.GachaNewbieSpin.GachaNewbieSpinResp;
|
||||
import emu.nebula.proto.GachaSpin.GachaSpinReq;
|
||||
import emu.nebula.util.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.gacha_newbie_spin_req)
|
||||
public class HandlerGachaNewbieSpinReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
@SuppressWarnings("unused")
|
||||
var req = GachaSpinReq.parseFrom(message);
|
||||
|
||||
// Temp
|
||||
var list = new IntArrayList();
|
||||
|
||||
for (var d : GameData.getCharacterDataTable()) {
|
||||
if (d.getGrade() == 1) {
|
||||
list.add(d.getId());
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
var rsp = GachaNewbieSpinResp.newInstance();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int id = Utils.randomElement(list);
|
||||
rsp.addCards(id);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.gacha_newbie_spin_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.GachaSpin.GachaCard;
|
||||
import emu.nebula.proto.GachaSpin.GachaSpinReq;
|
||||
import emu.nebula.proto.GachaSpin.GachaSpinResp;
|
||||
import emu.nebula.proto.Public.ItemTpl;
|
||||
import emu.nebula.util.Utils;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.gacha_spin_req)
|
||||
public class HandlerGachaSpinReq extends NetHandler {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = GachaSpinReq.parseFrom(message);
|
||||
|
||||
// Temp
|
||||
var list = new IntArrayList();
|
||||
|
||||
for (var def : GameData.getCharacterDataTable()) {
|
||||
if (def.getGrade() == 1 && def.isAvailable()) {
|
||||
list.add(def.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = GachaSpinResp.newInstance()
|
||||
.setTime(Nebula.getCurrentTime());
|
||||
|
||||
rsp.getMutableChange();
|
||||
rsp.getMutableNextPackage();
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
int id = Utils.randomElement(list);
|
||||
|
||||
var card = GachaCard.newInstance()
|
||||
.setCard(ItemTpl.newInstance().setTid(id).setQty(1));
|
||||
|
||||
rsp.addCards(card);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.gacha_spin_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Ike.IKEReq;
|
||||
import emu.nebula.proto.Ike.IKEResp;
|
||||
import emu.nebula.util.Utils;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.ike_req)
|
||||
public class HandlerIkeReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public boolean requireSession() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean requirePlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Make sure we dont already have a session
|
||||
if (session != null) {
|
||||
return this.encodeMsg(NetMsgId.ike_failed_ack);
|
||||
}
|
||||
|
||||
// Parse
|
||||
var req = IKEReq.parseFrom(message);
|
||||
|
||||
// Create session
|
||||
session = new GameSession();
|
||||
session.setClientKey(req.getPubKey());
|
||||
session.generateServerKey();
|
||||
session.calculateKey();
|
||||
|
||||
// Register session to game context
|
||||
Nebula.getGameContext().generateSessionToken(session);
|
||||
|
||||
// Create response
|
||||
var rsp = IKEResp.newInstance()
|
||||
.setToken(session.getToken())
|
||||
.setCipher(1) // 0 = gcm, 1 = chacha20
|
||||
.setServerTs(Nebula.getCurrentTime())
|
||||
.setPubKey(session.getServerPublicKey());
|
||||
|
||||
// Debug
|
||||
Nebula.getLogger().info("Client Public: " + Utils.base64Encode(session.getClientPublicKey()));
|
||||
Nebula.getLogger().info("Server Public: " + Utils.base64Encode(session.getServerPublicKey()));
|
||||
Nebula.getLogger().info("Server Private: " + Utils.base64Encode(session.getServerPrivateKey()));
|
||||
Nebula.getLogger().info("Key: " + Utils.base64Encode(session.getKey()));
|
||||
|
||||
// Encode and send to client
|
||||
return this.encodeMsg(NetMsgId.ike_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Public.Mails;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mail_list_req)
|
||||
public class HandlerMailListReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Build mail list proto
|
||||
var rsp = Mails.newInstance();
|
||||
|
||||
for (var mail : session.getPlayer().getMailbox()) {
|
||||
rsp.addList(mail.toProto());
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mail_list_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MailPin.MailPinRequest;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.mail.GameMail;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mail_pin_req)
|
||||
public class HandlerMailPinReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = MailPinRequest.parseFrom(message);
|
||||
|
||||
// Pin mail
|
||||
GameMail mail = session.getPlayer().getMailbox().pinMail(req.getId(), req.getFlag(), req.hasPin());
|
||||
|
||||
// Sanity check
|
||||
if (mail == null) {
|
||||
return this.encodeMsg(NetMsgId.mail_pin_failed_ack);
|
||||
}
|
||||
|
||||
// Build response
|
||||
var rsp = MailPinRequest.newInstance()
|
||||
.setId(mail.getId())
|
||||
.setFlag(mail.getFlag())
|
||||
.setPin(mail.isPin());
|
||||
|
||||
return this.encodeMsg(NetMsgId.mail_pin_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Public.MailRequest;
|
||||
import emu.nebula.proto.Public.UI32;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mail_read_req)
|
||||
public class HandlerMailReadReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = MailRequest.parseFrom(message);
|
||||
|
||||
boolean result = session.getPlayer().getMailbox().readMail(req.getId(), req.getFlag());
|
||||
|
||||
if (!result) {
|
||||
return this.encodeMsg(NetMsgId.mail_read_failed_ack);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mail_read_succeed_ack, UI32.newInstance().setValue(req.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MailRecv.MailRecvResp;
|
||||
import emu.nebula.proto.Public.MailRequest;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.game.player.PlayerChangeInfo;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mail_recv_req)
|
||||
public class HandlerMailRecvReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = MailRequest.parseFrom(message);
|
||||
|
||||
// Claim mail
|
||||
PlayerChangeInfo changes = session.getPlayer().getMailbox().recvMail(session.getPlayer(), req.getId());
|
||||
|
||||
// Build response
|
||||
var rsp = MailRecvResp.newInstance()
|
||||
.setItems(changes.toProto());
|
||||
|
||||
var recvList = (IntList) changes.getExtraData();
|
||||
|
||||
for (int id : recvList) {
|
||||
rsp.addIds(id);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mail_recv_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MailRemove.MailRemoveResp;
|
||||
import emu.nebula.proto.Public.MailRequest;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mail_remove_req)
|
||||
public class HandlerMailRemoveReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = MailRequest.parseFrom(message);
|
||||
|
||||
// Claim mail
|
||||
IntList removed = session.getPlayer().getMailbox().removeMail(session.getPlayer(), req.getId());
|
||||
|
||||
// Build response
|
||||
var rsp = MailRemoveResp.newInstance();
|
||||
|
||||
for (int id : removed) {
|
||||
rsp.addIds(id);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mail_remove_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MallGemListOuterClass.GemInfo;
|
||||
import emu.nebula.proto.MallGemListOuterClass.MallGemList;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mall_gem_list_req)
|
||||
public class HandlerMallGemListReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = MallGemList.newInstance();
|
||||
|
||||
for (var data : GameData.getMallGemDataTable()) {
|
||||
var info = GemInfo.newInstance()
|
||||
.setId(data.getIdString())
|
||||
.setMaiden(true);
|
||||
|
||||
rsp.addList(info);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mall_gem_list_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MallMonthlycardList.MallMonthlyCardList;
|
||||
import emu.nebula.proto.MallMonthlycardList.MonthlyCardInfo;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mall_monthlyCard_list_req)
|
||||
public class HandlerMallMonthlyCardListReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = MallMonthlyCardList.newInstance();
|
||||
|
||||
for (var data : GameData.getMallMonthlyCardDataTable()) {
|
||||
var info = MonthlyCardInfo.newInstance()
|
||||
.setId(data.getIdString())
|
||||
.setRemaining(9);
|
||||
|
||||
rsp.addList(info);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mall_monthlyCard_list_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MallPackageListOuterClass.MallPackageList;
|
||||
import emu.nebula.proto.MallPackageListOuterClass.PackageInfo;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mall_package_list_req)
|
||||
public class HandlerMallPackageListReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = MallPackageList.newInstance();
|
||||
|
||||
for (var data : GameData.getMallPackageDataTable()) {
|
||||
var info = PackageInfo.newInstance()
|
||||
.setId(data.getIdString())
|
||||
.setStock(data.getStock());
|
||||
|
||||
rsp.addList(info);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mall_package_list_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.MallShopList.MallShopProductList;
|
||||
import emu.nebula.proto.MallShopList.ProductInfo;
|
||||
import emu.nebula.net.HandlerId;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.data.GameData;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.mall_shop_list_req)
|
||||
public class HandlerMallShopListReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = MallShopProductList.newInstance();
|
||||
|
||||
long refreshTime = Nebula.getCurrentTime() + TimeUnit.DAYS.toSeconds(30);
|
||||
|
||||
for (var data : GameData.getMallShopDataTable()) {
|
||||
if (data.getStock() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var info = ProductInfo.newInstance()
|
||||
.setId(data.getIdString())
|
||||
.setStock(data.getStock())
|
||||
.setRefreshTime(refreshTime);
|
||||
|
||||
rsp.addList(info);
|
||||
}
|
||||
|
||||
return this.encodeMsg(NetMsgId.mall_shop_list_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.phone_contacts_info_req)
|
||||
public class HandlerPhoneContactsInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.phone_contacts_info_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_data_req)
|
||||
public class HandlerPlayerDataReq extends NetHandler {
|
||||
|
||||
public boolean requirePlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Check if player has been created yet
|
||||
if (session.getPlayer() == null) {
|
||||
return this.encodeMsg(NetMsgId.player_new_notify);
|
||||
}
|
||||
|
||||
// Encode player data
|
||||
return this.encodeMsg(NetMsgId.player_data_succeed_ack, session.getPlayer().toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerFormation.PlayerFormationReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_formation_req)
|
||||
public class HandlerPlayerFormationReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = PlayerFormationReq.parseFrom(message);
|
||||
|
||||
boolean success = session.getPlayer().getFormations().updateFormation(req.getFormation());
|
||||
|
||||
return this.encodeMsg(success ? NetMsgId.player_formation_succeed_ack : NetMsgId.player_formation_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_gender_edit_req)
|
||||
public class HandlerPlayerGenderEditReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
session.getPlayer().editGender();
|
||||
|
||||
return this.encodeMsg(NetMsgId.player_gender_edit_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerHeadInfo.PlayerHeadIconInfoResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_head_icon_info_req)
|
||||
public class HandlerPlayerHeadIconInfoReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = PlayerHeadIconInfoResp.newInstance();
|
||||
|
||||
return this.encodeMsg(NetMsgId.player_head_icon_info_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.Public.NewbieInfo;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_learn_req)
|
||||
public class HandlerPlayerLearnReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = NewbieInfo.parseFrom(message);
|
||||
|
||||
// TODO set newbie info
|
||||
session.getPlayer().setNewbieInfo(req.getGroupId(), req.getStepId());
|
||||
|
||||
return this.encodeMsg(NetMsgId.player_learn_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerLogin.LoginReq;
|
||||
import emu.nebula.proto.PlayerLogin.LoginResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_login_req)
|
||||
public class HandlerPlayerLoginReq extends NetHandler {
|
||||
|
||||
public boolean requirePlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = LoginReq.parseFrom(message);
|
||||
var loginToken = req.getOfficialOverseas().getToken();
|
||||
|
||||
// Login
|
||||
boolean result = session.login(loginToken);
|
||||
|
||||
if (!result) {
|
||||
return this.encodeMsg(NetMsgId.player_login_failed_ack);
|
||||
}
|
||||
|
||||
// Regenerate session token because we are switching encrpytion method
|
||||
Nebula.getGameContext().generateSessionToken(session);
|
||||
|
||||
// Create rsp
|
||||
var rsp = LoginResp.newInstance()
|
||||
.setToken(session.getToken());
|
||||
|
||||
// Encode and send to client
|
||||
return this.encodeMsg(NetMsgId.player_login_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_music_set_req)
|
||||
public class HandlerPlayerMusicSetReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.player_music_set_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerNameEdit.PlayerNameEditReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_name_edit_req)
|
||||
public class HandlerPlayerNameEditReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var req = PlayerNameEditReq.parseFrom(message);
|
||||
|
||||
boolean success = session.getPlayer().editName(req.getName());
|
||||
|
||||
return this.encodeMsg(success ? NetMsgId.player_name_edit_succeed_ack : NetMsgId.player_name_edit_failed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerPing.Pong;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_ping_req)
|
||||
public class HandlerPlayerPingReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
var rsp = Pong.newInstance()
|
||||
.setServerTs(Nebula.getCurrentTime());
|
||||
|
||||
return this.encodeMsg(NetMsgId.player_ping_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.PlayerRegOuterClass.PlayerReg;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.player.Player;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.player_reg_req)
|
||||
public class HandlerPlayerRegReq extends NetHandler {
|
||||
|
||||
public boolean requirePlayer() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse request
|
||||
var req = PlayerReg.parseFrom(message);
|
||||
|
||||
// Sanity
|
||||
if (req.getNickname() == null || req.getNickname().isEmpty()) {
|
||||
return this.encodeMsg(NetMsgId.player_reg_failed_ack);
|
||||
}
|
||||
|
||||
// Create player
|
||||
Player player = Nebula.getGameContext().getPlayerModule().createPlayer(session, req.getNickname(), req.getGender());
|
||||
|
||||
if (player == null) {
|
||||
return this.encodeMsg(NetMsgId.player_reg_failed_ack);
|
||||
}
|
||||
|
||||
// Encode player data
|
||||
return this.encodeMsg(NetMsgId.player_data_succeed_ack, session.getPlayer().toProto());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.StarTowerApply.StarTowerApplyReq;
|
||||
import emu.nebula.proto.StarTowerApply.StarTowerApplyResp;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.star_tower_apply_req)
|
||||
public class HandlerStarTowerApplyReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Parse req
|
||||
var req = StarTowerApplyReq.parseFrom(message);
|
||||
|
||||
// Apply to create a star tower instance
|
||||
var instance = session.getPlayer().getStarTowerManager().apply(req);
|
||||
|
||||
if (instance == null) {
|
||||
return this.encodeMsg(NetMsgId.star_tower_apply_failed_ack);
|
||||
}
|
||||
|
||||
// Create response
|
||||
var rsp = StarTowerApplyResp.newInstance()
|
||||
.setLastId(req.getId())
|
||||
.setInfo(instance.toProto());
|
||||
|
||||
rsp.getMutableChange();
|
||||
|
||||
return this.encodeMsg(NetMsgId.star_tower_apply_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.star_tower_build_brief_list_get_req)
|
||||
public class HandlerStarTowerBuildBriefListGetReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.star_tower_build_brief_list_get_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.proto.StarTowerInteract.StarTowerInteractReq;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.star_tower_interact_req)
|
||||
public class HandlerStarTowerInteractReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
// Get star tower instance
|
||||
var instance = session.getPlayer().getStarTowerManager().getInstance();
|
||||
|
||||
if (instance == null) {
|
||||
return this.encodeMsg(NetMsgId.star_tower_interact_failed_ack);
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = StarTowerInteractReq.parseFrom(message);
|
||||
|
||||
// Handle interaction
|
||||
var rsp = instance.handleInteract(req);
|
||||
|
||||
// Template
|
||||
return this.encodeMsg(NetMsgId.star_tower_interact_succeed_ack, rsp);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package emu.nebula.server.handlers;
|
||||
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgId;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.net.GameSession;
|
||||
|
||||
@HandlerId(NetMsgId.tower_growth_detail_req)
|
||||
public class HandlerTowerGrowthDetailReq extends NetHandler {
|
||||
|
||||
@Override
|
||||
public byte[] handle(GameSession session, byte[] message) throws Exception {
|
||||
return this.encodeMsg(NetMsgId.tower_growth_detail_succeed_ack);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,212 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.reflections.Reflections;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.GameContext;
|
||||
import emu.nebula.net.NetHandler;
|
||||
import emu.nebula.net.NetMsgIdUtils;
|
||||
import emu.nebula.net.GameSession;
|
||||
import emu.nebula.net.HandlerId;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import emu.nebula.util.Utils;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class AgentZoneHandler implements Handler {
|
||||
private final Int2ObjectMap<NetHandler> handlers;
|
||||
private final static byte[] EMPTY_BYTES = new byte[0];
|
||||
|
||||
public AgentZoneHandler() {
|
||||
this.handlers = new Int2ObjectOpenHashMap<>();
|
||||
this.registerHandlers();
|
||||
}
|
||||
|
||||
protected GameContext getGameContext() {
|
||||
return Nebula.getGameContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(Context ctx) throws Exception {
|
||||
// Setup session
|
||||
GameSession session = null;
|
||||
|
||||
byte[] sessionKey = AeadHelper.serverGarbleKey;
|
||||
boolean hasKey3 = false;
|
||||
|
||||
// Get token
|
||||
String token = ctx.header("X-Token");
|
||||
|
||||
// Set headers
|
||||
ctx.res().setHeader("Server", "agent");
|
||||
|
||||
// Check if we have a token
|
||||
if (token != null) {
|
||||
// Get session
|
||||
session = getGameContext().getSessionByToken(token);
|
||||
|
||||
// Uh oh - session not found
|
||||
if (session == null || session.getKey() == null) {
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set key
|
||||
sessionKey = session.getKey();
|
||||
hasKey3 = true;
|
||||
}
|
||||
|
||||
// Parse request
|
||||
byte[] data = null;
|
||||
int msgId = 0;
|
||||
|
||||
try {
|
||||
// Get message
|
||||
byte[] message = ctx.bodyAsBytes();
|
||||
int offset = 0;
|
||||
|
||||
// Sanity for malformed packets
|
||||
if (message.length <= 12) {
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Decrypt message
|
||||
if (hasKey3) {
|
||||
message = AeadHelper.decryptChaCha(message, sessionKey);
|
||||
offset = 10;
|
||||
} else {
|
||||
message = AeadHelper.decryptBasic(message, sessionKey);
|
||||
message = AeadHelper.decryptGCM(message, sessionKey);
|
||||
}
|
||||
|
||||
// Get message id
|
||||
msgId = (message[offset++] << 8) | (message[offset++] & 0xff);
|
||||
|
||||
// Set data
|
||||
data = new byte[message.length - offset];
|
||||
System.arraycopy(message, offset, data, 0, data.length);
|
||||
|
||||
// Log
|
||||
if (Nebula.getConfig().getLogOptions().packets) {
|
||||
this.logRecv(msgId, data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Decrypt error
|
||||
e.printStackTrace();
|
||||
ctx.status(500);
|
||||
ctx.result("");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update last active time for session
|
||||
if (session != null) {
|
||||
session.updateLastActiveTime();
|
||||
}
|
||||
|
||||
// Handle packet
|
||||
NetHandler handler = this.handlers.get(msgId);
|
||||
byte[] result = null;
|
||||
|
||||
try {
|
||||
if (handler == null) {
|
||||
Nebula.getLogger().warn("Unhandled request: " + msgId);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check handler requirements
|
||||
if (session == null) {
|
||||
if (handler.requireSession()) {
|
||||
return;
|
||||
}
|
||||
} else if (session.getPlayer() == null && handler.requirePlayer()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle data
|
||||
result = handler.handle(session, data);
|
||||
} catch (Exception e) {
|
||||
// Handler error
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
// Send result
|
||||
if (result == null) {
|
||||
ctx.status(500);
|
||||
ctx.result(EMPTY_BYTES);
|
||||
return;
|
||||
}
|
||||
|
||||
// Log
|
||||
if (Nebula.getConfig().getLogOptions().packets) {
|
||||
this.logSend(result);
|
||||
}
|
||||
|
||||
// Encrypt
|
||||
if (hasKey3) {
|
||||
result = AeadHelper.encryptChaCha(result, sessionKey);
|
||||
} else {
|
||||
result = AeadHelper.encryptGCM(result, sessionKey);
|
||||
result = AeadHelper.encryptBasic(result, sessionKey);
|
||||
}
|
||||
|
||||
// Send to client
|
||||
ctx.status(200);
|
||||
ctx.result(result);
|
||||
|
||||
ctx.res().setHeader("Content-Type", null);
|
||||
}
|
||||
}
|
||||
|
||||
// Loggers
|
||||
|
||||
private void logRecv(int msgId, byte[] data) {
|
||||
Nebula.getLogger().info("RECV: " + NetMsgIdUtils.getMsgIdName(msgId) + " (" + msgId + ")");
|
||||
System.out.println(Utils.bytesToHex(data));
|
||||
}
|
||||
|
||||
private void logSend(byte[] data) {
|
||||
int sendMsgId = (data[0] << 8) | (data[1] & 0xff);
|
||||
Nebula.getLogger().info("SEND: " + NetMsgIdUtils.getMsgIdName(sendMsgId) + " (" + sendMsgId + ")");
|
||||
System.out.println(Utils.bytesToHex(data, 2));
|
||||
}
|
||||
|
||||
// Register handlers
|
||||
|
||||
private void registerHandlers() {
|
||||
// Setup handlers
|
||||
Reflections reflections = new Reflections(Nebula.class.getPackageName());
|
||||
Set<Class<?>> handlers = reflections.getTypesAnnotatedWith(HandlerId.class);
|
||||
|
||||
for (Class<?> cls : handlers) {
|
||||
// Make sure class is a handler
|
||||
if (!NetHandler.class.isAssignableFrom(cls)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
NetHandler handler = (NetHandler) cls.getConstructor().newInstance();
|
||||
HandlerId def = cls.getAnnotation(HandlerId.class);
|
||||
|
||||
int opcode = def.value();
|
||||
if (opcode != 0) {
|
||||
// Put in handler map
|
||||
this.handlers.put(opcode, handler);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
// Log registration
|
||||
Nebula.getLogger().info("Registered " + handlers.size() + " handlers");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.server.HttpServer;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class CommonConfigHandler implements Handler {
|
||||
private HttpServer server;
|
||||
private String json;
|
||||
|
||||
public CommonConfigHandler(HttpServer server) {
|
||||
this.server = server;
|
||||
this.json = "{\"Code\":200,\"Data\":{\"AppConfig\":{\"ACCOUNT_RETRIEVAL\":{\"FIRST_LOGIN_POPUP\":false,\"LOGIN_POPUP\":false,\"PAGE_URL\":\"\"},\"AGREEMENT_POPUP_TYPE\":\"Browser\",\"APPLE_CURRENCY_BLOCK_LIST\":null,\"APPLE_TYPE_KEY\":\"apple_hk\",\"APP_CLIENT_LANG\":[\"en\"],\"APP_DEBUG\":0,\"APP_GL\":\"en\",\"BIND_METHOD\":[\"google\",\"apple_hk\",\"facebook\"],\"CAPTCHA_ENABLED\":false,\"CLIENT_LOG_REPORTING\":{\"ENABLE\":true},\"CREDIT_INVESTIGATION\":\"0.0\",\"DESTROY_USER_DAYS\":15,\"DESTROY_USER_ENABLE\":1,\"DETECTION_ADDRESS\":{\"AUTO\":{\"DNS\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"HTTP\":[\"${url}\",\"${url}\",\"${url}\"],\"MTR\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"PING\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"],\"TCP\":[\"${url}\",\"${url}\",\"${url}/meta/serverlist.html\"]},\"ENABLE\":true,\"ENABLE_MANUAL\":true,\"INTERNET\":\"https://www.google.com\",\"INTERNET_ADDRESS\":\"https://www.google.com\",\"NETWORK_ENDPORINT\":\"\",\"NETWORK_PROJECT\":\"\",\"NETWORK_SECRET_KEY\":\"\"},\"ENABLE_AGREEMENT\":true,\"ENABLE_MULTI_LANG_AGREEMENT\":false,\"ENABLE_TEXT_REVIEW\":true,\"ERROR_CODE\":\"4.4\",\"FILE_DOMAIN\":\"\",\"GEETEST_ENABLE\":false,\"GEETEST_ID\":\"\",\"GOOGLE_ANALYTICS_MEASUREMENT_ID\":\"\",\"MIGRATE_POPUP\":true,\"NICKNAME_REG\":\"^[A-Za-z0-9]{2,20}$\",\"POPUP\":{\"Data\":[{\"Lang\":\"ja\",\"Text\":\"YostarIDを作成\"},{\"Lang\":\"en\",\"Text\":\"CreateaYostaraccount\"},{\"Lang\":\"kr\",\"Text\":\"YOSTAR계정가입하기\"},{\"Lang\":\"fr\",\"Text\":\"CréezvotrecompteYostar\"},{\"Lang\":\"de\",\"Text\":\"EinenYostar-Accounterstellen\"}],\"Enable\":true},\"PRIVACY_AGREEMENT\":\"0.1\",\"RECHARGE_LIMIT\":{\"Enable\":false,\"IsOneLimit\":false,\"Items\":[],\"OneLimitAmount\":0},\"SHARE\":{\"CaptureScreen\":{\"AutoCloseDelay\":0,\"Enabled\":false},\"Facebook\":{\"AppID\":\"\",\"Enabled\":false},\"Instagram\":{\"Enabled\":false},\"Kakao\":{\"AppKey\":\"\",\"Enabled\":false},\"Naver\":{\"Enabled\":false},\"Twitter\":{\"Enabled\":false}},\"SLS\":{\"ACCESS_KEY_ID\":\"7b5d0ffd0943f26704fc547a871c68b1b5d56b5c9caeb354205b81f445d7af59\",\"ACCESS_KEY_SECRET\":\"4a5e9cc8a50819290c9bfa1fedc79da7c50e85189a05eb462a3d28a7688eabb0\",\"ENABLE\":false},\"SURVEY_POPUP_TYPE\":\"Browser\",\"UDATA\":{\"Enable\":false,\"URL\":\"${url}\"},\"USER_AGREEMENT\":\"0.1\",\"YOSTAR_PREFIX\":\"yoyo\"},\"EuropeUnion\":false,\"StoreConfig\":{\"ADJUST_APPID\":\"\",\"ADJUST_CHARGEEVENTTOKEN\":\"\",\"ADJUST_ENABLED\":0,\"ADJUST_EVENTTOKENS\":null,\"ADJUST_ISDEBUG\":0,\"AIRWALLEX_ENABLED\":false,\"AI_HELP\":{\"AihelpAppID\":\"yostar1_platform_2db52a57068b1ee3fe3652c8b53d581b\",\"AihelpAppKey\":\"YOSTAR1_app_bc226f4419a7447c9de95711f8a2d3d9\",\"AihelpDomain\":\"yostar1.aihelp.net\",\"CustomerServiceURL\":\"\",\"CustomerWay\":1,\"DisplayType\":\"Browser\",\"Enable\":1,\"Mode\":\"robot\"},\"APPLEID\":\"\",\"CODA_ENABLED\":false,\"ENABLED_PAY\":{\"AIRWALLEX_ENABLED\":false,\"CODA_ENABLED\":false,\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false,\"MYCARD_ENABLED\":false,\"PAYPAL_ENABLED\":true,\"RAZER_ENABLED\":false,\"STEAM_ENABLED\":false,\"STRIPE_ENABLED\":true,\"TOSS_ENABLED\":false,\"WEBMONEY_ENABLED\":false},\"FACEBOOK_APPID\":\"\",\"FACEBOOK_CLIENT_TOKEN\":\"\",\"FACEBOOK_SECRET\":\"\",\"FIREBASE_ENABLED\":0,\"GMO_CC_JS\":\"https://\",\"GMO_CC_KEY\":\"\",\"GMO_CC_SHOPID\":\"\",\"GMO_PAY_CHANNEL\":{\"GMOAlipay\":false,\"GMOAu\":false,\"GMOCreditcard\":false,\"GMOCvs\":false,\"GMODocomo\":false,\"GMOPaypal\":false,\"GMOPaypay\":false,\"GMOSoftbank\":false},\"GMO_PAY_ENABLED\":false,\"GOOGLE_CLIENT_ID\":\"\",\"GOOGLE_CLIENT_SECRET\":\"\",\"GUEST_CREATE_METHOD\":0,\"GUIDE_POPUP\":{\"DATA\":null,\"ENABLE\":0},\"LOGIN\":{\"DEFAULT\":\"yostar\",\"ICON_SIZE\":\"big\",\"SORT\":[\"google\",\"apple\",\"device\"]},\"MYCARD_ENABLED\":false,\"ONE_STORE_LICENSE_KEY\":\"\",\"PAYPAL_ENABLED\":false,\"RAZER_ENABLED\":false,\"REMOTE_CONFIG\":[],\"SAMSUNG_SANDBOX_MODE\":false,\"STEAM_APPID\":\"\",\"STEAM_ENABLED\":false,\"STEAM_PAY_APPID\":\"\",\"STRIPE_ENABLED\":false,\"TOSS_ENABLED\":false,\"TWITTER_KEY\":\"\",\"TWITTER_SECRET\":\"\",\"WEBMONEY_ENABLED\":false}},\"Msg\":\"OK\"}";
|
||||
|
||||
String address = server.getServerConfig().getDisplayAddress();
|
||||
this.json = this.json.replaceAll("\\$\\{url}", address);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(this.json);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.Nebula;
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.game.account.AccountHelper;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class GetAuthHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), GetAuthRequestJson.class);
|
||||
|
||||
if (req == null || req.Account == null || req.Account.isEmpty() || req.Code == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100600,\"Data\":{},\"Msg\":\"Error\"}"); // PARAM_IS_EMPTY
|
||||
return;
|
||||
}
|
||||
|
||||
// Get account
|
||||
Account account = AccountHelper.getAccountByEmail(req.Account);
|
||||
|
||||
if (account == null) {
|
||||
// Create an account if were allowed to
|
||||
if (Nebula.getConfig().getServerOptions().isAutoCreateAccount()) {
|
||||
account = AccountHelper.createAccount(req.Account, null, 0);
|
||||
}
|
||||
} else {
|
||||
// Check passcode sent by email
|
||||
if (!account.verifyCode(req.Code)) {
|
||||
account = null;
|
||||
}
|
||||
}
|
||||
|
||||
// Sanity
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Build request
|
||||
var response = new GetAuthResponseJson();
|
||||
|
||||
response.Code = 200;
|
||||
response.Msg = "OK";
|
||||
response.Data = new GetAuthResponseJson.GetAuthDataJson();
|
||||
response.Data.UID = account.getEmail();
|
||||
response.Data.Token = account.generateLoginToken();
|
||||
response.Data.Account = account.getEmail();
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(JsonUtils.encode(response));
|
||||
}
|
||||
|
||||
private static class GetAuthRequestJson {
|
||||
public String Account;
|
||||
public String Code;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class GetAuthResponseJson {
|
||||
public int Code;
|
||||
public GetAuthDataJson Data;
|
||||
public String Msg;
|
||||
|
||||
private static class GetAuthDataJson {
|
||||
public String UID;
|
||||
public String Token;
|
||||
public String Account;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
|
||||
public class HttpJsonResponse implements Handler {
|
||||
private final String json;
|
||||
|
||||
public HttpJsonResponse(String jsonString) {
|
||||
this.json = jsonString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
ctx.status(200);
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(json);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.proto.Pb.ServerAgent;
|
||||
import emu.nebula.proto.Pb.ServerListMeta;
|
||||
import emu.nebula.server.HttpServer;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public class MetaServerlistHandler implements Handler {
|
||||
private HttpServer server;
|
||||
private ServerListMeta list;
|
||||
private byte[] proto;
|
||||
|
||||
public MetaServerlistHandler(HttpServer server) {
|
||||
this.server = server;
|
||||
|
||||
// Create server list
|
||||
this.list = ServerListMeta.newInstance()
|
||||
.setVersion(22)
|
||||
.setReportEndpoint(server.getServerConfig().getDisplayAddress() + "/report");
|
||||
|
||||
var agent = ServerAgent.newInstance()
|
||||
.setName("Nebula") // TODO allow change in config
|
||||
.setAddr(server.getServerConfig().getDisplayAddress() + "/agent-zone-1/")
|
||||
.setStatus(1)
|
||||
.setZone(1);
|
||||
|
||||
this.list.addAgent(agent);
|
||||
|
||||
var agent2 = ServerAgent.newInstance()
|
||||
.setName("Test") // TODO allow change in config
|
||||
.setAddr(server.getServerConfig().getDisplayAddress() + "/agent-zone-1/")
|
||||
.setStatus(1)
|
||||
.setZone(1);
|
||||
|
||||
this.list.addAgent(agent2);
|
||||
|
||||
// Cache proto
|
||||
this.proto = list.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Result
|
||||
try {
|
||||
ctx.contentType(ContentType.APPLICATION_OCTET_STREAM);
|
||||
ctx.result(AeadHelper.encryptCBC(this.getProto()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.proto.Pb.ClientDiff;
|
||||
import emu.nebula.util.AeadHelper;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter(AccessLevel.PRIVATE)
|
||||
public class MetaWinHandler implements Handler {
|
||||
private ClientDiff list;
|
||||
private byte[] proto;
|
||||
|
||||
public MetaWinHandler() {
|
||||
// Create client diff
|
||||
this.list = ClientDiff.newInstance();
|
||||
|
||||
// TODO load from json or something
|
||||
|
||||
// Cache proto
|
||||
this.proto = list.toByteArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_OCTET_STREAM);
|
||||
ctx.result(AeadHelper.encryptCBC(this.getProto()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class UserLoginEntity {
|
||||
public int Code;
|
||||
public UserDetailJson Data;
|
||||
public String Msg;
|
||||
|
||||
public static class UserDetailJson {
|
||||
public long AgeVerifyMethod;
|
||||
public Object Destroy;
|
||||
public boolean IsTestAccount;
|
||||
public List<UserKeyJson> Keys;
|
||||
public long ServerNowAt;
|
||||
public UserInfoJson UserInfo;
|
||||
public LoginYostarJson Yostar;
|
||||
public Object YostarDestroy;
|
||||
}
|
||||
|
||||
public static class UserKeyJson {
|
||||
public String ID;
|
||||
public String Type;
|
||||
public String Key;
|
||||
public String NickName;
|
||||
public long CreatedAt;
|
||||
}
|
||||
|
||||
public static class UserInfoJson {
|
||||
public String ID;
|
||||
public int UID2;
|
||||
public String PID;
|
||||
public String Token;
|
||||
public String Birthday;
|
||||
public String RegChannel;
|
||||
public String TransCode;
|
||||
public int State;
|
||||
public String DeviceID;
|
||||
public long CreatedAt;
|
||||
}
|
||||
|
||||
public static class LoginYostarJson {
|
||||
public String ID;
|
||||
public String Country;
|
||||
public String Nickname;
|
||||
public String Picture;
|
||||
public int State;
|
||||
public int AgreeAd;
|
||||
public long CreatedAt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,127 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.game.account.AccountHelper;
|
||||
import emu.nebula.server.routes.UserLoginEntity.LoginYostarJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserDetailJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserInfoJson;
|
||||
import emu.nebula.server.routes.UserLoginEntity.UserKeyJson;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import io.javalin.http.Handler;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserLoginHandler implements Handler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Get account from header first
|
||||
Account account = this.getAccountFromHeader(ctx);
|
||||
|
||||
// Check req body for account details
|
||||
if (account == null) {
|
||||
account = this.getAccountFromBody(ctx);
|
||||
}
|
||||
|
||||
// Check
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Create response
|
||||
var response = new UserLoginEntity();
|
||||
|
||||
response.Code = 200;
|
||||
response.Msg = "OK";
|
||||
response.Data = new UserDetailJson();
|
||||
response.Data.Keys = new ArrayList<>();
|
||||
response.Data.UserInfo = new UserInfoJson();
|
||||
response.Data.Yostar = new LoginYostarJson();
|
||||
|
||||
response.Data.UserInfo.ID = account.getUid();
|
||||
response.Data.UserInfo.UID2 = 0;
|
||||
response.Data.UserInfo.PID = "NEBULA";
|
||||
response.Data.UserInfo.Token = account.getLoginToken();
|
||||
response.Data.UserInfo.Birthday = "";
|
||||
response.Data.UserInfo.RegChannel = "pc";
|
||||
response.Data.UserInfo.TransCode = "";
|
||||
response.Data.UserInfo.State = 1;
|
||||
response.Data.UserInfo.DeviceID = "";
|
||||
response.Data.UserInfo.CreatedAt = account.getCreatedAt();
|
||||
|
||||
response.Data.Yostar.ID = account.getUid();
|
||||
response.Data.Yostar.Country = "US";
|
||||
response.Data.Yostar.Nickname = account.getNickname();
|
||||
response.Data.Yostar.Picture = account.getPicture();
|
||||
response.Data.Yostar.State = 1;
|
||||
response.Data.Yostar.AgreeAd = 0;
|
||||
response.Data.Yostar.CreatedAt = account.getCreatedAt();
|
||||
|
||||
var key = new UserKeyJson();
|
||||
key.ID = account.getUid();
|
||||
key.Type = "yostar";
|
||||
key.Key = account.getEmail();
|
||||
key.NickName = account.getEmail();
|
||||
key.CreatedAt = account.getCreatedAt();
|
||||
|
||||
response.Data.Keys.add(key);
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result(JsonUtils.encode(response, true));
|
||||
}
|
||||
|
||||
protected Account getAccountFromBody(Context ctx) {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), UserLoginRequestJson.class);
|
||||
|
||||
if (req == null || req.OpenID == null || req.Token == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get account
|
||||
return AccountHelper.getAccountByLoginToken(req.Token);
|
||||
}
|
||||
|
||||
protected Account getAccountFromHeader(Context ctx) {
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.header("Authorization"), UserAuthDataJson.class);
|
||||
|
||||
if (req == null || req.Head == null || req.Head.Token == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Get account
|
||||
return AccountHelper.getAccountByLoginToken(req.Head.Token);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserLoginRequestJson {
|
||||
public String OpenID;
|
||||
public String Token;
|
||||
public String Type;
|
||||
public String UserName;
|
||||
public String Secret;
|
||||
public int CheckAccount;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserAuthDataJson {
|
||||
public UserAuthHeadJson Head;
|
||||
public String Sign;
|
||||
|
||||
protected static class UserAuthHeadJson {
|
||||
public String UID;
|
||||
public String Token;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package emu.nebula.server.routes;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import emu.nebula.game.account.Account;
|
||||
import emu.nebula.util.JsonUtils;
|
||||
import io.javalin.http.ContentType;
|
||||
import io.javalin.http.Context;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class UserSetDataHandler extends UserLoginHandler {
|
||||
|
||||
@Override
|
||||
public void handle(@NotNull Context ctx) throws Exception {
|
||||
// Get account from header first
|
||||
Account account = this.getAccountFromHeader(ctx);
|
||||
|
||||
// Check
|
||||
if (account == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100403,\"Data\":{},\"Msg\":\"Error\"}"); // TOKEN_AUTH_FAILED
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse request
|
||||
var req = JsonUtils.decode(ctx.body(), UserSetDataReqJson.class);
|
||||
|
||||
if (req.Key == null || req.Value == null) {
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":100110,\"Data\":{},\"Msg\":\"Error\"}"); // VALID_FAIL
|
||||
return;
|
||||
}
|
||||
|
||||
if (req.Key.equals("Nickname")) {
|
||||
account.setNickname(req.Value);
|
||||
account.save();
|
||||
}
|
||||
|
||||
// Result
|
||||
ctx.contentType(ContentType.APPLICATION_JSON);
|
||||
ctx.result("{\"Code\":200,\"Data\":{},\"Msg\":\"OK\"}");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class UserSetDataReqJson {
|
||||
public String Key;
|
||||
public String Value;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user